/* Nurseri Lestari — css/components.css (A): refinements of the sticker primitives from base.css (hover/focus/touch
   states), reveal variants for [data-reveal], and the masks for [data-split]. Nobody renames these classes. */

/* ---- buttons and chips: v2 (C3, 31 Oct) keeps the travelling arrow and the tipping glyph, drops every lift and hard offset
   shadow; hover is a flat tint, focus rings follow the pill ---- */
.btn { position: relative; }
.btn > .icon { transition: translate var(--dur-2) var(--ease-out), rotate var(--dur-3) var(--ease-out); }
@media (hover: hover) {
  .btn:hover > .icon:last-child:not(:only-child) { translate: 3px 0; }  /* trailing arrows travel */
  .btn:hover > .icon:first-child:not(:only-child) { rotate: -10deg; }    /* leading glyphs tip like a pot being picked up */
}
@media (hover: none) { .btn:hover { transform: none; } }
.btn:focus-visible { outline-offset: 4px; border-radius: var(--radius-pill); }
.btn:active > .icon { translate: 0 0; rotate: 0deg; }

a.tag, button.tag { cursor: pointer; transition: background var(--dur-1), color var(--dur-1), border-color var(--dur-1); }
@media (hover: hover) {
  a.tag:hover, button.tag:hover { background: rgb(var(--ink-rgb) / .06); border-color: rgb(var(--ink-rgb) / .3); }
  .on-dark a.tag:hover, .on-dark button.tag:hover { background: rgb(var(--sage-rgb) / .08); border-color: rgb(var(--sage-rgb) / .3); }
  .tag.is-active:hover, .tag[aria-pressed="true"]:hover { background: var(--ink); border-color: var(--ink); }
}
.tag:focus-visible { border-radius: var(--radius-pill); }

.link-u { transition: text-decoration-color var(--dur-1), text-decoration-thickness var(--dur-1); }
@media (hover: hover) { .link-u:hover { text-decoration-thickness: 3px; } }

/* ---- reveal variants (main.js adds .is-in once the element enters the viewport) ----
   data-reveal (default) rises 18px · "clip" wipes up · "scale" opens · "left"/"right" slide in · "settle" is a pot set down */
[data-reveal="clip"] { opacity: 1; transform: none; clip-path: inset(0 0 100% 0); }
[data-reveal="clip"].is-in { clip-path: inset(0 0 0 0); transition: clip-path var(--dur-4) var(--ease-out); }
[data-reveal="scale"] { transform: scale(.94); }
[data-reveal="left"] { transform: translateX(-28px); }
[data-reveal="right"] { transform: translateX(28px); }
[data-reveal="settle"] { transform: translateY(28px) scale(.96) rotate(-1.5deg); }
[data-reveal="settle"].is-in { transition-duration: var(--dur-4); }
html.no-js [data-reveal="clip"], html.reduced [data-reveal="clip"] { clip-path: none; }

/* ---- split headlines: lines rise from a clip; hidden until main.js splits them (html.motion is set before paint by layout.js) ---- */
html.motion [data-split] { visibility: hidden; }
html.motion.no-js [data-split] { visibility: visible; }
.split-line-mask, .line-mask { padding-bottom: .2em; margin-bottom: -.2em; } /* descender room inside the clip */

/* ---- product tiles (shared: the landing's featured four, the catalog, the detail page's related row). v2 (C3, 31 Oct 2026):
   a flat paper-2 card one tone above the ground, radius 24, no plank, no shadow, no lift. P2 (1 Nov 2026, client): the square
   Tokopedia card image fills the top of the tile edge to edge, whole (no mat, no 12 % crop, no multiply); the radius lives on
   the outer tile only (overflow clip rounds the image's top corners with it); under it name, category, then the price with
   "N terjual" beside it and, when asked for, a "Lihat produk" pill. Hover is the base .photo-hover image scale, clipped by
   the image box. Markup: tileHTML() in js/catalog.js; landing.js and tips.js import it. ---- */
.rak { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-6); }
.rak-item { display: grid; min-width: 0; }
.rak-card { display: flex; flex-direction: column; gap: .25rem; padding: 0 0 1rem; background: var(--paper-2); border-radius: var(--radius-lg); overflow: clip; color: var(--ink); }
.rak-mat { position: relative; display: block; aspect-ratio: 1; margin-bottom: .875rem; background: var(--paper-3); overflow: clip; }   /* paper-3 holds the square until the JPEG lands */
.rak-mat img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 50%; transition: transform var(--dur-4) var(--ease-out); }
.rak-name { padding-inline: 1rem; font-family: var(--font-display); font-weight: 600; font-size: 1.125rem; line-height: 1.2; color: var(--ink); display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }   /* at most two lines; the price is pinned to the card's foot so prices line up across the row */
.rak-cat { padding-inline: 1rem; font-size: var(--fs-xs); color: var(--mute); }
.rak-foot { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: .25rem .625rem; margin-top: auto; padding: .625rem 1rem 0; }
.rak-foot .price { font-size: 1.25rem; }
.rak-sold { font-size: var(--fs-xs); color: var(--mute); font-variant-numeric: tabular-nums; white-space: nowrap; }   /* mute: 5.0:1 on paper-2 */
.rak-cta { margin: .875rem 1rem 0; align-self: stretch; }
.rak-card:focus-visible { outline-offset: 3px; border-radius: var(--radius-lg); }
@media (max-width: 1023px) { .rak { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 639px) {
  .rak { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-4) var(--s-3); }
  .rak-card { padding-bottom: .875rem; }
  .rak-mat { margin-bottom: .625rem; }
  .rak-name, .rak-cat { padding-inline: .75rem; }
  .rak-foot { padding-inline: .75rem; }
  .rak-cta { margin-inline: .75rem; }
  .rak-name { font-size: 1rem; }
  .rak-foot .price { font-size: 1.125rem; }
}
