/* ═══════════════════════════════════════════════════════════════
   TAO Clean — homepage prototype
   Theme values are set on :root by js/main.js from js/themes.js.
   ═══════════════════════════════════════════════════════════════ */

@font-face {
  font-family: 'Outfit';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../assets/fonts/outfit-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+2000-206F, U+20AC, U+2122, U+2212;
}
@font-face {
  font-family: 'Outfit';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../assets/fonts/outfit-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+1E00-1E9F, U+2020, U+20A0-20AB, U+20AD-20C0;
}

:root {
  /* overwritten per theme by JS — defaults = Seaglass Green, the
     DEFAULT_THEME, so the first paint matches what the module will
     apply (the old Midnight defaults made the hero glass jump) */
  --bg: #adc8be;
  --bg-2: #adc8be;
  --surface: rgba(255, 255, 255, .42);
  --surface-strong: rgba(244, 250, 247, .78);
  --ink: #1d2b24;
  --muted: #48604f;
  --accent: #3e6f5b;
  --accent-ink: #ffffff;
  --accent-strong: #38634f;
  --hairline: rgba(29, 43, 36, .13);
  --shadow: 0 24px 60px rgba(30, 40, 60, .14);
  --ring-opacity: .85;
  --ring-color: #ffffff;
  --ring-color-2: #adc8be;

  --ease: cubic-bezier(.33, .01, .18, 1);
  --theme-fade: .7s;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; overflow-x: clip; }

body {
  font-family: 'Outfit', 'Avenir Next', 'Segoe UI', sans-serif;
  font-weight: 380;
  background: var(--bg-2);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  transition: background-color var(--theme-fade) var(--ease), color var(--theme-fade) var(--ease);
  overflow-x: clip;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
svg { display: block; }

/* Ryan's call (2026-07-12): no focus rings anywhere — selected states
   carry their own permanent rings instead (mode toggle thumb, swatch
   selection ring), and inputs restyle their borders on focus */
:focus, :focus-visible { outline: none; }

/* ══════════════ NAV ══════════════ */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 24px;
  padding: 14px clamp(20px, 4.5vw, 64px);
  /* part of the hero until you scroll; glass fades in after */
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: border-color .5s var(--ease);
}
/* the glass lives on its own layer so it can FADE in — backdrop-filter
   itself can't transition from nothing, but the layer's opacity can */
.nav::before {
  content: "";
  position: absolute; inset: 0;
  z-index: -1;
  background: color-mix(in srgb, var(--bg-2) 52%, transparent);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  backdrop-filter: saturate(180%) blur(20px);
  opacity: 0;
  transition: opacity .5s var(--ease), background-color var(--theme-fade) var(--ease);
  pointer-events: none;
}
.nav.is-scrolled::before { opacity: 1; }
.nav.is-scrolled { border-bottom-color: color-mix(in srgb, var(--ink) 8%, transparent); }
.logo svg { height: 30px; width: auto; color: var(--ink); transition: color var(--theme-fade) var(--ease); }
.nav-links { display: flex; gap: clamp(16px, 2.6vw, 40px); }
.nav-links a {
  font-size: 15.5px;
  font-weight: 430;
  letter-spacing: .01em;
  color: var(--ink);
  opacity: .86;
  padding: 6px 2px;
  transition: opacity .2s, color var(--theme-fade) var(--ease);
}
.nav-links a:hover { opacity: 1; }
.nav-actions { display: flex; gap: 6px; justify-self: end; }
.icon-btn {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  width: 40px; height: 40px; border-radius: 50%;
  display: grid; place-items: center;
  color: var(--ink);
  transition: background-color .25s;
}
.icon-btn svg { width: 21px; height: 21px; }
.icon-btn:hover { background: var(--surface); }

/* ══════════════ HERO ══════════════ */
.hero {
  position: relative;
  min-height: min(85svh, 870px);
  display: flex;
  align-items: center;
  overflow: hidden;
  /* one dial (desktop): copy panel AND artwork ride down together as a
     pure visual offset — the hero's height (and everything below it,
     like the features card) never moves */
  --hero-drop: 18px;
}
.hero-art {
  position: absolute; inset: 0;
  background: var(--bg-2);
  overflow: hidden;
  transition: background-color var(--theme-fade) var(--ease);
}
.art {
  position: absolute; inset: 0;
}
.art img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 52% 24%;
  user-select: none;
  -webkit-user-drag: none;
}
/* Desktop: render the plate ~2× so brush + base match the mockups'
   scale (product ≈ 84% of hero height, centred right of the copy).
   The empty counter foreground of the wide renders crops away. */
@media (min-width: 921px) {
  .art img {
    inset: auto;
    top: calc(var(--hero-top, 0%) + var(--hero-drop, 0px));
    left: calc(50% + min(205px, 15.2vw) + 52px);   /* product hugs the copy column like the mockups; +100px for breathing room beside the glass panel */
    height: var(--hero-h, 188%);
    width: auto;
    max-width: none;
    transform: translateX(var(--hero-cx, -55.5%));  /* product centre in the render */
  }
  .hero-copy { margin-left: clamp(20px, 5.5vw, 74px); translate: 0 var(--hero-drop, 0px); }
}
/* each colorway is ONE entity (plate + product cutout) that fades as a
   unit — layer-level sync issues cannot exist by construction */
.art-layer {
  position: absolute; inset: 0;
  transition: opacity var(--theme-fade) var(--ease);  /* same clock as the page colors */
}
.art-layer-b { opacity: 0; }
/* product cutout inside its entity, positioned exactly like the plate;
   the canopy canvas paints ABOVE the entities but masks itself around
   the product silhouette, so shadows land on walls only */
.hero-brush { display: none; }
@media (min-width: 921px) {
  .hero-brush {
    display: block;
    position: absolute;
    inset: auto;
    top: calc(var(--hero-top, 0%) + var(--hero-drop, 0px));
    left: calc(50% + min(205px, 15.2vw) + 52px);
    height: var(--hero-h, 188%);
    width: auto;
    max-width: none;
    transform: translateX(var(--hero-cx, -55.5%));
    pointer-events: none;
    user-select: none;
    -webkit-user-drag: none;
  }
}
/* sea-glass only: animated canopy shadows pinned over the plate's
   top-left corner (the clip is the top-left 1415×796 of the native
   3000×1536 plate); right and bottom edges dissolve into the still */
.hero-leaf {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--theme-fade) var(--ease);
  /* wide edge feather so the video never seams against the plate behind
     it, on any colorway */
  --leaf-feather: 100px;
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - var(--leaf-feather)), transparent),
                      linear-gradient(to bottom, #000 calc(100% - var(--leaf-feather)), transparent);
  -webkit-mask-composite: source-in;
  mask-image: linear-gradient(to right, #000 calc(100% - var(--leaf-feather)), transparent),
              linear-gradient(to bottom, #000 calc(100% - var(--leaf-feather)), transparent);
  mask-composite: intersect;
}
@media (max-width: 920px) { .hero-leaf { display: none; } }
@media (prefers-reduced-motion: reduce) { .hero-leaf { display: none; } }
/* blend the plate's counter into the page background below.
   Solid colour under a static alpha mask (not a gradient) so the
   colour itself can fade on the same clock as everything else. */
.hero::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: -1px; height: 16%;
  background: var(--bg-2);
  mask-image: linear-gradient(to bottom, transparent, #000);
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000);
  pointer-events: none;
  transition: background-color var(--theme-fade) var(--ease);
}

.hero-inner {
  position: relative;
  z-index: 5;
  width: min(1240px, 92vw);
  margin: 0 auto;
  /* clears the fixed nav; with margin-bottom:0 on the copy this also
     centers the panel evenly in the space below the nav (desktop) */
  padding-top: 68px;
}

/* ── first-load curtain ──────────────────────────────────────────
   The hero holds as a flat theme-colored stage until every layer
   (plate, cutout, canopy) is decoded and rendered, then everything
   fades up together — the copy panel rises into place a beat later. */
.hero-art { opacity: 0; }
.hero-inner { translate: 0 14px; }
/* fade CONTENT and tint, never the .hero-copy ancestor — backdrop-filter
   turns off inside opacity-animating ancestors and pops back at 1,
   which read as the pane changing transparency on load */
.hero-copy > * { opacity: 0; }
html.hero-ready .hero-art {
  opacity: 1;
  transition: opacity 1s var(--ease);
}
html.hero-ready .hero-inner {
  translate: 0 0;
  transition: translate 1s var(--ease) .18s;
}
html.hero-ready .hero-copy > * {
  opacity: 1;
  transition: opacity 1s var(--ease) .18s;
}
@media (prefers-reduced-motion: reduce) {
  .hero-art { opacity: 1; }
  .hero-inner { translate: none; }
  .hero-copy > * { opacity: 1; }
  html.hero-ready .hero-art, html.hero-ready .hero-inner,
  html.hero-ready .hero-copy > * { transition: none; }
}

/* frosted-glass panel lifts the copy off the busy product render so it
   reads cleanly on every colorway; fill + border derive from the theme
   so it adapts across light and dark modes */
.hero-copy {
  position: relative;
  --hero-row: 420px;
  max-width: 462px;
  margin-bottom: 0;
}
/* borderless legibility scrim, in two parts so color flips are perfect:
   ::before is the BLUR pane (identical for every theme — never fades);
   .copy-scrim holds two tint layers that opacity-crossfade in the same
   frame and on the same clock as the hero plate entities */
.hero-copy::before {
  content: "";
  position: absolute;
  inset: -48px -58px -56px -60px;
  z-index: -1;
  /* backdrop-filter clips to the border-box (it ignores the mask), so
     round the box generously to soften the glass edges */
  border-radius: 44px;
  -webkit-backdrop-filter: blur(12px) saturate(1.15);
  backdrop-filter: blur(12px) saturate(1.15);
  /* radial feather × right-edge dissolve: the glass thins from ~68% and
     is gone by the box edge, so the pane melts into the artwork the way
     the bottom does (stops start past the text column) */
  -webkit-mask-image: radial-gradient(ellipse at 44% 42%, #000 42%, transparent 78%),
                      linear-gradient(to right, #000 68%, transparent);
  -webkit-mask-composite: source-in;
  mask-image: radial-gradient(ellipse at 44% 42%, #000 42%, transparent 78%),
              linear-gradient(to right, #000 68%, transparent);
  mask-composite: intersect;
  pointer-events: none;
}
.copy-scrim {
  position: absolute;
  inset: -48px -58px -56px -60px;
  z-index: -1;
  pointer-events: none;
  /* same right-edge dissolve as the blur pane — one mask covers both
     tint layers so the crossfade pair can never disagree */
  -webkit-mask-image: linear-gradient(to right, #000 68%, transparent);
  mask-image: linear-gradient(to right, #000 68%, transparent);
}
.copy-scrim::before, .copy-scrim::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 44px;
  transition: opacity var(--theme-fade) var(--ease);   /* same spec as .art-layer */
}
.copy-scrim.no-fade::before, .copy-scrim.no-fade::after { transition: none; }
.copy-scrim::before {
  background: radial-gradient(ellipse at 44% 42%,
      color-mix(in srgb, var(--scrim-a, var(--bg-2)) 80%, transparent) 0%,
      color-mix(in srgb, var(--scrim-a, var(--bg-2)) 52%, transparent) 50%,
      transparent 78%);
  opacity: var(--scrim-a-op, 1);
}
.copy-scrim::after {
  background: radial-gradient(ellipse at 44% 42%,
      color-mix(in srgb, var(--scrim-b, var(--bg-2)) 80%, transparent) 0%,
      color-mix(in srgb, var(--scrim-b, var(--bg-2)) 52%, transparent) 50%,
      transparent 78%);
  opacity: var(--scrim-b-op, 0);
}

.pill {
  display: inline-block;
  font-size: 12.5px;
  font-weight: 560;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--accent-strong, var(--accent));
  background: var(--surface);
  border: 1px solid var(--hairline);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  padding: 8px 16px;
  border-radius: 999px;
  margin-bottom: 22px;
  transition: color var(--theme-fade) var(--ease), background-color var(--theme-fade) var(--ease), border-color var(--theme-fade) var(--ease);
}

.hero-copy h1 {
  font-size: clamp(52px, 6.4vw, 86px);
  font-weight: 590;
  letter-spacing: -.022em;
  line-height: 1.02;
}
.hero-copy .sub {
  font-size: clamp(21px, 2.1vw, 27px);
  font-weight: 400;
  color: var(--accent-strong, var(--accent));
  margin: 10px 0 18px;
  transition: color var(--theme-fade) var(--ease);
}

/* rating row — score · stars · review count, hairline rule below */
.rating {
  display: flex;
  align-items: center;
  gap: 15px;
  padding-bottom: 24px;
  margin-bottom: 26px;
  max-width: var(--hero-row, 420px);   /* rule matches the swatch row */
  border-bottom: 1px solid var(--hairline);
  transition: border-color var(--theme-fade) var(--ease);
}
.rating-score {
  font-size: 21px;
  font-weight: 560;
  letter-spacing: .01em;
}
.stars { display: flex; gap: 4px; color: var(--accent-strong, var(--accent)); transition: color var(--theme-fade) var(--ease); }
.stars svg { width: 24px; height: 24px; }
.rating-count { font-size: 17px; font-weight: 420; opacity: .92; }

.hero-points { list-style: none; display: grid; gap: 15px; margin-bottom: 36px; }
.hero-points li {
  display: flex; align-items: center; gap: 14px;
  font-size: 17.5px; font-weight: 410;
}
.pt-ic {
  flex: 0 0 auto;
  width: 24px; height: 24px;
  color: var(--accent-strong, var(--accent));
  transition: color var(--theme-fade) var(--ease);
}
.pt-ic svg { width: 100%; height: 100%; }

.cta-row { display: flex; align-items: center; gap: 26px; flex-wrap: wrap; }
/* combined Add to Cart + price pill (per the panel mockup) */
.btn-cart {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  width: var(--hero-row, 420px);   /* same width as the swatch row */
  max-width: 100%;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 19.5px;
  font-weight: 520;
  padding: 18px 28px;
  border-radius: 15px;
  box-shadow: 0 10px 28px color-mix(in srgb, var(--accent) 34%, transparent);
  transition: transform .25s var(--ease), box-shadow .25s var(--ease),
              background-color var(--theme-fade) var(--ease), color var(--theme-fade) var(--ease);
}
.btn-cart:hover { transform: translateY(-2px); box-shadow: 0 16px 34px color-mix(in srgb, var(--accent) 44%, transparent); }
.btn-cart:active { transform: translateY(0); }
.cart-ic { width: 26px; height: 26px; }
.cart-div {
  width: 1px;
  height: 28px;
  margin: 0 12px;
  background: color-mix(in srgb, var(--accent-ink) 38%, transparent);
}
.cart-price { font-size: 21px; font-weight: 580; letter-spacing: .01em; }
.btn-primary {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 16.5px; font-weight: 500;
  padding: 15px 28px;
  border-radius: 12px;
  box-shadow: 0 10px 28px color-mix(in srgb, var(--accent) 34%, transparent);
  transition: transform .25s var(--ease), box-shadow .25s var(--ease),
              background-color var(--theme-fade) var(--ease), color var(--theme-fade) var(--ease);
}
.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 16px 34px color-mix(in srgb, var(--accent) 44%, transparent); }
.btn-primary:active { transform: translateY(0); }
.btn-primary svg { width: 18px; height: 18px; }
.btn-ghost {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 16.5px; font-weight: 450;
  color: var(--ink); opacity: .85;
  transition: opacity .2s, color var(--theme-fade) var(--ease);
}
.btn-ghost:hover { opacity: 1; }
.btn-ghost svg { width: 17px; height: 17px; transition: transform .25s; }
.btn-ghost:hover svg { transform: translateY(2px); }

/* colorway picker — lives right under the CTA row */
.hero-trust {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  max-width: var(--hero-row, 420px);
  margin-top: 18px;
  font-size: 15.5px; font-weight: 460;
  color: var(--ink);
  transition: color var(--theme-fade) var(--ease);
}
.hero-trust svg { width: 19px; height: 19px; flex: 0 0 auto; color: var(--accent-strong, var(--accent)); }
.ht-div { width: 1px; height: 16px; background: var(--hairline); margin: 0 6px; }

.picker { margin-top: 26px; }
.swatches {
  display: flex; gap: 9px; flex-wrap: nowrap;
  width: var(--hero-row, 420px);
  justify-content: center;
  padding: 2px;
}
.swatch {
  appearance: none; border: 0; cursor: pointer;
  flex: 0 0 auto;
  width: 24px; height: 24px;
  border-radius: 50%;
  /* softly dimensional, mostly flat */
  background:
    radial-gradient(circle at 34% 28%, rgba(255,255,255,.34), rgba(255,255,255,.06) 42%, transparent 62%),
    var(--sw, #888);
  box-shadow:
    inset 0 0 0 1px rgba(0,0,0,.16),   /* same ring as the sticky bar's dot */
    0 2px 5px rgba(0,0,0,.16),
    inset 0 -2px 3px rgba(0,0,0,.10);
  transition: transform .2s var(--ease);
}
.swatch:hover { transform: scale(1.2); }
.swatch[aria-selected="true"],
.swatch:focus-visible {
  outline: none;
  box-shadow:
    0 0 0 1px #fff,
    0 4px 9px rgba(0,0,0,.26),
    inset 0 -2px 3px rgba(0,0,0,.10);
}
.picker-label {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  max-width: var(--hero-row, 420px);   /* centres under the swatch row */
  margin-top: 14px;
  font-size: 12px;
  font-weight: 540;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color var(--theme-fade) var(--ease);
}
/* quiet labeled pill so the auto-cycle control explains itself */
.picker-play {
  appearance: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px 4px 8px;
  border-radius: 999px;
  border: 1px solid var(--hairline);
  background: transparent;
  color: var(--muted);
  font: inherit;
  transition: background-color .2s, color .2s, border-color .2s;
}
.picker-play .pp-label {
  font-size: 10.5px;
  font-weight: 540;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.picker-play:hover {
  background: color-mix(in srgb, var(--ink) 8%, transparent);
  color: var(--ink);
  border-color: color-mix(in srgb, var(--ink) 22%, transparent);
}
.picker-play svg { width: 12px; height: 12px; }
.picker-play[aria-pressed="true"] {
  color: var(--accent-strong, var(--accent));
  border-color: color-mix(in srgb, var(--accent-strong, var(--accent)) 45%, transparent);
}

/* ══════════════ FEATURE STRIP ══════════════ */
.features { position: relative; z-index: 6; padding: 0 clamp(16px, 4vw, 56px); margin-top: -8px; }
/* the quad rides the same first-load curtain as the hero, a beat later.
   The card fades via its OWN opacity (safe: only ANCESTOR opacity
   disables backdrop-filter) — the .feat columns belong to the
   scroll-reveal system and are left alone */
.features { translate: 0 14px; }
.feature-card { opacity: 0; }
html.hero-ready .features {
  translate: 0 0;
  transition: translate 1s var(--ease) .32s;
}
html.hero-ready .feature-card {
  opacity: 1;
  transition: opacity 1s var(--ease) .32s,
              background-color var(--theme-fade) var(--ease),
              border-color var(--theme-fade) var(--ease),
              box-shadow var(--theme-fade) var(--ease),
              --tile-a var(--theme-fade) var(--ease), --tile-b var(--theme-fade) var(--ease);
}
@media (prefers-reduced-motion: reduce) {
  .features { translate: none; }
  .feature-card { opacity: 1; }
  html.hero-ready .features, html.hero-ready .feature-card { transition: none; }
}
.feature-card {
  width: min(1240px, 100%);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  /* badge tiles: ink-gradient lens on light colorways (see .feat-badge);
     the markup references ONLY the dark icon renders now — they were
     drawn for dark glass and that's where they look their best */
  --tile-a: color-mix(in srgb, var(--ink) 72%, var(--bg-2));
  --tile-b: color-mix(in srgb, var(--ink) 92%, var(--bg-2));
  border: 1px solid color-mix(in srgb, #fff 30%, var(--hairline));
  backdrop-filter: blur(28px) saturate(1.5);
  -webkit-backdrop-filter: blur(28px) saturate(1.5);
  border-radius: 26px;
  box-shadow: var(--shadow), inset 0 1px 0 color-mix(in srgb, #fff 35%, transparent);
  padding: 44px 10px;
  transition: background-color var(--theme-fade) var(--ease), border-color var(--theme-fade) var(--ease),
              box-shadow var(--theme-fade) var(--ease),
              --tile-a var(--theme-fade) var(--ease), --tile-b var(--theme-fade) var(--ease);
  /* own compositor layer: the hero plates opacity-crossfade right under
     this glass on every color flip, and Chromium sometimes drops the
     card's painted content when its backdrop keeps invalidating */
  transform: translateZ(0);
  isolation: isolate;
}
/* the card's fill lives on two stacked layers that opacity-crossfade in
   the same frame as the hero plates (see scrimTo in main.js) — a plain
   background color would fade on the CSS color clock and drift */
.feature-card::before, .feature-card::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 26px;
  z-index: -1;
  transition: opacity var(--theme-fade) var(--ease);
  pointer-events: none;
}
.feature-card.no-fade::before, .feature-card.no-fade::after { transition: none; }
.feature-card::before { background: var(--card-a, var(--surface)); opacity: var(--card-a-op, 1); }
.feature-card::after  { background: var(--card-b, var(--surface)); opacity: var(--card-b-op, 0); }
/* dark colorways: theme surfaces go muddy — use classic white-on-dark glass */
body[data-mode="dark"] .feature-card {
  border-color: rgba(255, 255, 255, .16);
  box-shadow: var(--shadow), inset 0 1px 0 rgba(255, 255, 255, .12);
}
.feat {
  text-align: center;
  padding: 6px 26px;
  border-left: 1px solid var(--hairline);
  transition: border-color var(--theme-fade) var(--ease);
}
.feat:first-child { border-left: 0; }
/* the badge tile's gradient stops are REGISTERED colors so the gradient
   itself can ride the theme clock — plain background-image never
   transitions, and an ink-derived fill would snap on every color flip */
@property --tile-a { syntax: '<color>'; inherits: true; initial-value: #1a1f28; }
@property --tile-b { syntax: '<color>'; inherits: true; initial-value: #0b0f16; }
.feat-badge {
  position: relative;
  display: grid; place-items: center;
  width: 48px; height: 48px; margin: 0 auto 12px;
  border-radius: 15px;   /* smoked squircle */
  overflow: hidden;
  /* ink-gradient lens, lit from above — dark enough on every light
     colorway that the icons keep their on-black contrast */
  background: linear-gradient(180deg, var(--tile-a), var(--tile-b));
  border: 1px solid rgba(255, 255, 255, .28);
  -webkit-backdrop-filter: blur(10px) saturate(1.4);
  backdrop-filter: blur(10px) saturate(1.4);
  box-shadow: 0 8px 20px color-mix(in srgb, var(--ink) 25%, transparent),
              inset 0 1px 0 rgba(255, 255, 255, .22);
  transition: background-color var(--theme-fade) var(--ease),
              border-color var(--theme-fade) var(--ease),
              box-shadow var(--theme-fade) var(--ease);
}
.feat-vid {
  display: block; width: 100%; height: 100%;
  border-radius: 14px; object-fit: cover;   /* alpha renders — lens shows through */
  transition: opacity var(--theme-fade) var(--ease);
}
/* dark-variant videos stack on their light twins and crossfade with the
   plates (opacity flips inside scrimTo, same frame/clock) */
.feat-vid-dark { position: absolute; inset: 0; opacity: var(--featdark-op, 0); }
.feat-badge:has(.feat-vid-dark) > .feat-vid:not(.feat-vid-dark) { opacity: calc(1 - var(--featdark-op, 0)); }
.feature-card.no-fade .feat-vid { transition: none; }
/* dark colorways: both gradient stops collapse to the classic smoked
   lens — pixel-identical to the old flat fill, and because only the
   registered colors change, light↔dark flips fade instead of snapping */
body[data-mode="dark"] .feature-card {
  --tile-a: rgba(8, 13, 22, .62);
  --tile-b: rgba(8, 13, 22, .62);
}
body[data-mode="dark"] .feat-badge {
  border-color: transparent;   /* rim vanishes but keeps its 1px of layout — border:0 resized the videos on theme flips */
  box-shadow: 0 8px 20px rgba(0, 0, 0, .18),
              inset 0 1px 0 rgba(255, 255, 255, .18),
              inset 0 -2px 3px rgba(255, 255, 255, .12);   /* light catches the lower curve */
}
.feat h3 { font-size: 17.5px; font-weight: 560; margin-bottom: 8px; }
.feat p { font-size: 15px; line-height: 1.55; color: var(--muted); transition: color var(--theme-fade) var(--ease); }

/* ══════════════ SONIC ══════════════ */
.sonic { padding: 0 clamp(16px, 4vw, 56px); overflow: clip; }
.sonic-inner {
  width: min(1140px, 100%);
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(24px, 5vw, 80px);
}
.sonic-stage {
  position: relative;
  height: clamp(380px, 48vh, 470px);
  --wave-y: 30%;                    /* bristle-head anchor for the brush */
  --ripple-y: 37%;                  /* wave origin: bottom of the bristles */
  --wave-x: calc(50% + 15px);       /* bristle mass sits right of stem centre */
}
/* ambient light emission around the head */
.sonic-stage::before {
  content: '';
  position: absolute;
  left: var(--wave-x); top: var(--ripple-y);
  width: min(150%, 820px);
  aspect-ratio: 1;
  translate: -50% -50%;
  background: radial-gradient(circle,
    color-mix(in srgb, var(--ring-color) var(--ring-halo, 16%), transparent) 0%,
    transparent 62%);
  pointer-events: none;
}
body[data-mode="dark"] .sonic { --ring-halo: 26%; }
/* brushing mode: Clean runs the waves at double playbackRate (set in
   pdp.js so the retime is seamless); Gentle softens the rings to 67% */
.sonic-stage[data-brushmode="gentle"] .rings { opacity: .67; }
/* waves fade out on the old palette and back in on the new one */
.rings, .sonic-stage::before { transition: opacity .3s var(--ease); }
.sonic-stage.wave-out .rings, .sonic-stage.wave-out::before { opacity: 0; }

.rings {
  position: absolute;
  width: min(150%, 820px);
  aspect-ratio: 1;
  left: var(--wave-x); top: var(--ripple-y);
  translate: -50% -50%;
  overflow: visible;
}
/* Uniform, non-scaling strokes keep every ring identical to the one it
   replaces at the loop point — the wrap is invisible. Brightness grading
   (--o0 → --o1) hands each ring the opacity of its successor for the
   same reason. */
.ring {
  fill: none;
  /* colour drifts from --ring-color (origin) to --ring-color-2 (rim);
     each ring ends on its successor's mix so the loop stays seamless */
  stroke: color-mix(in srgb, var(--ring-color-2) var(--m1, 0%), var(--ring-color, var(--accent-strong)));
  stroke-width: 4.5;
  vector-effect: non-scaling-stroke;
  opacity: calc(var(--ring-opacity) * var(--o1));
  transform-box: fill-box;
  transform-origin: center;
  animation: ripple 4.2s linear infinite;
}
.glowlayer .ring { stroke-width: 20; --glowmul: .5; }
.midlayer .ring { stroke-width: 10; --glowmul: .78; }
@keyframes ripple {
  from {
    transform: scale(1);
    stroke: color-mix(in srgb, var(--ring-color-2) var(--m0, 0%), var(--ring-color, var(--accent-strong)));
    opacity: calc(var(--ring-opacity) * var(--o0) * var(--glowmul, 1));
  }
  to {
    transform: scale(var(--grow));
    stroke: color-mix(in srgb, var(--ring-color-2) var(--m1, 0%), var(--ring-color, var(--accent-strong)));
    opacity: calc(var(--ring-opacity) * var(--o1) * var(--glowmul, 1));
  }
}
.brushhead {
  position: absolute;
  left: 50%; top: var(--wave-y);
  height: 175%;
  width: auto;
  transform: translate(-50%, -10.8%);
  object-fit: contain;
  filter: drop-shadow(0 16px 26px rgba(0,0,0,.25));
}
/* isolated bristles layer micro-shivers over the rigid handle (sonic
   hum) — Ryan's tuned physics: 0.035s loop, 2.5px width, no vertical
   jitter, 0.8px blur, no glow. Keyframes carry the base centering
   transform since transform is overwritten by the animation. */
.brushhead-bristles {
  --vpm-speed: 0.015s;
  --vpm-x: 2.3px;
  --vpm-y: 0px;
  --vpm-blur: 0.8px;
  --vpm-glow: 0px;
  filter: drop-shadow(0 0 var(--vpm-glow) rgba(14, 165, 233, .35)) blur(var(--vpm-blur));
  will-change: transform, filter;
  animation: sonicShiver var(--vpm-speed) infinite linear;
}
@keyframes sonicShiver {
  0%   { transform: translate(-50%, -10.8%); }
  20%  { transform: translate(calc(-50% - var(--vpm-x)), calc(-10.8% + 0.5 * var(--vpm-y))) rotate(-0.1deg); }
  40%  { transform: translate(calc(-50% + 0.7 * var(--vpm-x)), calc(-10.8% - var(--vpm-y))) rotate(0.1deg); }
  60%  { transform: translate(calc(-50% - 0.8 * var(--vpm-x)), calc(-10.8% + 0.5 * var(--vpm-y))) rotate(-0.05deg); }
  80%  { transform: translate(calc(-50% + var(--vpm-x)), calc(-10.8% - 0.5 * var(--vpm-y))) rotate(0.05deg); }
  100% { transform: translate(-50%, -10.8%); }
}
@media (prefers-reduced-motion: reduce) {
  .brushhead-bristles { animation: none; filter: none; }
}
.sonic-copy { position: relative; z-index: 2; }   /* text always above the waves */
.eyebrow {
  font-size: 13px; font-weight: 560;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--accent-strong, var(--accent));
  margin-bottom: 16px;
  transition: color var(--theme-fade) var(--ease);
}
.sonic-copy h2 {
  font-size: clamp(36px, 4.2vw, 56px);
  font-weight: 580;
  letter-spacing: -.018em;
  line-height: 1.06;
  margin-bottom: 20px;
}
.sonic-copy .body {
  font-size: 17.5px; line-height: 1.65;
  color: var(--muted);
  max-width: 44ch;
  margin-bottom: 26px;
  transition: color var(--theme-fade) var(--ease);
}
.text-link {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 16.5px; font-weight: 500;
  color: var(--accent-strong, var(--accent));
  transition: color var(--theme-fade) var(--ease);
}
.text-link svg { width: 17px; height: 17px; transition: transform .25s; }
.text-link:hover svg { transform: translateX(4px); }

/* ══════════════ TRUST ══════════════ */
.trust { padding: 0 clamp(16px, 4vw, 56px) clamp(44px, 6.5vh, 76px); }
.trust-card {
  width: min(1240px, 100%);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  background: var(--surface);
  border: 1px solid var(--hairline);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border-radius: 22px;
  padding: 30px 8px;
  transition: background-color var(--theme-fade) var(--ease), border-color var(--theme-fade) var(--ease);
}
.tr-item {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  padding: 8px 12px;
  border-left: 1px solid var(--hairline);
  color: var(--ink);
  transition: color var(--theme-fade) var(--ease), border-color var(--theme-fade) var(--ease);
}
.tr-item:first-child { border-left: 0; }
.tr-item svg { width: 30px; height: 30px; flex: 0 0 auto; color: var(--accent-strong, var(--accent)); transition: color var(--theme-fade) var(--ease); }
.tr-item p { font-size: 16px; font-weight: 450; line-height: 1.45; white-space: nowrap; }
@media (max-width: 1240px) {
  .tr-item p { white-space: normal; font-size: 14.5px; }
}

/* ══════════════ ABOUT / VIDEO ══════════════ */
.about { padding: 0 clamp(16px, 4vw, 56px) clamp(80px, 11vh, 140px); }
.about-inner { width: min(1240px, 100%); margin: 0 auto; text-align: center; }
.about h2 {
  font-size: clamp(34px, 4vw, 52px);
  font-weight: 580;
  letter-spacing: -.018em;
  line-height: 1.06;
  margin-bottom: 16px;
}
.about .body {
  font-size: 17.5px; line-height: 1.65;
  color: var(--muted);
  margin-bottom: 30px;
  transition: color var(--theme-fade) var(--ease);
}
.video-frame {
  position: relative;
  border-radius: 26px;
  aspect-ratio: 16 / 9;
  box-shadow: var(--shadow);
  transition: box-shadow var(--theme-fade) var(--ease);
  /* own stacking context so the z:-1 ambilight resolves inside the frame */
  isolation: isolate;
}
/* geometric clip (not overflow:hidden): composites cleanly on retina
   Chrome (no dark corner AA fringe on the composited <video>) and
   keeps the rounding on iOS — fix carried over from ryanpamplin.com */
.video-inner {
  position: absolute; inset: 0;
  border-radius: 26px;
  clip-path: inset(0 round 26px);
  background: #000;
  z-index: 0;
  isolation: isolate;
}
/* ambilight: blurred, color-matched copy of the current frame glowing
   around the player (drawn by a 30fps loop in main.js) */
.ambilight {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  z-index: -1;
  pointer-events: none;
  border-radius: 26px;
  transform: scale(1.08) translateZ(0);
  filter: blur(64px) saturate(170%) opacity(.5);
}
.video-frame video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
/* premium glass play button */
.video-cycle { position: absolute; inset: 0; z-index: 1; transition: opacity .45s var(--ease); }
.video-cycle img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity .9s var(--ease);
}
.video-cycle img.on { opacity: 1; }
.video-frame.playing .video-cycle { opacity: 0; pointer-events: none; }
.video-play {
  position: absolute;
  left: 50%; top: 50%;
  translate: -50% -50%;
  z-index: 2;
  width: clamp(88px, 12vw, 136px);
  aspect-ratio: 1;
  border-radius: 50%;
  border: 1.5px solid rgba(255,255,255,.55);
  background: rgba(255,255,255,.16);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: #fff;
  display: grid; place-items: center;
  cursor: pointer;
  box-shadow: 0 10px 40px rgba(0,0,0,.35);
  transition: transform .25s var(--ease), background-color .25s, opacity .3s var(--ease);
}
.video-play svg { width: 52%; height: 52%; margin-left: 3%; }
.video-play:hover { transform: scale(1.07); background: rgba(255,255,255,.26); }
.video-frame.playing .video-play { opacity: 0; pointer-events: none; }

/* ══════════════ FOOTER ══════════════ */
.footer {
  border-top: 1px solid var(--hairline);
  padding: 44px clamp(20px, 4.5vw, 64px) 120px;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 28px;
  transition: border-color var(--theme-fade) var(--ease);
}
.logo-footer svg { height: 24px; opacity: .9; }
.foot-links { display: flex; gap: 26px; justify-self: center; flex-wrap: wrap; }
.foot-links a { font-size: 14.5px; color: var(--muted); transition: color .2s; }
.foot-links a:hover { color: var(--ink); }
.fineprint { font-size: 13px; color: var(--muted); justify-self: end; transition: color var(--theme-fade) var(--ease); }

/* ══════════════ RESPONSIVE ══════════════ */
@media (max-width: 1080px) {
  .nav { grid-template-columns: auto 1fr auto; }
  .nav-links { justify-self: center; }
}
@media (max-width: 920px) {
  .nav-links { display: none; }
  .hero { align-items: flex-end; }
  .hero-inner { padding-top: 110px; }
  .hero-copy {
    max-width: 560px;
    margin-bottom: 6svh;
    padding: 24px 26px;
  }
  .art img { object-position: 52% 24%; }
  .feature-card { grid-template-columns: 1fr 1fr; row-gap: 34px; }
  .feat:nth-child(3) { border-left: 0; }
  .sonic-inner { grid-template-columns: 1fr; }
  .sonic-stage { order: 2; height: 36vh; }
  .sonic-copy { order: 1; text-align: center; }
  .sonic-copy .body { margin-inline: auto; }
  .trust-card { grid-template-columns: 1fr 1fr; row-gap: 22px; }
  .tr-item:nth-child(3) { border-left: 0; }
  .tr-item { justify-content: flex-start; }
  .footer { grid-template-columns: 1fr; justify-items: center; text-align: center; }
  .fineprint, .foot-links { justify-self: center; }
}
@media (max-width: 560px) {
  .feature-card { grid-template-columns: 1fr; }
  .feat { border-left: 0; border-top: 1px solid var(--hairline); padding-top: 26px; }
  .feat:first-child { border-top: 0; padding-top: 6px; }
  .trust-card { grid-template-columns: 1fr; }
  .tr-item { border-left: 0; }
  .cta-row { gap: 18px; }
}

/* ══════════════ MOTION PREFERENCES ══════════════ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .ring { animation: none; opacity: calc(var(--ring-opacity) * var(--o1)); transform: none; }
  .btn-primary, .btn-ghost svg, .text-link svg, .swatch { transition: none; }
}

/* ══════════════ WAVE TUNER (dev tool — remove with js/tuner.js) ══════════════ */
.wtuner {
  position: fixed;
  right: 16px; bottom: 16px;
  z-index: 300;
  width: 236px;
  background: rgba(16, 18, 24, .92);
  color: #e8ebf2;
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 14px;
  font-size: 12px;
  box-shadow: 0 14px 44px rgba(0,0,0,.4);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.wt-head {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px;
}
.wt-head strong { font-weight: 600; }
.wt-theme { color: #9aa3b5; margin-left: auto; }
.wt-min {
  appearance: none; border: 0; cursor: pointer;
  width: 20px; height: 20px; border-radius: 6px;
  background: rgba(255,255,255,.12); color: #e8ebf2;
  line-height: 1;
}
.wt-body { padding: 2px 12px 12px; display: grid; gap: 8px; }
.wt-collapsed .wt-body { display: none; }
.wt-row {
  display: grid;
  grid-template-columns: 52px 34px 1fr;
  align-items: center; gap: 8px;
}
.wt-row input[type="color"] {
  width: 34px; height: 26px; padding: 0; border: 0;
  background: none; cursor: pointer;
}
.wt-row input[type="text"] {
  width: 100%; padding: 5px 8px;
  background: rgba(255,255,255,.08);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: 8px;
  color: #e8ebf2; font: inherit; letter-spacing: .04em;
}
.wt-row input[type="range"] { width: 100%; grid-column: 2 / 3; accent-color: #7fa3e8; }
.wt-row span { color: #9aa3b5; text-align: right; }
.wt-btns { display: flex; gap: 6px; }
.wt-btns button {
  appearance: none; border: 0; cursor: pointer;
  flex: 1;
  padding: 7px 0;
  border-radius: 8px;
  background: rgba(255,255,255,.12);
  color: #e8ebf2; font: inherit; font-size: 11.5px;
}
.wt-btns button:hover { background: rgba(255,255,255,.2); }
.wtuner textarea {
  width: 100%; resize: vertical;
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 8px;
  color: #b9c1d2;
  font: 10.5px/1.4 ui-monospace, monospace;
  padding: 6px 8px;
}

/* boot guard: no transitions until the saved theme is fully applied */
html.no-fade body, html.no-fade * { transition: none !important; }
