/* ============================================================
   BUILT DIFFERENT, PARE — DESIGN SYSTEM
   ------------------------------------------------------------
   One stylesheet for the whole site: index, shop, checkout and
   order-confirmed all link to this file.

   ── WHERE THE COLOURS COME FROM ──────────────────────────────
   Sampled straight off the YouTube episode thumbnails, so the
   site and the channel read as one brand:

     #FFBF00  the amber every thumbnail title uses  ← THE accent
     #5B2C3C  deep wine     ┐
     #432946  plum          │ the studio wall behind Beng & Yen,
     #16303F  petrol teal   │ left → right. That sweep is the
     #945D49  warm copper   ┘ --band-hero gradient.

   Every band below is a segment of that same sweep, so the whole
   site feels like one continuous room.

   ── THE TWO ACCENTS (important) ──────────────────────────────
     --amber   #FFBF00, IDENTICAL in both themes. Only ever a
               FILL, and always carries near-black text on top
               (buttons, ticker, badges, prices-on-dark). Reads
               correctly on light or dark.
     --accent  the TEXT / BORDER accent. Amber text on white
               fails contrast, so light mode darkens it to a
               deep gold. NEVER use --accent as a fill behind
               dark text, and never use --amber as text on white.

   ── LIGHT MODE ───────────────────────────────────────────────
   theme.js stamps <html data-theme="light|dark"> before first
   paint. Light mode is deliberately quiet — white surfaces, one
   grey page tone, hairline rules, soft shadows instead of
   borders, gradients dropped almost entirely. The branding
   carries through the amber and the type, not through colour
   washes. Only tokens flip; component rules stay theme-agnostic.
============================================================ */

/* ============ RESET ============ */
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}

/* ============ TOKENS — DARK (default) ============ */
:root{
  /* surfaces */
  --ink:#140A0E;                  /* page background — warm near-black */
  --ink-2:#1C1014;
  --card:rgba(8,3,6,.42);         /* translucent card floating on a band */
  --card-solid:#211419;           /* opaque card on the flat background */
  --line:rgba(255,255,255,.15);
  --line-soft:rgba(255,255,255,.08);

  /* brand — straight off the thumbnails */
  --amber:#FFBF00;                /* FILL only; pairs with --on-amber */
  --on-amber:#140A0E;
  --accent:#FFBF00;               /* TEXT / BORDER accent */
  --accent-2:#FFD24D;
  --accent-soft:#FFD97A;
  --wine:#5B2C3C;
  --wine-deep:#3F0A1A;
  --plum:#432946;
  --petrol:#16303F;
  --petrol-2:#23415B;
  --copper:#945D49;
  --rust:#8A5658;

  /* type */
  --text:#F6EFE9;
  --muted:rgba(246,239,233,.64);
  --on-band:#FFFFFF;              /* text sitting on a gradient band */
  --on-band-muted:rgba(255,255,255,.72);

  /* bands — each one a segment of the studio-wall sweep */
  --band-hero:linear-gradient(105deg,#2A0710 0%,#5B2C3C 24%,#432946 46%,#16303F 68%,#6B4340 88%,#945D49 100%);
  --band-1:linear-gradient(160deg,#5B2C3C 0%,#4A2439 52%,#432946 100%);
  --band-2:linear-gradient(180deg,#3A2440 0%,#1E2E3D 100%);
  --band-3:linear-gradient(200deg,#16303F 0%,#3E2E3C 55%,#7E4E42 100%);
  --band-4:linear-gradient(160deg,#1B0E14 0%,#3A2038 55%,#170B10 100%);
  /* the copper band's mid-stop is kept deliberately dark — at
     #8A5546 the amber eyebrows dropped to 3.66:1 against it */
  --band-5:linear-gradient(180deg,#4E322D 0%,#6B3E35 58%,#2A1219 100%);
  --band-foot:linear-gradient(180deg,#22101A 0%,#120709 100%);

  /* hero atmospherics */
  --hero-beams:.5;
  --grain:.07;
  /* Capped by legibility, not taste: the pattern sits BEHIND body
     copy, so a bright line passing under muted text lifts the local
     background and eats contrast. .11 is the highest value that
     still clears AA in the worst case (amber line under muted text
     on the darkest band) — measured, see the note in README. */
  --pattern-op:.11;
  /* The VIBRANT layer — used wherever the backdrop is flat --ink and
     the only text over it is display-sized: the hero's revealed
     backdrop and About. Measured on #140A0E with the worst-lit contour
     pixel under muted body text: .34 → 4.6:1, .38 → 4.47 (just under
     AA), so .34 is the ceiling with margin. Do NOT apply this over the
     coloured bands — the same measurement on band-3's lightest stop
     (#7E4E42) gives 2.45:1. */
  --pattern-vibrant:.34;

  /* shadows */
  --sh-1:0 18px 44px rgba(0,0,0,.44);
  --sh-2:0 26px 70px rgba(0,0,0,.56);
  --glow:0 0 34px rgba(255,191,0,.34);

  /* fonts */
  --display:'Montserrat','Arial Black',system-ui,sans-serif;
  --body:'Barlow','Segoe UI',system-ui,sans-serif;

  --nav-h:74px;
  --radius:4px;
}

/* ============ TOKENS — LIGHT ============
   Apple/Facebook-quiet: one grey page tone, white cards,
   hairline rules, soft shadows, gradients gone. The amber and
   the big uppercase type are what keep it unmistakably BDP.
====================================================== */
:root[data-theme="light"]{
  /* warm neutrals, not clinical grey — the wine/copper end of the
     brand palette pulled almost all the way to white, so light
     mode still feels like the same brand rather than a blank page */
  --ink:#F7F4F1;                  /* page */
  --ink-2:#FFFFFF;
  --card:#FFFFFF;
  --card-solid:#FFFFFF;
  --line:#E8E1DB;
  --line-soft:#F1EBE6;

  --amber:#FFBF00;                /* unchanged — still a fill */
  --on-amber:#140A0E;
  --accent:#FFBF00;               /* brand yellow, kept as-is in light mode */
  --accent-2:#E8AE00;
  --accent-soft:#FFBF00;

  --text:#1B1114;
  /* a touch darker than it looks like it needs to be — buys the
     headroom the pattern layer costs behind secondary text */
  --muted:#5C5651;
  --on-band:#1B1114;
  --on-band-muted:#5C5651;

  /* bands alternate white / warm off-white. The brand colour
     arrives as soft washes (see .band::after below), not as
     flat fills — that's what keeps it clean but not sterile. */
  --band-hero:linear-gradient(180deg,#FFFFFF 0%,#FBF7F4 100%);
  --band-1:#FFFFFF;
  --band-2:#FAF6F2;
  --band-3:#FFFFFF;
  --band-4:#FAF6F2;
  --band-5:#FFFFFF;
  --band-foot:#F3EDE8;

  --hero-beams:0;
  --grain:.03;                    /* lighter — white shows noise more */
  --pattern-op:.16;               /* same legibility cap as dark mode */
  /* light's ink is #F7F4F1; measured with the DARKEST composited pixel
     under #5C5651 muted text: .30 → 4.85:1, .32 → 4.76, .40 → 4.37 */
  --pattern-vibrant:.30;

  /* warm-tinted shadows read richer than neutral black on cream */
  --sh-1:0 1px 2px rgba(74,38,26,.05), 0 10px 28px rgba(74,38,26,.07);
  --sh-2:0 2px 8px rgba(74,38,26,.07), 0 26px 58px rgba(74,38,26,.13);
  --glow:0 6px 22px rgba(255,191,0,.42);
}

/* ============ BASE ============ */
/* scroll-behavior is deliberately auto: main.js animates anchor
   jumps itself so the duration is short and consistent, instead
   of the browser's slower native easing */
html{scroll-behavior:auto;scroll-padding-top:calc(var(--nav-h) + 10px)}
body{
  background:var(--ink);
  color:var(--text);
  font-family:var(--body);
  font-size:1.02rem;
  font-weight:400;
  line-height:1.72;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}

/* ============ MOVING CONTOUR LAYER ============
   pattern.js appends this canvas to <body>. It is sandwiched
   between the backgrounds and the content:

       z-index 2+   text, images, cards, forms, pop-ups
       z-index 1    ← this canvas
       z-index auto section background gradients

   That works because none of the section elements create their
   own stacking context (position:relative with z-index:auto
   doesn't), so a section's BACKGROUND paints below any
   positioned element while .wrap — which every content
   container carries — is lifted to z-index 2 and paints above.
   Don't add a z-index to .band / .hero / section: it would trap
   the content underneath the pattern.

   Tune or kill it with --pattern-op.
====================================================== */
/* ONE fixed field for the whole site. Because it is position:fixed it
   never scrolls, never scales and never re-tiles, so the hero's
   revealed backdrop and About show the *same pixels* — that is what
   makes them read as one page, and it is also why the card shrinking
   over it can't drag the pattern into a pixelated zoom.
   Vibrant everywhere, per the owner's ask. --pattern-op is kept as the
   measured legibility cap for reference; if a real per-element audit
   ever flags text on the lighter band stops, darken that stop rather
   than dropping this back. */
.bg-pattern{
  position:fixed;inset:0;width:100%;height:100%;
  z-index:1;pointer-events:none;
  opacity:var(--pattern-vibrant);
}

/* ============ FILM GRAIN ============
   One fixed noise layer over the whole page. It sits above the
   content on purpose (that's what makes flat gradients read as
   printed rather than digital) but pointer-events:none means it
   never intercepts a click. Turn it off by setting --grain:0.
====================================================== */
body::after{
  content:'';position:fixed;inset:0;z-index:1200;pointer-events:none;
  opacity:var(--grain);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:190px 190px;
}
button,input,textarea,select{font:inherit;color:inherit}
::selection{background:var(--amber);color:var(--on-amber)}
:focus-visible{outline:3px solid var(--accent);outline-offset:3px}

h1,h2,h3,h4,.display{
  font-family:var(--display);
  font-weight:900;
  text-transform:uppercase;
  line-height:.94;
  letter-spacing:-.015em;
}

/* every content container rides above the pattern layer —
   see the .bg-pattern comment for why this z-index matters */
.wrap{width:min(1240px,90%);margin-inline:auto;position:relative;z-index:2}
/* the ticker is a full-bleed band with no .wrap of its own */
.ticker{position:relative;z-index:2}

/* full-bleed band */
/* NOTE: no z-index here on purpose — see .bg-pattern */
.band{position:relative;overflow:hidden;color:var(--on-band)}
.band-1{background:var(--band-1)}
/* About is flat --ink, the same surface the hero's stage reveals, and
   the same single fixed pattern shows through both — so crossing from
   the card's backdrop into About has no change of colour and no change
   of pattern. #about beats .band-1 on specificity; the token is left
   alone for any other band-1 use. */
#about.band-1{background:var(--ink)}
.band-2{background:var(--band-2)}
.band-3{background:var(--band-3)}
.band-4{background:var(--band-4)}
.band-5{background:var(--band-5)}
.sec{padding:112px 0}

/* soft floor shading, so a band has depth like the studio wall */
.band::after{
  content:'';position:absolute;inset:0;z-index:1;pointer-events:none;opacity:.5;
  background:
    radial-gradient(900px 420px at 12% 108%, rgba(0,0,0,.44), transparent 62%),
    radial-gradient(900px 420px at 88% 108%, rgba(0,0,0,.44), transparent 62%);
}
/* light mode: no dark floor shading — instead a very soft brand
   wash (amber top-right, wine bottom-left) so each band has some
   air and colour without losing the white-page cleanliness */
:root[data-theme="light"] .band::after{
  opacity:1;
  background:
    radial-gradient(680px 380px at 84% -10%, rgba(255,191,0,.11), transparent 66%),
    radial-gradient(560px 340px at 6% 110%, rgba(120,58,74,.055), transparent 66%);
}
/* hairline to separate stacked white / off-white bands */
:root[data-theme="light"] .band + .band,
:root[data-theme="light"] .feature{border-top:1px solid var(--line-soft)}

/* ============ SECTION HEADINGS ============ */
.sec-head{max-width:820px;margin-bottom:56px}
.sec-head.center{margin-inline:auto;text-align:center}
/* the lead paragraph is max-width capped, so it needs auto side
   margins too or it sits left inside a centred block */
.sec-head.center p{margin-inline:auto}
.eyebrow{
  display:inline-block;font-family:var(--display);font-weight:800;font-size:.72rem;
  text-transform:uppercase;letter-spacing:.3em;color:var(--accent);
  margin-bottom:18px;
}
.sec-head h2{font-size:clamp(2.5rem,6vw,4.6rem)}
.sec-head p{
  margin-top:22px;font-weight:300;font-size:1.02rem;line-height:1.85;
  color:var(--on-band-muted);max-width:64ch;
}
.sec-head p b{font-weight:600;color:var(--on-band)}
.hl{color:var(--accent)}

/* ============ BUTTONS ============ */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.5rem;
  font-family:var(--display);font-weight:800;font-size:.78rem;
  text-transform:uppercase;letter-spacing:.18em;
  padding:1.05rem 2.1rem;border:2px solid transparent;border-radius:var(--radius);
  cursor:pointer;transition:transform .2s,background .2s,color .2s,border-color .2s,box-shadow .2s;
  text-align:center;
}
.btn:hover{transform:translateY(-2px)}
/* solid amber + near-black text — identical in both themes */
.btn-primary{background:var(--amber);border-color:var(--amber);color:var(--on-amber)}
.btn-primary:hover{background:#FFCE33;border-color:#FFCE33;box-shadow:var(--glow)}
.btn-primary:disabled{opacity:.55;cursor:not-allowed;transform:none;box-shadow:none}
/* thin outline */
.btn-ghost{background:transparent;border-color:var(--line);color:var(--text)}
.btn-ghost:hover{border-color:var(--accent);color:var(--accent)}
.band .btn-ghost{border-color:rgba(255,255,255,.48);color:#fff}
.band .btn-ghost:hover{border-color:var(--amber);background:var(--amber);color:var(--on-amber)}
:root[data-theme="light"] .band .btn-ghost{border-color:var(--line);color:var(--text)}
:root[data-theme="light"] .band .btn-ghost:hover{background:var(--amber);border-color:var(--amber);color:var(--on-amber)}
/* small outlined pill used on cards */
.btn-mini{
  display:inline-block;font-family:var(--display);font-weight:800;font-size:.64rem;
  text-transform:uppercase;letter-spacing:.2em;padding:.82rem 1.3rem;
  border:1px solid var(--accent);color:var(--accent);border-radius:var(--radius);
  transition:background .2s,color .2s,border-color .2s;
}
.btn-mini:hover{background:var(--amber);border-color:var(--amber);color:var(--on-amber)}
.band .btn-mini{border-color:rgba(255,191,0,.6);color:var(--accent)}
:root[data-theme="light"] .band .btn-mini{border-color:var(--accent);color:var(--accent)}

/* ============ PILL ============ */
.pill{
  display:inline-flex;align-items:center;gap:.4rem;
  font-family:var(--display);font-weight:800;font-size:.66rem;
  text-transform:uppercase;letter-spacing:.22em;
  padding:.5rem 1.1rem;border:1px solid var(--line);border-radius:100px;
  color:var(--muted);
}
.pill-live{border-color:var(--accent);color:var(--accent)}
.band .pill{border-color:rgba(255,255,255,.4);color:#fff}
:root[data-theme="light"] .band .pill{border-color:var(--line);color:var(--muted)}
.band .pill-live{border-color:var(--accent);color:var(--accent)}

/* ============ ANNOUNCEMENT BAR ============
   Fixed strip above the navbar. --anno-h defaults to 0 (so every
   page that has no bar is unaffected and the nav sits at the top);
   home.js sets it to the bar height only when the promo is live and
   undismissed. The navbar reads the same variable for its own top,
   so bar and nav can never overlap. */
/* --anno-close-w is both the ✕ button's tap width and the gap the scrolling
   message is clipped at, so the two can never disagree. 46px clears the 44px
   minimum used everywhere else on the site; the bar is 40px tall, so the
   button is 46×40 rather than 44×44. */
:root{--anno-h:0px;--anno-close-w:46px}
.anno-bar{
  position:fixed;top:0;left:0;right:0;z-index:960;
  height:var(--anno-h);overflow:hidden;
  background:var(--amber);color:var(--on-amber);
  transition:height .25s ease;
}
/* The message scrolls right-to-left, same mechanism and the same speed as
   the .ticker strip further down the page (44.2px/s — the ticker's own
   1502px half-track over its 34s). home.js repeats the message until one
   half of the track is wider than the viewport, clones that half, and sets
   --anno-dur from the measured width, so the rate is identical on a phone
   and on a 4K monitor and the seam never shows.
   ⚠️ The viewport element is NOT the bar: it stops short of the ✕. Padding
   on .anno-bar could not do this job — `overflow:hidden` clips at the
   PADDING box, so the old `padding:0 2.4rem` did nothing to keep the text
   off the button, and at 375px the ✕ sat on top of the "Preorder →" link. */
.anno-viewport{
  position:absolute;inset:0 var(--anno-close-w) 0 0;
  overflow:hidden;display:flex;align-items:center;
}
.anno-track{display:flex;width:max-content;animation:anno-scroll var(--anno-dur,30s) linear infinite}
@keyframes anno-scroll{to{transform:translateX(-50%)}}
.anno-link{
  display:inline-flex;align-items:center;gap:.55rem;
  color:var(--on-amber);text-decoration:none;white-space:nowrap;
  font-family:var(--display);font-weight:800;font-size:.66rem;
  text-transform:uppercase;letter-spacing:.09em;
  padding-right:2.8rem;
}
.anno-cta{text-decoration:underline;text-underline-offset:2px}
.anno-close{
  position:absolute;right:0;top:0;
  width:var(--anno-close-w);height:100%;
  display:flex;align-items:center;justify-content:center;
  background:none;border:none;color:var(--on-amber);cursor:pointer;
  font-size:.85rem;line-height:1;padding:0;opacity:.75;
}
.anno-close:hover{opacity:1}
/* Matches the ticker: no autonomous motion when the visitor asks for none.
   The repeats collapse to the single real link and it re-centres, i.e. the
   static bar it has always been — so this path still has to FIT, which is
   why the narrow breakpoint below tightens the type. */
@media (prefers-reduced-motion:reduce){
  .anno-track{animation:none;width:auto}
  .anno-track .anno-link{padding-right:0}
  .anno-track .anno-link:not(:first-child){display:none}
  .anno-viewport{justify-content:center}
}
@media(max-width:520px){
  .anno-link{font-size:.58rem;letter-spacing:.05em;gap:.4rem}
}
/* Static + narrow is the one combination with nowhere to hide: the message
   cannot scroll and it has to clear the ✕, so it must physically fit the
   remaining ~329px at 375. Scoped to reduced-motion so the scrolling version
   keeps the larger type — it has the whole track to breathe in. */
@media (prefers-reduced-motion:reduce) and (max-width:520px){
  .anno-link{font-size:.5rem;letter-spacing:.015em;gap:.3rem}
}

/* ============ NAVBAR ============ */
.nav{
  position:fixed;top:var(--anno-h);left:0;right:0;z-index:900;height:var(--nav-h);
  display:flex;align-items:center;
  transition:top .25s ease,background .3s,border-color .3s,backdrop-filter .3s;
  border-bottom:1px solid transparent;
}
.nav.solid{
  background:color-mix(in srgb, var(--ink) 86%, transparent);
  backdrop-filter:saturate(180%) blur(16px);
  border-bottom-color:var(--line-soft);
}
.nav-inner{display:flex;align-items:center;justify-content:space-between;gap:1.4rem;width:min(1240px,90%)}
.brand-logo img{height:38px;width:auto}
/* the logo art is white — flip it to near-black on light surfaces */
:root[data-theme="light"] .brand-logo img{filter:invert(1) brightness(.14)}
.nav-links{display:flex;align-items:center;gap:2.1rem;list-style:none}
.nav-links a{
  font-family:var(--display);font-weight:700;font-size:.72rem;
  text-transform:uppercase;letter-spacing:.2em;color:var(--muted);
  padding:.45rem 0;position:relative;transition:color .2s;
}
.nav-links a::after{
  content:'';position:absolute;left:0;right:100%;bottom:0;height:2px;
  background:var(--amber);transition:right .25s;
}
.nav-links a:hover{color:var(--text)}
.nav-links a:hover::after,.nav-links a.active::after{right:0}
.nav-links a.active{color:var(--accent)}
.nav-links a.btn{color:var(--on-amber);padding:.75rem 1.5rem;letter-spacing:.16em}
.nav-links a.btn::after{display:none}
.nav-right{display:flex;align-items:center;gap:.7rem}

.icon-btn{
  /* 44px is the minimum comfortable touch target */
  width:44px;height:44px;display:grid;place-items:center;
  border:1px solid var(--line);border-radius:var(--radius);
  background:transparent;cursor:pointer;position:relative;
  transition:border-color .2s,color .2s;
}
.icon-btn:hover{border-color:var(--accent);color:var(--accent)}
.icon-btn svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.theme-toggle .ic-moon{display:none}
:root[data-theme="light"] .theme-toggle .ic-sun{display:none}
:root[data-theme="light"] .theme-toggle .ic-moon{display:block}
.cart-count{
  position:absolute;top:-7px;right:-7px;min-width:20px;height:20px;padding:0 5px;
  display:none;place-items:center;background:var(--amber);color:var(--on-amber);
  font-family:var(--display);font-weight:800;font-size:.62rem;border-radius:100px;
}
.cart-count.show{display:grid}

.burger{display:none;width:44px;height:44px;border:1px solid var(--line);border-radius:var(--radius);background:transparent;cursor:pointer;padding:12px 11px}
.burger span{display:block;height:2px;background:currentColor;margin:0 0 4px;transition:transform .25s,opacity .25s}
.burger span:last-child{margin-bottom:0}
body.nav-open .burger span:nth-child(1){transform:translateY(6px) rotate(45deg)}
body.nav-open .burger span:nth-child(2){opacity:0}
body.nav-open .burger span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}

/* ============ SIDE DOT NAV ============ */
.dotnav{
  position:fixed;right:26px;top:50%;transform:translateY(-50%);z-index:850;
  display:grid;gap:14px;
}
.dotnav a{
  width:9px;height:9px;border-radius:50%;border:1px solid var(--line);
  background:transparent;transition:background .2s,border-color .2s,transform .2s;
  position:relative;
}
.dotnav a::before{
  content:attr(data-label);position:absolute;right:20px;top:50%;transform:translateY(-50%);
  font-family:var(--display);font-weight:800;font-size:.6rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--accent);white-space:nowrap;
  opacity:0;pointer-events:none;transition:opacity .2s;
}
.dotnav a:hover::before{opacity:1}
.dotnav a:hover,.dotnav a.active{background:var(--amber);border-color:var(--amber);transform:scale(1.3)}

/* ============ HERO ============
   ONE section, and the card IS the page. The entire hero view —
   its background, its own contour layer, the h1, subtitle, CTAs and
   the hosts — lives inside .hero-shot, which scales down into the
   framed card as you scroll. What's revealed behind it is the ABOUT
   band colour, so when the stage unpins the page appears to continue
   straight into About with no seam. (The amber ticker moved below
   About for the same reason — it would cut that continuity in half.)

   Scroll becomes --p (0 → 1) on .hero-stage, written by main.js.
   Everything below is a pure CSS function of it, so nothing can
   drift out of sync and BDPHero.setProgress(p) reproduces any frame.

   .hero itself must stay free of z-index / transform / filter /
   opacity — any of those makes it a stacking context and drops its
   content under the contour pattern (same rule as .band).

   Stage layer order (its own context, .hero-stage is z-index 2):
     6  .hero-shot::after       amber frame, fades in
     5  .hero-meta, .hero-scroll, .hero-cap
     3  .hero-shot              the whole mini page (never fades)
     2  .hero-kin               sweeping type rows
     -  stage is TRANSPARENT — what shows through is the site-wide
        fixed .bg-pattern on flat --ink, the very same layer About
        shows, which is why the two are indistinguishable
============================================================ */
.hero{
  position:relative;
  height:220vh;              /* scroll runway — retime the whole
                                sequence here, taller = slower.
                                300vh felt sluggish; 220vh plus the
                                lerp in main.js matches the
                                reference's pacing */
  background:var(--ink);
}
.hero-stage{
  position:sticky;top:0;z-index:2;
  height:100svh;overflow:hidden;
  display:grid;
  /* minmax(0,…) NOT 1fr: a plain 1fr track sizes to max-content, and
     the nowrap marquee rows are thousands of pixels wide — they once
     blew the column to 6187px and dragged the row with it. */
  grid-template-rows:minmax(0,1fr);
  grid-template-columns:minmax(0,1fr);
  text-align:center;color:var(--on-band);
  /* TRANSPARENT on purpose. The colour comes from .hero (flat --ink,
     same as About) and the texture comes from the site-wide fixed
     .bg-pattern showing straight through — one field, shared with
     About, so there is literally nothing that can differ at the seam.
     Giving this its own background or its own canvas is what used to
     create the mismatch; don't reintroduce either. */
  background:transparent;
  --p:0;         /* scroll progress, written by main.js */
  --rs-move:1;   /* how much of the horizontal type sweep to allow */
}
.hero-stage > *{grid-area:1/1;min-width:0;min-height:0}

/* NOTE: there is no separate backdrop canvas any more. What the
   shrinking card reveals is the site-wide fixed .bg-pattern, already
   at full --pattern-vibrant and already the exact field About shows.
   Nothing to fade up: it was there the whole time, just covered. */

/* ---- the two type rows, sweeping past each other behind the card ----
   Sized and paired like the reference: a serif italic line over a
   heavy grotesk line, close together around the centre, so they read
   as one lockup sliding apart rather than two banners. */
.hero-kin{
  z-index:2;align-self:center;justify-self:stretch;pointer-events:none;
  font-family:var(--display);font-weight:900;
  font-size:clamp(1.7rem,5.4vw,4.3rem);line-height:1;
  text-transform:uppercase;letter-spacing:-.01em;white-space:nowrap;
  opacity:clamp(0,calc((var(--p) - .18) * 3),1);
  will-change:transform;
}
.hero-kin i{font-style:normal;opacity:.42;margin:0 .34em}
.hero-kin-a{
  font-family:'Playfair Display',Georgia,serif;font-weight:700;font-style:italic;
  letter-spacing:.01em;color:var(--accent);
  transform:translateY(-5.4vh) translateX(calc((16% - 44% * var(--p)) * var(--rs-move)));
}
.hero-kin-b{color:rgba(255,255,255,.92);
  transform:translateY(5.4vh) translateX(calc((-44% + 44% * var(--p)) * var(--rs-move)))}
/* light mode's backdrop is white: the white row flips to near-black.
   The amber row stays raw brand yellow — decorative display type at
   ~100px, same documented brand-mark exception as big headings. */
:root[data-theme="light"] .hero-kin-b{color:var(--text)}

/* ---- THE SHOT: the entire hero page in one scalable element ----
   The card NEVER fades. It shrinks and then stays, holding the frame
   until the stage unpins and About scrolls up over it. */
.hero-shot{
  position:relative;z-index:3;overflow:hidden;
  background:var(--band-hero);
  /* ONE source of truth for how far the card shrinks. The pattern
     canvas below counter-scales by exactly this, so the two always
     cancel — override --card-shrink alone (see the mobile block) and
     never the transform, or the counter-scale silently stops matching
     and the pattern zooms again. */
  --card-shrink:.58;                                    /* 1 → 0.42 */
  transform:scale(calc(1 - var(--card-shrink) * var(--p)));
  will-change:transform;
}
/* The hero's own texture: full vibrancy on landing, faded out by the
   time the card is small — the revealed fixed layer behind takes over.

   COUNTER-SCALED. Its parent is scale()d, and a canvas dragged through
   a scale gets resampled: the browser rasterises the promoted layer at
   one scale and stretches it, which is the pixelated "zoomed pattern"
   bug. scale(1 / cardScale) puts its NET on-screen scale back at 1, so
   it always paints 1:1 with its backing store. It also means the
   texture doesn't shrink with the card, so it stays the same size as
   the field around it — reading as one continuous surface seen through
   a window rather than a shrunken picture of one.
   Its own will-change gets it a layer rasterised at ITS scale, not the
   parent's. Overflow on .hero-shot clips the excess. */
.hero-shot-pattern{
  position:absolute;inset:0;z-index:0;
  width:100%;height:100%;pointer-events:none;
  opacity:clamp(0, calc(var(--pattern-vibrant) * (1 - var(--p) * 1.6)), 1);
  transform:scale(calc(1 / (1 - var(--card-shrink) * var(--p))));
  transform-origin:center;
  will-change:transform;
}
/* floor vignette so the type and hosts always have ground to sit on */
.hero-shot::before{
  content:'';position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    radial-gradient(1100px 700px at 20% 40%, rgba(0,0,0,.30), transparent 68%),
    linear-gradient(to top, rgba(12,5,8,.85) 0%, transparent 44%);
}
:root[data-theme="light"] .hero-shot::before{
  background:linear-gradient(to top, rgba(245,245,247,.92) 0%, transparent 42%);
}
/* the frame that makes the shrunken page read as a card */
.hero-shot::after{
  content:'';position:absolute;inset:0;z-index:6;pointer-events:none;
  border:1px solid var(--accent);opacity:calc(.7 * var(--p));
}

.hero-inner{
  position:absolute;inset:0;z-index:3;
  display:flex;flex-direction:column;align-items:center;
  padding:calc(var(--nav-h) + clamp(16px,4vh,52px)) 5vw 0;
}
.hero-mark{margin-bottom:clamp(10px,1.8vh,22px)}
.hero-mark img{width:clamp(42px,4.8vw,60px);height:auto;display:block;opacity:.94}
:root[data-theme="light"] .hero-mark img{filter:invert(1) brightness(.14)}

/* Three lines, ONE voice — equal size and weight, the middle line in
   brand amber. No small/large split. */
/* --cast-h is the single source for how tall the host cut-outs are.
   The hero's clearance maths depends on it: the transparent margin
   above their heads is ~32% of the image, so the heads occupy the
   bottom ~0.68 x --cast-h of the screen. Raise this and you eat into
   the CTA row again — re-measure if you do. */
:root{--cast-h:32svh}

.hero-name{
  font-weight:900;line-height:.95;letter-spacing:-.02em;
  /* the vh term is what stops a short desktop (1280x800) from
     rendering ~340px of headline and shoving the CTAs down into the
     hosts. On tall screens the 7.2rem cap still governs, so nothing
     changes there. */
  font-size:clamp(2.7rem,min(8.8vw,11svh),7.2rem);
}
.hero-name span{display:block}
.hero-name .hn-mid{color:var(--accent)}

.hero-sub{
  margin-top:clamp(14px,2.2vh,26px);max-width:56ch;
  font-weight:300;font-size:clamp(.95rem,1.35vw,1.12rem);line-height:1.75;
  color:var(--on-band-muted);
}
.hero-cta{
  display:flex;flex-wrap:wrap;gap:1rem;justify-content:center;
  margin-top:clamp(18px,3vh,34px);
}

/* the hosts, standing on the shot's bottom edge. They scale with the
   shot — that is the whole "page gets smaller" effect.
   ⚠️ READ THE WHOLE HISTORY BEFORE CHANGING z-index HERE. It has been
   flipped twice and the two owner requests behind those flips are NOT
   in conflict — they were about different things:

     29 Jul — cast in front (z4). Reference site does the same.
     1 Aug  — cast moved BEHIND (z2): "hosts are almost covering the
              CTAs". Measured at 1280x800 the heads started 62px ABOVE
              the button row and ran straight through the LABELS. The
              real culprit was a height-budget clash, not stacking:
              the hero's type block is a roughly fixed ~600px while the
              cast scales with the viewport, so on a short desktop the
              two did not both fit. --cast-h came down from 42svh and
              .hero-name gained a height term, which is what actually
              fixed it. Moving to z2 was the belt-and-braces half.
     1 Aug  — cast back in FRONT (z4, current). With the height budget
              already fixed the overlap is now tiny and only at the
              BOTTOM EDGE of the ghost button: at 390x844 the button
              runs 544.5->603.5 and the cut-outs start at 590.5, so 13px
              of border, nothing near the label. Behind the content that
              border drew a hard line across Beng's cap, which is what
              the owner saw on a phone.

   So: in front is right *while the heights stay budgeted*. If the type
   block or --cast-h ever grows again, fix the BUDGET (--cast-h, the
   .hero-name clamp, .hero-inner padding-bottom) — do not "solve" it by
   dropping the cast behind the content, or the cap gets sliced again.
   The guard rail is the check below: the heads must stay clear of the
   button LABELS, not merely of the buttons.

   pointer-events:none keeps the buttons clickable through the
   cut-outs regardless of which way the stacking goes. */
.hero-cast{
  position:absolute;left:0;right:0;bottom:0;z-index:4;
  display:flex;align-items:flex-end;justify-content:center;
  pointer-events:none;
}
.hero-cast img{
  width:auto;height:auto;max-width:30%;max-height:var(--cast-h);display:block;
  filter:drop-shadow(0 26px 50px rgba(0,0,0,.45));
}
:root[data-theme="light"] .hero-cast img{
  filter:drop-shadow(0 22px 40px rgba(70,48,36,.22));
}
.hc-beng{transform:translateX(9%)}
.hc-yen{transform:translateX(-9%)}

/* Caption above the card. Lives OUTSIDE the shot (which clips its
   overflow) and doesn't scale with it, so no counter-scaling games:
   at the end scale of .42 the card's top edge is 29svh from the top,
   and -23svh from centre puts this just above it. Small amber text
   needs the dark backing plate: raw amber over a lit contour measures
   4.38:1, under the 4.5:1 floor for text this size. */
.hero-cap{
  z-index:5;align-self:center;justify-self:center;
  transform:translateY(-23svh);
  white-space:nowrap;
  font-family:var(--display);font-weight:900;font-size:.56rem;
  text-transform:uppercase;letter-spacing:.26em;
  color:var(--accent);
  /* rises and STAYS — the card no longer fades, so the caption that
     belongs to it shouldn't either */
  opacity:clamp(0, calc(var(--p) * 2 - .6), 1);
  background:rgba(18,10,13,.72);padding:.34rem .7rem;border-radius:3px;
}

/* ---- corner furniture: leaves as the shot shrinks ---- */
.hero-meta{
  z-index:5;align-self:end;justify-self:start;
  margin:0 0 clamp(16px,3vh,32px) clamp(16px,4vw,44px);
  display:flex;flex-direction:column;gap:.3rem;text-align:left;
  font-family:var(--display);text-transform:uppercase;
  opacity:clamp(0,calc(1 - var(--p) * 3),1);
}
.hm-k{font-weight:900;font-size:.56rem;letter-spacing:.24em;color:var(--accent)}
.hm-v{font-weight:700;font-size:.58rem;letter-spacing:.15em;color:var(--on-band-muted)}
/* small yellow text can't sit on light mode's near-white — flip it to a
   filled chip, same rule as .eyebrow (see KEEPING THE BRAND YELLOW
   LEGIBLE at the bottom of this file) */
:root[data-theme="light"] .hm-k{
  align-self:flex-start;background:var(--amber);color:var(--on-amber);
  padding:.22rem .5rem;border-radius:3px;
}

/* min-width/padding are the TAP TARGET, not decoration: below 560px
   the "Scroll" label is hidden (see the mobile block) and all that's
   left is the 1px <i> rule, which was a 1×36px link — impossible to
   hit with a thumb and a WCAG 2.5.8 failure. The box stays ≥44px
   wide; nothing about it is visible. */
.hero-scroll{
  z-index:5;align-self:end;justify-self:end;
  margin:0 clamp(16px,4vw,44px) clamp(16px,3vh,32px) 0;
  min-width:44px;padding:4px 0;
  display:flex;flex-direction:column;align-items:center;gap:.6rem;
  font-family:var(--display);font-weight:800;font-size:.56rem;
  text-transform:uppercase;letter-spacing:.24em;color:var(--on-band-muted);
  transition:color .2s;
  opacity:clamp(0,calc(1 - var(--p) * 3),1);
}
.hero-scroll:hover{color:var(--accent)}
:root[data-theme="light"] .hero-scroll:hover{color:var(--text)}
.hero-scroll i{
  display:block;width:1px;height:36px;
  background:linear-gradient(to bottom,var(--accent),transparent);
  animation:scrollCue 2.4s ease-in-out infinite;transform-origin:top;
}
@keyframes scrollCue{0%,100%{transform:scaleY(.45);opacity:.5}50%{transform:scaleY(1);opacity:1}}

@media (max-width:560px){
  /* a .42-scale card of a 375px page is a postage stamp — end bigger,
     and move the caption up to match (half-height .6 × 50svh = 30svh).
     Override the VARIABLE only: the transform itself is shared so the
     pattern's counter-scale keeps cancelling it exactly. */
  /* phones get taller hosts back: the layout there centres the content
     above them rather than competing for the same band */
  .hero-shot{--card-shrink:.4}
  :root{--cast-h:40svh}
  .hero-cap{transform:translateY(-32svh)}
  /* Close the gap between the wordmark block and the hosts: centre the
     content in the space above them instead of pinning it under the
     navbar. The padding is what reserves the hosts' half of the screen
     — it tracks --cast-h so the two can't drift apart. The cast paints
     IN FRONT of the content (see .hero-cast), so a graze reads as the
     hosts standing over the button rather than a border sliced across a
     cap — but the padding is what keeps that graze off the LABELS, so
     lower it and the type starts disappearing behind a shoulder. */
  /* ⚠️ Do NOT raise this factor to buy clearance over the hosts. It was
     tried at .78 and it lifts the type block by half the change, which
     on a short phone drives the .hero-mark straight up into the navbar's
     own logo (measured at 375x667: mark 53.7-95.7 against a navbar of
     40-114). The height budget on short screens belongs to --cast-h,
     which is corrected below — shrinking the cast moves the heads DOWN
     and, because this padding tracks --cast-h, gently moves the type
     down too, instead of pushing it under the navbar. */
  .hero-inner{justify-content:center;padding-bottom:calc(var(--cast-h) * .62)}
  .hero-cast img{max-width:52%;max-height:var(--cast-h)}
  .hc-beng{transform:translateX(13%)}
  .hc-yen{transform:translateX(-13%)}
}
/* ⚠️ SHORT PHONES ARE THE REAL CASE, AND THEY ARE NOT THE DEVICE SIZE.
   A phone browser's visible viewport is far shorter than the spec sheet:
   Safari on a 390x844 iPhone with both toolbars showing is about 390x681,
   and svh sizes against that. The hero's type block is close to fixed
   height, so on a short viewport 40svh of cast leaves too little room and
   the heads ride up into the CTA row — which only matters now that the
   cast paints in FRONT of the content.
   The lever is to DROP the cast, not to shrink it and not to lift the
   type. Shrinking --cast-h barely helps, because this section's
   padding-bottom tracks --cast-h and pulls the type back down by half of
   whatever the heads gain (measured: 40svh -> 32svh bought only 4px).
   Lifting the type puts .hero-mark into the navbar. Dropping the cast is
   1px of clearance per 1px of drop, and it costs only torso, which the
   bottom of the screen was already cropping.
   At -7%: the label clears by 14.2px while the heads still cross the
   ghost button's border by 8.1px — the hosts read as standing IN FRONT
   of the button, which is the point, without touching the words.
   Measured with the cut-outs' true alpha — they carry ~33% transparent
   space above the heads, so the image's bounding box is meaningless here;
   scan for the first opaque row instead. */
@media (max-width:560px) and (max-height:740px){
  .hero-cast{bottom:calc(var(--cast-h) * -.07)}
}
/* Below roughly 630px of visible height the hero's type block and the cast
   simply do not both fit — a 360x640 Android showing its toolbar renders at
   about 360x560, and there the heads reach 37.7px into the "Preorder the
   drop" LABEL even after the drop above. In front, that would swallow the
   words; the drop needed to clear it would leave the hosts as a strip of
   shoulders along the bottom edge. So on those viewports only, the cast
   goes back behind the content: a border grazing a cap is cosmetic, an
   unreadable CTA is not. Everything taller keeps the hosts in front.
   Crossover measured: 360x610 label -13.5, 360x640 label +4.7. */
@media (max-width:560px) and (max-height:630px){
  .hero-cast{z-index:2}
  .hero-scroll span{display:none}
  .hero-kin-a{transform:translateY(-4.6vh) translateX(calc((16% - 44% * var(--p)) * var(--rs-move)))}
  .hero-kin-b{transform:translateY(4.6vh) translateX(calc((-44% + 44% * var(--p)) * var(--rs-move)))}
}

/* Reduced motion KEEPS the sequence. It is scroll-linked — it only
   moves while the visitor is moving, and stops the moment they stop,
   which is a different thing from animation that plays on its own.
   Switching it off outright made the hero look broken on any machine
   with Windows animations disabled, including this project's own.
   Only the wide horizontal type sweep is damped; the ambient pattern
   morph is autonomous motion, so pattern.js correctly freezes THAT
   to a static frame. */
@media (prefers-reduced-motion:reduce){
  .hero-stage{--rs-move:.2}
  .hero-scroll i{animation:none}
}

/* ============ TICKER (LED strip) ============ */
.ticker{
  background:var(--amber);color:var(--on-amber);overflow:hidden;
  padding:.85rem 0;
}
.ticker-track{display:flex;width:max-content;animation:tick 34s linear infinite}
.ticker-track span{
  font-family:var(--display);font-weight:900;font-size:.86rem;
  text-transform:uppercase;letter-spacing:.24em;white-space:nowrap;
}
.ticker-track i{font-style:normal;opacity:.5;margin:0 1.6rem}
@keyframes tick{to{transform:translateX(-50%)}}
@media (prefers-reduced-motion:reduce){.ticker-track{animation:none}}

/* ============ ABOUT ============ */
.story{display:grid;grid-template-columns:1.5fr 1fr;gap:56px;align-items:start}
.story p{margin-bottom:1.15rem;font-weight:300;line-height:1.9;color:var(--on-band-muted)}
.story p strong{font-weight:600;color:var(--on-band)}
.story-quote{border-left:3px solid var(--amber);padding-left:28px}
.story-quote .q{
  font-family:var(--display);font-weight:900;font-size:clamp(1.5rem,2.6vw,2.1rem);
  line-height:1.14;text-transform:uppercase;color:var(--on-band);
}
.story-quote .sig{
  margin-top:16px;font-family:var(--display);font-weight:700;font-size:.7rem;
  text-transform:uppercase;letter-spacing:.24em;color:var(--accent);
}

/* ============ HOSTS ============
   The cut-outs are transparent PNGs, so the photo deliberately
   BREAKS OUT of the card — it stands on the floor of the photo
   panel and overflows above the top edge. That needs
   overflow:visible on both the card and the panel, plus the
   170px of clearance .hosts reserves above itself.

   ── THE YELLOW ───────────────────────────────────────────────
   These are the only two portraits on the page, so they carry the
   brand colour rather than sitting in a grey box: an amber hairline
   round the card, the stage-light glow the cut-out stands in, a
   SOLID amber rule under the photo, an amber chip for the role and
   amber-outlined tags. Every one of those is a FILL or a border —
   the body copy underneath never turns yellow, so nothing here
   trades contrast for colour (see the light-mode note at the foot
   of this file). The washes are all kept above the paragraph and
   ≤.10 alpha, which leaves --on-band-muted where it already was.
====================================================== */
.hosts{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:26px;margin-top:170px}
.host{
  background:
    linear-gradient(180deg, color-mix(in srgb,var(--amber) 9%,transparent) 0%, transparent 62%),
    var(--card);
  border:1px solid color-mix(in srgb,var(--amber) 38%,transparent);
  overflow:visible;
  transition:transform .3s,border-color .3s,box-shadow .3s;
}
/* light mode drops borders everywhere else, but this one stays —
   it's the yellow, not a divider */
:root[data-theme="light"] .host{
  border-color:color-mix(in srgb,var(--amber) 55%,transparent);
  box-shadow:var(--sh-1);
}
.host:hover{
  transform:translateY(-6px);border-color:var(--amber);
  box-shadow:var(--sh-2), 0 16px 44px rgba(255,191,0,.20);
}
/* Light mode needs its own hover: the block above it is (0,3,0) and
   outranks .host:hover (0,2,0), so light mode lifted on hover but
   never lit up — it kept re-asserting the resting shadow. */
:root[data-theme="light"] .host:hover{
  border-color:var(--amber);
  box-shadow:var(--sh-2), 0 16px 44px rgba(255,191,0,.34);
}
.host-photo{
  position:relative;height:250px;overflow:visible;
  border-bottom:2px solid var(--amber);
  background:radial-gradient(420px 260px at 50% 120%, rgba(255,191,0,.34), rgba(67,41,70,.16) 56%, transparent 78%);
}
:root[data-theme="light"] .host-photo{
  background:radial-gradient(420px 260px at 50% 120%, rgba(255,191,0,.38), rgba(140,110,150,.10) 56%, transparent 78%);
}
.host-photo img{
  position:absolute;left:50%;bottom:0;transform:translateX(-50%);
  height:172%;width:auto;max-width:none;object-fit:contain;object-position:bottom;
  filter:drop-shadow(0 18px 34px rgba(0,0,0,.55));
}
:root[data-theme="light"] .host-photo img{filter:drop-shadow(0 18px 30px rgba(20,10,14,.24))}
.host-body{padding:26px 28px 30px}
.host h3{font-size:1.7rem;margin-bottom:8px}
.host h3 em{font-style:normal;color:var(--accent)}
/* The role reads as a printed chip in BOTH themes — light mode was
   already flipping it to a fill for contrast, dark just matches it
   now so the two themes show the same card.
   Selector is .host .host-role, not .host-role: this is a <p>, so the
   plain class (0,1,0) loses to .host p (0,1,1) below and the label
   would inherit muted white ON the amber fill.
   .who-card rides along so the guest page's host cards show the same
   chip — one source of truth for how a role label looks. */
.host .host-role,
.who-card .host-role{
  display:inline-block;
  font-family:var(--display);font-weight:700;font-size:.66rem;
  text-transform:uppercase;letter-spacing:.24em;
  background:var(--amber);color:var(--on-amber);
  padding:.34rem .8rem;border-radius:3px;margin-bottom:14px;
}
.host p{font-weight:300;font-size:.94rem;line-height:1.75;color:var(--on-band-muted)}
.host p strong{font-weight:600;color:var(--on-band)}
.tags{display:flex;flex-wrap:wrap;gap:7px;margin-bottom:14px}
/* amber outline + a whisper of amber fill. The label itself stays
   --on-band-muted: yellow text at 9px would fail on white. */
.tag{
  font-family:var(--display);font-weight:700;font-size:.58rem;
  text-transform:uppercase;letter-spacing:.16em;padding:.32rem .7rem;
  border:1px solid color-mix(in srgb,var(--amber) 46%,transparent);
  background:color-mix(in srgb,var(--amber) 8%,transparent);
  color:var(--on-band-muted);
}

/* ============ EPISODES ============ */
.ep-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:22px}
.ep-card{
  background:var(--card);border:1px solid var(--line);
  display:flex;flex-direction:column;overflow:hidden;
  transition:transform .3s,border-color .3s,box-shadow .3s;
}
:root[data-theme="light"] .ep-card{border-color:transparent;box-shadow:var(--sh-1)}
.ep-card:hover{transform:translateY(-8px);border-color:var(--accent);box-shadow:var(--sh-2)}
.yt-lite{
  display:block;width:100%;aspect-ratio:16/9;position:relative;overflow:hidden;
  border:0;padding:0;background:#120a0d;cursor:pointer;
}
.yt-lite img{width:100%;height:100%;object-fit:cover;transition:transform .5s,opacity .3s}
.yt-lite:hover img{transform:scale(1.06);opacity:.74}
.yt-lite iframe{width:100%;height:100%;border:0;display:block}
.yt-lite .play{
  position:absolute;inset:0;margin:auto;width:56px;height:56px;
  display:grid;place-items:center;border:2px solid #fff;border-radius:50%;
  background:rgba(0,0,0,.3);transition:background .25s,border-color .25s,transform .25s;
}
.yt-lite:hover .play{background:var(--amber);border-color:var(--amber);transform:scale(1.08)}
.yt-lite .play svg{width:22px;height:22px;fill:#fff;margin-left:3px}
.yt-lite:hover .play svg{fill:var(--on-amber)}
.ep-dur{
  position:absolute;right:8px;bottom:8px;
  background:rgba(10,4,7,.82);color:#fff;
  font-family:var(--display);font-weight:800;font-size:.6rem;
  letter-spacing:.08em;padding:.22rem .48rem;border-radius:3px;
}
.ep-body{padding:24px 22px 26px;display:flex;flex-direction:column;gap:10px;flex:1}
.ep-num{
  font-family:var(--display);font-weight:800;font-size:.64rem;
  text-transform:uppercase;letter-spacing:.24em;color:var(--accent);
}
.ep-body h3{font-size:1.22rem;line-height:1.15}
.ep-body .who{font-weight:300;font-size:.88rem;color:var(--on-band-muted)}
.ep-body .who b{font-weight:600;color:var(--accent)}
.ep-body .btn-mini{align-self:flex-start;margin-top:auto}

/* ============ FEATURED VIDEO BAND ============ */
.feature{
  position:relative;padding:96px 0;text-align:center;overflow:hidden;
  background:var(--band-4);color:var(--on-band);
}
.feature h2{font-size:clamp(2rem,4.6vw,3.4rem);margin-bottom:16px}
.feature .sub{
  font-family:var(--display);font-weight:700;font-size:.72rem;
  text-transform:uppercase;letter-spacing:.3em;color:var(--on-band-muted);margin-bottom:44px;
}
.player{
  position:relative;max-width:1000px;margin:0 auto;aspect-ratio:16/9;
  border:1px solid var(--line);background:#120a0d;overflow:hidden;box-shadow:var(--sh-2);
}
.player iframe{width:100%;height:100%;border:0;display:block}
.feature-cap{
  margin-top:26px;display:flex;justify-content:center;align-items:center;gap:.8rem;
  flex-wrap:wrap;font-weight:300;font-size:.92rem;color:var(--on-band-muted);
}
.live-dot{
  display:inline-flex;align-items:center;gap:.5rem;
  font-family:var(--display);font-weight:800;font-size:.64rem;
  text-transform:uppercase;letter-spacing:.22em;color:var(--accent);
}
.live-dot::before{
  content:'';width:8px;height:8px;border-radius:50%;background:var(--amber);
  animation:pulse 1.8s ease-in-out infinite;
}
@keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.35;transform:scale(.72)}}

/* ============ THE DROP ============
   Campaign shot on the left, the actual garments as a stacked
   list on the right, preorder timeline underneath. The product
   photos are shot on white, so every tile that holds one stays
   white in BOTH themes — that's why .drop-thumb and .prod-img
   don't use a theme token.
====================================================== */
.drop{display:grid;grid-template-columns:.92fr 1.08fr;gap:38px;align-items:start}

.drop-shot{position:relative;overflow:hidden;border:1px solid var(--line);background:#fff}
:root[data-theme="light"] .drop-shot{border-color:transparent;box-shadow:var(--sh-1)}
.drop-shot img{width:100%;display:block}
.drop-shot figcaption{
  position:absolute;left:0;bottom:0;
  background:var(--amber);color:var(--on-amber);
  font-family:var(--display);font-weight:800;font-size:.66rem;
  text-transform:uppercase;letter-spacing:.2em;padding:.62rem 1.1rem;
}

.drop-list{display:grid;gap:16px}
/* The whole card is an <a> to shop.html — clicking the product is the
   obvious gesture and it used to do nothing, with only the small
   corner button live. Inheriting colour and killing the underline
   keeps it looking exactly like the panel it was. */
.drop-item{
  display:grid;grid-template-columns:104px 1fr auto;gap:20px;align-items:center;
  background:var(--card);border:1px solid var(--line);padding:16px;
  transition:transform .3s,border-color .3s,box-shadow .3s;
  text-decoration:none;color:inherit;cursor:pointer;
}
/* the card is one focus stop, so it needs a visible ring of its own */
.drop-item:focus-visible{outline:2px solid var(--amber);outline-offset:3px}
:root[data-theme="light"] .drop-item{border-color:transparent;box-shadow:var(--sh-1)}
.drop-item:hover{transform:translateY(-4px);border-color:var(--accent);box-shadow:var(--sh-2)}
.drop-thumb{position:relative;aspect-ratio:1;overflow:hidden;background:#fff;display:grid;place-items:center}
.drop-thumb img{width:100%;height:100%;object-fit:contain}
.drop-thumb img.ph{width:60%;height:auto;opacity:.32;filter:invert(1) brightness(.2)}
/* .drop-flag — the savings sticker that used to sit at the top-left of
   the product photo — was removed on 1 Aug 2026. On a flat-lay mockup
   there is no dead space in that corner: it landed squarely on the
   garment it was meant to sell. The figure now lives on the Preorder
   button as .dg-save, which is also where it does more work — it reads
   as part of the offer at the moment of the click instead of as a
   sticker slapped over the product. Don't put it back on the image. */
.drop-info{display:grid;gap:5px;min-width:0}
.drop-kind{
  font-family:var(--display);font-weight:800;font-size:.6rem;
  text-transform:uppercase;letter-spacing:.24em;color:var(--accent);
}
.drop-info h3{font-size:1.02rem;line-height:1.2}
.drop-info p{font-weight:300;font-size:.85rem;color:var(--on-band-muted);line-height:1.5}
.drop-meta{display:flex;align-items:baseline;gap:.9rem;flex-wrap:wrap;margin-top:3px}
.drop-price{font-family:var(--display);font-weight:900;font-size:1.4rem;color:var(--accent)}
.drop-price s{font-size:.5em;font-weight:700;opacity:.5;margin-right:.3rem}
.drop-sizes{
  font-family:var(--display);font-weight:700;font-size:.6rem;
  text-transform:uppercase;letter-spacing:.16em;color:var(--on-band-muted);
}
/* the torn ticket edge, kept as a nod to the drop being a "ticket" */
.drop-go{
  align-self:stretch;display:grid;place-items:center;
  background:var(--amber);color:var(--on-amber);
  font-family:var(--display);font-weight:800;font-size:.66rem;
  text-transform:uppercase;letter-spacing:.18em;
  padding:1rem .6rem 1.35rem;min-width:118px;text-align:center;
  border:0;cursor:pointer;transition:background .25s;
  --zig:13px;
  -webkit-mask:conic-gradient(from -45deg at bottom,#0000,#000 1deg 89deg,#0000 90deg) 50%/var(--zig) 100% repeat-x;
  mask:conic-gradient(from -45deg at bottom,#0000,#000 1deg 89deg,#0000 90deg) 50%/var(--zig) 100% repeat-x;
}
/* hovering anywhere on the card lights the button, because the whole
   card is the link now — the button alone no longer owns the gesture */
.drop-item:hover .drop-go{background:#FFCE33}
/* two stacked lines: the action, then what it saves you */
.drop-go{row-gap:.3rem}
.dg-save{
  font-size:.6rem;letter-spacing:.1em;
  /* --on-amber at 82% still lands ~9:1 on the amber fill, so this
     stays comfortably readable while sitting under the main label */
  color:color-mix(in srgb,var(--on-amber) 82%,transparent);
}

.drop-steps{
  list-style:none;display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));
  gap:20px;margin-top:44px;
}
.drop-steps li{border-top:2px solid var(--amber);padding-top:15px;display:grid;gap:3px}
.drop-steps .k{
  font-family:var(--display);font-weight:900;font-size:.66rem;
  letter-spacing:.22em;color:var(--accent);
}
.drop-steps b{font-family:var(--display);font-weight:800;font-size:.86rem;text-transform:uppercase;letter-spacing:.1em}
.drop-steps span:last-child{font-weight:300;font-size:.88rem;color:var(--on-band-muted)}
:root[data-theme="light"] .drop-steps .k{color:var(--text)}

.drop-foot{
  display:flex;flex-wrap:wrap;gap:1rem;align-items:center;
  margin-top:38px;font-weight:300;font-size:.9rem;color:var(--on-band-muted);
}

/* ============ PLATFORMS ============ */
.plat-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:20px}
.plat{
  display:flex;flex-direction:column;align-items:center;gap:14px;
  padding:34px 18px;border:1px solid var(--line);background:var(--card);
  text-align:center;transition:transform .3s,border-color .3s,box-shadow .3s;
}
:root[data-theme="light"] .plat{border-color:transparent;box-shadow:var(--sh-1)}
/* Hover lights the card in ITS platform's colour — --brand comes off
   the inline style on each card. TikTok's is deliberately black (owner's
   call), so that one reads as a dark keyline and lift rather than a glow. */
.plat:hover{
  transform:translateY(-6px);border-color:var(--brand,var(--accent));
  box-shadow:var(--sh-2), 0 14px 38px color-mix(in srgb, var(--brand,var(--accent)) 22%, transparent);
}
/* same specificity story as .host:hover — the light-mode resting rule
   above is (0,3,0), so the hover has to be restated at (0,4,0) or light
   mode shows no colour at all */
:root[data-theme="light"] .plat:hover{
  border-color:var(--brand,var(--accent));
  box-shadow:var(--sh-2), 0 14px 40px color-mix(in srgb, var(--brand,var(--accent)) 32%, transparent);
}
/* platform marks are monochrome: white on dark, black on light.
   The paths carry their own fill="" attributes, so the rule has
   to target the paths — styling the <svg> alone won't win. */
.plat svg{width:34px;height:34px}
.plat svg path{fill:#FFFFFF}
:root[data-theme="light"] .plat svg path{fill:#000000}
/* The website card's globe is the one DRAWN mark in the row — the
   others are filled logo glyphs. It has to opt out of the fill rules
   above (both of them: the light-mode one is the more specific, so
   fill:none has to be repeated there or the globe fills in black). */
.plat .ic-globe circle,
.plat .ic-globe path{
  fill:none;stroke:#FFFFFF;stroke-width:1.5;
  stroke-linecap:round;stroke-linejoin:round;
}
:root[data-theme="light"] .plat .ic-globe circle,
:root[data-theme="light"] .plat .ic-globe path{fill:none;stroke:#000000}
.plat b{font-family:var(--display);font-weight:800;font-size:.78rem;letter-spacing:.16em;text-transform:uppercase}
.plat span{font-weight:300;font-size:.8rem;color:var(--on-band-muted)}

/* ============ FAQ ============
   Native <details>, so it works with no JS and search engines
   read every answer whether it's open or not.
====================================================== */
.faq{display:grid;gap:12px;max-width:900px}
.faq-item{
  background:var(--card);border:1px solid var(--line);
  transition:border-color .25s,box-shadow .25s;
}
:root[data-theme="light"] .faq-item{border-color:transparent;box-shadow:var(--sh-1)}
.faq-item[open],.faq-item:hover{border-color:var(--accent)}
.faq-item summary{
  display:flex;align-items:center;gap:16px;cursor:pointer;
  padding:20px 24px;list-style:none;
}
.faq-item summary::-webkit-details-marker{display:none}
.faq-item summary h3{
  font-size:1rem;letter-spacing:.02em;flex:1;line-height:1.3;color:var(--on-band);
}
.faq-item summary::after{
  content:'+';flex:none;width:26px;height:26px;display:grid;place-items:center;
  border:1px solid var(--line);color:var(--accent);
  font-family:var(--display);font-weight:800;font-size:1rem;line-height:1;
  transition:transform .25s,background .25s,color .25s;
}
.faq-item[open] summary::after{
  content:'−';background:var(--amber);border-color:var(--amber);color:var(--on-amber);
}
.faq-item p{
  padding:0 24px 22px;font-weight:300;font-size:.95rem;line-height:1.8;
  color:var(--on-band-muted);max-width:72ch;
}
.faq-item p a{color:var(--accent);border-bottom:1px solid currentColor}
:root[data-theme="light"] .faq-item p a{color:var(--text)}

/* ============ CONTACT ============ */
.contact-grid{display:grid;grid-template-columns:1fr 1.05fr;gap:60px;align-items:start}
.contact-copy .big{
  font-family:var(--display);font-weight:900;font-size:clamp(1.6rem,2.8vw,2.25rem);
  line-height:1.12;text-transform:uppercase;margin-bottom:20px;
}
.contact-copy p{font-weight:300;color:var(--muted);margin-bottom:26px;line-height:1.85}
.contact-mail{
  display:inline-block;font-family:var(--display);font-weight:800;
  font-size:clamp(1.05rem,2vw,1.4rem);letter-spacing:.02em;
  border-bottom:2px solid var(--amber);padding-bottom:5px;transition:color .2s;
}
.contact-mail:hover{color:var(--accent)}

/* ============ FORMS ============ */
.form{position:relative;display:grid;gap:18px}
.form-row{display:grid;grid-template-columns:1fr 1fr;gap:18px}
.form label{
  display:block;font-family:var(--display);font-weight:700;font-size:.62rem;
  text-transform:uppercase;letter-spacing:.22em;color:var(--on-band-muted);margin-bottom:8px;
}
.form .req{color:var(--accent)}
/* the counterpart to .req — quiet, because "optional" should reassure
   without competing with the label it qualifies */
.form .opt{color:var(--muted);font-weight:300;font-size:.86em}
/* date + select joined the list for the guest page's booking
   fallback — no other form uses them, and they inherit the same
   underline treatment so the row doesn't look bolted on */
.form input[type=text],.form input[type=tel],.form input[type=email],
.form input[type=date],.form select,.form textarea{
  width:100%;background:transparent;border:0;border-bottom:1px solid var(--line);
  padding:.7rem 0;font-weight:300;font-size:1rem;color:var(--on-band);
  border-radius:0;transition:border-color .2s;
}
/* a native select renders its own chrome; strip it and draw the
   caret, or Chrome and Safari disagree by ~20px of height */
.form select{
  appearance:none;cursor:pointer;padding-right:1.6rem;
  background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),linear-gradient(135deg,currentColor 50%,transparent 50%);
  background-position:calc(100% - 12px) 1.15rem,calc(100% - 7px) 1.15rem;
  background-size:5px 5px,5px 5px;background-repeat:no-repeat;
}
/* the dropdown list itself is painted by the OS — it inherits the
   page's transparent background and goes white-on-white in dark mode */
.form select option{background:var(--card-solid);color:var(--text)}
/* Chrome's date field puts its picker icon in the text colour, which
   is near-white on the dark card — invert it so it's visible */
.form input[type=date]::-webkit-calendar-picker-indicator{
  filter:invert(1) brightness(1.6);cursor:pointer;
}
:root[data-theme="light"] .form input[type=date]::-webkit-calendar-picker-indicator{filter:none}
.form input::placeholder,.form textarea::placeholder{color:var(--on-band-muted);opacity:.6}
/* The amber underline is the focus style for a POINTER. A bare
   `:focus{outline:none}` also stripped the ring for keyboard users,
   who then had a 1px underline as their only position indicator —
   and on light mode that underline is amber on near-white. Scoping
   the removal to :not(:focus-visible) hands the global 3px ring back
   to anyone tabbing, and changes nothing for mouse users. */
.form input:focus,.form textarea:focus,.form select:focus{border-bottom-color:var(--accent)}
.form input:focus:not(:focus-visible),
.form textarea:focus:not(:focus-visible),
.form select:focus:not(:focus-visible){outline:none}
.form .btn{justify-self:start;margin-top:6px}

.consent{display:none;gap:12px;padding-top:4px}
.consent.show{display:grid}
.chk{display:grid;grid-template-columns:auto 1fr;gap:11px;align-items:start;cursor:pointer}
.chk input{
  appearance:none;width:19px;height:19px;margin-top:3px;flex:none;
  border:1px solid var(--line);background:transparent;cursor:pointer;position:relative;
  transition:background .2s,border-color .2s;
}
.chk input:checked{background:var(--amber);border-color:var(--amber)}
.chk input:checked::after{
  content:'';position:absolute;left:6px;top:2px;width:5px;height:10px;
  border:solid var(--on-amber);border-width:0 2px 2px 0;transform:rotate(45deg);
}
/* .chk is a <label>, so it inherits .form label's Montserrat +
   uppercase + .22em tracking. That's right for a three-word field
   label and wrong for a 60-word SMS/marketing consent disclosure —
   it rendered as three lines of tracked-out caps, which is the
   hardest possible way to read the one paragraph a visitor actually
   has to understand before ticking. Reset it to body copy. */
.chk span{
  font-family:var(--body);font-weight:300;font-size:.8rem;line-height:1.6;
  text-transform:none;letter-spacing:normal;color:var(--on-band-muted);
}

.form-status{font-size:.9rem;font-weight:400;min-height:1.2em}
.form-status.err{color:#FF8A7A}
.form-status.ok{color:var(--accent)}
:root[data-theme="light"] .form-status.err{color:#B3261E}

.form-done{
  position:absolute;inset:-16px;display:none;place-items:center;text-align:center;
  background:var(--card-solid);border:1px solid var(--amber);padding:30px;z-index:5;
}
.form-done.show{display:grid}
.form-done .big{font-family:var(--display);font-weight:900;font-size:1.9rem;text-transform:uppercase;margin-bottom:10px;color:var(--accent)}
.form-done p{font-weight:300;color:var(--muted)}

.hint{font-weight:300;font-size:.82rem;line-height:1.6;color:var(--muted);margin-top:7px}

/* ============ FOOTER ============ */
footer{background:var(--band-foot);border-top:1px solid var(--line-soft);padding:70px 0 40px;color:var(--on-band)}
.foot-top{display:grid;justify-items:center;gap:24px;text-align:center}
.foot-logo img{height:52px;width:auto}
:root[data-theme="light"] .foot-logo img{filter:invert(1) brightness(.14)}
.foot-tag{
  font-family:var(--display);font-weight:800;font-size:.72rem;
  text-transform:uppercase;letter-spacing:.28em;color:var(--on-band-muted);
}
.foot-nav{display:flex;flex-wrap:wrap;justify-content:center;gap:1.7rem}
.foot-nav a{
  font-family:var(--display);font-weight:700;font-size:.68rem;
  text-transform:uppercase;letter-spacing:.2em;color:var(--on-band-muted);transition:color .2s;
}
.foot-nav a:hover{color:var(--accent)}
.foot-social{display:flex;gap:12px}
.foot-social a{
  width:44px;height:44px;display:grid;place-items:center;
  border:1px solid var(--line);transition:background .25s,border-color .25s,transform .25s,color .25s;
}
.foot-social a:hover{background:var(--amber);border-color:var(--amber);color:var(--on-amber);transform:translateY(-3px)}
.foot-social svg{width:17px;height:17px;fill:currentColor}
.copyright{font-weight:300;font-size:.85rem;color:var(--muted);padding-top:12px;border-top:1px solid var(--line-soft);width:100%;margin-top:8px}
.copyright .hl{font-weight:600}

/* ============ REVEAL + BACK TO TOP ============ */
.reveal{opacity:0;transform:translateY(30px);transition:opacity .75s ease,transform .75s cubic-bezier(.2,.7,.2,1)}
.reveal.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){.reveal{opacity:1;transform:none;transition:none}}

.to-top{
  position:fixed;right:24px;bottom:26px;z-index:880;
  width:46px;height:46px;display:grid;place-items:center;
  background:var(--amber);color:var(--on-amber);border:0;cursor:pointer;
  opacity:0;pointer-events:none;transform:translateY(12px);
  transition:opacity .3s,transform .3s,background .2s;box-shadow:var(--sh-1);
}
.to-top.show{opacity:1;pointer-events:auto;transform:none}
.to-top:hover{background:#FFCE33}
/* lift the button clear of the dock player when one is on screen */
body.has-dock .to-top{bottom:calc(26px + var(--dock-h))}

/* ============ THE DOCK PLAYER (home page only) ============
   A fixed bar at the bottom carrying the episode list. Sits at
   z-index 940: above .to-top (880) and the dot nav (850) so it is
   never buried, but below the cart drawer (950) and every overlay
   (1000+) so it can't cover a modal.

   --dock-h is the single source for its height. body.has-dock adds
   the same value as padding-bottom (see below), which is what stops
   the bar from covering the last few lines of the footer — set the
   height here and everything else follows. */
:root{--dock-h:66px}
.dock{
  position:fixed;left:0;right:0;bottom:0;z-index:940;
  background:color-mix(in srgb,var(--ink) 92%,transparent);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  border-top:1px solid var(--line);
}
/* the bar itself never scrolls; only the list above it does.
   width matches .wrap exactly — min(1240px,90%) — so the dock's
   contents line up with every other column on the page. */
.dock-bar{
  height:var(--dock-h);display:flex;align-items:center;gap:.9rem;
  width:min(1240px,90%);margin-inline:auto;
}
.dock-play{
  flex:0 0 auto;width:42px;height:42px;display:grid;place-items:center;
  background:var(--amber);color:var(--on-amber);border:0;cursor:pointer;
  transition:background .2s;
}
.dock-play:hover{background:#FFCE33}
.dock-play svg{width:20px;height:20px;fill:currentColor}
.dock-play .ic-pause{display:none}
.dock-play.playing .ic-play{display:none}
.dock-play.playing .ic-pause{display:block}
/* link mode — there is no file for this episode yet, so the
   transport would be a lie. Hide it and let "Watch ↗" carry the
   row instead. */
.dock.no-audio .dock-play,
.dock.no-audio .dock-scrub{display:none}

.dock-now{min-width:0;flex:1 1 auto}
.dock-title{
  font-family:var(--display);font-weight:800;font-size:.82rem;
  text-transform:uppercase;letter-spacing:.06em;color:var(--text);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.dock-meta{font-weight:300;font-size:.72rem;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.dock-scrub{flex:2 1 260px;display:flex;align-items:center;gap:.7rem;min-width:0}
.dock-seek{
  flex:1 1 auto;min-width:0;height:4px;-webkit-appearance:none;appearance:none;
  background:var(--line);cursor:pointer;
}
.dock-seek::-webkit-slider-thumb{
  -webkit-appearance:none;appearance:none;width:13px;height:13px;border-radius:50%;
  background:var(--amber);border:0;cursor:pointer;
}
.dock-seek::-moz-range-thumb{width:13px;height:13px;border-radius:50%;background:var(--amber);border:0;cursor:pointer}
.dock-time{font-weight:300;font-size:.7rem;color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}

.dock-watch,.dock-list-btn{
  flex:0 0 auto;font-family:var(--display);font-weight:700;font-size:.64rem;
  text-transform:uppercase;letter-spacing:.14em;color:var(--muted);
  background:none;border:1px solid var(--line);padding:.5rem .8rem;cursor:pointer;
  display:inline-flex;align-items:center;gap:.45rem;text-decoration:none;
}
.dock-watch:hover,.dock-list-btn:hover{color:var(--text);border-color:var(--amber)}
.dock-list-btn svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2.2;transition:transform .25s}
.dock.open .dock-list-btn svg{transform:rotate(180deg)}
.dock-close{
  flex:0 0 auto;width:30px;height:30px;background:none;border:0;cursor:pointer;
  color:var(--muted);font-size:.85rem;line-height:1;
}
.dock-close:hover{color:var(--text)}

/* the playlist. max-height + overflow so seven episodes can't grow
   taller than the viewport on a phone. */
.dock-list{
  max-height:min(46vh,340px);overflow-y:auto;
  border-top:1px solid var(--line-soft);
  width:min(1240px,90%);margin-inline:auto;
}
.dock-row{
  width:100%;display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:.9rem;
  padding:.75rem .2rem;background:none;border:0;border-bottom:1px solid var(--line-soft);
  text-align:left;cursor:pointer;text-decoration:none;color:inherit;font:inherit;
}
.dock-row:last-child{border-bottom:0}
.dock-row:hover{background:color-mix(in srgb,var(--amber) 8%,transparent)}
.dock-row.on{background:color-mix(in srgb,var(--amber) 13%,transparent)}
.dr-n{
  font-family:var(--display);font-weight:700;font-size:.6rem;text-transform:uppercase;
  letter-spacing:.14em;color:var(--accent);white-space:nowrap;
}
/* amber at 9.6px on light's near-white is unreadable — same rule as
   every other small accent label on the site */
:root[data-theme="light"] .dr-n{color:var(--text)}
.dr-t{font-weight:400;font-size:.85rem;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dr-d{font-weight:300;font-size:.72rem;color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap}

/* ---- THE COLLAPSED PILL: the player's DEFAULT state ----
   Bottom-left, small, out of the way. The full bar only exists once
   someone opens it. Sits in the same corner the hero's old "7
   episodes · 0 scripts" label used to occupy — that label was removed
   rather than have the two fight over the spot. */
.dock-pill{
  position:fixed;left:24px;bottom:26px;z-index:940;
  display:inline-flex;align-items:center;gap:.55rem;
  font-family:var(--display);font-weight:700;font-size:.62rem;
  text-transform:uppercase;letter-spacing:.14em;
  background:var(--amber);color:var(--on-amber);border:0;cursor:pointer;
  padding:.62rem .95rem;box-shadow:var(--sh-1);
  transition:background .2s;
}
.dock-pill:hover{background:#FFCE33}
.dock-pill .dp-ic{
  display:grid;place-items:center;width:18px;height:18px;flex:0 0 auto;
}
.dock-pill .dp-ic svg{width:14px;height:14px;fill:currentColor}
/* while something is actually playing the glyph becomes a pause bar,
   so the pill doubles as a transport without opening the whole player */
.dock-pill.playing .dp-ic svg{display:none}
.dock-pill.playing .dp-ic::before{
  content:'';width:11px;height:12px;
  border-left:3.5px solid currentColor;border-right:3.5px solid currentColor;
}
@media (max-width:780px){
  /* thumb-sized, and clear of the bottom edge on phones with a home bar */
  .dock-pill{left:16px;bottom:calc(16px + env(safe-area-inset-bottom,0px));min-height:44px}
}

/* keep the footer clear of the bar */
body.has-dock{padding-bottom:var(--dock-h)}

@media (max-width:780px){
  /* on a phone the scrub bar and the watch link are the first to go:
     the title, the transport and the episode list are what matter,
     and a 4px range input under a thumb is a poor target anyway */
  .dock-scrub,.dock-watch{display:none}
  .dock-list-btn span{display:none}
  .dock-bar{gap:.7rem}
  /* every control in the bar gets a real thumb target. The bar is
     66px tall, so 44px fits with room to spare — and the space
     freed by hiding the scrub and watch controls pays for it. */
  .dock-play{width:44px;height:44px}
  .dock-list-btn,.dock-close{min-width:44px;min-height:44px;justify-content:center;padding:.5rem}
  .dock-row{padding-block:.85rem}
}
@media (prefers-reduced-motion:reduce){
  .dock-list-btn svg{transition:none}
}

/* ============ NEWSLETTER POP-UP ============ */
/* HIDDEN MEANS HIDDEN. opacity:0 + pointer-events:none stops the
   MOUSE but leaves every field inside reachable by Tab and readable
   by a screen reader — a keyboard visitor would tab into an invisible
   newsletter form. visibility:hidden takes the subtree out of both.
   It's transitioned at 0s with a delay so the fade still plays out on
   close, then the subtree disappears. Same pattern on .modal-overlay
   and .cart-drawer below — keep all three in step. */
.popup-overlay{
  position:fixed;inset:0;z-index:1000;display:grid;place-items:center;padding:20px;
  background:rgba(10,4,7,.8);backdrop-filter:blur(6px);
  opacity:0;pointer-events:none;visibility:hidden;
  transition:opacity .35s,visibility 0s linear .35s;
}
:root[data-theme="light"] .popup-overlay{background:rgba(26,18,22,.44)}
.popup-overlay.show{opacity:1;pointer-events:auto;visibility:visible;transition:opacity .35s,visibility 0s}
.popup-card{
  position:relative;width:min(560px,100%);max-height:92vh;overflow-y:auto;
  background:var(--card-solid);border:1px solid var(--line);padding:44px 38px 36px;
  box-shadow:var(--sh-2);transform:translateY(20px);transition:transform .35s;
}
.popup-overlay.show .popup-card{transform:none}
.popup-card h3{font-size:2rem;margin:16px 0 12px}
.popup-card > p{font-weight:300;color:var(--muted);margin-bottom:26px;line-height:1.75}
.popup-card > p strong{font-weight:600;color:var(--text)}
.popup-close{
  position:absolute;top:14px;right:14px;width:34px;height:34px;
  background:transparent;border:1px solid var(--line);cursor:pointer;
  font-size:1rem;line-height:1;transition:border-color .2s,color .2s;
}
.popup-close:hover{border-color:var(--accent);color:var(--accent)}
.popup-dismiss{
  display:block;margin:16px auto 0;background:none;border:0;cursor:pointer;
  font-weight:300;font-size:.82rem;color:var(--muted);text-decoration:underline;
  text-underline-offset:3px;
}
.popup-dismiss:hover{color:var(--accent)}

/* ============================================================
   GUEST INVITATION  —  be-our-guest.html only
   ------------------------------------------------------------
   An unlisted page we send to people we want on the show. It
   borrows the homepage's bands, .sec-head, .form, .faq and
   .drop-steps wholesale; everything below is the handful of
   pieces that page needs and no other page has.
============================================================ */
.guest-hero{
  position:relative;background:var(--band-hero);color:var(--on-band);
  padding:clamp(64px,11vh,120px) 0 clamp(56px,9vh,96px);
  text-align:center;overflow:hidden;
}
.guest-hero h1{font-size:clamp(2.8rem,8vw,6rem);margin:24px 0 22px}
.gh-sub{
  font-weight:300;font-size:clamp(1rem,1.5vw,1.15rem);line-height:1.85;
  color:var(--on-band-muted);max-width:60ch;margin:0 auto;
}
.gh-cta{display:flex;flex-wrap:wrap;gap:1rem;justify-content:center;margin-top:36px}
.gh-note{
  margin-top:20px;font-family:var(--display);font-weight:700;font-size:.64rem;
  text-transform:uppercase;letter-spacing:.24em;color:var(--on-band-muted);
}

/* the numbers. Every one is checkable against the channel — if you
   add an episode, update these too (and llms.txt, and the JSON-LD). */
.stat-row{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:18px;margin:56px 0 64px;
}
.stat{
  border-top:2px solid var(--amber);padding-top:16px;display:grid;gap:4px;
}
.stat b{font-family:var(--display);font-weight:900;font-size:clamp(1.9rem,4vw,2.9rem);line-height:1;color:var(--on-band)}
.stat span{
  font-family:var(--display);font-weight:700;font-size:.62rem;
  text-transform:uppercase;letter-spacing:.2em;color:var(--on-band-muted);
}

.who-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:22px}
.who-card{
  background:var(--card);border:1px solid color-mix(in srgb,var(--amber) 34%,transparent);
  padding:28px 30px;
}
:root[data-theme="light"] .who-card{border-color:color-mix(in srgb,var(--amber) 50%,transparent);box-shadow:var(--sh-1)}
.who-card h3{font-size:1.5rem;margin-bottom:8px}
.who-card h3 em{font-style:normal;color:var(--accent)}
.who-card p{font-weight:300;font-size:.94rem;line-height:1.75;color:var(--on-band-muted)}
.who-card p strong{font-weight:600;color:var(--on-band)}

.guest-eps-label{
  margin:44px 0 18px;font-family:var(--display);font-weight:700;font-size:.66rem;
  text-transform:uppercase;letter-spacing:.24em;color:var(--on-band-muted);text-align:center;
}
.guest-eps{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:20px}
.guest-eps a{
  display:grid;gap:6px;background:var(--card);border:1px solid var(--line);padding:14px;
  transition:transform .3s,border-color .3s,box-shadow .3s;
}
:root[data-theme="light"] .guest-eps a{border-color:transparent;box-shadow:var(--sh-1)}
.guest-eps a:hover{transform:translateY(-5px);border-color:var(--amber);box-shadow:var(--sh-2)}
.guest-eps img{width:100%;aspect-ratio:16/9;object-fit:cover;margin-bottom:8px}
.ge-num{
  font-family:var(--display);font-weight:800;font-size:.6rem;
  text-transform:uppercase;letter-spacing:.24em;color:var(--accent);
}
:root[data-theme="light"] .ge-num{color:var(--text)}
.guest-eps b{font-family:var(--display);font-weight:800;font-size:.95rem;line-height:1.3;color:var(--on-band)}
.ge-meta{font-weight:300;font-size:.82rem;color:var(--on-band-muted)}

.where-row{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:.55rem;
  margin-top:44px;font-weight:300;font-size:.92rem;color:var(--on-band-muted);
}
.where-row a{
  font-family:var(--display);font-weight:800;font-size:.7rem;
  text-transform:uppercase;letter-spacing:.14em;color:var(--accent);
  border-bottom:1px solid currentColor;padding-bottom:2px;
}
:root[data-theme="light"] .where-row a{color:var(--text)}

.topic-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:20px}
.topic-card{background:var(--card);border:1px solid var(--line);padding:26px 24px;display:grid;gap:10px;align-content:start}
:root[data-theme="light"] .topic-card{border-color:transparent;box-shadow:var(--sh-1)}
.tc-k{
  font-family:var(--display);font-weight:800;font-size:.68rem;
  text-transform:uppercase;letter-spacing:.18em;color:var(--accent);
}
:root[data-theme="light"] .tc-k{color:var(--text)}
.topic-card p{font-weight:300;font-size:.9rem;line-height:1.7;color:var(--on-band-muted)}

/* the booking calendar's slot — an iframe drops straight in here */
.cal-slot{max-width:860px;margin:0 auto;min-height:120px}
.cal-slot iframe{width:100%;border:0;display:block;min-height:640px;background:transparent}
.cal-placeholder{
  border:2px dashed color-mix(in srgb,var(--amber) 55%,transparent);
  background:color-mix(in srgb,var(--amber) 7%,transparent);
  padding:46px 32px;text-align:center;display:grid;gap:16px;justify-items:center;
}
.cp-k{
  font-family:var(--display);font-weight:800;font-size:.66rem;
  text-transform:uppercase;letter-spacing:.26em;color:var(--accent);
}
:root[data-theme="light"] .cp-k{color:var(--text)}
.cal-placeholder p{font-weight:300;font-size:.95rem;line-height:1.75;color:var(--on-band-muted);max-width:52ch}
.cal-placeholder p b{font-weight:600;color:var(--on-band)}

.guest-form-wrap{
  max-width:760px;background:var(--card);border:1px solid var(--line);padding:38px 36px;
}
:root[data-theme="light"] .guest-form-wrap{border-color:transparent;box-shadow:var(--sh-1)}
/* the stand-in for the calendar — visually grouped so it's obvious
   this block is one unit to delete once booking is live */
/* ---- be-our-guest.html: the collapsed optional fields ----
   The <summary> is styled to read as a control rather than a heading,
   because it is one. list-style:none + the ::marker reset kills the
   default triangle in every engine; the ▸ is drawn in ::after so it
   can rotate. Keyboard focus is left to the global :focus-visible
   ring — don't add outline:none here. */
.guest-more{
  border:1px solid var(--line);border-radius:4px;
  background:color-mix(in srgb,var(--card) 60%,transparent);
}
.guest-more > summary{
  cursor:pointer;list-style:none;padding:15px 18px;
  display:flex;align-items:center;gap:.55rem;
  font-family:var(--display);font-weight:700;font-size:.64rem;
  text-transform:uppercase;letter-spacing:.2em;color:var(--text);
}
.guest-more > summary::-webkit-details-marker{display:none}
.guest-more > summary::marker{content:""}
.guest-more > summary::after{
  content:"▸";margin-left:auto;color:var(--accent);
  font-size:.9rem;transition:transform .2s;
}
.guest-more[open] > summary::after{transform:rotate(90deg)}
.guest-more > summary:hover{color:var(--accent)}
.guest-more .gm-note{
  font-family:var(--body);font-weight:300;font-size:.68rem;
  letter-spacing:.02em;text-transform:none;color:var(--muted);
}
/* Scoped to [open], and explicitly hidden when closed. Both halves
   matter. A bare `.guest-more-body{display:grid}` sets `display` on a
   direct child of <details>, which overrides the UA rule that hides
   closed content — the panel then renders expanded no matter what the
   open attribute says, and the disclosure silently does nothing. */
.guest-more:not([open]) > .guest-more-body{display:none}
.guest-more[open] > .guest-more-body{display:grid;gap:18px;padding:4px 18px 20px}
@media (prefers-reduced-motion: reduce){
  .guest-more > summary::after{transition:none}
}

.book-fallback{
  display:grid;gap:18px;padding:22px 20px;
  border:1px solid color-mix(in srgb,var(--amber) 34%,transparent);
  background:color-mix(in srgb,var(--amber) 6%,transparent);
}
.bf-title{
  font-family:var(--display);font-weight:800;font-size:.64rem;
  text-transform:uppercase;letter-spacing:.22em;color:var(--accent);
}
:root[data-theme="light"] .bf-title{color:var(--text)}
.hint-inline{
  font-family:var(--body);font-weight:400;font-size:.62rem;letter-spacing:.06em;
  text-transform:none;color:var(--accent);margin-left:.4rem;
}
:root[data-theme="light"] .hint-inline{color:var(--text)}
.hint.bad{color:#FF8A7A}
:root[data-theme="light"] .hint.bad{color:#B3261E}

.faq-foot{margin-top:34px;font-weight:300;font-size:.95rem;color:var(--on-band-muted)}

@media (max-width:640px){
  .guest-form-wrap{padding:26px 20px}
  .stat-row{margin:40px 0 48px}
}

/* ============================================================
   STORE  —  shop.html / checkout.html / order-confirmed.html
============================================================ */
/* The store carries the LANDING PAGE'S colourway, not a flat ink
   page: the same --band-hero sweep (wine → plum → petrol → copper)
   that the hero card shows. background-attachment:fixed pins it to
   the viewport so it sits still under the fixed contour layer,
   exactly the way it does behind the hero — scroll the store and the
   backdrop behaves like the landing page's, not like a long banner.
   Light mode's --band-hero is already the quiet white sweep, so this
   needs no separate override. */
.store-page{
  background:var(--band-hero);
  background-attachment:fixed;
}
/* The hero can carry --band-hero raw because .hero-shot lays a vignette
   over it before any type goes down. The store has no such layer, and
   the sweep's copper end (#945D49) is bright enough that body copy on a
   translucent --card drops to ~2.5:1 against it. This is that missing
   floor: fixed so it tracks the fixed gradient, and at z-index 0 so the
   contour layer (z1) still reads at full vibrancy on top of it and the
   content (.wrap, z2) stays above both.
   Measured with the scrim: muted text on a card over the copper end
   goes 2.58:1 → 6.6:1, and the store-head intro copy — which sits on
   the bare backdrop with no card under it, so it's the tightest case
   on these pages — clears at .62. Don't lower this value without
   re-running the per-element audit on shop + returns. */
.store-page::before{
  content:'';position:fixed;inset:0;z-index:0;pointer-events:none;
  background:rgba(12,5,8,.62);
}
/* light mode's --band-hero is already the quiet white sweep — a scrim
   there would only mud it */
:root[data-theme="light"] .store-page::before{background:transparent}
.nav-min{background:color-mix(in srgb, var(--ink) 90%, transparent);backdrop-filter:saturate(180%) blur(16px);border-bottom:1px solid var(--line-soft)}
main{padding-top:var(--nav-h)}

.store-head{padding:78px 0 8px;text-align:center}
.store-head h1{font-size:clamp(2.6rem,6.4vw,4.8rem);margin:22px 0 20px}
.store-head p{font-weight:300;color:var(--muted);max-width:60ch;margin:0 auto .6rem}
.store-head .pay-line{font-size:.9rem}
.store-head .pay-line b{font-weight:600;color:var(--text)}
/* ---- preorder promo banner ---- */
.promo-banner{
  margin:0 auto 22px;max-width:46ch;
  display:flex;flex-direction:column;gap:6px;align-items:center;
  padding:15px 24px;
  border:1px solid var(--amber);
  background:color-mix(in srgb, var(--amber) 12%, transparent);
}
.promo-banner[hidden]{display:none}
.promo-kicker{
  font-family:var(--display);font-weight:800;font-size:.62rem;
  text-transform:uppercase;letter-spacing:.22em;color:var(--accent);
}
.promo-banner strong{
  font-family:var(--display);font-weight:900;font-size:1.08rem;
  line-height:1.24;color:var(--text);
}
.promo-save{
  font-family:var(--display);font-weight:800;font-size:.8rem;letter-spacing:.04em;
  background:var(--amber);color:var(--on-amber);padding:.22rem .66rem;
}
.promo-sub{font-weight:300;font-size:.82rem;color:var(--muted);max-width:40ch}
.store-sec{padding:56px 0 96px}

/* underlined, not amber: small raw-amber text fails on light mode's
   near-white, and this sits in body copy at ~14px */
.policy-link{
  color:var(--text);border-bottom:1px solid var(--accent);
  padding-bottom:1px;transition:color .2s,border-color .2s;
}
.policy-link:hover{color:var(--accent)}
:root[data-theme="light"] .policy-link:hover{color:var(--text);border-bottom-width:2px}
.store-foot-note{
  margin:44px auto 0;max-width:62ch;text-align:center;
  font-weight:300;font-size:.9rem;line-height:1.8;color:var(--muted);
}

/* ---- shop.html: the product detail block under the grid ----
   Visible copy, not an SEO hidden-text trick — see the long comment
   on the markup in shop.html. Deliberately quiet: the cards above are
   the thing that should pull the eye, this is for the buyer who has
   already looked and wants to know what the fabric is. */
.prod-detail{margin:64px auto 0;max-width:72ch;display:grid;gap:30px}
.prod-detail > h2{
  font-size:1.05rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);font-weight:600;margin:0;text-align:center;
}
.prod-detail-item{
  background:var(--card);border:1px solid var(--line);border-radius:4px;
  padding:24px 26px;box-shadow:var(--sh-1);
}
:root[data-theme="light"] .prod-detail-item{background:var(--card-solid);border-color:transparent}
.prod-detail-item h3{
  font-size:1.06rem;line-height:1.45;margin:0 0 .55rem;
  display:flex;flex-wrap:wrap;align-items:baseline;gap:.6rem;
}
.prod-detail-item .pd-price{
  font-family:inherit;font-size:.85rem;font-weight:600;
  color:var(--accent);white-space:nowrap;
}
.prod-detail-item .pd-price s{color:var(--muted);font-weight:400;margin-left:.25rem}
.prod-detail-item .desc{margin:0}

/* ---- returns.html ---- */
.policy{max-width:820px;display:grid;gap:34px}
.policy-block{
  background:var(--card);border:1px solid var(--line);border-radius:4px;
  padding:30px 32px;box-shadow:var(--sh-1);
}
:root[data-theme="light"] .policy-block{background:var(--card-solid);border-color:transparent}
.policy-block h2{
  display:flex;align-items:center;gap:.7rem;
  font-size:clamp(1.15rem,2.2vw,1.5rem);margin-bottom:1rem;
}
/* numeral in an amber chip — the fill/text pairing that stays legible
   in BOTH themes, unlike small raw-amber text on white */
.policy-n{
  flex:0 0 auto;display:grid;place-items:center;
  width:1.9rem;height:1.9rem;border-radius:3px;
  background:var(--amber);color:var(--on-amber);
  font-family:var(--display);font-weight:900;font-size:.85rem;
}
.policy-block p{font-weight:300;line-height:1.8;color:var(--muted)}
.policy-block ul,.policy-block ol{margin:1rem 0 0;padding-left:1.1rem;display:grid;gap:.85rem}
.policy-block li{font-weight:300;line-height:1.8;color:var(--muted)}
.policy-block li b{font-weight:600;color:var(--text)}
.policy-3r{counter-reset:r}
.policy-cta{
  display:flex;flex-wrap:wrap;gap:1rem;align-items:center;
  padding-top:6px;
}
.policy-cta .hint{flex:1 1 100%;margin-bottom:.2rem}
@media (max-width:560px){
  .policy-block{padding:24px 20px}
  .policy-cta .btn{flex:1 1 100%;text-align:center}
}

/* ---- product grid ---- */
.prod-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:26px}
.prod-card{
  display:flex;flex-direction:column;text-align:left;cursor:pointer;
  background:var(--card-solid);border:1px solid var(--line);padding:0;overflow:hidden;
  transition:transform .3s,border-color .3s,box-shadow .3s;
}
:root[data-theme="light"] .prod-card{border-color:transparent;box-shadow:var(--sh-1)}
.prod-card:hover{transform:translateY(-8px);border-color:var(--accent);box-shadow:var(--sh-2)}
/* product photography is shot on white, so the tile stays white
   in both themes rather than following a surface token */
.prod-img{
  position:relative;aspect-ratio:1;overflow:hidden;
  background:#FFFFFF;display:grid;place-items:center;
}
.prod-img img{width:100%;height:100%;object-fit:contain}
/* fallback when a product photo is missing — the logo art is
   white, so it has to be inverted to show on the white tile */
.prod-img img.ph{width:52%;height:auto;object-fit:contain;opacity:.32;filter:invert(1) brightness(.2)}
.prod-tag{
  position:absolute;top:12px;left:12px;z-index:2;
  font-family:var(--display);font-weight:800;font-size:.6rem;
  text-transform:uppercase;letter-spacing:.18em;
  background:var(--amber);color:var(--on-amber);padding:.35rem .8rem;
}
.prod-info{padding:24px 22px 26px;display:grid;gap:8px}
.prod-info h3{font-size:1.05rem;line-height:1.25}
.prod-info .sub{font-weight:300;font-size:.88rem;color:var(--muted)}
.prod-price{font-family:var(--display);font-weight:900;font-size:1.5rem;color:var(--accent)}
.prod-price .was{font-size:.62em;font-weight:700;color:var(--muted);text-decoration:line-through;margin-right:.4rem}
.prod-price .now{color:inherit}
/* "Save ₱X" deal chip — an amber FILL (not amber text) so it reads
   at a glance and stays legible in light mode, same as .prod-tag.
   Shared by the grid card, the product modal and the homepage cards. */
.save-chip{
  display:inline-block;vertical-align:.16em;
  font-family:var(--display);font-weight:800;font-size:.5em;
  text-transform:uppercase;letter-spacing:.1em;
  background:var(--amber);color:var(--on-amber);
  padding:.32em .62em;margin-left:.5rem;white-space:nowrap;
}
.drop-price .now{color:inherit}

/* ---- product modal ---- */
/* visibility:hidden — see the note on .popup-overlay. This one also
   carries aria-hidden="true" while closed, and aria-hidden over
   focusable children is an outright ARIA violation, so the two have
   to agree. */
.modal-overlay{
  position:fixed;inset:0;z-index:1000;display:grid;place-items:center;padding:20px;
  background:rgba(10,4,7,.84);backdrop-filter:blur(6px);
  opacity:0;pointer-events:none;visibility:hidden;
  transition:opacity .3s,visibility 0s linear .3s;
}
:root[data-theme="light"] .modal-overlay{background:rgba(26,18,22,.44)}
.modal-overlay.show{opacity:1;pointer-events:auto;visibility:visible;transition:opacity .3s,visibility 0s}
.modal-card{
  position:relative;width:min(880px,100%);max-height:92vh;overflow-y:auto;
  background:var(--card-solid);border:1px solid var(--line);box-shadow:var(--sh-2);
  display:grid;grid-template-columns:1fr 1fr;
}
.modal-card > .prod-img{aspect-ratio:auto;min-height:100%}
.modal-body{padding:36px 34px 34px;display:grid;gap:14px;align-content:start}
.modal-body h2{font-size:1.6rem;line-height:1.18}
.modal-close{
  position:absolute;top:12px;right:12px;z-index:3;width:34px;height:34px;
  background:var(--card-solid);border:1px solid var(--line);cursor:pointer;
  font-size:.95rem;line-height:1;transition:border-color .2s,color .2s;
}
.modal-close:hover{border-color:var(--accent);color:var(--accent)}

/* ---- size-guide link (in the product modal) ---- */
.size-guide-link{
  display:inline-flex;align-items:center;gap:.45rem;justify-self:start;
  background:none;border:none;cursor:pointer;padding:.1rem 0;
  font-family:var(--display);font-weight:700;font-size:.72rem;
  text-transform:uppercase;letter-spacing:.14em;color:var(--text);
  border-bottom:1px solid var(--amber);
}
.size-guide-link[hidden]{display:none}
.size-guide-link svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.size-guide-link:hover{color:var(--accent)}

/* ---- size-chart viewer (layers above the product modal) ---- */
.sizechart-overlay{z-index:1010}
.sizechart-card{
  position:relative;width:min(560px,100%);max-height:92vh;overflow-y:auto;
  background:var(--card-solid);border:1px solid var(--line);box-shadow:var(--sh-2);
  padding:16px;display:grid;gap:10px;justify-items:center;
}
/* the charts are black-on-white artwork — keep their white ground in
   both themes so they stay readable on the dark card */
.sizechart-card img{width:100%;height:auto;background:#fff}
.sizechart-card .hint{margin:0 0 2px;text-align:center}

.release-line{font-weight:300;font-size:.85rem;color:var(--muted)}
.desc{font-weight:300;font-size:.94rem;line-height:1.75;color:var(--muted)}
.opt-label{
  font-family:var(--display);font-weight:700;font-size:.62rem;
  text-transform:uppercase;letter-spacing:.22em;color:var(--muted);margin-bottom:9px;
}
.size-group{margin-top:4px}
.size-row{display:flex;flex-wrap:wrap;gap:8px}
.size-btn{
  min-width:50px;padding:.6rem .9rem;background:transparent;
  border:1px solid var(--line);cursor:pointer;
  font-family:var(--display);font-weight:800;font-size:.72rem;letter-spacing:.1em;
  transition:border-color .2s,background .2s,color .2s;
}
.size-btn:hover{border-color:var(--accent);color:var(--accent)}
.size-btn.sel{background:var(--amber);border-color:var(--amber);color:var(--on-amber)}
.qty-row{display:flex;align-items:center;gap:18px;margin-top:6px}
.qty-row .opt-label{margin-bottom:0}
.qty-stepper{display:inline-flex;align-items:center;border:1px solid var(--line)}
.qty-stepper button{
  width:36px;height:36px;background:transparent;border:0;cursor:pointer;
  font-size:1.05rem;line-height:1;transition:background .2s,color .2s;
}
.qty-stepper button:hover{background:var(--amber);color:var(--on-amber)}
.qty-val{min-width:38px;text-align:center;font-family:var(--display);font-weight:800;font-size:.9rem}
.modal-status{font-size:.85rem;color:#FF8A7A;min-height:1.1em}
:root[data-theme="light"] .modal-status{color:#B3261E}

/* ---- cart drawer ---- */
.drawer-overlay{
  position:fixed;inset:0;z-index:940;background:rgba(10,4,7,.7);backdrop-filter:blur(4px);
  opacity:0;pointer-events:none;transition:opacity .3s;
}
:root[data-theme="light"] .drawer-overlay{background:rgba(26,18,22,.38)}
.drawer-overlay.show{opacity:1;pointer-events:auto}
/* A drawer parked off-screen with transform is still ON the page:
   its Checkout link and every qty button stay in the tab order, so
   Tab would walk a keyboard visitor into a cart they can't see.
   visibility:hidden after the slide-out — see .popup-overlay. */
.cart-drawer{
  position:fixed;top:0;right:0;bottom:0;z-index:950;width:min(430px,100%);
  background:var(--card-solid);border-left:1px solid var(--line);
  display:flex;flex-direction:column;transform:translateX(102%);visibility:hidden;
  transition:transform .35s cubic-bezier(.2,.7,.2,1),visibility 0s linear .35s;
  box-shadow:var(--sh-2);
}
.cart-drawer.show{
  transform:none;visibility:visible;
  transition:transform .35s cubic-bezier(.2,.7,.2,1),visibility 0s;
}
.cart-head{display:flex;align-items:center;justify-content:space-between;padding:24px 24px 18px;border-bottom:1px solid var(--line)}
.cart-head h3{font-size:1.4rem}
.cart-head .modal-close{position:static}
.cart-items{flex:1;overflow-y:auto;padding:20px 24px;display:grid;gap:18px;align-content:start}
.cart-item{
  display:grid;grid-template-columns:74px 1fr auto;gap:14px;align-items:start;
  padding-bottom:18px;border-bottom:1px solid var(--line-soft);
}
.cart-item .prod-img{aspect-ratio:1}
.cart-item h4{font-size:.84rem;line-height:1.3;margin-bottom:5px}
.cart-item .meta{font-weight:300;font-size:.78rem;color:var(--muted);margin-bottom:9px}
.cart-item .qty-stepper button{width:28px;height:28px;font-size:.9rem}
.cart-item .qty-val{min-width:30px;font-size:.8rem}
.line-price{font-family:var(--display);font-weight:900;font-size:.98rem;text-align:right;color:var(--accent)}
/* The hit area, not the text, is what got bigger here. This measured
   38x20 — under the 24x24 WCAG 2.5.8 floor — on a control that
   destroys a cart line, sitting inside a drawer people use on a phone.
   The padding does the work and the negative margin absorbs it, so the
   type size and the visual alignment are unchanged. */
.cart-remove{
  display:block;margin-left:auto;margin-top:1px;margin-right:-6px;
  padding:8px 6px;background:none;border:0;cursor:pointer;
  min-height:24px;
  font-weight:300;font-size:.74rem;color:var(--muted);text-decoration:underline;text-underline-offset:2px;
}
.cart-remove:hover{color:var(--accent)}
.cart-empty{text-align:center;font-weight:300;color:var(--muted);padding:46px 0;line-height:1.8}
.cart-foot{padding:20px 24px 24px;border-top:1px solid var(--line);display:grid;gap:14px}
.cart-total-row{display:flex;justify-content:space-between;align-items:baseline;
  font-family:var(--display);font-weight:800;font-size:.76rem;text-transform:uppercase;letter-spacing:.2em}
.cart-total-row .amt{font-size:1.6rem;letter-spacing:0;color:var(--accent)}
.cart-foot .btn{width:100%}
.cart-note{font-weight:300;font-size:.74rem;line-height:1.6;color:var(--muted)}

/* ---- checkout ---- */
.steps{display:flex;flex-wrap:wrap;gap:10px;justify-content:center;margin-bottom:36px}
.step-dot{
  font-family:var(--display);font-weight:800;font-size:.64rem;
  text-transform:uppercase;letter-spacing:.18em;padding:.6rem 1.2rem;
  border:1px solid var(--line);color:var(--muted);
}
.step-dot.on{background:var(--amber);border-color:var(--amber);color:var(--on-amber)}
.step-dot.done{border-color:var(--accent);color:var(--accent)}
/* The "Cart on hold 15:00" strip that used to sit here between the
   step dots and the card was deleted in the August 2026 CRO pass,
   along with its .co-timer / .ct-dot / ctPulse rules. It claimed a
   hold that never existed and it ran while buyers were away in
   GCash. Don't rebuild it — the reasoning is in full at the top of
   checkout.html and in assets/js/pages/checkout.js. */
/* The two ways out of the "still thinking?" nudge. Stacked, not
   side by side: the card's content box is 484px, and two buttons
   with these labels wrap to two lines each at that width. */
.hold-actions{display:flex;flex-direction:column;gap:.7rem}
.hold-actions .btn{width:100%}

.co-panel{display:none}
.co-panel.show{display:block;animation:fadeUp .45s ease both}
@keyframes fadeUp{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}
.co-card{
  max-width:760px;margin:0 auto;background:var(--card-solid);
  border:1px solid var(--line);padding:36px 34px;box-shadow:var(--sh-1);
}
:root[data-theme="light"] .co-card{border-color:transparent}
.co-actions{display:flex;flex-wrap:wrap;gap:14px;justify-content:space-between;align-items:center;margin-top:26px}
.co-back{
  background:none;border:0;cursor:pointer;font-weight:300;font-size:.88rem;color:var(--muted);
  text-decoration:underline;text-underline-offset:3px;
}
.co-back:hover{color:var(--accent)}

.fulfill-row{display:grid;gap:12px;margin-bottom:24px}
.fulfill-opt{
  display:grid;grid-template-columns:1fr auto;gap:12px;align-items:center;cursor:pointer;
  border:1px solid var(--line);padding:16px 18px;transition:border-color .2s,background .2s;
}
.fulfill-opt:hover{border-color:var(--accent)}
.fulfill-opt.sel{border-color:var(--accent);background:color-mix(in srgb,var(--amber) 12%,transparent)}
.fulfill-opt input{position:absolute;opacity:0;pointer-events:none}
.fo-body{display:grid;gap:4px}
.fo-title{font-family:var(--display);font-weight:800;font-size:.8rem;text-transform:uppercase;letter-spacing:.12em}
.fo-sub{font-weight:300;font-size:.8rem;color:var(--muted);line-height:1.55}
.fo-sub a{color:var(--accent);text-decoration:underline;text-underline-offset:2px}
.fo-price{font-family:var(--display);font-weight:900;font-size:1.05rem;color:var(--accent)}

.sum-lines{display:grid;gap:9px;margin-top:22px;padding-top:18px;border-top:1px solid var(--line)}
.sum-line{display:flex;justify-content:space-between;font-weight:300;font-size:.92rem;color:var(--muted)}
.sum-line.total{
  font-family:var(--display);font-weight:800;font-size:.8rem;text-transform:uppercase;
  letter-spacing:.2em;color:var(--text);padding-top:11px;border-top:1px solid var(--line);
}
.sum-line.total .amt{font-size:1.55rem;letter-spacing:0;color:var(--accent)}

.qr-box{display:grid;gap:20px;justify-items:center;margin:26px 0}
.qr-frame{
  width:min(280px,72vw);aspect-ratio:1;display:grid;place-items:center;
  background:#fff;border:2px solid var(--amber);padding:14px;
}
.qr-frame img{width:100%;height:100%;object-fit:contain}
.qr-missing{
  font-family:var(--display);font-weight:800;font-size:.72rem;text-transform:uppercase;
  letter-spacing:.14em;color:#6E4800;text-align:center;line-height:1.7;
}
.pay-amount{color:var(--accent)}
.wallet-row{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;margin-top:10px}
.wallet-chip{
  font-family:var(--display);font-weight:700;font-size:.6rem;text-transform:uppercase;
  letter-spacing:.16em;border:1px solid var(--line);padding:.32rem .7rem;color:var(--muted);
}
/* ---- the name reconciliation under the QR ----
   Quiet by design. It is reassurance, not a warning: styling it like
   an alert would create the doubt it exists to remove. */
.payee-note{
  margin:.5rem auto 0;max-width:34ch;
  font-weight:300;font-size:.78rem;line-height:1.55;color:var(--muted);
}
.payee-note b.hl{font-weight:600;letter-spacing:.04em;color:var(--accent)}
:root[data-theme="light"] .payee-note b.hl{color:var(--text)}

/* ---- "Save QR to my phone" ----
   The primary action on a phone: you cannot scan a QR with the same
   screen that is showing it, so this is how a mobile buyer pays at
   all. Full width so it is unmissable under the code. */
.qr-save{margin-top:1.1rem;width:min(280px,72vw)}

/* ---- tap-to-copy total inside the pay instructions ----
   Inline, so it reads as part of the sentence rather than a control
   bolted next to it. Dashed underline = "this does something",
   without borrowing the look of a link that navigates away. */
.pay-copy{
  display:inline-flex;align-items:center;gap:.35em;
  cursor:pointer;color:var(--accent);
  border-bottom:1px dashed color-mix(in srgb,var(--accent) 55%,transparent);
  /* a comfortable tap area without disturbing the line box */
  padding:.15em .1em;
}
:root[data-theme="light"] .pay-copy{color:var(--text);border-bottom-color:var(--line)}
.pay-copy:hover{border-bottom-style:solid}
.pay-copy-ic{font-size:.85em;opacity:.75}
/* success reuses the site's existing .form-status.ok convention —
   accent in dark, --text in light — rather than introducing a green
   that appears nowhere else in the palette (and that would fail on
   light's near-white at this size) */
.pay-copy.copied{color:var(--accent);border-bottom-color:transparent}
:root[data-theme="light"] .pay-copy.copied{color:var(--text)}
.pay-copy.copy-fail{color:var(--muted)}
/* the glyph flips ⧉ → ✓ as well as changing colour, so the
   confirmation never depends on colour alone */
.pay-copy.copied .pay-copy-ic{opacity:1}

.pay-list{margin:22px 0 0;padding-left:1.3rem;display:grid;gap:9px;font-weight:300;font-size:.92rem;color:var(--muted);line-height:1.65}
.pay-list b{font-weight:600;color:var(--text)}
/* trust + preorder-timeline strip on the pay step */
.pay-reassure{
  margin-top:1.5rem;padding-top:1.2rem;border-top:1px solid var(--line-soft);
  display:grid;gap:.55rem;font-weight:300;font-size:.84rem;line-height:1.55;color:var(--muted);
}
.pay-reassure b{font-weight:600;color:var(--text)}
.pay-reassure b.hl{color:var(--accent)}
/* the release date is information in light mode, not branding — keep it legible */
:root[data-theme="light"] .pay-reassure b.hl{color:var(--text)}

.pickup-card{display:grid;gap:5px;border:1px solid var(--accent);padding:18px 20px;background:color-mix(in srgb,var(--amber) 10%,transparent)}
.pc-name{font-family:var(--display);font-weight:800;font-size:.86rem;text-transform:uppercase;letter-spacing:.12em}
.pc-addr{font-weight:300;font-size:.86rem;color:var(--muted)}
.pc-note{font-weight:300;font-size:.8rem;color:var(--muted);margin-top:5px;line-height:1.6}
.pickup-card a{color:var(--accent);font-size:.84rem;text-decoration:underline;text-underline-offset:3px}

.upload-box{
  position:relative;
  border:1px dashed var(--line);padding:28px 20px;text-align:center;cursor:pointer;
  transition:border-color .2s,background .2s;
}
.upload-box:hover,.upload-box.drag{border-color:var(--accent);background:color-mix(in srgb,var(--amber) 8%,transparent)}
/* ⚠️ NOT display:none. The receipt upload is a REQUIRED step of a
   real purchase, and a display:none input can't be focused — with the
   dashed box being a plain <div>, that left no way at all to attach a
   receipt with a keyboard. Hidden-but-focusable instead: the input
   still takes Tab (Enter/Space opens the file picker), and
   :focus-within lights the whole box so the focus is visible.
   pointer-events:none keeps a mouse click from hitting the input and
   re-triggering the box's own click → fileInput.click() handler. */
.upload-box input[type=file]{
  position:absolute;width:1px;height:1px;opacity:0;pointer-events:none;
  inset-inline-start:0;inset-block-start:0;
}
.upload-box:focus-within{
  outline:3px solid var(--accent);outline-offset:3px;
  border-color:var(--accent);background:color-mix(in srgb,var(--amber) 8%,transparent);
}
.up-title{font-family:var(--display);font-weight:800;font-size:.82rem;text-transform:uppercase;letter-spacing:.14em;margin-bottom:6px}
.upload-box p{font-weight:300;font-size:.8rem;color:var(--muted)}
.upload-box img{max-height:210px;width:auto;margin:0 auto 10px;border:1px solid var(--line)}

/* ---- order confirmed ---- */
.confirm-wrap{display:grid;place-items:center}
.confirm-card{
  max-width:720px;text-align:center;background:var(--card-solid);
  border:1px solid var(--line);padding:52px 40px 46px;box-shadow:var(--sh-1);
}
:root[data-theme="light"] .confirm-card{border-color:transparent}
.confirm-card h1{font-size:clamp(2.4rem,5.6vw,3.8rem)}
.order-no{
  display:inline-block;margin:22px 0 30px;padding:.9rem 2rem;
  background:var(--amber);color:var(--on-amber);
  font-family:var(--display);font-weight:900;font-size:1.5rem;letter-spacing:.1em;
}
.next-steps{display:grid;gap:18px;text-align:left;margin-top:8px}
.next-step{display:grid;grid-template-columns:auto 1fr;gap:16px;align-items:start}
.next-step .n{
  width:34px;height:34px;flex:none;display:grid;place-items:center;
  border:1px solid var(--accent);color:var(--accent);
  font-family:var(--display);font-weight:900;font-size:.86rem;
}
.next-step p{font-weight:300;font-size:.94rem;line-height:1.7;color:var(--muted)}
.next-step p b{font-weight:600;color:var(--text)}

/* ============================================================
   LIGHT MODE — KEEPING THE BRAND YELLOW LEGIBLE
   ------------------------------------------------------------
   --accent is the real brand yellow #FFBF00 in BOTH themes, so
   the site never goes gold/brown. On white that's only ~1.7:1,
   which is fine for the huge display type (a 60px+ yellow
   headline reads as a deliberate brand mark) but unreadable at
   label size.

   So in light mode, small yellow text flips to the same yellow
   as a FILL with near-black text on top — still 100% #FFBF00,
   now at 11.8:1. Numbers people actually have to read (prices,
   totals) go near-black; they're information, not branding.
============================================================ */
:root[data-theme="light"] .eyebrow,
:root[data-theme="light"] .ep-num,
:root[data-theme="light"] .host-role,
:root[data-theme="light"] .story-quote .sig,
:root[data-theme="light"] .drop-kind,
:root[data-theme="light"] .live-dot,
:root[data-theme="light"] .pill-live{
  background:var(--amber);color:var(--on-amber);
  border-color:var(--amber);
  padding:.34rem .8rem;border-radius:3px;
}
/* block-level ones have to hug their text to read as a chip */
:root[data-theme="light"] .eyebrow,
:root[data-theme="light"] .ep-num,
:root[data-theme="light"] .host-role,
:root[data-theme="light"] .story-quote .sig,
:root[data-theme="light"] .drop-kind{
  display:inline-block;width:auto;justify-self:start;
}
:root[data-theme="light"] .live-dot::before{background:var(--on-amber)}
:root[data-theme="light"] .pill-live{border-radius:100px;padding:.5rem 1.1rem}

/* outline-on-white disappears at 1px of yellow — go solid instead */
:root[data-theme="light"] .btn-mini,
:root[data-theme="light"] .band .btn-mini{
  background:var(--amber);border-color:var(--amber);color:var(--on-amber);
}
:root[data-theme="light"] .btn-mini:hover,
:root[data-theme="light"] .band .btn-mini:hover{background:var(--accent-2);border-color:var(--accent-2)}

/* figures are information, not branding — these must be readable */
:root[data-theme="light"] .prod-price,
:root[data-theme="light"] .line-price,
:root[data-theme="light"] .drop-price,
:root[data-theme="light"] .cart-total-row .amt,
:root[data-theme="light"] .sum-line.total .amt,
:root[data-theme="light"] .fo-price,
:root[data-theme="light"] .pay-amount,
:root[data-theme="light"] .form .req{color:var(--text)}

/* small inline .hl inside body copy would vanish — only the big
   display headings keep raw yellow text */
:root[data-theme="light"] .promo-kicker,
:root[data-theme="light"] .copyright .hl,
:root[data-theme="light"] .next-step .hl,
:root[data-theme="light"] .store-head p .hl,
:root[data-theme="light"] .cart-note b,
:root[data-theme="light"] .fo-sub a,
:root[data-theme="light"] .pickup-card a,
:root[data-theme="light"] .next-step a{color:var(--text)}

/* hairline borders that were amber need a neutral in light */
:root[data-theme="light"] .next-step .n{border-color:var(--line);color:var(--text)}
:root[data-theme="light"] .step-dot.done{border-color:var(--line);color:var(--muted)}
:root[data-theme="light"] .pickup-card{border-color:var(--line)}
:root[data-theme="light"] .fulfill-opt.sel{border-color:var(--amber)}
:root[data-theme="light"] .form-done{border-color:var(--amber)}
:root[data-theme="light"] .form-done .big{color:var(--text)}
:root[data-theme="light"] .form-status.ok{color:var(--text)}
:root[data-theme="light"] .icon-btn:hover,
:root[data-theme="light"] .modal-close:hover,
:root[data-theme="light"] .popup-close:hover,
:root[data-theme="light"] .size-btn:hover{border-color:var(--text);color:var(--text)}
:root[data-theme="light"] .nav-links a.active{color:var(--text)}
:root[data-theme="light"] .foot-nav a:hover,
:root[data-theme="light"] .cart-remove:hover,
:root[data-theme="light"] .co-back:hover,
:root[data-theme="light"] .popup-dismiss:hover,
:root[data-theme="light"] .contact-mail:hover,
:root[data-theme="light"] .dotnav a::before{color:var(--text)}

/* ============ RESPONSIVE ============ */
@media (max-width:1080px){
  .story{grid-template-columns:1fr;gap:36px}
  .contact-grid{grid-template-columns:1fr;gap:44px}
  .drop{grid-template-columns:1fr;gap:30px}
  .dotnav{display:none}
}
@media (max-width:900px){
  /* ⚠️ The top offset MUST include --anno-h, not just --nav-h. This panel
     is position:fixed, so its top is measured from the VIEWPORT, while the
     navbar itself starts at --anno-h (below the announcement bar). Using
     --nav-h alone put the panel 40px too high on the one page that has an
     announcement bar — the homepage — and because the panel is collapsed to
     max-height:0 the only thing that rendered was its 1px border-bottom:
     a hairline straight across the middle of the navbar, cutting through the
     logo and the burger. It looked like a stray rule, not a menu.
     The toggle survived it only because .theme-toggle is position:relative
     and so paints above the panel, while the static logo and burger paint
     under it — which is exactly how the bug was reported.
     Store pages never showed it because they have no announcement bar, so
     --anno-h is 0 there and the two expressions happen to agree.
     Dismissing the bar sets --anno-h to 0px live; this follows it. */
  /* ⚠️ A CLOSED MENU MUST PAINT NOTHING. `max-height:0` + `overflow:hidden`
     collapses the CONTENT box only — padding and border-width are outside it
     and still render, so a "collapsed" panel carrying `padding:14px 6%` and a
     1px border was a 29px opaque strip (maroon --card-solid in dark, white in
     light) permanently laid across the top of the page, covering whatever
     scrolled under it. It read as a stray rule under the navbar rather than as
     a menu, and it was worst with the announcement bar open because the whole
     stack sits that much lower over the content.
     So padding and border-width are 0 in the closed state and only appear on
     .nav-open; both are animatable, so the panel still slides rather than
     snapping. Do NOT put padding back on the base rule.
     The navbar keeps its own separator — `.nav.solid` once scrolled, and
     `.nav-min` on store pages — so nothing is lost visually by this. */
  .nav-links{
    position:fixed;inset:calc(var(--anno-h) + var(--nav-h)) 0 auto 0;flex-direction:column;gap:0;
    background:var(--card-solid);border-bottom:0 solid var(--line);
    padding:0 6%;max-height:0;overflow:hidden;
    transition:max-height .35s,padding .35s,border-bottom-width .35s;
  }
  body.nav-open .nav-links{max-height:70vh;padding:20px 6% 26px;border-bottom-width:1px}
  .nav-links li{width:100%}
  .nav-links a{display:block;padding:.85rem 0;font-size:.82rem;border-bottom:1px solid var(--line-soft)}
  .nav-links a::after{display:none}
  .nav-links a.btn{margin-top:14px;justify-content:center;border-bottom:2px solid var(--amber)}
  .burger{display:block}
  .modal-card{grid-template-columns:1fr}
  .modal-card > .prod-img{aspect-ratio:16/10;min-height:0}
}
@media (max-width:640px){
  .sec{padding:76px 0}
  .sec-head{margin-bottom:40px}
  .form-row{grid-template-columns:1fr}
  .co-card,.confirm-card,.popup-card{padding:28px 22px}
  .hosts{margin-top:140px}
  .host-photo{height:210px}
  .host-body{padding:22px 22px 26px}
  .foot-nav{gap:1.1rem}
  .drop-item{grid-template-columns:76px 1fr;gap:14px}
  .drop-go{grid-column:1/-1;padding:.85rem .6rem 1.2rem;min-width:0}
}
