/* ==========================================================================
   ZELYTE — styles.css (v2)

   Shared by all thirteen pages. Sections in order:
     00 Fonts            09 Marquee
     01 Tokens           10 Hero + orbit
     02 Reset & base     11 Feature cards
     03 Type             12 How it works (25:00 timeline)
     04 Buttons          13 Spec table + counters
     05 Lockup           14 Flavors
     06 The Split        15 Built for
     07 Loader           16 FAQ / accordion
     08 Floating nav     17 Forms
     08b Card stack      17b Auth & account
                         18 Shop / bundles / compare / story
                         18b Product pages (hero, the pan, swap)
                         19 Footer          21 Responsive
                         20 Reveal          22 Reduced motion
   ========================================================================== */


/* 00 FONTS ================================================================ */
@font-face{font-family:'Archivo Black';src:url('assets/fonts/Archivo-Black.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Barlow';src:url('assets/fonts/Barlow-Regular.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Barlow';src:url('assets/fonts/Barlow-Medium.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:'Barlow';src:url('assets/fonts/Barlow-SemiBold.woff2') format('woff2');font-weight:600;font-style:normal;font-display:swap}
@font-face{font-family:'JetBrains Mono';src:url('assets/fonts/JetBrainsMono-Regular.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'JetBrains Mono';src:url('assets/fonts/JetBrainsMono-Medium.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap}


/* 01 TOKENS =============================================================== */
:root{
  /* The palette. Nothing outside these eight values. */
  --chalk:#E9EBEA;
  --asphalt:#0C0E10;
  --voltage:#2447F5;
  --iron:#45494D;
  --frost:#C7CDD1;
  --white:#FFFFFF;
  --mint:#4E8FD6;
  --cherry:#6E1B2E;

  /* Hairlines: the same palette colors carried at alpha, not new colors. */
  --hair-light:rgba(69,73,77,.22);
  --hair-dark:rgba(199,205,209,.22);

  --display:'Archivo Black',system-ui,sans-serif;
  --body:'Barlow',system-ui,sans-serif;
  --data:'JetBrains Mono',ui-monospace,monospace;

  --cap-ratio:0.688;        /* Archivo Black sCapHeight/upm, measured */
  --strike-ratio:0.73209;   /* traced mark 552x754 */

  --wrap:1180px;
  --gutter:clamp(20px,4vw,56px);
  --frame:clamp(6px,1vw,14px);   /* black margin around every card */
  --r-card:18px;
  --r-btn:4px;
  --sec:clamp(56px,7vw,104px);
  --ease:cubic-bezier(.16,1,.3,1);
  --nav-h:54px;   /* pre-JS fallback; main.js measures the real shell height */
}


/* 02 RESET & BASE ========================================================= */
*,*::before,*::after{box-sizing:border-box}
/* The UA rule for [hidden] is display:none at zero specificity, so ANY author
   display wins and the element stays on screen with its attribute set. That
   is not theoretical: .capture__form is display:flex, and main.js hides it by
   setting form.hidden — so a successful launch-list signup used to print
   "You are on the list" underneath a form that was still sitting there
   inviting a second submit. Same trap for .auth__form (grid) and .btn
   (inline-flex). !important because the whole point is to beat the component
   rule that sets display in the first place.
   The .menu[hidden] rule in section 08 was a one-off patch for this and is
   now redundant; it is left alone rather than churned. */
[hidden]{display:none!important}
html{-webkit-text-size-adjust:100%;background:var(--asphalt)}
body{
  margin:0;
  background:var(--asphalt);color:var(--asphalt);
  font-family:var(--body);font-weight:400;font-size:clamp(16px,1.05vw,17px);line-height:1.5;
  -webkit-font-smoothing:antialiased;
  /* clip, NOT hidden: overflow:hidden establishes a scroll container and
     breaks every position:sticky in the card stack. */
  overflow-x:clip;
}
img{max-width:100%;height:auto;display:block}
svg{display:block}
.sprite{position:absolute;width:0;height:0;overflow:hidden}
.wrap{width:100%;max-width:var(--wrap);margin-inline:auto;padding-inline:var(--gutter)}
.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
[id]{scroll-margin-top:calc(var(--nav-h) + 28px)}

.skip{
  position:fixed;left:var(--gutter);top:14px;z-index:900;
  transform:translateY(-200%);
  background:var(--voltage);color:var(--chalk);
  font-family:var(--data);font-size:12px;letter-spacing:.05em;text-transform:uppercase;
  padding:10px 16px;border-radius:var(--r-btn);text-decoration:none;
  transition:transform 180ms var(--ease);
}
.skip:focus{transform:none}

:focus-visible{outline:2px solid var(--voltage);outline-offset:2px;border-radius:2px}
/* Voltage on asphalt is only ~2.6:1, so dark surfaces flip to chalk on focus
   and the ring sits on chalk instead. */
.is-dark :focus-visible,.footer :focus-visible,.menu :focus-visible{
  background:var(--chalk);color:var(--asphalt);outline-offset:3px;
}


/* 03 TYPE ================================================================= */
.display{
  font-family:var(--display);font-weight:400;
  text-transform:uppercase;letter-spacing:-.03em;line-height:.95;
  margin:0;text-wrap:balance;
}
.display .line{display:block}
h1.display{font-size:clamp(2.6rem,min(9vw,11vh),6.6rem)}
h2.display{font-size:clamp(1.9rem,5vw,3.9rem)}
h3{margin:0}

.eyebrow{
  font-family:var(--data);font-weight:500;font-size:12px;
  letter-spacing:.05em;text-transform:uppercase;color:var(--iron);
  margin:0 0 clamp(18px,2.5vw,28px);
}
.is-dark .eyebrow{color:var(--frost)}
.lede{
  font-size:clamp(1.02rem,1.4vw,1.2rem);line-height:1.5;
  color:var(--iron);max-width:52ch;margin:clamp(18px,2.5vw,28px) 0 0;
}
.is-dark .lede{color:var(--frost)}
p{max-width:68ch}
/* Links inside prose. Without this the browser's default link blue is the one
   color on the site outside the palette. Voltage is 5.34:1 on chalk but only
   2.6:1 on asphalt, so dark surfaces carry chalk — same rule as .btn--ghost. */
.lede a,.qa__a a,.uses p a,.feat p a{color:var(--voltage);text-underline-offset:3px;text-decoration-thickness:1px}
.is-dark .lede a,.is-dark .qa__a a,.is-dark .uses p a,.is-dark .feat p a{color:var(--chalk)}


/* 04 BUTTONS ============================================================== */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  background:var(--voltage);color:var(--chalk);
  font-family:var(--data);font-weight:500;font-size:13px;
  letter-spacing:.05em;text-transform:uppercase;
  padding:14px 24px;border:1px solid var(--voltage);border-radius:var(--r-btn);
  text-decoration:none;cursor:pointer;
  transition:opacity 180ms var(--ease),transform 180ms var(--ease);
}
.btn:hover{opacity:.88}
.btn--ghost{background:transparent;color:var(--asphalt);border-color:var(--hair-light)}
.btn--ghost:hover{border-color:var(--asphalt);opacity:1}
.is-dark .btn--ghost{color:var(--chalk);border-color:var(--hair-dark)}
.is-dark .btn--ghost:hover{border-color:var(--chalk)}
.btn--sm{padding:10px 18px;font-size:12px}


/* 05 LOCKUP ===============================================================
   One property, --cap, drives all three measured ratios:
     icon height 1.757x cap | descends 0.571x below baseline | gap 0.171x
   The overshoot above and below the caps is the brand, not a bug.
   ========================================================================== */
.lockup{
  --cap:22px;
  display:inline-flex;align-items:baseline;
  gap:calc(var(--cap) * .171);
  color:var(--asphalt);text-decoration:none;
}
.lockup__icon{
  height:calc(var(--cap) * 1.757);
  width:calc(var(--cap) * 1.757 * var(--strike-ratio));
  margin-bottom:calc(var(--cap) * -.571);
  fill:currentColor;flex:none;
}
.lockup__word{
  font-family:var(--display);font-weight:400;
  font-size:calc(var(--cap) / var(--cap-ratio));
  letter-spacing:-.035em;text-transform:uppercase;line-height:1;
}
.lockup--dark{color:var(--chalk)}
/* Nav wears the wordmark alone. The footer keeps the full lockup. */
.lockup--word .lockup__icon{display:none}
.lockup--word{gap:0}


/* 06 THE SPLIT ============================================================
   Instrumentation. Elements only — no gradient functions anywhere.
   ========================================================================== */
.split{width:100%}
.split__rule{
  position:relative;height:5px;
  border-bottom:1px solid var(--iron);
  display:flex;justify-content:space-between;align-items:flex-end;
}
.split__rule i{width:1px;height:3px;background:var(--iron);flex:none}
.split__rule i:first-child,.split__rule i:last-child{height:5px}
.split__fill{
  position:absolute;left:0;right:0;bottom:-1px;height:1px;
  background:var(--voltage);
  transform:scaleX(var(--p,0));transform-origin:left center;
}
.split__labels{
  display:flex;justify-content:space-between;align-items:baseline;gap:12px;
  margin-top:7px;
  font-family:var(--data);font-weight:400;font-size:11px;
  letter-spacing:.05em;text-transform:uppercase;color:var(--iron);
}
.split__label{flex:1;text-align:center}
.split--dark .split__rule{border-bottom-color:var(--frost)}
.split--dark .split__rule i{background:var(--frost)}
.split--dark .split__labels{color:var(--frost)}
.split--progress{
  position:fixed;top:0;left:0;right:0;z-index:800;
  padding:0 var(--frame);height:6px;display:flex;align-items:flex-end;
}
.split--progress .split__rule{width:100%;border-bottom-color:var(--hair-dark)}
.split--progress .split__rule i{background:var(--hair-dark)}
.split--track{margin-top:clamp(18px,2.5vw,26px)}
.split--track .split__fill{height:2px;bottom:-1px}


/* 07 LOADER ===============================================================
   Blank asphalt, the Strike turns one full revolution, lands where it
   started, then the page fades up. Gated on .js so a script failure can
   never leave the page hidden.
   ========================================================================== */
.loader{
  position:fixed;inset:0;z-index:1000;
  background:var(--asphalt);
  display:flex;align-items:center;justify-content:center;
  transition:opacity 300ms var(--ease),visibility 300ms;
}
.loader__mark{position:relative;width:clamp(74px,11vw,116px);aspect-ratio:var(--strike-ratio);perspective:1000px}
.mark3d{
  position:absolute;inset:0;transform-style:preserve-3d;
  transform:rotateY(var(--ry,0deg));will-change:transform;
}
/* Stacked flat layers fake the extrusion. Two flat fills, no shading,
   so the form reads dimensional without a single gradient. */
.mark3d__l{position:absolute;inset:0;width:100%;height:100%;fill:var(--iron)}
.mark3d__l--face{fill:var(--chalk)}
.loader.is-done{opacity:0;visibility:hidden;pointer-events:none}
/* The overlay alone hides the page. Deliberately NOT opacity:0 on the body's
   children — elements at zero opacity are never LCP candidates, which cost a
   measurable LCP (Lighthouse reported NO_LCP) and would hurt real Core Web
   Vitals, not just the audit. The page paints immediately behind the overlay
   and is revealed by the overlay fading out. */
html.js.is-ready main{animation:page-rise 480ms var(--ease) both}
@keyframes page-rise{from{transform:translateY(14px)}to{transform:none}}


/* 08 FLOATING NAV =========================================================
   Two boxes, deliberately. The SHELL (.nav) is transparent and a constant
   52px; the PILL (.nav__inner) carries the chalk and is the only thing that
   shrinks on scroll. main.js measures nav.offsetHeight into --nav-h, which
   drives every card's top padding and every [id]'s scroll-margin — so if the
   shell resized, starting to scroll would relayout the whole card stack.
   flex-start keeps the pill's top edge planted; it thins downward.
   ========================================================================== */
.nav{
  position:fixed;z-index:700;
  top:10px;left:50%;transform:translateX(-50%);
  width:calc(100% - (var(--frame) * 2));max-width:1120px;
  /* 54, not 52: the resting pill is 9+9 padding + a 34px row + its OWN 1px
     borders. Sized to 52 the shell tracked the pill down to 52 when stuck,
     which is the 2px relayout this split exists to prevent. Measured. */
  min-height:54px;display:flex;align-items:flex-start;
  background:transparent;border:0;
}
.nav__inner{
  width:100%;
  display:flex;align-items:center;gap:18px;
  background:var(--chalk);
  border:1px solid transparent;border-radius:999px;
  /* The 34px row is stated, not inherited. Pages with a .nav__cta got it free
     from the button's own height; pages without one (the homepage, the auth
     pages) collapsed to the 22px link row and read as a thinner nav. These are
     border-box totals, so each one is 34 + its own padding + the 1px borders. */
  min-height:54px;
  padding:9px clamp(14px,1.8vw,20px);
  transition:padding 200ms var(--ease),min-height 200ms var(--ease),border-color 200ms var(--ease);
}
/* 9+9+34+2 = 54 at rest, 5+5+34+2 = 46 scrolled. */
.nav.is-stuck .nav__inner{min-height:46px;padding-block:5px;border-color:var(--hair-light)}
.nav .lockup{--cap:15px;margin-right:auto}
.nav__links{display:flex;gap:clamp(14px,1.8vw,28px)}
/* Stays 12px. The nav gets thinner through padding and the wordmark, never by
   shrinking type — small text was the thing to fix, not the thing to add. */
.nav__links a{
  font-family:var(--data);font-size:12px;letter-spacing:.05em;
  text-transform:uppercase;color:var(--iron);text-decoration:none;
  transition:color 180ms var(--ease);
}
.nav__links a:hover,.nav__links a[aria-current="page"]{color:var(--asphalt)}
.nav__cta{padding:7px 16px;font-size:12px;border-radius:999px}
/* 32px sits under the pill's 34px floor, so mobile keeps the desktop 54. */
.nav__toggle{
  display:none;position:relative;width:32px;height:32px;padding:0;margin-right:-4px;
  background:none;border:0;cursor:pointer;
  flex-direction:column;justify-content:center;align-items:flex-end;gap:5px;
}
/* Hit area back up to 48x48 without giving the box any layout size. */
.nav__toggle::after{content:"";position:absolute;inset:-8px}
.nav__toggle span{display:block;width:20px;height:1px;background:var(--asphalt);transition:transform 180ms var(--ease)}
.nav__toggle span:last-child{width:13px}

.menu{
  position:fixed;inset:0;z-index:690;
  background:var(--asphalt);color:var(--chalk);
  padding:calc(var(--nav-h) + 40px) var(--gutter) var(--gutter);
  display:flex;flex-direction:column;justify-content:space-between;
}
.menu[hidden]{display:none}
.menu__links{display:flex;flex-direction:column;gap:clamp(8px,1.6vw,14px)}
.menu__links a{
  font-family:var(--display);font-size:clamp(1.9rem,8.5vw,2.8rem);
  text-transform:uppercase;letter-spacing:-.03em;line-height:1;
  color:var(--chalk);text-decoration:none;
}
body.menu-open{overflow:hidden}
body.menu-open .nav{z-index:700}
body.menu-open .nav__inner{background:transparent;border-color:transparent}
body.menu-open .nav .lockup{color:var(--chalk)}
body.menu-open .nav__toggle span{background:var(--chalk)}
body.menu-open .nav__toggle span:first-child{transform:translateY(3px) rotate(45deg)}
body.menu-open .nav__toggle span:last-child{width:20px;transform:translateY(-3px) rotate(-45deg)}


/* 08b CARD STACK ==========================================================
   Each item supplies the scroll distance; the card inside pins to the top
   for that distance. Consecutive cards therefore rise over one another.
   Depth comes from scale + the black showing through, never a shadow.
   ========================================================================== */
.stack{background:var(--asphalt);position:relative}
.stack__item{position:relative;height:100svh}
.stack__item--auto{height:auto}
/* Extra scroll distance for the scroll-scrubbed sections. CLASSES, not inline
   styles: section 22 flattens the stack with .stack__item{height:auto}, and a
   stylesheet rule can never override an inline height — which left 2.2 screens
   of black under prefers-reduced-motion for as long as this was written on the
   element. Two of them because the two sections want different speeds: the
   25:00 clock wants a long, slow scrub; the pan wants to keep up with the
   finger (see the ratio note in section 18b). */
.stack__item--tall{height:300svh}
.stack__item--pan{height:220svh}
.stack__card{
  position:sticky;top:0;
  min-height:100svh;
  margin-inline:var(--frame);
  background:var(--chalk);
  border-radius:var(--r-card);
  overflow:hidden;                      /* clips its own content only */
  display:flex;align-items:center;
  padding:calc(var(--nav-h) + 28px) 0 var(--sec);
  transform-origin:center top;
  will-change:transform,opacity;
}
/* Cards whose content genuinely cannot fit one screen (long tables, the FAQ
   list) opt out of pinning and simply scroll — still a rounded card on black. */
.stack__item--flow{height:auto}
/* margin-bottom keeps the black frame visible between two adjacent flow cards,
   which pinned cards get for free from their scale-down. */
.stack__item--flow .stack__card{position:static;min-height:0;padding:var(--sec) 0;margin-bottom:var(--frame)}
.stack__card.is-dark{background:var(--asphalt);color:var(--chalk)}
.stack__card>.wrap{width:100%}
.stack__item+.stack__item{margin-top:0}


/* 09 MARQUEE ============================================================== */
.marquee{
  background:var(--asphalt);color:var(--chalk);
  overflow:hidden;padding:15px 0;
  border-block:1px solid var(--hair-dark);
  margin-inline:var(--frame);
}
/* --group is one authored group's measured width, set by main.js. Translating
   by a percentage instead left a visible empty run at the end of each cycle. */
.marquee__track{display:flex;width:max-content;animation:marquee 34s linear infinite}
.marquee__track span{
  font-family:var(--data);font-size:12px;letter-spacing:.05em;
  text-transform:uppercase;padding-inline:22px;white-space:nowrap;
}
.marquee__track span::after{content:"·";margin-left:22px;color:var(--voltage)}
@keyframes marquee{from{transform:translateX(0)}to{transform:translateX(calc(-1 * var(--group,50%)))}}


/* 10 HERO + ORBIT ========================================================= */
/* The orbit is an absolute background layer now, so the hero is a single
   constrained column of copy sitting on top of it. */
/* Deliberately NOT positioned: the orbit should anchor to the sticky card so
   it centres in the full hero height, not in the copy block's height. */
.hero__grid{width:100%}
/* 62%, not 56%: measured, that is where the column's right edge meets the tin's
   left edge at every desktop width, so it is the most the headline can take
   without running onto the tin. */
.hero__copy{position:relative;z-index:2;max-width:min(62%,700px)}
/* No UA h1 margin here — the span owns all the spacing. */
.hero__h1{margin:0}
/* Sized to keep BOTH headline lines on ONE line each. Measured at this
   letter-spacing: "DROP THE BOTTLE." renders 10.07x its font-size wide (the
   longer of the two; "NOT THE PACE." is 7.95x), so the longer line is what
   every term below is derived from. This rule fits the 62% column above, i.e.
   right up to the tin. The column is narrowest (~575px) at a 1025px viewport —
   just above the breakpoint where it goes full width — so that point, not
   1440, is what caps the vw term. The stacked layout under 1024 has no tin
   beside it and is sized separately in section 21. Measured to hold one line
   from 360px up; it wraps somewhere under that, which is deliberate: no
   white-space:nowrap, since clipping beats wrapping there. */
.hero__fuel{
  display:block;                 /* inline spans ran onto one line at 375 */
  font-family:var(--display);text-transform:uppercase;
  font-size:clamp(1.84rem,min(5.3vw,7.7vh),3.95rem);
  letter-spacing:-.045em;line-height:.82;margin:0;
}
/* .eyebrow's margin assumes it sits above the headline; under it, it flips.
   The size overrides .eyebrow's flat 12px, which read as a footnote under a
   headline this large. Scoped here so every other eyebrow is untouched. */
.hero__kicker{margin:clamp(14px,2vw,20px) 0 0;font-size:clamp(13px,1.6vw,19px)}
.hero__actions{display:flex;flex-wrap:wrap;gap:10px;margin-top:clamp(22px,3vw,34px)}
.hero__split{margin-top:clamp(22px,3vw,34px)}

/* The solar system. A background layer inside the hero card, centred on the
   right, wide enough that the outer rings drift behind the headline. The
   card's own overflow:hidden clips them at the rounded edge — intended. */
.orbit{
  position:absolute;z-index:0;pointer-events:none;
  top:50%;left:74%;transform:translate(-50%,-50%);
  width:clamp(620px,96vw,1560px);aspect-ratio:1;
}
.orbit__tin{
  position:absolute;left:50%;top:50%;
  width:clamp(190px,24vw,380px);   /* absolute, so it is independent of the
                                      now-much-larger orbit box */
  transform:translate(-50%,-50%) rotate(var(--tin-rot,0deg));
  z-index:1;
}
.orbit__ring{position:absolute;inset:0;animation:orbit var(--dur) linear infinite}
.orbit__ring--rev{animation-direction:reverse}
/* rotate(--a) turns this slot's local frame to the tangent, which is exactly
   the orientation the pouch should inherit — so the image adds no rotation of
   its own. Flat at the top of the circle, on its side at the left and right. */
.orbit__slot{
  position:absolute;left:50%;top:50%;width:0;height:0;
  transform:rotate(var(--a)) translateY(calc(-1 * var(--r)));
}
/* Floor stops the outer rings dissolving into specks on a narrow phone, where
   --w is a fraction of a much smaller orbit box. */
.orbit__slot img{width:max(var(--w),16px);max-width:none;transform:translate(-50%,-50%)}
@keyframes orbit{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}


/* 11 FEATURE CARDS ======================================================== */
.feats{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(14px,1.6vw,20px);margin-top:clamp(32px,4vw,52px)}
.feat{
  background:var(--white);border:1px solid var(--hair-light);border-radius:calc(var(--r-card) - 6px);
  padding:clamp(22px,2.6vw,32px);
  transition:transform 200ms var(--ease),border-color 200ms var(--ease);
}
.feat:hover{transform:translateY(-4px);border-color:var(--iron)}
.is-dark .feat{background:transparent;border-color:var(--hair-dark)}
.feat__n{font-family:var(--data);font-size:11px;letter-spacing:.05em;color:var(--voltage);display:block;margin-bottom:16px}
.feat__h{font-family:var(--data);font-weight:500;font-size:13px;letter-spacing:.05em;text-transform:uppercase;margin-bottom:10px}
.feat p{margin:0;font-size:1rem;color:var(--iron)}
.is-dark .feat p{color:var(--frost)}

/* 12 HOW IT WORKS ========================================================= */
.how__clock{
  font-family:var(--data);font-weight:500;
  font-size:clamp(2.4rem,6.5vw,4.6rem);line-height:1;
  letter-spacing:.02em;color:var(--voltage);font-variant-numeric:tabular-nums;
}
.how__stages{
  list-style:none;margin:clamp(26px,3.4vw,44px) 0 0;padding:0;
  display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(16px,2.4vw,34px);
}
.stage{
  opacity:.85;transform:translateY(10px);
  transition:opacity 220ms var(--ease),transform 220ms var(--ease);
  border-top:1px solid var(--hair-light);padding-top:14px;
}
.stage.is-on{opacity:1;transform:none;border-top-color:var(--iron)}
.stage__t{display:block;font-family:var(--data);font-weight:500;font-size:12px;letter-spacing:.05em;color:var(--iron);margin-bottom:8px;transition:color 220ms var(--ease)}
.stage.is-on .stage__t{color:var(--voltage)}
.stage__h3{font-family:var(--data);font-weight:500;font-size:13px;letter-spacing:.05em;text-transform:uppercase;margin-bottom:8px;color:var(--iron);transition:color 220ms var(--ease)}
.stage.is-on .stage__h3{color:var(--asphalt)}
.stage p{margin:0;font-size:1rem;color:var(--iron)}
.is-dark .stage p{color:var(--frost)}


/* 13 SPEC TABLE + COUNTERS ================================================ */
.spec{
  width:100%;border-collapse:collapse;
  font-family:var(--data);font-weight:400;font-size:13px;
  letter-spacing:.05em;text-transform:uppercase;min-width:560px;
}
.spec th,.spec td{text-align:left;padding:16px 14px 16px 0;border-bottom:1px solid var(--hair-light);font-weight:400}
.spec thead th{color:var(--iron);font-weight:500;font-size:12px;padding-top:0;border-bottom-color:var(--iron)}
.spec tbody th{color:var(--asphalt);width:44%}
.spec tbody td{color:var(--iron);font-variant-numeric:tabular-nums}
.spec tbody td:first-of-type{color:var(--asphalt)}
.is-dark .spec th,.is-dark .spec td{border-bottom-color:var(--hair-dark)}
.is-dark .spec tbody th,.is-dark .spec tbody td:first-of-type{color:var(--chalk)}
.is-dark .spec tbody td,.is-dark .spec thead th{color:var(--frost)}
.table-wrap{overflow-x:auto}

.stats{display:flex;flex-wrap:wrap;gap:clamp(24px,4vw,60px);margin:clamp(28px,3.6vw,44px) 0 0;padding:0;list-style:none}
.stat dt,.stat__k{font-family:var(--data);font-size:12px;letter-spacing:.05em;text-transform:uppercase;color:var(--iron);margin-bottom:8px}
.is-dark .stat__k{color:var(--frost)}
.stat__v{font-family:var(--data);font-weight:500;font-size:clamp(1.7rem,3.4vw,2.6rem);letter-spacing:.02em;font-variant-numeric:tabular-nums;line-height:1}


/* 14 FLAVORS ==============================================================
   Identical cards. Only the ring and the name carry the SKU accent.
   ========================================================================== */
.flavors__grid{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(14px,1.8vw,24px)}
.sku{
  background:var(--white);border:1px solid var(--hair-light);
  border-radius:calc(var(--r-card) - 6px);
  padding:clamp(24px,3vw,40px);
  display:flex;flex-direction:column;align-items:flex-start;
  transition:transform 200ms var(--ease),border-color 200ms var(--ease);
}
.sku:hover{transform:translateY(-4px);border-color:var(--sku)}
/* Product shot. Both tin files are exported at an identical 900x948 with the
   tin normalised to the same 900px content width, so height:100% renders the
   two flavors at matching scale and the copy below them stays aligned. */
.sku__img{
  width:100%;margin-bottom:clamp(20px,2.6vw,28px);
  display:flex;justify-content:center;
}
/* Height sits on the img, not the box: a percentage height would have to
   resolve against the box and Chrome leaves it auto here, which let the tin
   overflow and paint over the copy. Both files are 900x948, so an absolute
   height gives the two flavors identical rendered widths. */
.sku__img img{height:clamp(180px,22vw,280px);width:auto;max-width:100%;transition:transform 320ms var(--ease)}
.sku:hover .sku__img img{transform:scale(1.05)}
.sku__name{font-family:var(--display);font-size:clamp(1.5rem,2.8vw,2.1rem);text-transform:uppercase;letter-spacing:-.03em;line-height:1;color:var(--sku);margin-bottom:14px}
.sku__desc{color:var(--iron);margin:0 0 clamp(20px,2.6vw,28px)}
.sku__spec{display:flex;flex-wrap:wrap;gap:20px;margin:0 0 clamp(22px,3vw,30px);padding-top:18px;border-top:1px solid var(--hair-light);width:100%}
.sku__spec div{display:flex;flex-direction:column;gap:5px}
.sku__spec dt{font-family:var(--data);font-size:12px;letter-spacing:.05em;text-transform:uppercase;color:var(--iron)}
.sku__spec dd{margin:0;font-family:var(--data);font-weight:500;font-size:15px;letter-spacing:.02em}
.sku__btn{margin-top:auto}
.sku--mint{--sku:var(--mint)}
.sku--cherry{--sku:var(--cherry)}


/* 15 BUILT FOR ============================================================ */
.built__shots{display:grid;grid-template-columns:1fr 1fr;gap:clamp(12px,1.6vw,20px);margin-top:clamp(28px,3.6vw,48px)}
.shot{margin:0;border-radius:calc(var(--r-card) - 6px);overflow:hidden}
.shot img{width:100%;height:100%;object-fit:cover;transition:transform 400ms var(--ease)}
.shot:hover img{transform:scale(1.03)}
.uses{list-style:none;margin:clamp(28px,3.6vw,48px) 0 0;padding:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(168px,1fr));gap:clamp(18px,2.4vw,32px)}
/* Defaults to the light card and flips under .is-dark, same as .feat and .lede.
   It used to assume a dark card, which broke the moment one landed on white. */
.uses li{border-top:1px solid var(--hair-light);padding-top:14px}
.is-dark .uses li{border-top-color:var(--hair-dark)}
.uses__k{display:block;font-family:var(--data);font-weight:500;font-size:13px;letter-spacing:.05em;text-transform:uppercase;margin-bottom:8px}
.uses p{margin:0;color:var(--iron);font-size:1rem}
.is-dark .uses p{color:var(--frost)}


/* 16 FAQ ================================================================== */
.faq__list{border-top:1px solid var(--hair-light)}
.faq__group{font-family:var(--data);font-size:12px;letter-spacing:.05em;text-transform:uppercase;color:var(--voltage);margin:clamp(28px,3.4vw,42px) 0 0;padding-bottom:10px}
.qa{border-bottom:1px solid var(--hair-light)}
.qa summary{display:flex;align-items:baseline;gap:clamp(14px,2.4vw,28px);padding:20px 0;cursor:pointer;list-style:none}
.qa summary::-webkit-details-marker{display:none}
.qa__k{font-family:var(--data);font-size:12px;letter-spacing:.05em;color:var(--iron);flex:none}
.qa__q{font-family:var(--data);font-weight:500;font-size:clamp(13px,1.6vw,15px);letter-spacing:.05em;text-transform:uppercase;flex:1}
.qa__i{position:relative;width:11px;height:11px;flex:none;align-self:center}
.qa__i::before,.qa__i::after{content:"";position:absolute;background:var(--asphalt);transition:opacity 180ms var(--ease)}
.qa__i::before{left:0;right:0;top:5px;height:1px}
.qa__i::after{top:0;bottom:0;left:5px;width:1px}
.qa[open] .qa__i::after{opacity:0}
.qa__a{padding:0 0 22px}
.qa__a p{margin:0;color:var(--iron)}
/* Answers that carry more than one fact become a list rather than a paragraph. */
.qa__a ul{margin:0;padding-left:18px;display:flex;flex-direction:column;gap:7px;color:var(--iron);max-width:68ch}
.qa__a p + ul{margin-top:10px}


/* 17 FORMS ================================================================ */
.capture__form{display:flex;flex-wrap:wrap;gap:10px;max-width:540px}
.capture__input{
  flex:1 1 250px;min-width:0;
  background:var(--white);color:var(--asphalt);
  border:1px solid var(--hair-light);border-radius:var(--r-btn);
  padding:14px 15px;font-family:var(--data);font-size:15px;letter-spacing:.02em;
}
.is-dark .capture__input{background:transparent;color:var(--chalk);border-color:var(--hair-dark)}
.capture__input::placeholder{color:var(--iron);opacity:.75}
.is-dark .capture__input::placeholder{color:var(--frost);opacity:.65}
.capture__input:focus{border-color:var(--voltage)}
.capture__input[aria-invalid="true"]{border-color:var(--cherry)}
.capture__micro{font-family:var(--data);font-size:12px;letter-spacing:.05em;text-transform:uppercase;color:var(--iron);margin:16px 0 0}
.is-dark .capture__micro{color:var(--frost)}
.capture__micro.is-error{color:var(--cherry)}
.capture__micro.is-ok{color:var(--voltage)}


/* 17b AUTH & ACCOUNT ======================================================
   Almost nothing new. The input is .capture__input, the status line is
   .capture__micro with its existing .is-error / .is-ok, the button is .btn,
   the account numbers are .stats/.stat, and the flavor picker is .buy__card.

   What IS new is a stacked label-above-input row, because the launch
   capture's one-line flex row cannot carry four fields, and because a
   password field needs a visible label where an email placeholder was enough.

   Eight colors, as everywhere. --voltage for interactive and success,
   --cherry for errors (the .capture__micro convention already), --iron on
   light cards and --frost on .is-dark. Radii from --r-card / --r-btn. No
   shadow, no gradient, no blur.
   ========================================================================== */
.auth{max-width:420px}
.auth__form{display:grid;gap:clamp(12px,1.6vw,16px);margin-top:clamp(24px,3vw,34px)}
.field{display:grid;gap:7px}
.field label{font-family:var(--data);font-size:12px;letter-spacing:.05em;text-transform:uppercase;color:var(--iron)}
.is-dark .field label{color:var(--frost)}
/* .capture__input carries flex:1 1 250px, which is inert outside a flex row —
   inside this grid it has to be told to fill the column. */
.field .capture__input{width:100%}
.field__hint{font-family:var(--data);font-size:11px;letter-spacing:.05em;text-transform:uppercase;color:var(--iron);margin:0}
.is-dark .field__hint{color:var(--frost)}
.auth__form .btn{width:100%;margin-top:6px}

.auth__alt{font-family:var(--data);font-size:12px;letter-spacing:.05em;text-transform:uppercase;color:var(--iron);margin:clamp(20px,2.6vw,26px) 0 0}
.auth__alt a{color:var(--voltage);text-decoration:none}
.auth__alt a:hover{text-decoration:underline;text-underline-offset:3px}
/* Voltage is 2.6:1 on asphalt, so dark cards carry chalk instead — the same
   rule .btn--ghost and the prose links already follow. */
.is-dark .auth__alt{color:var(--frost)}
.is-dark .auth__alt a{color:var(--chalk)}

.check{display:flex;align-items:flex-start;gap:10px}
/* accent-color takes a palette token, so the checkbox is not a ninth color. */
.check input{width:16px;height:16px;flex:0 0 auto;margin:2px 0 0;accent-color:var(--voltage)}
.check span{font-family:var(--data);font-size:12px;letter-spacing:.05em;text-transform:uppercase;color:var(--iron);line-height:1.5}
.is-dark .check span{color:var(--frost)}

/* The launch code. .stat__v already sizes the mono display; this is the box
   it sits in, so the code reads as something issued rather than as copy. */
.code{display:flex;flex-wrap:wrap;align-items:center;gap:12px;margin-top:10px}
.code__v{font-family:var(--data);font-weight:500;font-size:clamp(1.1rem,2.2vw,1.5rem);letter-spacing:.05em;padding:10px 14px;border:1px solid var(--hair-light);border-radius:var(--r-btn)}
.is-dark .code__v{border-color:var(--hair-dark)}

/* Flavor preference. The card IS .buy__card; .pick only adds the selected
   border, and it is the same voltage border .buy__card--best already uses. */
.pick__grid{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(14px,1.8vw,24px);margin-top:clamp(20px,2.6vw,28px)}
.pick{cursor:pointer}
.pick.is-on,.pick:focus-within{border-color:var(--voltage)}
.pick__d{margin:0;font-size:1rem;color:var(--iron)}
.is-dark .pick__d{color:var(--frost)}

.account__row{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-top:clamp(24px,3vw,32px)}

/* Values arrive from Supabase after the page has painted, so the markup ships
   an em dash rather than a blank or a spinner. No opacity: --iron is 9.08:1
   on the card but ~4.0:1 at .7, under the body threshold — the same reason
   .buy__unit s carries none. */
.is-busy{color:var(--iron)}
.is-dark .is-busy{color:var(--frost)}


/* 18 SHOP / BUNDLES / COMPARE / STORY ===================================== */
/* Two packs, not three — takezelyte.com sells no single tin. */
.buy{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(14px,1.8vw,24px);margin-top:clamp(28px,3.6vw,44px)}
.buy__card{
  background:var(--white);border:1px solid var(--hair-light);border-radius:calc(var(--r-card) - 6px);
  padding:clamp(24px,3vw,36px);display:flex;flex-direction:column;position:relative;
  transition:transform 200ms var(--ease),border-color 200ms var(--ease);
}
.buy__card:hover{transform:translateY(-4px);border-color:var(--iron)}
.buy__card--best{border-color:var(--voltage)}
.buy__tag{position:absolute;top:12px;right:12px;font-family:var(--data);font-size:11px;letter-spacing:.02em;text-transform:uppercase;color:var(--chalk);background:var(--voltage);padding:4px 8px;border:1px solid var(--voltage);border-radius:var(--r-btn);white-space:nowrap}
/* Elite's "best value" sits one level below Pro's "most popular", so it reads
   as an outline rather than a second solid block competing for the same eye. */
.buy__tag--ghost{background:transparent;color:var(--voltage)}
.buy__n{font-family:var(--data);font-weight:500;font-size:13px;letter-spacing:.05em;text-transform:uppercase;margin-bottom:14px}
.buy__price{font-family:var(--display);font-size:clamp(2.1rem,4vw,3rem);letter-spacing:-.03em;line-height:1}
.buy__unit{font-family:var(--data);font-size:12px;letter-spacing:.05em;text-transform:uppercase;color:var(--iron);margin:8px 0 18px}
.buy__list{list-style:none;margin:0 0 clamp(22px,3vw,30px);padding:18px 0 0;border-top:1px solid var(--hair-light);display:flex;flex-direction:column;gap:9px}
.buy__list li{font-family:var(--data);font-size:12px;letter-spacing:.05em;text-transform:uppercase;color:var(--iron)}
.buy__btn{margin-top:auto}
/* No opacity here: --iron is 9.08:1 on the card but drops to ~4.0:1 at .7,
   under the 4.5 body threshold. The line-through already marks it as the old
   price without dimming it. */
.buy__unit s{color:var(--iron)}
.buy__note{font-family:var(--data);font-size:12px;letter-spacing:.05em;text-transform:uppercase;color:var(--voltage);margin:0 0 clamp(18px,2.4vw,24px)}

/* ONE TIME / SUBSCRIBE & SAVE ---------------------------------------------
   Both price sets are authored into the markup and CSS shows one of them, so
   the page still prices correctly with JavaScript off. The section carries
   the mode; JS only swaps that one class. */
.is-mode-sub .m-one,.is-mode-one .m-sub{display:none}
.mode{
  display:inline-flex;gap:4px;padding:4px;margin-top:clamp(24px,3vw,32px);
  background:var(--white);border:1px solid var(--hair-light);border-radius:999px;
}
.is-dark .mode{background:transparent;border-color:var(--hair-dark)}
.mode__btn{
  font-family:var(--data);font-weight:500;font-size:12px;
  letter-spacing:.05em;text-transform:uppercase;
  color:var(--iron);background:transparent;border:0;border-radius:999px;
  padding:9px 16px;cursor:pointer;white-space:nowrap;
  transition:background-color 180ms var(--ease),color 180ms var(--ease);
}
.mode__btn:hover{color:var(--asphalt)}
.is-dark .mode__btn{color:var(--frost)}
.is-dark .mode__btn:hover{color:var(--chalk)}
/* chalk on voltage — 5.32:1, the same pairing the primary button uses. */
.mode__btn.is-on,.is-dark .mode__btn.is-on{background:var(--voltage);color:var(--chalk)}

.compare{width:100%;border-collapse:collapse;font-family:var(--data);font-size:13px;letter-spacing:.05em;text-transform:uppercase;min-width:680px}
.compare th,.compare td{padding:15px 12px;border-bottom:1px solid var(--hair-dark);text-align:center;font-weight:400}
.compare thead th{font-weight:500;font-size:12px;color:var(--frost);border-bottom-color:var(--frost)}
.compare thead th:first-child,.compare tbody th{text-align:left}
.compare tbody th{color:var(--chalk);font-weight:400;width:34%}
.compare thead th.is-us{color:var(--voltage)}
.compare td.is-us{color:var(--voltage)}
.compare td{color:var(--frost)}

.story{display:grid;grid-template-columns:1fr 1fr;gap:clamp(28px,4vw,64px);align-items:center}
/* Barlow, not Archivo Black: a long pull quote in heavy caps becomes a wall
   and competes with the headline above it. */
.story__q{font-family:var(--body);font-weight:500;font-size:clamp(1.1rem,1.9vw,1.5rem);line-height:1.38;letter-spacing:-.01em;margin:0 0 clamp(18px,2.4vw,26px)}
.is-dark .story__q{color:var(--chalk)}
.story__by{font-family:var(--data);font-size:12px;letter-spacing:.05em;text-transform:uppercase;color:var(--frost);margin-top:clamp(20px,2.6vw,28px)}
.story__img{border-radius:calc(var(--r-card) - 6px);overflow:hidden;margin:0}

.timeline{list-style:none;margin:clamp(28px,3.6vw,48px) 0 0;padding:0;display:grid;gap:0}
.timeline li{display:grid;grid-template-columns:88px 1fr;gap:clamp(16px,2.4vw,32px);padding:18px 0;border-top:1px solid var(--hair-dark)}
.timeline__y{font-family:var(--data);font-weight:500;font-size:12px;letter-spacing:.05em;color:var(--voltage)}
.timeline p{margin:0;color:var(--frost);font-size:1rem}


/* 18b PRODUCT PAGES =======================================================
   THE FLAVOR ACCENT, and why it is only ever a fill.

   The two flavor colors are legible on opposite surfaces. Measured:

                 on --chalk        on --asphalt
     --mint        2.82:1 fail       5.73:1 pass
     --cherry      9.43:1 pass       1.71:1 fail

   So no single "headline is the flavor color" rule can work for both pages.
   Inverted it is symmetric: as a FILL with the opposing palette color as ink,
   asphalt-on-mint is 5.73:1 and chalk-on-cherry is 9.43:1 — both pass body AA.
   Hence --sku is a background and --sku-ink is its text. Headlines stay
   chalk/asphalt, interactive elements stay voltage, exactly as elsewhere.
   ========================================================================== */
.pdp{--sku:var(--voltage);--sku-ink:var(--chalk)}
.pdp--mint{--sku:var(--mint);--sku-ink:var(--asphalt)}
.pdp--cherry{--sku:var(--cherry);--sku-ink:var(--chalk)}

.pdp__hero{display:grid;grid-template-columns:.92fr 1.08fr;gap:clamp(24px,4vw,64px);align-items:center;width:100%}
.pdp__stage{display:flex;justify-content:center}
/* Composited transform only. The three custom properties are driven by the
   hero's own scroll progress in main.js, so the move reads as a deliberate
   quarter-turn on exit rather than an endless drift. */
.pdp__tin{
  width:clamp(190px,25vw,360px);height:auto;max-width:100%;
  transform:translateY(var(--tin-y,0)) rotate(var(--tin-rot,0deg)) scale(var(--tin-s,1));
  will-change:transform;
}
.pdp__chip{
  display:inline-block;margin:0 0 clamp(16px,2.2vw,24px);
  font-family:var(--data);font-weight:500;font-size:12px;
  letter-spacing:.05em;text-transform:uppercase;
  background:var(--sku);color:var(--sku-ink);
  padding:5px 10px;border-radius:var(--r-btn);
}
/* Its own clamp, not h1.display: the flavor name is set on two deliberate
   lines inside a half-width column, so it must not reach for 9vw. */
.pdp__h1{font-size:clamp(2.6rem,min(7vw,10vh),5.2rem)}
.pdp__spec{margin-top:clamp(24px,3.2vw,36px)}

/* THE PAN — five panels tracking sideways while the card is pinned. The
   right gutter is pulled off so the first panel lines up with the headline
   and the row runs off the card edge; .stack__card's overflow does the clip.

   PANEL WIDTH IS THE SPEED CONTROL. What decides whether this reads as an
   animation is travel ÷ scroll distance. At 340px wide, 3.1 of the 5 panels
   were already on screen, so the row only had 656px to travel across 1800px
   of scroll — 0.36x, slow enough to read as "nothing is happening". At 460px
   only 2.3 fit, travel is 1256px, and --pan cuts the scroll span to 1080px:
   1.16x, so the row moves marginally faster than the finger. Measured 0.89x
   at 1024 and 1.02x at 375. Do not shrink these without re-checking that. */
.pan{overflow:hidden;margin-top:clamp(28px,3.6vw,44px);margin-right:calc(-1 * var(--gutter))}
.pan__track{display:flex;gap:clamp(12px,1.6vw,20px);width:max-content;margin:0;padding:0;list-style:none;will-change:transform}
.pan__panel{
  flex:none;width:clamp(260px,34vw,460px);
  /* The svh term stops a taller panel pushing the card past its scroll slot
     on a short laptop screen. */
  min-height:min(clamp(230px,24vw,300px),34svh);
  background:var(--white);border:1px solid var(--hair-light);
  border-radius:calc(var(--r-card) - 6px);
  padding:clamp(22px,2.6vw,32px);
  display:flex;flex-direction:column;
}
/* Index pinned to the top, everything else pushed to the bottom by the auto
   margin — so the empty middle is deliberate at any panel height rather than
   a fixed gap that only happens to look right at one size. */
.pan__n{font-family:var(--data);font-size:11px;letter-spacing:.05em;color:var(--voltage);margin:0}
.pan__v{font-family:var(--display);font-size:clamp(1.9rem,3.2vw,2.8rem);letter-spacing:-.03em;line-height:1;font-variant-numeric:tabular-nums;margin-top:auto}
.pan__k{font-family:var(--data);font-weight:500;font-size:13px;letter-spacing:.05em;text-transform:uppercase;margin:14px 0 10px}
.pan__panel p{margin:0;color:var(--iron);font-size:1rem}
/* The payoff: the last panel arrives in the flavor color as the pan lands. */
.pan__panel--end{background:var(--sku);border-color:var(--sku);color:var(--sku-ink)}
.pan__panel--end .pan__n,.pan__panel--end p{color:var(--sku-ink)}
.pan__foot{margin-top:clamp(24px,3vw,34px)}

/* Cross-link to the other flavor. */
.pdp__swap{
  display:flex;align-items:center;gap:clamp(16px,2vw,24px);
  margin-top:clamp(28px,3.6vw,44px);padding:clamp(14px,1.8vw,20px);
  border:1px solid var(--hair-dark);border-radius:calc(var(--r-card) - 6px);
  max-width:520px;text-decoration:none;color:inherit;
  transition:border-color 200ms var(--ease),transform 200ms var(--ease);
}
.pdp__swap:hover{border-color:var(--chalk);transform:translateX(4px)}
.pdp__swap img{width:clamp(54px,7vw,74px);height:auto;flex:none}
.pdp__swap-k{display:block;font-family:var(--data);font-size:12px;letter-spacing:.05em;text-transform:uppercase;color:var(--frost);margin-bottom:7px}
.pdp__swap-n{font-family:var(--display);font-size:clamp(1.1rem,2vw,1.5rem);text-transform:uppercase;letter-spacing:-.03em;line-height:1}
.pdp__swap-a{margin-left:auto;font-family:var(--data);font-size:13px;letter-spacing:.05em;color:var(--chalk)}


/* 19 FOOTER =============================================================== */
.footer{
  background:var(--asphalt);color:var(--chalk);
  margin:var(--frame);border-radius:var(--r-card);
  padding:var(--sec) 0 clamp(28px,3.4vw,42px);
  border:1px solid var(--hair-dark);
}
.footer__top{display:flex;flex-wrap:wrap;justify-content:space-between;gap:clamp(28px,4vw,56px);margin-bottom:clamp(40px,5vw,68px)}
.footer__lockup{--cap:28px}
.footer__cols{display:flex;flex-wrap:wrap;gap:clamp(28px,4vw,64px)}
.footer__cols div{display:flex;flex-direction:column;gap:11px}
.footer__h{font-family:var(--data);font-weight:500;font-size:12px;letter-spacing:.05em;text-transform:uppercase;color:var(--frost);margin:0 0 4px}
.footer__cols a{font-family:var(--data);font-size:13px;letter-spacing:.05em;text-transform:uppercase;color:var(--chalk);text-decoration:none}
.footer__cols a:hover{color:var(--frost)}
.footer__legal{margin-top:clamp(28px,3.4vw,42px);display:flex;flex-wrap:wrap;gap:14px clamp(20px,3.4vw,44px);align-items:flex-start}
.footer__legal p{margin:0;font-family:var(--data);font-size:12px;line-height:1.6;letter-spacing:.05em;text-transform:uppercase;color:var(--frost)}
.footer__legal p:last-of-type{max-width:60ch}
.footer__legal nav{display:flex;gap:18px;margin-left:auto}
.footer__legal a{font-family:var(--data);font-size:12px;letter-spacing:.05em;text-transform:uppercase;color:var(--frost);text-decoration:none}
.footer__legal a:hover{color:var(--chalk)}


/* 20 REVEAL =============================================================== */
.reveal{
  opacity:0;transform:translateY(16px);
  transition:opacity 240ms var(--ease),transform 240ms var(--ease);
  transition-delay:calc(var(--i,0) * 60ms);
}
.reveal.is-in{opacity:1;transform:none}


/* 21 RESPONSIVE =========================================================== */
@media (max-width:1024px){
  /* Orbit re-centres above the copy; the copy takes top padding so the
     headline clears the tin instead of sitting on top of it. */
  .orbit{top:0;left:50%;transform:translate(-50%,-14%);width:min(150%,720px)}
  .hero__copy{max-width:none;padding-top:min(52vw,300px)}
  /* The copy is full width here — no tin beside it — so the headline is fitted
     to the wrap instead of to the 62% column, which is worth far more size than
     the base rule allows. Full-width fit is 9.14vw from 500px up and ~8.85vw at
     360; 8.2vw clears both with margin (8.5 wrapped at 360 — it landed exactly
     on the fit). The vh term is doing real work in this range: the
     stacked hero also carries up to 300px of padding-top to clear the orbit, so
     a short landscape window is the one case where the card runs out of height
     before it runs out of width. */
  .hero__fuel{font-size:clamp(1.84rem,min(8.2vw,10vh),5.4rem)}
  .feats{grid-template-columns:1fr}
  .how__stages{grid-template-columns:repeat(2,1fr)}
  .story{grid-template-columns:1fr}
  .built__shots{grid-template-columns:1fr}
}
@media (max-width:820px){
  :root{--r-card:14px}
  .nav__links,.nav__cta{display:none}
  .nav__toggle{display:flex}
  .flavors__grid{grid-template-columns:1fr}
  /* Two bundle cards are comfortable at 1024; they only need stacking here. */
  .buy{grid-template-columns:1fr}
  /* The product hero stays side-by-side to 820, unlike the index hero: it has
     no orbit to make room for, and stacking it at 1024 put the card 145px past
     its scroll slot on a 1024x768 laptop. Stacked, the tin is then competing
     with the copy for the card's height, so it is capped against the viewport
     rather than only its width. */
  .pdp__hero{grid-template-columns:1fr;gap:clamp(18px,3vw,28px)}
  .pdp__tin{width:min(clamp(180px,40vw,320px),22svh)}
  .footer__top{flex-direction:column}
  .footer__legal nav{margin-left:0}
}
@media (max-width:560px){
  .stack__card{padding-top:calc(var(--nav-h) + 20px)}
  .how__stages{grid-template-columns:1fr;gap:9px}
  .stage{padding-top:9px}
  .stage__t{margin-bottom:4px}
  .stage__h3{margin-bottom:4px;font-size:12px}
  .stage p{font-size:.95rem;line-height:1.45}
  .how__clock{font-size:2.2rem}
  .capture__form{flex-direction:column}
  .capture__form .btn{width:100%}
  .pick__grid{grid-template-columns:1fr}
  .split__label{display:none}
  .timeline li{grid-template-columns:1fr;gap:6px}
}


/* 22 REDUCED MOTION =======================================================
   Everything at rest. JS additionally skips the loader, never starts the
   rAF loop, and never registers the scroll listener.
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important;
  }
  .reveal{opacity:1;transform:none}
  .stage{opacity:1;transform:none;border-top-color:var(--iron)}
  .split--track .split__fill{transform:scaleX(1)}
  /* Cards un-stick and simply flow. */
  .stack__item{height:auto}
  .stack__card{position:static;min-height:0;transform:none!important;opacity:1!important;margin-bottom:var(--frame)}
  /* The pan gives up scroll-scrubbing. It does NOT become a sideways scroller:
     that left the row clipped with two panels off the edge and a progress rule
     that could never fill, which read as an unfinished section. The panels wrap
     into a grid instead, so all five are visible and nothing is cut off. */
  .pan{overflow:visible;margin-right:0}
  /* 280px, so a desktop lands on 3+2 rather than a lopsided 4+1. */
  .pan__track{
    display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));
    width:auto;transform:none!important;
  }
  /* The min-height exists to give the pinned row a consistent panel size;
     stacked in a grid it only opens up voids, so the panels size to content. */
  .pan__panel{width:auto;min-height:0}
  .pan__foot{display:none}
  .pdp__tin{transform:none!important}
  /* Orbit holds a still, deliberate arrangement. */
  .orbit__ring,.marquee__track{animation-play-state:paused}
  .loader{display:none}
  html.js body>*:not(.loader){opacity:1}
  html.js.is-ready main{animation:none}
}
