/* ==========================================================================
   MAVERA CHOCOLATES — The Art of Gifting
   A Diwali designer card. Mobile-first; on a wide screen the card stays a
   card and the room around it does the atmosphere.

   Colour is pulled off the real logo: the gold runs #8A5A22 → #F0D49A, the
   roundel brown sits near #3A1B0E, and everything dark is chocolate rather
   than black so the gold never looks like it is floating in a void.
   ========================================================================== */

:root {
  --ink:        #0E0603;
  --cocoa:      #170C06;
  --cocoa-up:   #241309;
  --cocoa-hi:   #341C0F;
  --wine:       #3A0E18;
  --wine-up:    #4E1420;

  --gold:       #C8923C;
  --gold-lo:    #8A5A22;
  --gold-hi:    #F0D49A;
  --copper:     #B5713F;
  --champagne:  #E8D3AE;
  --ivory:      #F7F0E4;

  --tx:         rgba(247, 240, 228, .80);
  --tx-dim:     rgba(247, 240, 228, .52);
  --hair:       rgba(200, 146, 60, .26);
  --hair-soft:  rgba(200, 146, 60, .14);

  --col:        26px;                      /* side gutter */
  --card-w:     452px;
  --r:          16px;

  --ease:       cubic-bezier(.22, .61, .25, 1);
  --ease-out:   cubic-bezier(.16, 1, .3, 1);

  --dur:        .9s;

  --bloom-rest: .30;                       /* warm bloom when nothing drives it */
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--tx);
  font: 300 16px/1.62 'Jost', system-ui, -apple-system, 'Segoe UI', sans-serif;
  letter-spacing: .005em;
  overflow-x: clip;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

img { display: block; max-width: 100%; height: auto; }
svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 1.5;
      stroke-linecap: round; stroke-linejoin: round; }

::selection { background: var(--gold); color: var(--ink); }

:where(a, button, input):focus-visible {
  outline: 2px solid var(--gold-hi);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip {
  position: fixed; left: 12px; top: 10px; z-index: 90;
  padding: 10px 18px; border-radius: 999px;
  background: var(--gold); color: var(--ink); font-weight: 500; text-decoration: none;
  clip-path: inset(50%); opacity: 0;
}
.skip:focus { clip-path: none; opacity: 1; }


/* ── Atmosphere ─────────────────────────────────────────────────────────── */

.atmos { position: fixed; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }

.atmos__wash {
  position: absolute; inset: 0;
  background:
    radial-gradient(118% 62% at 50% -8%,  #4A2412 0%, transparent 62%),
    radial-gradient(96%  54% at 10% 104%, var(--wine) 0%, transparent 60%),
    radial-gradient(90%  50% at 92% 72%,  #30180C 0%, transparent 64%),
    linear-gradient(176deg, var(--cocoa) 0%, var(--ink) 54%, #10070B 100%);
}

/* The warm bloom that swells for the Diwali scene. */
.atmos__bloom {
  position: absolute; left: 50%; top: 52%;
  width: min(150vw, 980px); aspect-ratio: 1;
  transform: translate(-50%, -50%) scale(.9);
  opacity: var(--bloom-rest);
  background: radial-gradient(circle,
    rgba(255, 186, 94, .40) 0%,
    rgba(230, 126, 40, .16) 34%,
    rgba(120, 40, 20, .05) 56%,
    transparent 72%);
  will-change: transform, opacity;
}

.atmos__dust { position: absolute; inset: 0; width: 100%; height: 100%; }

.atmos__grain {
  position: absolute; inset: -50%;
  opacity: .038;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Scroll progress, hairline thin. */
.rail {
  position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 40;
  background: rgba(200, 146, 60, .10);
}
.rail__fill {
  display: block; height: 100%; width: 100%;
  transform: scaleX(0); transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--gold-lo), var(--gold-hi), var(--gold));
}


/* ── The card column ────────────────────────────────────────────────────── */

.card {
  position: relative; z-index: 1;
  width: 100%; max-width: var(--card-w);
  margin-inline: auto;
}

@media (min-width: 620px) {
  .card {
    background: linear-gradient(180deg, rgba(36, 19, 9, .40), rgba(14, 6, 3, .55));
    box-shadow:
      0 0 0 1px var(--hair-soft),
      0 40px 120px -40px rgba(0, 0, 0, .9),
      0 0 160px -60px rgba(200, 146, 60, .22);
  }
  .atmos__wash { background-size: cover; }
}


/* ── Typography ─────────────────────────────────────────────────────────── */

.display {
  margin: 0;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-weight: 300;
  font-size: clamp(42px, 13.2vw, 58px);
  line-height: .98;
  letter-spacing: -.012em;
  color: var(--ivory);
}
.display--sm { font-size: clamp(34px, 10.4vw, 46px); }

.display em, .gold {
  font-style: italic;
  background: linear-gradient(100deg, var(--gold-lo) 2%, var(--gold-hi) 36%, var(--gold) 62%, var(--gold-hi) 94%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}

.eyebrow {
  margin: 0 0 14px;
  font-size: 10.5px; font-weight: 400; letter-spacing: .34em; text-transform: uppercase;
  color: var(--champagne); opacity: .66;
}

.lede {
  margin: 20px 0 0;
  font-size: 15.5px; line-height: 1.74; color: var(--tx);
  max-width: 34ch;
}
.lede--sm { font-size: 14.5px; margin-top: 14px; }


/* ── Reveal primitives ──────────────────────────────────────────────────── */

.ln { display: block; overflow: hidden; }
.ln > i { display: block; font-style: inherit; }

.js .ln > i,
.js [data-reveal] {
  opacity: 0;
  transform: translateY(var(--up, 22px));
  transition:
    opacity var(--dur) var(--ease-out) calc(var(--i, 0) * 90ms + var(--d, 0ms)),
    transform var(--dur) var(--ease-out) calc(var(--i, 0) * 90ms + var(--d, 0ms));
}
.js .ln > i { --up: 102%; }

.js .in .ln > i,
.js [data-reveal].in,
.js .in [data-reveal] {
  opacity: 1;
  transform: none;
}


/* ── Scene frame ────────────────────────────────────────────────────────── */

.scene {
  position: relative;
  padding: clamp(56px, 13vw, 78px) var(--col);
}


/* ══ 01 · The arrival ═══════════════════════════════════════════════════ */

.scene--open {
  min-height: 100svh;
  display: flex; flex-direction: column; justify-content: center; align-items: center;
  text-align: center;
  padding-block: 86px 72px;
  overflow: hidden;
}
.scene--open .lede { margin-inline: auto; }

.open__halo {
  position: absolute; left: 50%; top: 33%;
  width: 124%; aspect-ratio: 1; transform: translate(-50%, -50%);
  background: radial-gradient(circle, rgba(200, 146, 60, .19) 0%, transparent 58%);
  pointer-events: none;
}

.open__crest { position: relative; margin-bottom: clamp(30px, 8vw, 44px); }

/* ── The medallion ──────────────────────────────────────────────────────
   The real roundel, masked to its circle, with two gold rings turning
   around it at different speeds and in opposite directions.             */

.medal {
  position: relative; display: grid; place-items: center;
  width: clamp(196px, 56vw, 238px); aspect-ratio: 1; margin-inline: auto;
}

.medal__glow {
  position: absolute; inset: -18%; border-radius: 50%;
  background: radial-gradient(circle, rgba(200, 146, 60, .34) 0%, rgba(200, 146, 60, .07) 46%, transparent 68%);
}

.medal__face {
  position: relative;
  width: 65%; border-radius: 50%;
  box-shadow: 0 20px 46px -18px rgba(0, 0, 0, .95);
}

/* The hairline that sits right on the roundel's own edge. */
.medal__rim {
  position: absolute; width: 65%; aspect-ratio: 1; border-radius: 50%;
  box-shadow: 0 0 0 1px rgba(240, 212, 154, .5);
}

.medal__ring {
  position: absolute; border-radius: 50%;
  --w: 2px;
  -webkit-mask: radial-gradient(circle, #0000 calc(50% - var(--w)), #000 calc(50% - var(--w)) 50%, #0000 50%);
          mask: radial-gradient(circle, #0000 calc(50% - var(--w)), #000 calc(50% - var(--w)) 50%, #0000 50%);
}

/* Beaded ring, close in, turning slowly clockwise. */
.medal__ring--dash {
  width: 79%; aspect-ratio: 1; --w: 2.5px;
  background: repeating-conic-gradient(from 0deg,
    var(--gold-hi) 0deg 1.9deg, transparent 1.9deg 6.2deg);
  filter: drop-shadow(0 0 3px rgba(200, 146, 60, .6));
  animation: turn 30s linear infinite;
}

/* Two bright arcs, further out, drifting the other way. */
.medal__ring--arc {
  width: 97%; aspect-ratio: 1; --w: 1.6px;
  background: conic-gradient(from 0deg,
    transparent 0deg, var(--gold) 10deg, var(--gold-hi) 36deg, var(--gold) 62deg, transparent 84deg,
    transparent 176deg, var(--gold-lo) 188deg, var(--gold-hi) 214deg, var(--gold) 236deg, transparent 262deg,
    transparent 360deg);
  filter: drop-shadow(0 0 5px rgba(240, 212, 154, .5));
  animation: turn 19s linear infinite reverse;
}

@keyframes turn { to { transform: rotate(360deg); } }

.js .medal { opacity: 0; transform: scale(.88); }
.js .open--lit .medal {
  opacity: 1; transform: none;
  transition: opacity 1.1s ease .1s, transform 1.4s var(--ease-out) .1s;
}

.open__rule {
  display: block; width: 0; height: 1px; margin: 20px auto 11px;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
}
.js .open--lit .open__rule { width: 136px; transition: width 1.1s var(--ease-out) .8s; }
html:not(.js) .open__rule { width: 136px; }

.open__kicker {
  display: block;
  font-size: 10px; letter-spacing: .4em; text-transform: uppercase;
  color: var(--champagne); opacity: 0;
}
.js .open--lit .open__kicker { opacity: .6; transition: opacity .9s ease 1.1s; }
html:not(.js) .open__kicker { opacity: .6; }

.scene--open .display { --i: 0; }
.scene--open .ln:nth-child(1) > i { --d: 980ms; }
.scene--open .ln:nth-child(2) > i { --d: 1080ms; }
.scene--open .ln:nth-child(3) > i { --d: 1180ms; }
.scene--open .lede        { --i: 0; --d: 1380ms; }
.scene--open .open__cue   { --i: 0; --d: 1580ms; }

.open__cue {
  margin-top: clamp(34px, 9vh, 64px);
  display: flex; align-items: center; justify-content: center; gap: 13px;
  font-size: 10.5px; letter-spacing: .26em; text-transform: uppercase;
  color: var(--tx-dim);
}
.open__cue-line {
  width: 44px; height: 1px; background: var(--hair); position: relative; overflow: hidden;
}
.open__cue-line::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, var(--gold-hi), transparent);
  animation: cue 2.6s var(--ease) infinite;
}
@keyframes cue { 0% { transform: translateX(-100%); } 60%, 100% { transform: translateX(100%); } }


/* ══ 02 · The gifting reveal ════════════════════════════════════════════ */

.scene--reveal { padding: 0; }

/* The tall runway and the sticky only exist once something can drive them;
   `scrub` goes on <html> when GSAP has loaded. Until then — and for good,
   if it never arrives — this is an ordinary section showing the open box. */
.reveal__track { height: auto; }
.scrub .reveal__track { height: 196svh; }

.reveal__sticky {
  display: flex; flex-direction: column; justify-content: center;
  gap: clamp(22px, 5vw, 28px);
  padding: 64px var(--col) 96px;          /* the dock lives in that bottom strip */
}
.scrub .reveal__sticky { position: sticky; top: 0; min-height: 100svh; }

.frame {
  --open: 1;
  position: relative;
  aspect-ratio: 5 / 7;
  /* On a short viewport the box would push the caption under the dock. The
     cap wins over the ratio there, leaving a wider frame and a slightly
     tighter crop — which object-fit absorbs without complaint. */
  width: 100%;
  max-height: calc(100svh - 376px);
  border-radius: var(--r);
  overflow: hidden;
  background: var(--cocoa-up);
  box-shadow: 0 30px 70px -34px rgba(0, 0, 0, .92);
}

.frame__photo { position: absolute; inset: 0; }
.frame__photo img {
  width: 100%; height: 100%; object-fit: cover;
  transform: scale(calc(1.16 - .16 * var(--open)));
  /* Ends a shade under full brightness with a trace of sepia left in, so
     the studio white of the packshot belongs to this warm room. */
  filter:
    brightness(calc(.60 + .34 * var(--open)))
    saturate(calc(.80 + .18 * var(--open)))
    sepia(calc(.16 - .09 * var(--open)));
}

/* Foil lid: two halves that part.
   The ramp is deliberately uneven — a narrow specular band near 37% and
   two duller returns after it. An even gradient reads as plastic. */
.foil {
  position: absolute; left: 0; right: 0; height: 50.4%;
  background-image:
    repeating-linear-gradient(117deg,
      rgba(255, 246, 224, .07) 0 1px, rgba(48, 24, 2, .06) 1px 2px, transparent 2px 7px),
    linear-gradient(101deg,
      #40240A  0%,  #6A420D  7%,  #95611A 16%, #BE8530 24%,
      #EBC57C 32%,  #FDF0CD 37%,  #DFB45E 42%,
      #A97524 51%,  #7A5014 61%,  #9E6C1E 70%,
      #CE9942 79%,  #875715 90%,  #3E2309 100%);
  box-shadow: inset 0 0 40px rgba(38, 17, 0, .45);
  will-change: transform;
}
.foil--top { top: 0;    transform: translateY(calc(-100% * var(--open))); }
.foil--bot { bottom: 0; transform: translateY(calc(100% * var(--open))); }

/* The cut edge catches the light; the body of the lid throws a shadow. */
.foil--top { box-shadow: inset 0 0 40px rgba(38, 17, 0, .45), inset 0 -2px 0 rgba(255, 243, 214, .62), 0 12px 26px -8px rgba(0, 0, 0, .66); }
.foil--bot { box-shadow: inset 0 0 40px rgba(38, 17, 0, .45), inset 0  2px 0 rgba(255, 243, 214, .62), 0 -12px 26px -8px rgba(0, 0, 0, .66); }

/* A double rule pressed into the foil, the way a gift box is blind-embossed. */
.foil__orn {
  position: absolute; inset: 14px;
  border: 1px solid rgba(66, 34, 4, .42);
  box-shadow: 0 1px 0 rgba(255, 240, 206, .22);
}
.foil__orn::before {
  content: ''; position: absolute; inset: 5px;
  border: 1px solid rgba(66, 34, 4, .20);
}
/* Corner ticks — small, and the only ornament that is not a straight line. */
.foil__orn::after {
  content: ''; position: absolute; left: 50%; width: 34px; height: 1px;
  transform: translateX(-50%);
  background: linear-gradient(90deg, transparent, rgba(66, 34, 4, .5), transparent);
}
.foil--top .foil__orn::after { top: 16px; }
.foil--bot .foil__orn::after { bottom: 16px; }

/* Wax seal over the seam. */
.seal {
  position: absolute; left: 50%; top: 50%;
  width: 31%; aspect-ratio: 1;
  display: grid; place-items: center;
  transform: translate(-50%, -50%) scale(calc(1 - .42 * var(--open))) rotate(calc(-14deg * var(--open)));
  opacity: clamp(0, calc(1 - var(--open) * 3.4), 1);
}
.seal__ring {
  position: absolute; inset: 0; border-radius: 50%;
  background: radial-gradient(circle at 34% 28%, #52230F, #2E1208 72%);
  box-shadow:
    0 0 0 1.5px rgba(240, 212, 154, .62),
    inset 0 0 0 5px rgba(240, 212, 154, .14),
    0 10px 26px -8px rgba(0, 0, 0, .8);
}
.seal__mark {
  position: relative; width: 58%;
  filter: drop-shadow(0 1px 5px rgba(240, 212, 154, .45));
}

/* Light passing over the revealed packaging. */
.frame__sweep {
  position: absolute; inset: -30% -60%;
  background: linear-gradient(104deg,
    transparent 38%, rgba(255, 238, 206, .015) 44%,
    rgba(255, 244, 222, .30) 50%, rgba(255, 238, 206, .015) 56%, transparent 62%);
  transform: translateX(calc(-62% + 150% * var(--sweep, 0)));
  opacity: var(--sweep-o, 0);
  mix-blend-mode: screen;
}

.frame__edge {
  position: absolute; inset: 0; border-radius: var(--r);
  box-shadow: inset 0 0 0 1px var(--hair), inset 0 0 44px rgba(0, 0, 0, .5);
}

.reveal__say .eyebrow { margin-bottom: 11px; }
.scrub .reveal__say [data-say] { opacity: 0; transform: translateY(16px); }
.scrub .reveal__say [data-say].in {
  opacity: 1; transform: none;
  transition: opacity .8s var(--ease-out), transform .8s var(--ease-out);
}
.js .reveal__say .ln[data-say] { overflow: visible; }
.js .reveal__say .ln[data-say] > i { opacity: 1; transform: none; transition: none; }


/* ══ 03 · The catalogue ═════════════════════════════════════════════════
   Two levels. The five collections are the resting state; opening one
   swaps them for that collection's pieces and a rail to hop between the
   rest. Tapping a piece opens the sheet at the bottom of this file.

   Without JavaScript neither swap happens: the collections are anchor
   links, and all five groups sit open underneath them.                  */

.cat__head { margin-bottom: clamp(24px, 6vw, 32px); }
.cat__head .lede { margin-top: 16px; }


/* ── Level one · the collections ────────────────────────────────────────── */

.cats { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }

.cat__hit {
  position: relative; display: block;
  aspect-ratio: 16 / 10;
  border-radius: var(--r); overflow: hidden;
  text-decoration: none; color: inherit;
  box-shadow: 0 22px 44px -26px rgba(0, 0, 0, .95), inset 0 0 0 1px var(--hair-soft);
  transition: transform .4s var(--ease-out), box-shadow .4s var(--ease);
}
.cat__hit:active { transform: scale(.985); }

.cat__media { position: absolute; inset: 0; }
.cat__media > img,
.cat__vid {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .9s var(--ease-out), opacity .7s var(--ease);
}
/* The clip fades in over its own poster frame, so nothing ever jumps. */
.cat__vid { opacity: 0; }
.cat__vid.on { opacity: 1; }

.cat__hit:hover .cat__media > img,
.cat__hit:hover .cat__vid { transform: scale(1.045); }

.cat__veil {
  position: absolute; inset: 0;
  background:
    linear-gradient(183deg, rgba(14, 6, 3, .10) 0%, rgba(14, 6, 3, .34) 42%, rgba(14, 6, 3, .92) 100%),
    radial-gradient(88% 64% at 50% 108%, rgba(58, 14, 24, .5) 0%, transparent 70%);
}

.cat__say {
  position: absolute; left: 18px; right: 76px; bottom: 15px;
  display: grid; gap: 3px;
}
.cat__say b {
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-weight: 400; font-size: clamp(25px, 7vw, 30px); line-height: 1.08;
  color: var(--ivory); letter-spacing: -.005em;
}
.cat__say i {
  font-style: normal; font-size: 12px; line-height: 1.45;
  letter-spacing: .035em; color: var(--tx-dim);
}

/* How many pieces are inside, and the way in. A dark token with the number
   alone read as decoration, so this is the gold the card uses everywhere for
   something you press, and it carries a chevron: the count is the label, the
   arrow is the promise that the tile opens. */
.cat__n {
  position: absolute; right: 14px; bottom: 15px;
  display: flex; align-items: center;
  height: 32px; padding: 0 29px 0 13px;
  border-radius: 999px;
  font-size: 12.5px; font-weight: 500; letter-spacing: .02em;
  color: #2A1206;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232A1206' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 5.5 15.5 12 9 18.5'/%3E%3C/svg%3E"),
    linear-gradient(100deg, var(--gold-hi) 0%, var(--gold) 55%, var(--gold-lo) 100%);
  background-size: 13px 13px, auto;
  background-position: right 10px center, center;
  background-repeat: no-repeat;
  box-shadow: 0 4px 14px -5px rgba(0, 0, 0, .85), inset 0 0 0 1px rgba(42, 18, 6, .2);
  transition: transform .34s var(--ease-out);
}
.cat__hit:hover .cat__n { transform: translateX(3px); }


/* ── Level two · the pieces ─────────────────────────────────────────────── */

/* JavaScript owns which half is on screen. Before it runs — and if it never
   does — the collections and every group are all simply visible. */
.js .cats[hidden],
.js .rack[hidden],
.js .grp[hidden] { display: none; }

.rack { margin-top: 4px; }

.rack__bar {
  position: sticky; top: 0; z-index: 12;
  display: flex; align-items: center; gap: 10px;
  margin: 0 calc(var(--col) * -1) 20px;
  padding: 10px var(--col);
  background: linear-gradient(180deg, rgba(14, 6, 3, .94) 62%, rgba(14, 6, 3, 0) 100%);
  backdrop-filter: blur(9px);
}
.rack__bar[hidden] { display: none; }

.rack__back {
  flex: none; display: flex; align-items: center; gap: 7px;
  height: 36px; padding: 0 14px 0 11px;
  border: 0; border-radius: 999px; cursor: pointer;
  font: 400 12px/1 'Jost', sans-serif; letter-spacing: .05em;
  color: var(--champagne); background: rgba(52, 28, 15, .55);
  box-shadow: inset 0 0 0 1px var(--hair);
  transition: background .3s var(--ease);
}
.rack__back svg { width: 15px; height: 15px; }
.rack__back:active { transform: scale(.97); }

.rack__rail {
  display: flex; gap: 7px; min-width: 0;
  overflow-x: auto; overscroll-behavior-x: contain;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
  mask-image: linear-gradient(90deg, #000 86%, transparent 100%);
}
.rack__rail::-webkit-scrollbar { display: none; }

.rack__rail button {
  flex: none; height: 36px; padding: 0 15px;
  border: 0; border-radius: 999px; cursor: pointer; white-space: nowrap;
  font: 300 12px/1 'Jost', sans-serif; letter-spacing: .05em;
  color: var(--tx-dim); background: rgba(36, 19, 9, .5);
  box-shadow: inset 0 0 0 1px var(--hair-soft);
  transition: color .3s var(--ease), background .3s var(--ease), box-shadow .3s var(--ease);
}
.rack__rail button[aria-current="true"] {
  color: var(--ink); font-weight: 500;
  background: linear-gradient(100deg, var(--gold-lo), var(--gold) 40%, var(--gold-hi));
  box-shadow: none;
}

.grp + .grp { margin-top: clamp(44px, 10vw, 60px); }

.grp__h {
  margin: 0 0 5px;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-weight: 400; font-size: clamp(27px, 8vw, 33px); line-height: 1.1;
  color: var(--ivory); letter-spacing: -.005em;
}
.grp__line {
  margin: 0 0 20px;
  font-size: 12.5px; letter-spacing: .04em; color: var(--tx-dim);
}

.prods {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: 1fr 1fr; gap: 14px 11px;
}

.prod__hit { display: block; text-decoration: none; color: inherit; outline-offset: 5px; }
.prod__hit:active { transform: scale(.975); }
.prod__hit { transition: transform .3s var(--ease-out); }

.prod__img {
  position: relative; display: block;
  aspect-ratio: 1; border-radius: 13px; overflow: hidden;
  box-shadow: 0 16px 32px -22px rgba(0, 0, 0, .95), inset 0 0 0 1px var(--hair-soft);
}
.prod__img img {
  width: 100%; height: 100%; object-fit: cover;
  filter: saturate(.92) brightness(.94);
  transition: transform .8s var(--ease-out), filter .5s var(--ease);
}
.prod__hit:hover .prod__img img { transform: scale(1.06); filter: none; }

/* A gold corner mark, so a piece reads as something that opens rather than
   somewhere it takes you. It carries a plus, because an unmarked disc just
   looks like a smudge on the photograph. Scoped to .js: without JavaScript
   a piece goes straight out to WhatsApp, and promising a sheet would lie. */
.prod__img::after {
  content: ''; position: absolute; right: 9px; bottom: 9px;
  width: 26px; height: 26px; border-radius: 50%;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232A1206' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M12 7v10M7 12h10'/%3E%3C/svg%3E"),
    linear-gradient(135deg, var(--gold-hi) 0%, var(--gold) 55%, var(--gold-lo) 100%);
  background-size: 13px 13px, auto;
  background-position: center, center;
  background-repeat: no-repeat;
  box-shadow: 0 3px 11px -2px rgba(0, 0, 0, .85), inset 0 0 0 1px rgba(42, 18, 6, .22);
  opacity: 0; transform: translateY(5px) scale(.8);
  transition: opacity .34s var(--ease), transform .34s var(--ease-out);
}
.js .prod__img::after { opacity: 1; transform: none; }

.prod__say { display: grid; gap: 3px; padding: 11px 2px 0; }
.prod__say b {
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-weight: 400; font-size: 19px; line-height: 1.16; color: var(--ivory);
}
.prod__say i {
  font-style: normal; font-size: 11.5px; line-height: 1.5; color: var(--tx-dim);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
}


/* ══ 04 · Made personal ═════════════════════════════════════════════════ */

.steps { list-style: none; margin: clamp(28px, 7vw, 38px) 0 0; padding: 0; }

.step {
  position: relative;
  display: grid; grid-template-columns: 38px 1fr 74px; align-items: center; gap: 15px;
  padding: 19px 0;
  border-top: 1px solid var(--hair-soft);
}
.step:last-child { border-bottom: 1px solid var(--hair-soft); }

.step__no {
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic; font-size: 21px; color: var(--gold); opacity: .8;
  text-align: center;
}
.step__say h3 {
  margin: 0 0 3px;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-weight: 400; font-size: 22px; line-height: 1.16; color: var(--ivory);
}
.step__say p { margin: 0; font-size: 12.5px; line-height: 1.58; color: var(--tx-dim); }

.step__thumb {
  width: 74px; height: 92px; object-fit: cover;
  border-radius: 9px;
  box-shadow: 0 12px 26px -14px rgba(0, 0, 0, .9), inset 0 0 0 1px var(--hair-soft);
  filter: saturate(.84) brightness(.9);
}

/* The tag you write before you order it. */
.tagger {
  margin-top: clamp(30px, 8vw, 40px);
  padding: 22px 20px 24px;
  border-radius: var(--r);
  background: linear-gradient(168deg, rgba(52, 28, 15, .62), rgba(23, 12, 6, .5));
  box-shadow: inset 0 0 0 1px var(--hair-soft);
}

.tagger__label {
  display: block; margin-bottom: 12px;
  font-size: 10.5px; letter-spacing: .3em; text-transform: uppercase;
  color: var(--champagne); opacity: .64;
}

.tagger__input {
  width: 100%; padding: 13px 15px;
  font: 300 15px/1.4 'Jost', sans-serif; color: var(--ivory);
  background: rgba(14, 6, 3, .55);
  border: 1px solid var(--hair);
  border-radius: 10px;
  transition: border-color .3s var(--ease), background .3s var(--ease);
}
.tagger__input::placeholder { color: rgba(247, 240, 228, .3); }
.tagger__input:focus { border-color: var(--gold); background: rgba(14, 6, 3, .8); outline: none; }

.tag {
  position: relative;
  margin: 26px auto 0; padding: 34px 20px 30px;
  width: min(202px, 72%);
  text-align: center;
  border-radius: 7px 7px 10px 10px;
  background:
    repeating-linear-gradient(92deg, rgba(120, 78, 32, .05) 0 2px, transparent 2px 5px),
    linear-gradient(170deg, #F4E7CF 0%, #E6D2AE 62%, #DCC49C 100%);
  box-shadow: 0 16px 34px -16px rgba(0, 0, 0, .85), inset 0 0 0 1px rgba(120, 78, 32, .22);
  transform: rotate(-1.6deg);
}
.tag::before {
  content: ''; position: absolute; inset: 7px;
  border: 1px solid rgba(138, 90, 34, .3); border-radius: 4px;
  pointer-events: none;
}
.tag__hole {
  position: absolute; left: 50%; top: 11px; transform: translateX(-50%);
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--cocoa);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, .7), 0 1px 0 rgba(255, 255, 255, .5);
}
.tag__orn {
  position: absolute; left: 50%; top: 30px; transform: translateX(-50%);
  width: 46px; height: 1px;
  background: linear-gradient(90deg, transparent, var(--gold-lo), transparent);
}
.tag figcaption { display: block; }
.tag__for {
  display: block; margin-top: 8px;
  font-size: 9px; letter-spacing: .34em; text-transform: uppercase;
  color: #8A5A22; opacity: .72;
}
.tag__name {
  display: block; margin: 7px 0 10px; min-height: 1.1em;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic; font-weight: 500; font-size: 27px; line-height: 1.1;
  color: #3A1B0E;
  overflow-wrap: anywhere;
}
.tag__from {
  display: block;
  font-size: 9.5px; letter-spacing: .2em; text-transform: uppercase;
  color: #6B4316; opacity: .66;
}

.tagger__note {
  margin: 20px 0 0; text-align: center;
  font-size: 11.5px; line-height: 1.6; color: var(--tx-dim);
}


/* ══ 05 · The Diwali moment ═════════════════════════════════════════════ */

.scene--diwali { padding: 0; }

.diwali__track { height: auto; }
.scrub .diwali__track { height: 158svh; }

.diwali__sticky {
  --lamp: 1;
  display: flex; flex-direction: column; justify-content: center;
  gap: clamp(20px, 5vw, 28px);
  padding: 62px var(--col) 94px;          /* ditto */
  overflow: hidden;
}
.scrub .diwali__sticky { position: sticky; top: 0; min-height: 100svh; }

/* Every piece below is a percentage of the stage, so capping the stage on a
   short viewport scales the whole tableau instead of pushing it under the
   dock. object-fit absorbs the changing crop. */
.diwali__stage {
  position: relative;
  aspect-ratio: 4 / 5;
  max-height: calc(100svh - 352px);
}

.diwali__glow {
  position: absolute; left: 50%; top: 52%;
  width: 150%; aspect-ratio: 1; transform: translate(-50%, -50%) scale(calc(.5 + .6 * var(--lamp)));
  background: radial-gradient(circle,
    rgba(255, 196, 112, .52) 0%, rgba(240, 150, 60, .22) 28%,
    rgba(150, 60, 24, .08) 48%, transparent 68%);
  opacity: var(--lamp);
  mix-blend-mode: screen;
}

/* Soft light rays from above, the way a diya throws them on a wall. */
.diwali__rays {
  position: absolute; left: 50%; top: -12%;
  width: 190%; height: 112%; transform: translateX(-50%);
  background: conic-gradient(from 184deg at 50% 0%,
    transparent 0deg, rgba(255, 206, 136, .10) 5deg, transparent 10deg,
    transparent 18deg, rgba(255, 206, 136, .07) 23deg, transparent 29deg,
    transparent 44deg, rgba(255, 206, 136, .09) 49deg, transparent 55deg);
  opacity: calc(var(--lamp) * .9);
  mix-blend-mode: screen;
  filter: blur(2px);
}

.diwali__hero {
  position: absolute; left: 12%; right: 12%; top: 0; bottom: 17%;
  margin: 0; border-radius: 13px; overflow: hidden;
  box-shadow: 0 34px 70px -28px rgba(0, 0, 0, .95), inset 0 0 0 1px var(--hair-soft);
  transform: translateY(calc(28px - 28px * var(--lamp)));
}
.diwali__hero img {
  width: 100%; height: 100%; object-fit: cover;
  filter: brightness(calc(.48 + .52 * var(--lamp))) saturate(calc(.62 + .46 * var(--lamp)));
}

.diwali__inset {
  position: absolute; bottom: 0; margin: 0;
  width: 38%; height: 40%; border-radius: 11px; overflow: hidden;
  box-shadow: 0 24px 48px -20px rgba(0, 0, 0, .95), inset 0 0 0 1px var(--hair-soft);
}
.diwali__inset img {
  width: 100%; height: 100%; object-fit: cover;
  filter: brightness(calc(.44 + .56 * var(--lamp))) saturate(calc(.6 + .5 * var(--lamp)));
}
.diwali__inset--a {
  left: -1%;
  transform: translateY(calc(44px - 44px * var(--lamp))) rotate(-3.4deg);
}
.diwali__inset--b {
  right: -1%; bottom: 7%;
  transform: translateY(calc(62px - 62px * var(--lamp))) rotate(2.8deg);
}

/* Light actually landing on the tableau, rather than only behind it. */
.diwali__fall {
  position: absolute; inset: -12%;
  background: radial-gradient(58% 46% at 50% 16%,
    rgba(255, 212, 150, .40) 0%, rgba(255, 168, 78, .13) 40%, transparent 72%);
  mix-blend-mode: screen;
  opacity: var(--lamp);
  pointer-events: none;
}

.scrub .diwali__say [data-lamp] { opacity: 0; transform: translateY(16px); }
.scrub .diwali__say [data-lamp].in {
  opacity: 1; transform: none;
  transition: opacity .8s var(--ease-out), transform .8s var(--ease-out);
}
.js .diwali__say .ln[data-lamp] { overflow: visible; }
.js .diwali__say .ln[data-lamp] > i { opacity: 1; transform: none; transition: none; }


/* ══ 06 · The order ═════════════════════════════════════════════════════ */

.scene--order { padding-bottom: 136px; }

.acts { display: grid; gap: 11px; margin-top: clamp(32px, 8vw, 40px); }

.act {
  position: relative; overflow: hidden;
  display: flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 56px; padding: 0 22px;
  border: 0; border-radius: 13px;
  font: 400 14.5px/1 'Jost', sans-serif; letter-spacing: .055em;
  text-decoration: none; cursor: pointer;
  transition: transform .34s var(--ease-out), box-shadow .34s var(--ease);
}
.act svg { width: 18px; height: 18px; flex: none; }
.act:active { transform: scale(.975); }

.act--go {
  color: #2A1206;
  background: linear-gradient(100deg, var(--gold-lo) 0%, var(--gold) 26%, var(--gold-hi) 52%, var(--gold) 76%, var(--gold-lo) 100%);
  background-size: 220% 100%;
  box-shadow: 0 16px 34px -16px rgba(200, 146, 60, .72);
  font-weight: 500;
}
.act--go::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(100deg, transparent 40%, rgba(255, 255, 255, .5) 50%, transparent 60%);
  transform: translateX(-130%);
  animation: shine 5.5s var(--ease) 1.6s infinite;
}
@keyframes shine { 0% { transform: translateX(-130%); } 26%, 100% { transform: translateX(130%); } }

.act--ghost {
  color: var(--champagne);
  background: rgba(52, 28, 15, .4);
  box-shadow: inset 0 0 0 1px var(--hair);
}

.links {
  list-style: none; margin: 15px 0 0; padding: 0;
  display: grid; grid-template-columns: 1fr 1fr; gap: 9px;
}
/* Two columns, so an odd number of tiles leaves a hole: the last one
   standing takes the whole row. :nth-child cannot see this — a hidden <li>
   is still a child — so app.js counts them and marks the tile. Without
   JavaScript every tile in the markup shows, and :has covers the odd one out. */
.links > li.is-wide { grid-column: span 2; }
html:not(.js) .links:has(> li[hidden]) > li:last-child { grid-column: span 2; }

.links a, .links button {
  width: 100%;
  display: flex; align-items: center; gap: 11px;
  min-height: 62px; padding: 0 14px;
  border: 0; border-radius: 12px; text-align: left; cursor: pointer;
  background: rgba(36, 19, 9, .46);
  box-shadow: inset 0 0 0 1px var(--hair-soft);
  color: var(--tx); text-decoration: none; font-family: inherit;
  transition: background .3s var(--ease), box-shadow .3s var(--ease), transform .3s var(--ease-out);
}
.links a:active, .links button:active { transform: scale(.98); }
.links svg { width: 19px; height: 19px; flex: none; color: var(--gold); }
.links span { display: grid; min-width: 0; }
.links b { font-size: 13px; font-weight: 400; color: var(--ivory); }
.links i {
  font-style: normal; font-size: 10.5px; color: var(--tx-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.sign {
  margin-top: clamp(40px, 11vw, 54px);
  padding-top: clamp(28px, 8vw, 36px);
  border-top: 1px solid var(--hair-soft);
  text-align: center;
}
.sign__mark {
  width: 84px; margin: 0 auto 16px; border-radius: 50%;
  box-shadow: 0 0 0 1px var(--hair), 0 14px 34px -14px rgba(0, 0, 0, .9);
}
.sign__line {
  margin: 0 0 9px;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-style: italic; font-size: 20px; color: var(--champagne);
}
.sign__fine {
  margin: 0; font-size: 10.5px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--tx-dim);
}
/* The street address, which the tracked-out uppercase line above cannot hold. */
.sign__addr {
  margin: 10px auto 0; max-width: 26ch;
  font-size: 11px; line-height: 1.55; color: var(--tx-dim);
}
.sign__by { margin: 22px 0 0; font-size: 10.5px; color: rgba(247, 240, 228, .3); }
.sign__by a { color: rgba(247, 240, 228, .46); text-decoration: none; border-bottom: 1px solid var(--hair-soft); }


/* ── The dock ───────────────────────────────────────────────────────────── */

.dock {
  position: fixed; z-index: 30;
  left: 50%; bottom: 0; transform: translateX(-50%);
  width: 100%; max-width: var(--card-w);
  display: flex; gap: 9px;
  padding: 11px var(--col) calc(11px + env(safe-area-inset-bottom));
  background: linear-gradient(180deg, rgba(14, 6, 3, 0), rgba(14, 6, 3, .86) 36%, rgba(14, 6, 3, .96));
  backdrop-filter: blur(9px); -webkit-backdrop-filter: blur(9px);
}
.dock[hidden] { display: none; }

.js .dock {
  opacity: 0; transform: translate(-50%, 100%);
  transition: opacity .5s var(--ease), transform .5s var(--ease-out);
}
.js .dock.up { opacity: 1; transform: translate(-50%, 0); }

.dock__go {
  flex: 1;
  display: flex; align-items: center; justify-content: center;
  min-height: 50px; padding: 0 18px; border-radius: 12px;
  color: #2A1206; text-decoration: none;
  font: 500 14px/1 'Jost', sans-serif; letter-spacing: .05em;
  background: linear-gradient(100deg, var(--gold-lo), var(--gold) 32%, var(--gold-hi) 54%, var(--gold) 78%, var(--gold-lo));
  box-shadow: 0 12px 26px -14px rgba(200, 146, 60, .8);
}
.dock__up {
  flex: none; width: 50px; height: 50px;
  display: grid; place-items: center;
  border: 0; border-radius: 12px; cursor: pointer;
  color: var(--champagne);
  background: rgba(52, 28, 15, .7);
  box-shadow: inset 0 0 0 1px var(--hair);
}
.dock__up svg { width: 18px; height: 18px; }


/* ── Toast ──────────────────────────────────────────────────────────────── */

.toast {
  position: fixed; z-index: 50;
  left: 50%; bottom: 86px; transform: translate(-50%, 10px);
  padding: 11px 20px; border-radius: 999px;
  font-size: 12.5px; letter-spacing: .03em;
  color: var(--ink); background: var(--champagne);
  box-shadow: 0 14px 34px -12px rgba(0, 0, 0, .8);
  opacity: 0; pointer-events: none;
  transition: opacity .34s var(--ease), transform .34s var(--ease-out);
}
.toast.on { opacity: 1; transform: translate(-50%, 0); }


/* ── The piece, up close ────────────────────────────────────────────────
   One dialog, refilled for whichever piece was tapped, so there is never
   more than one of these in the page. It comes up from the bottom of a
   phone and sits in the middle once there is room for it to.            */

.sheet { position: fixed; inset: 0; z-index: 60; display: grid; align-items: end; }
.sheet[hidden] { display: none; }

.sheet__scrim {
  position: absolute; inset: 0;
  background: rgba(8, 4, 2, .80);
  backdrop-filter: blur(7px);
  opacity: 0; transition: opacity .4s var(--ease);
}
.sheet.on .sheet__scrim { opacity: 1; }

.sheet__panel {
  position: relative; z-index: 1;
  width: min(100%, 460px); margin-inline: auto;
  max-height: 94svh; overflow-y: auto; overscroll-behavior: contain;
  padding: 14px var(--col) calc(24px + env(safe-area-inset-bottom));
  border-radius: 22px 22px 0 0;
  background: linear-gradient(176deg, var(--cocoa-hi) 0%, var(--cocoa) 46%, var(--ink) 100%);
  box-shadow: 0 -26px 60px -22px rgba(0, 0, 0, .92), inset 0 1px 0 var(--hair);
  transform: translateY(13%); opacity: 0;
  transition: transform .5s var(--ease-out), opacity .4s var(--ease);
}
.sheet.on .sheet__panel { transform: none; opacity: 1; }

/* The grab handle a bottom sheet is expected to have. */
.sheet__panel::before {
  content: ''; display: block; width: 38px; height: 4px; margin: 0 auto 10px;
  border-radius: 999px; background: var(--hair);
}

/* Sticky rather than absolute: the panel scrolls, and the way out should
   not scroll away with it. */
.sheet__x {
  position: sticky; top: 0; z-index: 2;
  display: grid; place-items: center;
  width: 34px; height: 34px; margin: 0 -6px 2px auto;
  border: 0; border-radius: 50%; cursor: pointer;
  color: var(--champagne); background: rgba(23, 12, 6, .72);
  box-shadow: inset 0 0 0 1px var(--hair);
  backdrop-filter: blur(6px);
}
.sheet__x svg { width: 15px; height: 15px; }

.sheet__media {
  margin: 2px 0 18px;
  border-radius: 14px; overflow: hidden;
  background: rgba(10, 5, 2, .5);
  box-shadow: 0 20px 44px -26px rgba(0, 0, 0, .95), inset 0 0 0 1px var(--hair-soft);
}
.sheet__media img {
  width: 100%; max-height: 46svh; object-fit: contain;
  background: var(--ink);
}

.sheet__cat {
  margin: 0 0 7px;
  font-size: 10px; letter-spacing: .3em; text-transform: uppercase;
  color: var(--gold); opacity: .8;
}
.sheet__name {
  margin: 0 0 9px;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-weight: 400; font-size: clamp(27px, 8vw, 32px); line-height: 1.1;
  color: var(--ivory); letter-spacing: -.005em;
}
.sheet__note { margin: 0 0 20px; font-size: 13.5px; line-height: 1.62; color: var(--tx-dim); }

.sheet__acts { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.sheet__acts .act { min-height: 52px; padding: 0 14px; font-size: 13.5px; }

.sheet__step {
  display: flex; align-items: center; justify-content: center; gap: 16px;
  margin-top: 16px;
}
.sheet__step button {
  display: grid; place-items: center;
  width: 36px; height: 36px; flex: none;
  border: 0; border-radius: 50%; cursor: pointer;
  color: var(--champagne); background: rgba(36, 19, 9, .55);
  box-shadow: inset 0 0 0 1px var(--hair-soft);
  transition: color .3s var(--ease), box-shadow .3s var(--ease);
}
.sheet__step button svg { width: 15px; height: 15px; }
.sheet__step button:disabled { opacity: .3; cursor: default; }
.sheet__step span {
  font-size: 11px; letter-spacing: .14em; color: var(--tx-dim);
  min-width: 62px; text-align: center;
}

/* While a piece is open the page behind must not scroll under it. */
.sheet-open body { overflow: hidden; }


/* ── Wider than a phone ─────────────────────────────────────────────────── */

@media (min-width: 620px) {
  :root { --col: 34px; }
  .dock { border-radius: 0; }

  /* The card column never grows past --card-w, so the catalogue keeps its
     phone layout at every width. Only the sheet, which is outside the
     column, has room to do anything different. */
  .sheet { align-items: center; }
  .sheet__panel {
    max-height: 90svh;
    border-radius: var(--r);
    padding-top: 16px;
    box-shadow: 0 40px 100px -30px rgba(0, 0, 0, .92), inset 0 0 0 1px var(--hair-soft);
  }
  .sheet__panel::before { display: none; }
}

/* ── Reduced motion: keep the composition, drop the choreography ────────── */

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

  .js .ln > i,
  .js [data-reveal],
  .js .reveal__say [data-say],
  .js .diwali__say [data-lamp] {
    opacity: 1 !important; transform: none !important; transition: none !important;
  }
  .js .open__logo { clip-path: none; opacity: 1; }
  .js .open__rule { width: 128px; }
  .js .open__kicker { opacity: .6; }

  .open__cue-line::after,
  .act--go::after,
  .medal__ring { animation: none; }
  .js .medal { opacity: 1; transform: none; }

  /* app.js never loads the scrubs here, and never starts a collection clip.
     What is left to quiet is the hover-weight motion. */
  .cat__hit, .cat__media > img, .cat__vid, .cat__n,
  .prod__hit, .prod__img img,
  .sheet__scrim, .sheet__panel { transition: none; }

  .cat__hit:hover .cat__media > img,
  .cat__hit:hover .cat__vid,
  .cat__hit:hover .cat__n,
  .prod__hit:hover .prod__img img { transform: none; }

  .sheet__panel { transform: none; opacity: 1; }
  .js .dock { transition: none; }
}

/* ── No JavaScript at all ───────────────────────────────────────────────
   Nothing to undo. Every scene already defaults to its finished state, and
   the catalogue is plain markup: the five collections are anchor links and
   all five groups of pieces sit open below them, each piece still carrying
   its own link. The one thing to drop is the gold dot that promises a
   piece will open in a sheet, because here it will not — it goes straight
   to WhatsApp instead. That is handled by scoping the dot to .js.       */
