/* ═══════════════════════════════════════════════════════════
   ONLYTRIBE — CATALOGUE
   Standalone landing surface, hosted apart from the Shopify theme.

   The palette, the type scale and the square edges are lifted from the
   theme's base.css on purpose: this page and the store have to look like
   the same brand on the day the store opens. Tokens are duplicated rather
   than imported because this site ships alone — one stylesheet, no build.
   ═══════════════════════════════════════════════════════════ */

:root {
  --paper:      #F7EFE1;
  --paper-warm: #FCF6EC;
  --paper-deep: #EDE2CE;
  --ink:        #16150F;
  --lime:       #DCE839;
  --terracotta: #C4714A;
  --night:      #23212E;

  --text:        var(--ink);
  --text-soft:   #514B3E;
  /* Cleared against all three paper surfaces at 4.5:1 — the muted-on-paper
     failure this palette invites is why these are fixed values, not guesses. */
  --text-muted:  #696152;
  --accent:      var(--terracotta);
  --accent-text: #964C29;
  --accent-dark: #A2542F;
  --border:      rgba(22, 21, 15, 0.16);
  --border-soft: rgba(22, 21, 15, 0.08);

  --font-display: 'SHAKA', Georgia, 'Times New Roman', serif;
  --font-ui: 'Outfit', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --t: 0.3s var(--ease);

  --gutter: clamp(1.25rem, 4vw, 3rem);
  --measure: 1180px;
  --section-y: clamp(3.5rem, 9vh, 7rem);
}

@font-face {
  font-family: 'SHAKA';
  src: url('fonts/SHAKA.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Outfit';
  src: url('fonts/outfit-var-latin.woff2') format('woff2-variations');
  font-weight: 100 900; font-style: normal; font-display: swap;
}

*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  /* The grain the store theme puts under every scene. Two offset dot fields,
     no request, and it stops the paper reading as flat #F7EFE1. */
  background-image:
    radial-gradient(circle at 50% 50%, rgba(22,21,15,0.030) 0.6px, transparent 0.7px),
    radial-gradient(circle at 50% 50%, rgba(196,113,74,0.030) 0.6px, transparent 0.7px);
  background-size: 18px 18px, 29px 29px;
  background-position: 0 0, 9px 14px;
  color: var(--text);
  font-family: var(--font-ui);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
a { color: inherit; }

/* The parts nobody draws still carry the design. */
::selection { background: var(--lime); color: var(--ink); }
:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 3px; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ink); color: var(--paper);
  padding: 0.75rem 1.25rem; font-size: 0.8rem;
}
.skip:focus { left: 0; }

/* SHAKA is uppercase-only by design — its lowercase is a different, much
   noisier animal. Every display use goes through this class. */
.display {
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  word-spacing: -0.12em;
  font-weight: 400;
  line-height: 0.95;
}

.wrap {
  max-width: var(--measure);
  margin-inline: auto;
  padding: var(--section-y) var(--gutter);
}

/* ── Masthead ─────────────────────────────────────────── */
.masthead {
  position: sticky; top: 0; z-index: 40;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem;
  padding: 0.75rem var(--gutter);
  background: var(--paper);
  border-bottom: 1px solid var(--border-soft);
}
.masthead__logo img { height: 26px; width: auto; filter: brightness(0); }
.masthead__nav {
  display: flex; align-items: center; gap: clamp(0.75rem, 2.5vw, 1.75rem);
  font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase;
}
.masthead__nav a { text-decoration: none; transition: color var(--t); }
.masthead__nav a:hover { color: var(--accent-text); }
.masthead__order {
  background: var(--ink); color: var(--paper);
  padding: 0.5rem 0.9rem;
}
.masthead__order:hover { background: var(--accent-text); color: var(--paper); }
@media (max-width: 460px) {
  .masthead__nav a:not(.masthead__order) { display: none; }
}

/* ── Hero ─────────────────────────────────────────────── */
.hero {
  position: relative;
  min-height: min(78svh, 720px);
  display: flex; align-items: flex-end;
  overflow: clip;
  background: var(--ink);
  isolation: isolate;
}
.hero__frame { position: absolute; inset: 0; z-index: 0; }
/* Slides are stacked and cross-faded rather than swapped: a hard cut between
   two photographs reads as a broken image loading, a fade reads as a look
   changing. The slow drift stops the still frame from looking frozen. */
.hero__frame img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  opacity: 0;
  transform: scale(1.06);
  transition: opacity 1.1s var(--ease);
}
.hero__frame img.is-on {
  opacity: 1;
  animation: drift 14s ease-out forwards;
}
@keyframes drift { from { transform: scale(1.06); } to { transform: scale(1.005); } }
.hero__empty { width: 100%; height: 100%; background: var(--paper-deep); opacity: 0.5; }
.hero::after {
  content: '';
  position: absolute; z-index: 2;
  left: 0; right: 0; bottom: 0; height: 10px;
  background-image: radial-gradient(circle at 50% 50%, var(--lime) 2px, transparent 2.4px);
  background-size: 16px 10px;
  opacity: 0.9;
}
.hero__scrim {
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(to top, rgba(22,21,15,0.66) 0%, rgba(22,21,15,0.12) 45%, rgba(22,21,15,0) 70%);
}
.hero__type {
  position: relative; z-index: 2;
  width: 100%; max-width: var(--measure);
  margin-inline: auto;
  padding: 0 var(--gutter) clamp(2.5rem, 7vh, 5rem);
  color: var(--paper);
}
.hero__title {
  font-size: clamp(2.6rem, 8vw, 5.5rem);
  margin: 0;
  text-shadow: 0 2px 24px rgba(22, 21, 15, 0.45);
}
.hero__actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.75rem; }
.btn--ghost {
  background: transparent; color: var(--paper); border-color: rgba(247,239,225,0.55);
}
.btn--ghost:hover { background: var(--paper); color: var(--ink); border-color: var(--paper); }

.hero__dots {
  position: absolute; z-index: 3;
  right: var(--gutter); bottom: clamp(2.5rem, 7vh, 5rem);
  display: flex; flex-direction: column; gap: 0.5rem;
}
.hero__dot {
  width: 3px; height: 22px;
  padding: 0; border: none;
  background: rgba(247, 239, 225, 0.4);
  cursor: pointer;
  transition: background 0.3s var(--ease), height 0.3s var(--ease);
}
.hero__dot[aria-current="true"] { background: var(--lime); height: 34px; }
@media (max-width: 640px) { .hero__dots { display: none; } }

.hero__line {
  max-width: 34ch;
  margin: 1rem 0 0;
  font-weight: 300;
  color: rgba(247, 239, 225, 0.9);
  text-shadow: 0 1px 12px rgba(22, 21, 15, 0.4);
}

/* Block-print ground for any slot whose image has not landed yet. Two
   repeating radial dots, no request, and it reads as a printed textile
   rather than as a missing file. */
.bandhani {
  background-color: var(--paper-deep);
  background-image:
    radial-gradient(circle at 50% 50%, rgba(196,113,74,0.22) 1.4px, transparent 1.6px),
    radial-gradient(circle at 50% 50%, rgba(22,21,15,0.10) 1px, transparent 1.2px);
  background-size: 22px 22px, 22px 22px;
  background-position: 0 0, 11px 11px;
}

/* ── Buttons ──────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; gap: 0.6rem;
  padding: 0.85rem 1.5rem;
  font-family: var(--font-ui);
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  text-decoration: none;
  border: 1px solid currentColor;
  transition: background var(--t), color var(--t), border-color var(--t);
}
.btn--light {
  background: var(--paper); color: var(--ink); border-color: var(--paper);
}
.btn--light:hover { background: transparent; color: var(--paper); }
.btn--wa {
  width: 100%; justify-content: center;
  background: var(--ink); color: var(--paper); border-color: var(--ink);
  margin-top: 0.5rem;
}
.btn--wa:hover { background: var(--accent-text); border-color: var(--accent-text); }

/* ── Marquee ──────────────────────────────────────────── */
.marquee {
  background: var(--lime);
  border-block: 1px solid var(--ink);
  overflow: hidden;
  padding: 0.55rem 0;
}
.marquee__track {
  display: flex; gap: 2.5rem;
  width: max-content;
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: clamp(1.1rem, 3vw, 1.9rem);
  color: var(--ink);
  white-space: nowrap;
  /* translate3d, not translateX: iOS keeps a 2D transform on the main thread
     and re-rasterises a strip this wide on every frame, which is what tore the
     type. will-change and the backface hint keep it on its own layer. */
  animation: slide 38s linear infinite;
  will-change: transform;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
@keyframes slide {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}
/* A strip that is off screen has no business animating. */
.marquee { contain: paint; }
/* A loop that runs whether or not anything happened is decoration, and this
   setting refuses it. The words stay, the movement stops. */
@media (prefers-reduced-motion: reduce) {
  .marquee__track { animation: none; }
  .marquee { overflow-x: auto; }
}

.launch {
  max-width: 46ch;
  margin: clamp(2.5rem, 6vh, 4rem) auto 0;
  padding-inline: var(--gutter);
  text-align: center;
  color: var(--text-soft);
  font-size: 0.95rem;
}

/* ── Section heads ────────────────────────────────────── */
.head { margin-bottom: clamp(2rem, 5vh, 3rem); }
.head__label {
  display: flex; align-items: center; gap: 0.75rem;
  font-size: 0.62rem; font-weight: 600;
  letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--accent-text);
  margin-bottom: 0.85rem;
}
.head__label::after {
  content: '';
  flex: 0 0 clamp(28px, 6vw, 64px);
  height: 5px;
  background-image: radial-gradient(circle at 50% 50%, currentColor 1.4px, transparent 1.7px);
  background-size: 9px 5px;
  opacity: 0.75;
}
.head__title {
  font-size: clamp(2rem, 5.5vw, 3.4rem);
  margin: 0 0 0.9rem;
  max-width: 18ch;
}
.head__body {
  margin: 0;
  max-width: 56ch;
  color: var(--text-soft);
}

/* ── Filters ──────────────────────────────────────────── */
/* ── Fit ─────────────────────────────────────────────────
   The one band on the page that inverts: ink ground, paper type. It is the
   only moment asking for a message rather than an order, and it should not
   look like another product section. */
.fit {
  background: var(--ink);
  color: var(--paper);
  padding: clamp(3.5rem, 10vh, 6.5rem) var(--gutter);
  position: relative;
  overflow: hidden;
}
.fit::before {
  content: '';
  position: absolute; inset: 0;
  background-image: radial-gradient(circle at 50% 50%, rgba(220,232,57,0.16) 1.5px, transparent 1.8px);
  background-size: 30px 30px;
  opacity: 0.5;
}
.fit__inner { position: relative; max-width: 62ch; margin-inline: auto; text-align: center; }
.fit__label {
  margin: 0 0 1rem;
  font-size: 0.62rem; font-weight: 600;
  letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--lime);
}
.fit__title {
  font-size: clamp(1.9rem, 5vw, 3.2rem);
  margin: 0 0 1.1rem;
  color: var(--paper);
}
.fit__body {
  margin: 0 auto 2rem;
  color: rgba(247, 239, 225, 0.82);
  font-size: 0.95rem;
}
.btn--fit {
  background: var(--lime); color: var(--ink); border-color: var(--lime);
}
.btn--fit:hover { background: transparent; color: var(--lime); }

/* ── Facts ────────────────────────────────────────────── */
.facts {
  list-style: none; margin: 0;
  padding: clamp(2rem, 5vh, 3.5rem) var(--gutter);
  max-width: var(--measure);
  margin-inline: auto;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1.5rem 2rem;
  border-top: 1px solid var(--border-soft);
}
.facts b {
  display: block;
  font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  margin-bottom: 0.35rem;
}
.facts p { margin: 0; font-size: 0.88rem; color: var(--text-soft); }

/* ── Footer ───────────────────────────────────────────── */
.foot {
  background: var(--ink); color: var(--paper);
  padding: clamp(3rem, 8vh, 5rem) var(--gutter);
  text-align: center;
}
.foot__word { font-size: clamp(2.5rem, 10vw, 6rem); margin: 0 0 1.5rem; }
.foot__links {
  display: flex; justify-content: center; gap: 1.5rem;
  font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
}
.foot__links a { text-decoration: none; padding-bottom: 2px; border-bottom: 1px solid rgba(247,239,225,0.4); }
.foot__links a:hover { border-bottom-color: var(--lime); color: var(--lime); }
.foot__note { margin: 1.75rem 0 0; font-size: 0.8rem; color: rgba(247, 239, 225, 0.6); }

/* ── Detail sheet ─────────────────────────────────────── */
.sheet {
  width: min(940px, calc(100vw - 2rem));
  max-height: min(88vh, 900px);
  padding: 0;
  border: none;
  background: var(--paper);
  color: var(--text);
  overflow: hidden;
}

/* The drag handle exists only in the bottom-sheet layout. Declared here,
   before the media query that shows it, so source order does not undo it. */
.sheet__grab { display: none; }

/* On a phone the dialog becomes a bottom sheet: it arrives from the edge the
   thumb is already at, and it is dismissed by pulling it back there. A centred
   modal on a 6in screen is a page that pretends to be a window. */
@media (max-width: 759px) {
  .sheet {
    width: 100%;
    max-width: none;
    max-height: 92svh;
    margin: auto 0 0;
    /* --drag is written by the pointer handler while the sheet is being
       pulled down, so the sheet tracks the thumb rather than animating on
       release only. */
    transform: translateY(var(--drag, 0px));
    animation: sheet-up 0.32s var(--ease);
  }
  .sheet[data-dragging] { transition: none; }
  .sheet__grab {
    display: block;
    padding: 0.75rem 0 0.35rem;
    touch-action: none;
    cursor: grab;
  }
  .sheet__grab::before {
    content: '';
    display: block;
    width: 42px; height: 4px;
    margin-inline: auto;
    background: var(--border);
  }
  .sheet__close { top: 0.25rem; }
  .sheet__media { aspect-ratio: 4 / 5; }
  .sheet__media--empty { min-height: 0; }
  .btn--wa {
    /* The order button stays on screen while the description and the spec
       table scroll underneath it. display:flex, not inline-flex: an inline box
       shrinks to its text and leaves a half-width bar. */
    position: sticky; bottom: 0;
    display: flex;
    margin-inline: calc(clamp(1.5rem, 4vw, 2.5rem) * -1);
    width: auto;
    padding-inline: 1.5rem;
  }
}
@keyframes sheet-up { from { transform: translateY(100%); } }
@media (prefers-reduced-motion: reduce) {
  .sheet { animation: none; }
  .hero__frame img.is-on { animation: none; transform: none; }
  .hero__frame img { transition: none; }
}

/* Swiping between pieces inside the sheet. The pager is the phone's version of
   "back to the grid and into the next one" — three taps become one thumb
   movement, which is the whole difference on a catalogue this size. */
.sheet__pager {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.75rem;
  padding: 0.6rem 0 0;
  font-size: 0.68rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-muted);
}
.sheet__pager button {
  display: grid; place-items: center;
  min-width: 44px; min-height: 44px;
  padding: 0;
  background: none; border: 1px solid var(--border);
  color: inherit; font: inherit; cursor: pointer;
  transition: border-color var(--t), color var(--t);
}
.sheet__pager button:hover:not(:disabled) { border-color: var(--ink); color: var(--ink); }
.sheet__pager button:disabled { opacity: 0.35; cursor: default; }
.sheet__count { font-variant-numeric: tabular-nums; }
.sheet__media { touch-action: pan-y; }
.sheet::backdrop { background: rgba(22, 21, 15, 0.62); }
.sheet__close {
  position: absolute; top: 0.5rem; right: 0.75rem; z-index: 2;
  width: 40px; height: 40px;
  background: var(--paper); border: none;
  font-size: 1.6rem; line-height: 1; color: var(--ink);
  cursor: pointer;
}
.sheet__body {
  display: grid;
  grid-template-columns: 1fr;
  max-height: min(88vh, 900px);
  overflow-y: auto;
}
@media (min-width: 760px) {
  .sheet__body { grid-template-columns: 1fr 1fr; }
  /* A known box, matching the 3:4 the photographs are actually shot at. Left
     to stretch, the media column follows the height of the detail column,
     which pushes the gallery dots below the sheet's own visible area on a
     short window — the indicator that there are more photographs ends up
     where nobody can see it. */
  .sheet__media { aspect-ratio: 3 / 4; align-self: start; }
}
.sheet__media { background: var(--paper-deep); position: relative; overflow: hidden; }
.sheet__media img { width: 100%; height: 100%; object-fit: cover; }
.sheet__media--empty { min-height: 320px; }

/* ── Gallery ──────────────────────────────────────────────
   A real track that slides, not a src swap: the movement is what tells you
   there is another photograph, and it follows the thumb while dragging rather
   than jumping on release. */
.gallery { position: absolute; inset: 0; }
.gallery__track {
  display: flex;
  height: 100%;
  transform: translate3d(calc(var(--slide, 0) * -100% + var(--drag-x, 0px)), 0, 0);
  transition: transform 0.42s var(--ease);
  will-change: transform;
}
.gallery[data-dragging] .gallery__track { transition: none; }
.gallery__track > figure { flex: 0 0 100%; margin: 0; height: 100%; }
.gallery__track img { width: 100%; height: 100%; object-fit: cover; }

.gallery__nav {
  position: absolute; top: 50%; z-index: 2;
  transform: translateY(-50%);
  display: grid; place-items: center;
  width: 44px; height: 44px;
  padding: 0; border: none;
  background: rgba(22, 21, 15, 0.42);
  backdrop-filter: blur(6px);
  color: var(--paper);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.25s var(--ease), background 0.2s var(--ease);
}
.gallery__nav--prev { left: 0.6rem; }
.gallery__nav--next { right: 0.6rem; }
.gallery__nav:hover { background: rgba(22, 21, 15, 0.68); }
.gallery__nav:disabled { opacity: 0 !important; pointer-events: none; }
.sheet__media:hover .gallery__nav,
.gallery__nav:focus-visible { opacity: 1; }
/* No hover on a phone, so the arrows sit at a low opacity instead of never
   appearing at all. */
@media (hover: none) {
  .gallery__nav { opacity: 0.72; }
}
.gallery__nav svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2.2; }

.gallery__dots {
  position: absolute; z-index: 2;
  left: 0; right: 0; bottom: 0;
  display: flex; justify-content: center; gap: 0.4rem;
  /* Pale dots on a pale photograph are no indicator at all — half these
     frames are white cotton on white tile. The gradient is the floor they
     stand on, and it fades out rather than banding across the image. */
  padding: 2rem 0 0.85rem;
  background: linear-gradient(to top, rgba(22, 21, 15, 0.5), rgba(22, 21, 15, 0));
  pointer-events: none;
}
.gallery__dot { pointer-events: auto; }
.gallery__dot {
  width: 22px; height: 3px;
  padding: 0; border: none;
  background: rgba(247, 239, 225, 0.45);
  cursor: pointer;
  transition: background 0.25s var(--ease);
}
.gallery__dot[aria-current="true"] { background: var(--paper); }
.gallery__dot:hover { background: rgba(247, 239, 225, 0.8); }

@media (prefers-reduced-motion: reduce) {
  .gallery__track { transition: none; }
}
.sheet__detail { padding: clamp(1.5rem, 4vw, 2.5rem); }
.sheet__vibe {
  margin: 0 0 0.6rem;
  font-size: 0.62rem; font-weight: 600;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--accent-text);
}
.sheet__title { font-size: clamp(1.7rem, 4vw, 2.6rem); margin: 0 0 0.6rem; }
.sheet__price {
  margin: 0 0 1.2rem;
  font-size: 1.15rem; font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.sheet__pricenote {
  margin: -0.9rem 0 1.2rem;
  font-size: 0.82rem;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.sheet__desc { margin: 0 0 1.5rem; color: var(--text-soft); }

.sheet__sizes { margin: 0 0 1.5rem; }
.sheet__grouplabel {
  margin: 0 0 0.6rem;
  font-size: 0.62rem; font-weight: 600;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--text-muted);
}
.sizerow { display: flex; flex-wrap: wrap; gap: 0.4rem; }
/* Radios, not buttons: one choice out of a set, with arrow-key movement and
   a real checked state the browser already understands. */
.sizerow label {
  position: relative;
  display: grid; place-items: center;
  min-width: 48px; min-height: 44px;
  padding: 0.5rem 0.85rem;
  border: 1px solid var(--border);
  font-size: 0.78rem; font-weight: 500;
  cursor: pointer;
  transition: background var(--t), color var(--t), border-color var(--t);
}
.sizerow input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.sizerow label:hover { border-color: var(--ink); }
.sizerow label:has(input:checked) { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.sizerow label:has(input:focus-visible) { outline: 2px solid var(--accent-text); outline-offset: 2px; }

.sheet__spec { margin: 0 0 1.5rem; font-size: 0.85rem; }
.sheet__spec div { display: flex; gap: 0.75rem; padding: 0.45rem 0; border-bottom: 1px solid var(--border-soft); }
.sheet__spec dt { flex: 0 0 5.5rem; color: var(--text-muted); }
.sheet__spec dd { margin: 0; color: var(--text-soft); }
.sheet__small { margin: 0.8rem 0 0; font-size: 0.76rem; color: var(--text-muted); }

@media (prefers-reduced-motion: reduce) {
  .card__frame img, .card:hover .card__frame img { transition: none; transform: none; }
}


/* ── Arrival ──────────────────────────────────────────────
   Scroll-driven, so it follows the thumb rather than firing on a timer, and
   it costs no JavaScript and no observer. Browsers without support get the
   finished state, which is the correct fallback for a reveal. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .grid > li, .facts li {
      animation: rise linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 42%;
    }
    @keyframes rise {
      from { opacity: 0; transform: translateY(18px); }
      to   { opacity: 1; transform: none; }
    }
  }
}


/* ── Size chart, inside the sheet ───────────────────────── */
.sheet__sizehead {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem;
}
.chartbtn {
  background: none; border: none; padding: 0;
  font-family: var(--font-ui);
  font-size: 0.68rem; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--accent-text);
  cursor: pointer;
  border-bottom: 1px solid currentColor;
}
.chartbtn:hover { color: var(--ink); }
.sheet__chart[hidden] { display: none; }
.sheet__chart {
  margin: 0.9rem 0 0;
  overflow-x: auto;
}
.sheet__chart table {
  width: 100%; min-width: 320px;
  border-collapse: collapse;
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
}
.sheet__chart th, .sheet__chart td {
  padding: 0.4rem 0.5rem;
  text-align: left;
  border-bottom: 1px solid var(--border-soft);
}
.sheet__chart thead th {
  font-size: 0.58rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-muted);
}
.sheet__chart tbody th { font-weight: 600; }
.sheet__chart caption {
  caption-side: bottom;
  padding-top: 0.6rem;
  font-size: 0.72rem; color: var(--text-muted);
  text-align: left;
}


/* ── Cut rows ─────────────────────────────────────────────
   Each silhouette is the head of its own shelf: the type stands on the left
   and its pieces run off to the right. It is how a rack is read in a shop,
   and it puts the answer to "which cut is this" next to the thing itself
   rather than three sections away. */
.rows { display: flex; flex-direction: column; gap: clamp(3rem, 8vh, 5.5rem); }

.row { display: grid; gap: 1.25rem; }
@media (min-width: 900px) {
  .row {
    grid-template-columns: minmax(200px, 250px) minmax(0, 1fr);
    gap: clamp(1.5rem, 3vw, 3rem);
    align-items: start;
  }
}

/* The head was floating on bare paper, which read as a caption rather than as
   the head of a shelf. It sits on its own printed plate now — the same block
   print the brand uses everywhere — and the whole row responds when the
   reader is anywhere near it. */
.row__head {
  position: relative;
  display: flex; flex-direction: column; gap: 0.65rem;
  padding: clamp(1.1rem, 2.5vw, 1.6rem);
  background: var(--paper-warm);
  border: 1px solid var(--border-soft);
  overflow: hidden;
  transition: background 0.45s var(--ease), border-color 0.45s var(--ease);
}
.row__head::before {
  content: '';
  position: absolute; inset: 0;
  background-image: radial-gradient(circle at 50% 50%, rgba(196,113,74,0.18) 1.3px, transparent 1.5px);
  background-size: 24px 24px;
  opacity: 0.5;
  transition: opacity 0.45s var(--ease), transform 0.9s var(--ease);
}
/* A lime hairline down the inside edge — the brand's loudest colour, used as a
   marker rather than a fill. It grows out of the top on approach. */
.row__head::after {
  content: '';
  position: absolute; left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--lime);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.55s var(--ease);
}
.row:hover .row__head,
.row:focus-within .row__head {
  background: var(--paper-deep);
  border-color: var(--border);
}
.row:hover .row__head::before,
.row:focus-within .row__head::before {
  opacity: 0.85;
  transform: translate(6px, -6px);
}
.row:hover .row__head::after,
.row:focus-within .row__head::after { transform: scaleY(1); }

.row__head > * { position: relative; }

@media (max-width: 899px) {
  /* Drawing and name on one line, the punchy line kept, the long description
     dropped: on a phone the cut is a label for the shelf below it, not an
     essay to read before seeing a single piece. */
  .row__head {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-areas: "fig name" "wears wears";
    align-items: center;
    gap: 0.25rem 0.9rem;
    padding: 0.9rem 1rem;
  }
  .row__fig { grid-area: fig; width: 38px; }
  .row__name { grid-area: name; font-size: 1.35rem; }
  .row__line { display: none; }
  .row__wears {
    grid-area: wears;
    padding-top: 0.5rem;
    margin-top: 0.15rem;
    font-size: 0.74rem;
  }
  .row__count {
    grid-area: name;
    justify-self: end;
    align-self: center;
  }
}

@media (min-width: 900px) {
  /* Declared after the base rule on purpose: position:relative there would
     otherwise override this and the head would stop sticking to its shelf. */
  .row__head { position: sticky; top: 96px; }
}

.row__fig {
  width: 62px; height: auto;
  color: var(--ink);
  opacity: 0.85;
  transition: color 0.45s var(--ease), opacity 0.45s var(--ease), transform 0.55s var(--ease);
}
.row:hover .row__fig,
.row:focus-within .row__fig {
  color: var(--accent-dark);
  opacity: 1;
  transform: translateY(-2px) scale(1.04);
}
.row__name {
  font-family: var(--font-display);
  text-transform: uppercase; letter-spacing: 0.02em;
  font-size: clamp(1.5rem, 4vw, 2.1rem);
  line-height: 1; margin: 0;
}
.row__line { margin: 0; font-size: 0.84rem; color: var(--text-soft); max-width: 30ch; }
.row__wears {
  margin: 0; padding-top: 0.55rem;
  border-top: 1px solid var(--border-soft);
  font-size: 0.76rem; color: var(--accent-text);
  max-width: 30ch;
}
.row__count {
  font-family: var(--font-ui);
  font-size: 0.64rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* ── The shelf ── */
.rail {
  /* On a phone one garment should own the screen with the next one peeking,
     not two cramped thumbnails. 180px on a 390px screen gave the photographs
     less than half the width, and the photograph is the product. */
  --card: min(72vw, 300px);
  list-style: none; margin: 0; padding: 0;
  display: flex;
  gap: clamp(0.75rem, 2vw, 1.4rem);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  /* Room for the scaled-up card to breathe without being clipped. */
  padding: 1.5rem 0 2rem;
}
.rail::-webkit-scrollbar { display: none; }
@media (min-width: 700px) { .rail { --card: clamp(200px, 30vw, 260px); } }
@media (min-width: 900px) {
  /* Half a card of lead-out, so the last piece can still reach the middle. */
  .rail { padding-right: 30%; }
}
.rail__item {
  flex: 0 0 var(--card);
  scroll-snap-align: center;
  /* Written by the scroll handler from the card's distance to the middle of
     the shelf. Defaults are the flat state, so with no JS this is an ordinary
     row of equal cards rather than a broken one. */
  transform: scale(var(--s, 1));
  opacity: var(--o, 1);
  transition: transform 0.5s var(--ease), opacity 0.5s var(--ease);
  transform-origin: center bottom;
  will-change: transform;
}

.pcard {
  display: block; width: 100%;
  padding: 0; border: none; background: none;
  font: inherit; color: inherit; text-align: left;
  cursor: pointer;
}
.pcard__frame {
  position: relative; display: block;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  background: var(--paper-deep);
}
.pcard__frame img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 0.6s var(--ease);
}
.pcard:hover .pcard__frame img { transform: scale(1.04); }
/* A soft disc behind the garment, the way the reference lights its subject —
   ink-toned rather than neon, because this is paper and not a sneaker ad. */
.pcard__glow {
  position: absolute; z-index: 0;
  left: 50%; top: 46%;
  width: 78%; aspect-ratio: 1;
  transform: translate(-50%, -50%) scale(var(--glow, 0.7));
  border-radius: 50%;
  background: radial-gradient(circle, rgba(196,113,74,0.32), rgba(196,113,74,0) 70%);
  opacity: var(--glowo, 0);
  transition: transform 0.6s var(--ease), opacity 0.6s var(--ease);
  pointer-events: none;
}
.pcard__meta {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 0.75rem; padding-top: 0.7rem;
}
.pcard__name { font-size: 0.88rem; font-weight: 500; line-height: 1.3; }
.pcard:hover .pcard__name { color: var(--accent-text); }
.pcard__price { font-size: 0.85rem; color: var(--text-muted); font-variant-numeric: tabular-nums; flex: none; }

/* The order prompt belongs to whichever card is centred — one call to action
   on the shelf, not one per card competing with the others. */
.pcard__cta {
  display: block;
  margin-top: 0.7rem;
  padding: 0.55rem 0;
  text-align: center;
  background: var(--lime); color: var(--ink);
  border: 1px solid var(--ink);
  font-family: var(--font-ui);
  font-size: 0.64rem; font-weight: 600;
  letter-spacing: 0.16em; text-transform: uppercase;
  opacity: var(--ctao, 0);
  transform: translateY(var(--ctay, 6px));
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .rail__item, .pcard__glow, .pcard__cta { transition: none; }
  .row__head, .row__head::before, .row__head::after, .row__fig { transition: none; }
  .row:hover .row__head::before { transform: none; }
  .row:hover .row__fig { transform: none; }
  .pcard:hover .pcard__frame img { transform: none; }
}
