/* preserved from the artifact runtime shell - load-bearing: without it,
   [hidden] mains (e.g. the Product view) would render under Home, since
   the author rule main[data-view]{display:block;} below would otherwise
   beat the browser's default [hidden]{display:none}. */
[hidden]:not([hidden=until-found]){display:none!important}

  :root{
    color-scheme: light;
    --paper:#fffbf5;
    --cream:#ffe7c2;
    --amber:#ffbd59;
    --cocoa:#7a4900;
    --umber:#8e6426;
    --ink:#4b3e2b;
    --ink-soft:#6f5d45;
    --sw-mustard:#ffbd59; --sw-cocoa:#7a4900; --sw-grape:#7b68d9;
    --sw-lagoon:#5fa8c4; --sw-sage:#93b06f; --sw-ink:#2f2a24; --sw-cream:#fffbf5;
    --line: rgba(75,62,43,.14);
    --line-strong: rgba(75,62,43,.30);
    --surface: radial-gradient(circle at 38% 28%, #ded0b8, #c3ad8c);
    --shadow-card: 0 26px 50px -30px rgba(74,57,20,.45);
    --shadow-soft: 0 14px 30px -18px rgba(74,57,20,.32);
    --radius-l:22px; --radius-m:16px; --radius-s:10px; --radius-pill:999px;
    --maxw:1240px;
  }
  *{box-sizing:border-box;}
  /* Deliberately NOT scroll-behavior:smooth. Every pinned/sticky effect on
     this page (the hero object, keychain wall, beat sequences) reads the
     scroll position directly every animation frame and expects it to track
     the input device 1:1 - smooth-scroll's animated catch-up fights that.
     It also measurably stalls out once three WebGL scenes are running
     their own requestAnimationFrame loops simultaneously: the smooth-scroll
     animation starves on the saturated main thread and scrolling can stop
     responding almost entirely. */
  html{scroll-behavior:auto;}
  body{margin:0;background:var(--paper);color:var(--ink);font-family:'Figtree',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;font-size:16px;line-height:1.62;-webkit-font-smoothing:antialiased;}
  h1,h2,h3{font-family:'Anton','Arial Narrow',sans-serif;font-weight:400;text-transform:uppercase;letter-spacing:.015em;line-height:1;text-wrap:balance;margin:0;color:var(--ink);}
  p{margin:0;}
  a{color:inherit;text-decoration:none;}
  button{font-family:inherit;cursor:pointer;background:none;border:none;color:inherit;}
  img,svg{display:block;max-width:100%;}
  a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible{outline:2px solid var(--cocoa);outline-offset:3px;border-radius:4px;}
  [hidden]{display:none!important;}

  .eyebrow{font-family:'Figtree',sans-serif;font-weight:700;font-size:.72rem;text-transform:uppercase;letter-spacing:.24em;color:var(--umber);}
  .on-dark .eyebrow{color:var(--amber);}
  .wrap{max-width:var(--maxw);margin:0 auto;padding-inline:clamp(1.5rem,4.5vw,3.5rem);}

  /* ---------- buttons ---------- */
  .btn{display:inline-flex;align-items:center;gap:.55rem;font-weight:600;font-size:.95rem;letter-spacing:.01em;padding:.85rem 1.65rem;border-radius:var(--radius-pill);white-space:nowrap;transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease;}
  @media (prefers-reduced-motion:reduce){.btn{transition:none;}}
  .btn-primary{background:var(--amber);color:var(--ink);box-shadow:var(--shadow-soft);}
  .btn-primary:hover{transform:translateY(-2px);}
  .btn-ghost{border:1.5px solid var(--line-strong);color:var(--ink);}
  .btn-ghost:hover{border-color:var(--ink);}
  .btn-ghost.on-dark{border-color:rgba(255,251,245,.4);color:var(--paper);}
  .btn-ghost.on-dark:hover{border-color:var(--paper);}

  /* ---------- nav (refined lockup, thin rule, underline active state) ---------- */
  /* fixed (not sticky) so it floats OVER the hero — including the full-bleed
     video, which now reaches all the way to the top of the page behind it. */
  .site-nav{position:fixed;top:0;left:0;width:100%;z-index:40;background:rgba(255,251,245,.92);backdrop-filter:blur(8px);border-bottom:1px solid var(--line);transition:transform .32s ease,background-color .32s ease,border-color .32s ease;}
  /* Home's hero is meant to run full-bleed under the fixed header, so it gets
     no offset; every other view needs room so its own content starts below it. */
  main[data-view="products"],main[data-view="product"]{padding-top:var(--nav-h,88px);}
  @media (prefers-reduced-motion:reduce){.site-nav{transition:none;}}
  .site-nav.nav-hidden{transform:translateY(-100%);}
  .site-nav.nav-on-video{background:transparent;backdrop-filter:none;border-bottom-color:transparent;}
  .site-nav.nav-on-video .wordmark{color:var(--paper);}
  .site-nav.nav-on-video .tagline{color:var(--cream);opacity:.9;}
  .site-nav.nav-on-video .nav-links a{color:var(--paper);}
  .site-nav.nav-on-video .nav-links a:hover{border-color:rgba(255,251,245,.5);}
  .site-nav.nav-on-video .nav-links a.active{border-color:var(--amber);}
  /* thin overall-page scroll indicator, sits on the header's own bottom edge */
  .scroll-progress{position:absolute;left:0;right:0;bottom:-2px;height:2px;background:rgba(75,62,43,.12);}
  .site-nav.nav-on-video .scroll-progress{background:rgba(255,251,245,.25);}
  .scroll-progress span{display:block;height:100%;width:0%;background:var(--amber);}
  @media (prefers-reduced-motion:no-preference){.scroll-progress span{transition:width .1s linear;}}
  .nav-bar{display:flex;align-items:flex-end;justify-content:space-between;gap:2rem;padding:1.6rem clamp(1.5rem,4.5vw,3.5rem);}
  .brand-lockup{display:block;}
  .brand-lockup .wordmark{font-family:'Anton',sans-serif;font-size:clamp(1.35rem,2.1vw,1.7rem);letter-spacing:.03em;display:block;}
  .brand-lockup .tagline{font-family:'Figtree',sans-serif;font-weight:700;font-size:.62rem;letter-spacing:.34em;color:var(--umber);opacity:.85;margin-top:.18rem;display:block;}
  .nav-right{display:flex;align-items:center;gap:2.2rem;}
  .nav-links{display:flex;gap:2rem;font-weight:600;font-size:.95rem;}
  .nav-links a{padding-bottom:.35rem;border-bottom:2px solid transparent;cursor:pointer;}
  .nav-links a:hover{border-color:var(--line-strong);}
  .nav-links a.active{border-color:var(--amber);}
  @media (max-width:760px){.nav-links{display:none;}}

  /* ---------- shared: product stand-ins (kept — this technique reads well already) ---------- */
  .keychain-shape{position:relative;display:inline-flex;align-items:center;padding:.4rem .2rem;}
  .kc-ring{width:1.4em;height:1.4em;border-radius:50%;border:.28em solid var(--kc-base,var(--cocoa));margin-right:-.5em;flex:none;background:transparent;}
  .kc-text{font-family:'Anton',sans-serif;font-size:2.2rem;color:var(--kc-wording,var(--cocoa));-webkit-text-stroke:3px var(--kc-base,var(--cream));paint-order:stroke fill;text-shadow:0 2px 0 rgba(74,57,20,.15),0 8px 14px rgba(74,57,20,.28);white-space:nowrap;}
  .kc-text.font-chunky{-webkit-text-stroke-width:7px;}
  .kc-text.font-condensed{transform:scaleX(.74);transform-origin:left center;}
  .figure-shape{position:relative;width:88px;height:118px;}
  .figure-silhouette{position:absolute;inset:0;background:var(--fig-finish,var(--sw-grape));clip-path:polygon(50% 0%,70% 9%,79% 28%,69% 40%,86% 54%,92% 100%,8% 100%,14% 54%,31% 40%,21% 28%,30% 9%);}
  .figure-shade{position:absolute;inset:0;background:rgba(47,42,36,.18);clip-path:polygon(50% 0%,70% 9%,79% 28%,69% 40%,86% 54%,92% 100%,50% 100%);}
  .figure-highlight{position:absolute;inset:0;background:rgba(255,251,245,.30);clip-path:polygon(50% 0%,30% 9%,21% 28%,31% 40%,14% 54%,8% 62%,40% 30%);}
  .calendar-shape{width:132px;border-radius:10px;overflow:hidden;box-shadow:var(--shadow-soft);}
  .cal-head{background:var(--cal-base,var(--sw-lagoon));color:var(--paper);font-weight:800;font-size:.7rem;letter-spacing:.12em;text-transform:uppercase;text-align:center;padding:.4rem 0;}
  .cal-body{background:var(--paper);padding:.5rem .6rem .7rem;}
  .cal-numeral{font-family:'Anton',sans-serif;font-size:2.6rem;line-height:1;color:var(--paper);-webkit-text-stroke:2.5px var(--cal-base,var(--sw-lagoon));paint-order:stroke fill;text-align:center;display:block;}
  .cal-msg{margin-top:.35rem;font-size:.62rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--ink);text-align:center;overflow-wrap:anywhere;}
  .nfc-shape{position:relative;width:150px;height:92px;border-radius:18px;background:var(--nfc-colour,var(--sw-ink));box-shadow:var(--shadow-soft);display:flex;align-items:center;justify-content:center;}
  .nfc-shape.type-tag{width:100px;height:100px;border-radius:24px;}
  .nfc-shape.type-stand{margin-bottom:14px;}
  .nfc-shape.type-stand::after{content:"";position:absolute;left:14%;right:14%;bottom:-14px;height:14px;background:var(--ink);clip-path:polygon(8% 0,92% 0,100% 100%,0% 100%);border-radius:0 0 4px 4px;}
  .nfc-chip{position:absolute;top:10px;left:12px;width:16px;height:12px;border-radius:3px;background:rgba(255,251,245,.85);}
  .nfc-wave{color:var(--paper);width:44px;height:44px;}

  .stage-surface{background:var(--surface);border-radius:var(--radius-l);display:grid;place-items:center;min-height:280px;padding:2.4rem;box-shadow:var(--shadow-card);}

  /* ---------- routed views ---------- */
  main[data-view]{display:block;}
  .reveal{opacity:1;transform:none;filter:none;}
  @media (prefers-reduced-motion:no-preference){
    .reveal{opacity:0;transform:translateY(22px);filter:blur(9px);transition:opacity 1s ease,transform 1s ease,filter 1s ease;}
    .reveal.in{opacity:1;transform:none;filter:blur(0);}
  }

  /* ================= HOME ================= */
  /* hero is centred, text-first, and fully sharp at rest — the blur/soft-focus
     language (borrowed from poetry.camera's scroll-resolve type) is reserved
     for what scrolls in *after* it, never for the first-frame content itself. */
  /* hero is now a genuine full-bleed video hero: the clip is the section's own
     background (behind a scrim for legibility), not a separate card beneath it. */
  /* fixed (not in normal flow) so it stays put as a backdrop while the next
     section — the story-chapter "card" — scrolls up over it. A same-height
     spacer right after it (see .hero-spacer) holds open the scroll room this
     reveal needs, since a fixed element no longer occupies flow space. */
  .home-hero{
    position:fixed;top:0;left:0;width:100%;z-index:0;overflow:hidden;display:flex;align-items:center;
    height:100vh;height:100svh;overflow-y:auto;
    padding-block:clamp(6.5rem,14vw,9.5rem) clamp(3rem,7vw,5rem);text-align:center;
  }
  .hero-spacer{height:100vh;height:100svh;}
  .hero-bg{position:absolute;inset:0;z-index:0;}
  .hero-video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;background:var(--ink);}
  .hero-video-fallback{position:absolute;inset:0;display:grid;place-items:center;background:var(--surface);transition:opacity .6s ease;}
  @media (prefers-reduced-motion:reduce){.hero-video-fallback{transition:none;}}
  .hero-video-fallback.is-hidden{opacity:0;pointer-events:none;}
  .hero-scrim{position:absolute;inset:0;background:linear-gradient(185deg,rgba(42,32,24,.62) 0%,rgba(42,32,24,.4) 45%,rgba(42,32,24,.7) 100%);}
  .hero-cycle{position:absolute;inset:0;display:grid;place-items:center;opacity:0;}
  .home-hero .hero-inner{position:relative;z-index:2;max-width:820px;margin-inline:auto;}
  .home-hero .eyebrow{color:var(--amber);}
  .home-hero h1{color:var(--paper);font-size:clamp(2.6rem,6.2vw,5rem);margin-top:1.2rem;}
  .home-hero .poem-line{margin-top:1.4rem;font-family:'Figtree',sans-serif;font-style:italic;font-weight:600;font-size:1.18rem;color:var(--cream);max-width:42ch;margin-inline:auto;}
  .home-hero .hero-sub{margin-top:1.3rem;max-width:52ch;margin-inline:auto;font-size:1.05rem;color:rgba(255,251,245,.82);font-weight:500;}
  .hero-ctas{display:flex;flex-wrap:wrap;gap:.9rem;margin-top:2.2rem;justify-content:center;}
  .scroll-cue{position:absolute;left:50%;bottom:1.8rem;transform:translateX(-50%);z-index:2;display:flex;flex-direction:column;align-items:center;gap:.4rem;color:rgba(255,251,245,.75);font-size:.7rem;font-weight:700;text-transform:uppercase;letter-spacing:.18em;}
  @media (prefers-reduced-motion:no-preference){.scroll-cue svg{animation:cue-bob 1.8s ease-in-out infinite;}}
  @keyframes cue-bob{0%,100%{transform:translateY(0);}50%{transform:translateY(6px);}}
  @media (prefers-reduced-motion:reduce){.scroll-cue{display:none;}}
  @media (prefers-reduced-motion:no-preference){
    .hero-cycle{animation:cycle 16s ease-in-out infinite;}
    .hero-cycle.c2{animation-delay:4s;}
    .hero-cycle.c3{animation-delay:8s;}
    .hero-cycle.c4{animation-delay:12s;}
  }
  @media (prefers-reduced-motion:reduce){.hero-cycle{opacity:0;}.hero-cycle.c1{opacity:1;}}
  @keyframes cycle{
    0%,3%{opacity:0;}
    6%,21%{opacity:1;}
    24%,100%{opacity:0;}
  }


  /* ---------- real spinning showcase: an actual print file, cloned into a
     drag-to-spin cloud (WebGL/three.js) — not a CSS stand-in like the rest
     of the site's product icons. ---------- */
  .spin-showcase{position:relative;z-index:1;overflow:hidden;border-bottom:1px solid var(--line);background:var(--cream);}
  .spin-showcase .wrap{position:relative;z-index:2;align-self:flex-start;margin-left:0;margin-right:0;padding-top:clamp(2.4rem,6vw,4rem);}
  .spin-showcase .wrap > .hero-sub{margin-top:1rem;max-width:56ch;}
  .spin-showcase h2{margin-top:.6rem;font-size:clamp(1.9rem,4vw,2.8rem);max-width:24ch;}
  .spin-viewport{position:absolute;inset:0;width:100%;height:100%;overflow:hidden;background:var(--cream);touch-action:none;cursor:grab;}
  .spin-viewport.grabbing{cursor:grabbing;}
  .spin-viewport canvas{display:block;width:100%;height:100%;}
  .spin-loading{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);font-size:.78rem;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-soft);}
  .spin-loading[hidden]{display:none;}
  .spin-hint{position:absolute;left:1.2rem;bottom:1.1rem;display:flex;align-items:center;gap:.5rem;font-size:.76rem;color:var(--ink-soft);background:rgba(255,251,245,.9);padding:.45rem .9rem;border-radius:var(--radius-pill);box-shadow:var(--shadow-soft);}

  /* only the flagship story/showcase moments still force a full screen —
     manifesto+teaser (the pinned-object chapter) and the 3D showcase. Everything
     else sizes to its own content with generous padding instead, so the page
     isn't longer to scroll than the content actually needs. */
  .manifesto,.teaser,.spin-showcase{
    min-height:100vh;
    min-height:100svh;
    display:flex;
    align-items:center;
  }
  .craft,.feature-band,.stat-strip,.close-cta{
    display:flex;
    align-items:center;
  }

  /* shared-background chapter: one continuous backdrop spans the manifesto,
     teaser and steps (no seam between them) — see .hero-block and
     .keychain-wall below for what's actually pinned inside it. */
  .story-chapter{position:relative;z-index:1;background:linear-gradient(180deg,var(--paper) 0%,var(--cream) 50%,var(--paper) 100%);border-bottom:1px solid var(--line);border-radius:32px 32px 0 0;box-shadow:0 -30px 60px -24px rgba(42,32,24,.35);}
  .chapter-slide{position:relative;z-index:1;}
  /* wraps just the two headline sections so the pinned 3D keychain below
     (.pin-object) is bounded to their combined height and releases exactly
     where #teaser-beats begins, instead of spanning the whole chapter. */
  .hero-block{position:relative;z-index:1;}
  /* the pinned waypoint object: position:sticky (not fixed) so it stays on
     screen for its containing .hero-block's whole scroll range without the
     stacking problems a raw position:fixed layer caused earlier — it
     auto-releases once .hero-block itself, its containing block, runs out
     of height. Fixed at the right gutter the whole time now (no more
     left/right slide - see the JS below: it spins to a front-facing rest
     pose by the time "Steps to customise..." begins, then freezes there in
     place rather than moving anywhere). Hidden below the width where that
     gutter gets too narrow to guarantee no overlap with the centred column.
     Right-anchored the same way as .keychain-wall/#wall-canvas below (same
     padding, same right edge) so the two line up, but WIDER than it - the
     zoom-and-tilt flourish (see the JS) needs more than 480px of horizontal
     room on each side of its centre or it clips its own canvas at peak
     zoom. The canvas itself is transparent with pointer-events:none, so
     the extra width harmlessly overlaps the text column next to it -
     nothing there becomes unclickable. js/hero-pin.js corrects the
     keychain's on-screen X position during its morph so it still lands
     exactly on the wall's column centre at the handoff, despite the wider
     box. */
  .pin-object{
    position:sticky;top:0;z-index:1;
    height:100vh;margin-bottom:-100vh;
    display:flex;align-items:center;justify-content:flex-end;
    padding-right:0;
    pointer-events:none;
  }
  @supports (height:100svh){
    .pin-object{height:100svh;margin-bottom:-100svh;}
  }
  #pin-canvas{width:min(900px,62vw);height:100%;display:block;will-change:transform,opacity;}
  @media (max-width:1150px){
    .pin-object{display:none;}
  }

  /* keychain-wall: replaces the old CSS-sprite parallax placeholder. Three
     columns of real 3D keychains (WebGL/three.js, same load technique as
     the spin showcase), endlessly looping vertically as you scroll — see
     the JS below. Sticky for the whole #teaser-beats range (like
     .pin-object is for .hero-block), sitting behind the crossfading step
     panels rather than inside any one of them, so it reads as one
     continuous backdrop across all four steps. Same right-gutter anchoring
     and hide-below-1150px convention as .pin-object. */
  .keychain-wall{
    position:sticky;top:0;z-index:0;
    height:100vh;margin-bottom:-100vh;
    display:flex;align-items:center;justify-content:flex-end;
    padding-right:0;
    pointer-events:none;
  }
  @supports (height:100svh){
    .keychain-wall{height:100svh;margin-bottom:-100svh;}
  }
  #wall-canvas{
    /* full sticky-container height, no aspect-ratio lock - the canvas's own
       top/bottom/right edges now ARE the viewport's edges, so a keychain
       going off-canvas means genuinely leaving the visible screen, not
       vanishing on a smaller floating rectangle sitting inside it (that
       floating box, ~560px tall inside an ~820px viewport, was itself the
       "invisible edge" items were disappearing at - no mask-fade fixes a
       box that's simply smaller than the screen). No mask needed now that
       the canvas edge is the screen edge. */
    width:min(480px,40vw);height:100%;display:block;
  }
  @media (max-width:1150px){
    .keychain-wall{display:none;}
  }

  .manifesto{padding-block:clamp(5rem,10vw,8rem);}
  .manifesto .wrap{max-width:860px;}
  .manifesto h2{font-size:clamp(2rem,4.6vw,3.2rem);}
  .manifesto p.lede{margin-top:1.4rem;max-width:58ch;font-size:1.1rem;color:var(--ink-soft);font-weight:500;}

  /* "same page trick": .page-hold is a tall wrapper; .page-hold-stage pins
     via position:sticky and stays fully opaque while its wrapper scrolls
     past beneath it, then fades in the final stretch (see JS, which reads
     each instance's own [data-hold] fraction) - same z-index convention as
     .chapter-slide so it stacks correctly with its story-chapter siblings. */
  .page-hold{position:relative;z-index:1;}
  .page-hold-stage{position:sticky;top:0;height:100vh;display:flex;align-items:center;overflow:hidden;}
  @supports (height:100svh){.page-hold-stage{height:100svh;}}
  .page-hold-stage .wrap{max-width:860px;}
  .page-hold-stage h2{font-size:clamp(2rem,4.6vw,3.2rem);}

  /* ---------- beat sequence (rotating-wheel pinned scroll) ----------
     A tall wrapper containing N beats, each an absolutely-positioned panel
     stacked at the exact same spot, mounted (conceptually) on the inside of
     a big drum the user "turns" by scrolling: every panel's lift/tilt/fade
     is a continuous function of live scroll position (set as inline styles
     by the JS below every scroll frame) rather than a threshold-triggered
     CSS transition, so the next beat is visibly rising into frame the whole
     time you scroll toward it - never a hard swap. A dot-rail at the bottom
     tracks whichever beat is nearest centre. */
  .beat-sequence{position:relative;}
  .beat-stage{position:sticky;top:0;height:100vh;overflow:hidden;display:flex;align-items:center;perspective:1400px;}
  @supports (height:100svh){.beat-stage{height:100svh;}}
  .beat-panel{
    position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;
    width:100%;max-width:var(--maxw);margin-inline:auto;padding-inline:clamp(1.5rem,4.5vw,3.5rem);
    opacity:0;pointer-events:none;will-change:transform,opacity;
  }
  /* transform/opacity come from JS as inline styles, updated every scroll
     frame - no transition here, or it would lag behind and fight the
     per-frame updates instead of scrubbing 1:1 with the scroll. */
  .beat-panel.is-active{opacity:1;pointer-events:auto;}
  .beat-panel .beat-ghost{
    position:absolute;left:clamp(1.5rem,4.5vw,3.5rem);top:50%;transform:translateY(-50%);
    font-family:'Anton',sans-serif;font-size:clamp(9rem,22vw,15rem);line-height:1;
    color:var(--line-strong);z-index:0;user-select:none;
  }
  .beat-panel h2{position:relative;z-index:1;font-size:clamp(2rem,4.6vw,3.2rem);max-width:14ch;}
  .beat-panel .beat-line{position:relative;z-index:1;margin-top:1.1rem;max-width:56ch;font-size:1.08rem;color:var(--ink-soft);font-weight:500;}
  .beat-rail{position:absolute;left:0;right:0;bottom:clamp(1.5rem,5vh,3rem);z-index:2;display:flex;align-items:center;justify-content:center;gap:.55rem;}
  .beat-dot{width:.5rem;height:.5rem;border-radius:50%;background:var(--line-strong);flex:none;}
  @media (prefers-reduced-motion:no-preference){.beat-dot{transition:background .3s ease,transform .3s ease;}}
  .beat-dot.is-on{background:var(--cocoa);}
  .beat-dot.is-current{background:var(--amber);transform:scale(1.5);}
  .beat-track{width:2.2rem;height:1px;background:var(--line-strong);flex:none;}
  /* split variant: text beside a product stand-in, used by the teaser beats */
  /* steps 01-04: text, then its own mini-stage stacked below (not beside —
     the right-hand gutter now belongs to the shared .keychain-wall parallax
     behind these panels, not to each panel's own visual). The mini-stage
     itself is reshaped rectangular (wide, short) to read as a strip under
     the text rather than a square card. */
  .beat-panel--split .beat-split{position:relative;z-index:1;max-width:640px;}
  .beat-split-text .beat-link{margin-top:1.4rem;}
  .beat-split-visual{margin-top:1.6rem;}
  /* 01-03 have no "Start customising" button under their text, so their
     mini-stage sits much closer to the panel's big background numeral
     (vertically centered, partly behind the text) than 04's does - 04's
     button + its own margin already push things down and clear the
     numeral reasonably. Give 01-03 that same effective breathing room
     directly, so the mini-stage stops covering the numeral's lower half. */
  .beat-panel[data-beat="0"] .beat-split-visual,
  .beat-panel[data-beat="1"] .beat-split-visual,
  .beat-panel[data-beat="2"] .beat-split-visual{margin-top:5.5rem;}
  .beat-split-visual .mini-stage{background:var(--surface);border-radius:var(--radius-l);min-height:120px;width:100%;display:flex;align-items:center;justify-content:center;padding:1.4rem 1.8rem;box-shadow:var(--shadow-card);}

  .teaser{padding-block:clamp(3.5rem,7vw,5.5rem);}
  .teaser-grid{margin-top:2.6rem;display:grid;grid-template-columns:repeat(4,1fr);gap:1.4rem;}
  .teaser-tile{border:1px solid var(--line);border-radius:var(--radius-l);padding:1.6rem;display:flex;flex-direction:column;gap:1.1rem;box-shadow:var(--shadow-soft);transition:transform .2s ease,box-shadow .2s ease;}
  .teaser-tile:hover{transform:translateY(-5px);box-shadow:var(--shadow-card);}
  @media (prefers-reduced-motion:reduce){.teaser-tile{transition:none;}.teaser-tile:hover{transform:none;}}
  .teaser-tile .mini-stage{background:var(--surface);border-radius:var(--radius-m);min-height:120px;display:grid;place-items:center;}
  .teaser-tile h3{font-size:1.05rem;}
  .teaser-tile .go{margin-top:auto;font-size:.76rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--umber);}

  .craft{position:relative;z-index:1;padding-block:clamp(4rem,8vw,6.5rem);border-bottom:1px solid var(--line);background:var(--paper);}
  .craft h2{font-size:clamp(2rem,4.6vw,3.2rem);max-width:16ch;}
  .craft-steps{margin-top:2.6rem;display:grid;grid-template-columns:repeat(4,1fr);gap:1.8rem;}
  .craft-step{border-top:1px solid var(--line-strong);padding-top:1.1rem;}
  .craft-step .step-num{font-family:'Anton',sans-serif;font-size:1.3rem;color:var(--umber);}
  .craft-step h3{font-size:1.02rem;margin-top:.5rem;}
  .craft-step p{font-size:.9rem;color:var(--ink-soft);margin-top:.35rem;}

  .feature-band{position:relative;z-index:1;background:var(--cocoa);color:var(--paper);padding-block:clamp(5.5rem,11vw,8.5rem);border-bottom:1px solid var(--line);}
  .feature-band blockquote{margin:0;font-family:'Anton',sans-serif;text-transform:uppercase;font-size:clamp(1.9rem,4.6vw,3.4rem);line-height:1.06;max-width:20ch;}
  .feature-band p.cite{margin-top:1.4rem;font-size:.9rem;color:rgba(255,251,245,.7);font-weight:600;letter-spacing:.06em;text-transform:uppercase;}

  .stat-strip{position:relative;z-index:1;padding-block:clamp(2.6rem,5vw,3.6rem);border-bottom:1px solid var(--line);background:var(--paper);}
  .stat-grid{display:grid;grid-template-columns:repeat(4,1fr);}
  .stat{padding-inline:1.5rem;border-left:1px solid var(--line);}
  .stat:first-child{border-left:none;padding-left:0;}
  .stat-num{display:block;font-family:'Anton',sans-serif;font-size:clamp(1.8rem,3.6vw,2.6rem);color:var(--cocoa);}
  .stat-label{display:block;font-size:.78rem;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:var(--umber);margin-top:.3rem;}

  .close-cta{position:relative;z-index:1;padding-block:clamp(5.5rem,11vw,8.5rem);text-align:center;border-bottom:1px solid var(--line);background:var(--paper);}
  .close-cta h2{font-size:clamp(2.2rem,5vw,3.6rem);max-width:18ch;margin-inline:auto;}
  .close-cta .hero-ctas{justify-content:center;margin-top:2.1rem;}

  /* ================= PRODUCTS ================= */
  .page-header{padding-block:clamp(3rem,6vw,4.5rem) clamp(2rem,4vw,3rem);border-bottom:1px solid var(--line);}
  .page-header h1{font-size:clamp(2.4rem,5.4vw,3.8rem);margin-top:.6rem;max-width:18ch;}
  .page-header p.hero-sub{margin-top:1.1rem;max-width:56ch;font-size:1.05rem;color:var(--ink-soft);font-weight:500;}

  .showcase{padding-block:clamp(3rem,6vw,4.5rem);}
  .showcase-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1.6rem;}
  .show-card{border:1px solid var(--line);border-radius:var(--radius-l);padding:1.9rem;display:flex;flex-direction:column;gap:1.2rem;box-shadow:var(--shadow-soft);transition:transform .2s ease,box-shadow .2s ease;}
  .show-card:hover{transform:translateY(-4px);box-shadow:var(--shadow-card);}
  @media (prefers-reduced-motion:reduce){.show-card{transition:none;}.show-card:hover{transform:none;}}
  .show-card.card-custom{background:var(--ink);color:var(--paper);border-color:var(--ink);}
  .show-card.card-custom .eyebrow{color:var(--amber);}
  .show-card .mini-stage{background:var(--surface);border-radius:var(--radius-m);min-height:150px;display:grid;place-items:center;padding:1.2rem;}
  .show-card h3{font-size:1.3rem;}
  .show-card p.desc{font-size:.92rem;font-weight:500;color:var(--ink-soft);}
  .show-card.card-custom p.desc{color:rgba(255,251,245,.75);}
  .show-card .card-foot{margin-top:auto;display:flex;align-items:center;justify-content:space-between;font-weight:700;font-size:.85rem;padding-top:.9rem;border-top:1px solid var(--line);}
  .show-card.card-custom .card-foot{border-top-color:rgba(255,251,245,.2);}
  .show-card .price{font-weight:800;color:var(--cocoa);}
  .show-card.card-custom .price{color:var(--amber);}
  .show-card .go{text-transform:uppercase;letter-spacing:.06em;color:var(--umber);}
  .show-card.card-custom .go{color:var(--amber);}
  @media (max-width:900px){.showcase-grid{grid-template-columns:repeat(2,1fr);}}
  @media (max-width:600px){.showcase-grid{grid-template-columns:1fr;}}

  /* ================= PRODUCT (zoom-in — matches the referenced customiser look) ================= */
  .product-header{padding-block:1.6rem;border-bottom:1px solid var(--line);}
  .crumb{font-size:.8rem;font-weight:600;color:var(--ink-soft);}
  .crumb a{border-bottom:1px solid transparent;}
  .crumb a:hover{border-color:var(--ink-soft);}
  .cat-switch{margin-top:1.1rem;display:flex;flex-wrap:wrap;gap:.6rem;}
  .cat-switch button{padding:.5rem 1.05rem;border:1.5px solid var(--line-strong);border-radius:var(--radius-pill);font-weight:600;font-size:.82rem;}
  .cat-switch button.active{background:var(--ink);color:var(--paper);border-color:var(--ink);}
  .product-intro{padding-block:clamp(2rem,4vw,2.8rem) 0;}
  .product-intro h1{font-size:clamp(2rem,4.6vw,3.2rem);}
  .product-intro .hero-sub{margin-top:.9rem;max-width:58ch;font-size:1.02rem;color:var(--ink-soft);font-weight:500;}
  .product-meta{display:flex;gap:2.2rem;flex-wrap:wrap;margin-top:1.3rem;}
  .product-meta .k{display:block;font-size:.7rem;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--umber);}
  .product-meta .v{display:block;font-size:1rem;font-weight:700;color:var(--cocoa);margin-top:.2rem;}

  /* Category-tab switch: the heading block and the active customiser panel
     are two separate elements, but they get .is-switching added/removed on
     the exact same tick (see the JS router below) with identical timing, so
     they read as one connected block dissolving into the next rather than
     two things cutting independently. */
  .product-intro .wrap,.product-panel{transition:filter .22s ease,opacity .22s ease,transform .22s ease;filter:blur(0);opacity:1;transform:translateY(0);}
  .product-intro .wrap.is-switching,.product-panel.is-switching{filter:blur(10px);opacity:0;transform:translateY(10px);transition-duration:.16s;}

  .customiser{padding-block:clamp(2.6rem,5vw,4rem);}
  .customiser-grid{display:grid;grid-template-columns:1fr 1fr;gap:clamp(2.5rem,5vw,4.5rem);align-items:start;}
  .stage-col{position:sticky;top:6rem;}
  .price-tag{margin-top:1.2rem;font-weight:800;font-size:1.05rem;color:var(--cocoa);text-align:center;}
  .price-tag .note{display:block;font-weight:500;font-size:.78rem;color:var(--ink-soft);margin-top:.2rem;}
  .panel-col h2{font-size:clamp(1.7rem,3.2vw,2.5rem);margin-top:.3rem;margin-bottom:1.6rem;max-width:18ch;}

  .field{margin-bottom:1.5rem;}
  .field-label,label{display:block;font-weight:700;font-size:.76rem;text-transform:uppercase;letter-spacing:.1em;color:var(--umber);margin-bottom:.6rem;}
  .text-input,textarea,select{width:100%;font-family:'Figtree',sans-serif;font-size:1rem;font-weight:600;color:var(--ink);background:var(--paper);border:1.5px solid var(--line-strong);border-radius:12px;padding:.8rem 1rem;}
  textarea{resize:vertical;min-height:5.2rem;font-weight:500;}

  .swatch-group{display:flex;flex-wrap:wrap;gap:.65rem;}
  .swatch{width:2.4rem;height:2.4rem;border-radius:50%;border:1.5px solid var(--line-strong);position:relative;box-shadow:0 3px 8px rgba(74,57,20,.18);}
  .swatch.active{box-shadow:0 0 0 3px var(--paper),0 0 0 5.5px var(--amber),0 3px 8px rgba(74,57,20,.18);}

  .choice-group{display:flex;flex-wrap:wrap;gap:.6rem;}
  .choice-group button{padding:.6rem 1.05rem;border:1.5px solid var(--line-strong);border-radius:var(--radius-pill);font-weight:600;font-size:.85rem;background:var(--paper);}
  .choice-group button.active{background:var(--ink);color:var(--paper);border-color:var(--ink);}

  .custom-panel{padding-block:1rem;}
  .custom-panel .hero-sub{margin-top:.6rem;max-width:58ch;color:var(--ink-soft);font-weight:500;}
  .custom-form{margin-top:2rem;border:1px solid var(--line);border-radius:var(--radius-l);padding:2rem;box-shadow:var(--shadow-card);max-width:560px;}

  footer{position:relative;z-index:1;background:var(--paper);padding-block:2.8rem;border-top:1px solid var(--line);}
  .footer-grid{display:flex;flex-wrap:wrap;gap:1.6rem 3rem;justify-content:space-between;align-items:flex-start;}
  .footer-note{max-width:46ch;font-size:.85rem;color:var(--ink-soft);margin-top:.9rem;}
  .footer-links{display:flex;gap:1.3rem;font-weight:600;font-size:.88rem;flex-wrap:wrap;}
  .footer-links a{cursor:pointer;}
  .footer-fine{margin-top:2.2rem;font-size:.78rem;color:var(--ink-soft);border-top:1px solid var(--line);padding-top:1.3rem;}

  @media (max-width:900px){
    .home-hero .hero-grid,.customiser-grid{grid-template-columns:1fr;}
    .stat-grid,.teaser-grid,.craft-steps{grid-template-columns:repeat(2,1fr);}
    .stat{border-left:none;border-top:1px solid var(--line);padding:1rem 0 0;}
    .stat:first-child{border-top:none;padding-top:0;}
    .stage-col{position:static;}
  }
