/* ============================================================
   Sokai Sciences — design tokens (real brand palette)
   Sciences = crystal light bg + sky blue / navy / indigo / mist
   Type: Fraunces (display, editorial serif) / IBM Plex Sans (body) /
   IBM Plex Mono (spec data, numbered-section eyebrows)

   Visual language rebuilt to closely track a client reference
   (scfo.de)'s structure — numbered sections, a scroll-spy sidebar, and
   a persistent scroll-choreographed 3D scene
   (public/js/molecule-scene.js) that swaps pose per homepage section —
   but recolored to Sokai's own light brand palette rather than the
   reference's black. Every surface (cards, forms, the molecule-scene's
   own materials, nav) is a *light*-glass treatment now, not a dark one:
   see the `--card-on-dark`/`--glass-*` token comment below for how that
   flip was done without renaming every call site. The footer and the
   nav pill/hamburger both stay on dark navy bands, deliberately —
   Sokai's own brand tokens already treat "--origin-navy" as the
   shared-identity contrast color (matching sokai.io's shell), so a
   dark anchor at the very top and very bottom of an otherwise light
   page is brand-consistent, not a leftover from the fully-dark pass
   this replaced. See "Design system" in README for the full breakdown.
   ============================================================ */

:root {
  --crystal: #F4F4F4;
  --crystal-2: #ECEEF8;
  --white: #FFFFFF;
  --slate: #161616;
  --beaker: #4D495B;

  --sky: #2132D0;
  --navy: #05106E;
  --indigo: #231DB3;
  --mist: #B7CBF2;

  --origin-navy: #060638;
  --origin-navy-2: #0C0A4A;
  --spark: #FF90A5;
  --accent-amber: #B8781F;
  --danger: #C0392B;

  --line: rgba(5, 16, 110, 0.12);
  --line-strong: rgba(5, 16, 110, 0.24);

  /* Glass-surface tokens — nav pill/hamburger (still dark-glass, see
     above), and, as of this pass, every card/input/tilted-section-wash
     sitewide is *light*-glass instead: --card-on-dark and
     --card-on-dark-hover keep their names (touched by dozens of rules —
     product cards, cart summary, trust/stat/about cards, form fields,
     step rows, FAQ items) but now hold a subtle navy-tinted-on-white
     value instead of a white-tinted-on-black one, so every rule that
     already referenced them picked up the flip for free. Same idea for
     --line-on-dark (grid-lines, marquee border) and --glass-border. */
  --glass-bg: rgba(9, 9, 58, 0.66);
  --glass-border: rgba(5, 16, 110, 0.14);
  --line-on-dark: rgba(5, 16, 110, 0.08);
  --card-on-dark: rgba(5, 16, 110, 0.035);
  --card-on-dark-hover: rgba(5, 16, 110, 0.06);

  --font-display: 'Fraunces', ui-serif, Georgia, 'Times New Roman', serif;
  --font-body: 'IBM Plex Sans', ui-sans-serif, system-ui, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'SFMono-Regular', monospace;

  --container: 1200px;
  --radius: 4px;
  --radius-pill: 999px;
  --shadow-card: 0 1px 2px rgba(5, 16, 110, 0.06), 0 12px 32px rgba(5, 16, 110, 0.08);
}

/* ---------- Reset ---------- */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--crystal);
  color: var(--slate);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; margin: 0; padding: 0; }
button { font: inherit; cursor: pointer; }
input, select { font: inherit; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.05;
  margin: 0 0 0.5em;
  letter-spacing: -0.005em;
}
h1 em, h2 em, h3 em, h4 em { font-style: italic; font-weight: 500; }
p { margin: 0 0 1em; }

:focus-visible {
  outline: 2px solid var(--sky);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}

/* ---------- Layout ---------- */
.container {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 24px;
}

.section { padding: 80px 0; }
.section--tight { padding: 44px 0; }

/* ---------- Mono / eyebrow / hex-tag / spec text ---------- */
.mono {
  font-family: var(--font-mono);
  letter-spacing: 0.02em;
}
.eyebrow {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sky);
}
.eyebrow--muted { color: var(--beaker); }
.eyebrow--on-dark { color: var(--sky); }

.hex-tag {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--mist);
  opacity: 0.85;
}

.spec-list {
  font-family: var(--font-mono);
  font-size: 13px;
  border-top: 1px solid var(--line);
}
.spec-list__row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}
.spec-list__label {
  color: var(--beaker);
  white-space: nowrap;
}
.spec-list__leader {
  flex: 1;
  border-bottom: 1px dotted var(--line-strong);
  height: 0;
  transform: translateY(-4px);
}
.spec-list__value {
  white-space: nowrap;
  color: var(--slate);
  font-weight: 500;
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 26px;
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 14.5px;
  letter-spacing: 0.01em;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
}
.btn--primary {
  background: var(--sky);
  color: var(--white);
}
.btn--primary:hover { background: var(--navy); box-shadow: 0 0 0 4px rgba(255, 144, 165, 0.4); transform: translateY(-1px); }

.btn--spark {
  background: var(--origin-navy);
  color: var(--white);
}
.btn--spark:hover { box-shadow: 0 0 0 3px rgba(255, 144, 165, 0.35); transform: translateY(-1px); }

/* Same spark-bg/navy-text pairing the "Beyond the Known" tagline pill
   used to have — the hero CTA inherited both the copy and the color
   when the pill was dropped. */
.btn--pink {
  background: var(--spark);
  color: var(--navy);
}
.btn--pink:hover { background: var(--white); box-shadow: 0 0 0 4px rgba(5, 16, 110, 0.15); transform: translateY(-1px); }

.btn--outline {
  background: transparent;
  border-color: var(--slate);
  color: var(--slate);
}
.btn--outline:hover { background: var(--slate); color: var(--crystal); border-color: var(--slate); }

/* For use on the dark bands (footer, nav) — everywhere else is light
   now, where .btn--outline above is the right default. */
.btn--outline-light {
  background: transparent;
  border-color: rgba(244, 244, 244, 0.4);
  color: var(--white);
}
.btn--outline-light:hover { background: rgba(244, 244, 244, 0.12); border-color: var(--white); }

.btn--block { width: 100%; }
.btn--hero {
  padding: 18px 44px;
  font-size: 15.5px;
}
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 600;
  font-size: 14px;
  color: var(--sky);
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.link-arrow:hover { border-color: var(--spark); color: var(--spark); }

/* ---------- Header: floating glass pill nav ----------
   Always a dark glass pill regardless of the page underneath (light
   Shop/legal pages or the dark homepage) — a consistent anchor rather
   than the old full-width bar that changed with scroll. */
.logo-full { height: 54px; width: auto; }

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  justify-content: center;
  padding: 18px 24px 0;
  pointer-events: none;
}
/* Homepage: no pill/brand/links — just a bare logo mark top-left and a
   bare hamburger top-right, so the hero stays uncluttered but both
   corners still anchor something. */
.site-header--home { justify-content: flex-end; }
.site-header__inner {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  pointer-events: auto;
  max-width: 100%;
}
.nav-pill {
  display: flex;
  align-items: center;
  gap: 26px;
  padding: 8px 10px 8px 18px;
  border-radius: var(--radius-pill);
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  box-shadow: 0 8px 24px rgba(5, 6, 40, 0.18);
}
.nav-pill__brand {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--crystal);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
}
.nav-pill__brand-icon { height: 18px; width: auto; }
.nav-pill__divider {
  width: 1px;
  height: 20px;
  background: var(--glass-border);
  flex-shrink: 0;
}
.nav-pill__links {
  display: flex;
  gap: 22px;
  font-size: 13.5px;
  font-weight: 500;
}
.nav-pill__links a {
  color: rgba(244, 244, 244, 0.68);
  transition: color 0.15s ease;
  position: relative;
  padding-bottom: 2px;
}
.nav-pill__links a:hover,
.nav-pill__links a.is-active {
  color: var(--white);
}
.nav-pill__links a.is-active::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -4px;
  height: 2px;
  background: var(--spark);
  border-radius: 1px;
}
/* Cart lives inside the same pill now (not a second floating pill) —
   an icon-only link with a badge, following the last divider. */
.nav-pill__cart {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  color: rgba(244, 244, 244, 0.75);
  border-radius: 50%;
  transition: color 0.15s ease, background-color 0.15s ease;
}
.nav-pill__cart:hover { color: var(--white); background: rgba(244, 244, 244, 0.08); }
.cart-link__count {
  position: absolute;
  top: -2px;
  right: -2px;
  background: var(--spark);
  color: var(--origin-navy);
  border-radius: 50%;
  width: 16px;
  height: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 700;
  font-family: var(--font-mono);
}

/* Homepage-only hamburger — standalone (not nested in a pill), so it
   carries its own glass background instead of borrowing one. */
/* No background/border/box — just the three lines themselves, sized up
   and colored navy so they read clearly against the light hero without
   needing a dark chip behind them. Padding keeps the tap target
   reasonable (~44px) despite the visible glyph being smaller than that. */
.nav-hamburger {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px;
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--navy);
  transition: color 0.15s ease, transform 0.15s ease;
}
.nav-hamburger:hover { color: var(--sky); }
.nav-hamburger[aria-expanded="true"] { color: var(--spark); }

.nav-menu-panel {
  position: absolute;
  top: calc(100% + 10px);
  left: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 180px;
  padding: 10px;
  border-radius: 16px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  box-shadow: 0 8px 24px rgba(5, 6, 40, 0.28);
}
.nav-menu-panel[hidden] { display: none; }
.nav-menu-panel a {
  padding: 10px 12px;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 500;
  color: rgba(244, 244, 244, 0.8);
  transition: background-color 0.15s ease, color 0.15s ease;
}
.nav-menu-panel a:hover { background: rgba(244, 244, 244, 0.08); color: var(--white); }
/* Home variant hangs off the right-anchored hamburger, so it opens
   right-aligned instead of clipping off the viewport edge. */
.nav-menu-panel--home {
  left: auto;
  right: 0;
  min-width: 220px;
}
.nav-menu-panel__brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--white) !important;
  white-space: nowrap;
}
.nav-menu-panel__divider {
  height: 1px;
  margin: 6px 4px;
  background: var(--glass-border);
}
.nav-menu-panel__cart {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
/* Inline badge here, not the absolute-positioned corner badge used on
   the icon-only cart button elsewhere — this is a text row, not an icon. */
.nav-menu-panel__cart .cart-link__count { position: static; }

/* ---------- Hero (dark origin band) ----------
   No solid background of its own — body's --void already covers that,
   and a solid fill here would sit in front of (visually block) the
   fixed, full-viewport `.molecule-scene` canvas behind it, which needs
   to show through. `.hero__scrim` already does the actual "text stays
   legible over the 3D object" contrast work with its own left-to-right
   gradient, so a second, uniform full-hero fill isn't needed. */
.hero {
  position: relative;
  color: var(--slate);
  overflow: hidden;
  padding: 96px 0 108px;
}
.hero__visual {
  position: relative;
  height: 100%;
  min-height: 480px;
}
/* A soft, always-on ambient glow behind the sphere, shaped like the Sokai
   icon mark (dumbbell + sphere — public/images/logo-icon-watermark.svg,
   the single-tint variant made for exactly this: sitting on a dark
   background) instead of a plain circle. Pure CSS/image, so the right
   column never goes visually blank while the WebGL script below is
   loading, or in the rare case it never loads at all (no WebGL, the CDN
   import fails, JS disabled). The sphere fades in on top of it. */
.hero__glow {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  opacity: 1;
  transition: opacity 1s ease;
}
/* Once the real 3D scene has actually rendered a frame
   (public/js/molecule-scene.js adds this to <body>), this blurred
   fallback glow fades out — left on, the two together read as a muddy
   rectangular "shadow" sitting behind the crisp spinning molecule
   rather than a clean single visual. */
body.molecule-scene-ready .hero__glow { opacity: 0; }
.hero__glow-img {
  width: 62%;
  max-width: 420px;
  height: auto;
  filter: blur(40px);
  opacity: 0.5;
  /* multiply, not screen — screen blends toward white and is
     effectively invisible against a light background; multiply instead
     tints the crystal background with the mark's own mist color,
     reading as a soft brand-colored shadow rather than a light source. */
  mix-blend-mode: multiply;
}
.hero__molecule {
  position: absolute;
  inset: 0;
  z-index: 0;
  opacity: 0.45;
  pointer-events: none;
}
.molecule-svg { width: 100%; height: 100%; display: block; }
/* The hero's right column is otherwise empty — deliberately, so the
   persistent, full-viewport 3D molecule (public/js/molecule-scene.js,
   `.molecule-scene`, fixed behind every section) shows through it. The
   flat SVG + glow above are the only-ever-rendered fallback if that
   WebGL layer never loads. */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(
    90deg,
    var(--crystal) 0%,
    rgba(244, 244, 244, 0.92) 28%,
    rgba(244, 244, 244, 0.55) 48%,
    rgba(244, 244, 244, 0.1) 68%,
    transparent 82%
  );
}
.molecule-bond { stroke: rgba(5, 16, 110, 0.22); stroke-width: 2.5; }
.molecule-node { fill-opacity: 0.92; }
.molecule-node--sky { fill: var(--sky); }
.molecule-node--navy { fill: var(--indigo); }
.molecule-node--mist { fill: var(--mist); }
.molecule-node--pink { fill: var(--spark); }

.molecule-spin {
  transform-origin: 700px 300px;
  animation: molecule-spin 90s linear infinite;
}
.molecule-bob {
  animation: molecule-bob 10s ease-in-out infinite;
}
@keyframes molecule-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
@keyframes molecule-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-18px); }
}
.molecule-satellite { opacity: 0.75; }
.molecule-satellite--pink { fill: var(--spark); }
.molecule-satellite--mist { fill: var(--mist); }
.molecule-satellite--1 { animation: satellite-float 6.5s ease-in-out infinite; }
.molecule-satellite--2 { animation: satellite-float 8s ease-in-out infinite 1.4s; }
.molecule-satellite--3 { animation: satellite-float 5.8s ease-in-out infinite 0.7s; }
.molecule-satellite--4 { animation: satellite-float 7.2s ease-in-out infinite 2.1s; }
@keyframes satellite-float {
  0%, 100% { transform: translate(0, 0); opacity: 0.45; }
  50% { transform: translate(8px, -22px); opacity: 0.9; }
}
@media (prefers-reduced-motion: reduce) {
  .molecule-spin, .molecule-bob,
  .molecule-satellite--1, .molecule-satellite--2,
  .molecule-satellite--3, .molecule-satellite--4 {
    animation: none;
  }
}

.hero__grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: 56px;
  align-items: center;
}
/* The official full logo lockup — but with "Sokai" recolored to match
   the icon mark's own dumbbell navy (#060638, --origin-navy) rather
   than the lockup's stock near-black (#161616): `logo-full-hero.svg`,
   a copy of `logo-full.svg` with only that one fill swapped (see the
   "Logo" note further down for the rest of the variant family).
   Sitting directly in the hero copy rather than the header — the
   homepage header is hamburger-only (see header.ejs), so this is the
   one place the homepage actually shows the brand mark and the "Sokai
   Sciences" wordmark together. The tagline pill that used to sit next
   to it was dropped on request — its copy ("Beyond the Known") moved
   into the CTA button below instead ("Go Beyond the Known"). */
.hero__brand-row { margin-bottom: 32px; }
.hero__logo {
  height: 132px;
  width: auto;
}
.hero h1 {
  font-size: clamp(40px, 5.2vw, 62px);
  color: var(--navy);
  margin: 0 0 20px;
  max-width: 16ch;
}
.hero__sub {
  font-size: 18px;
  color: var(--beaker);
  max-width: 46ch;
  margin-bottom: 30px;
}
.hero__cta { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; }
.hero__trust {
  margin-top: 36px;
  font-size: 12px;
  color: rgba(5, 16, 110, 0.55);
}

/* ---------- Section headers ---------- */
.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  margin-bottom: 36px;
  gap: 24px;
}
.section-head h2 { font-size: 32px; margin: 6px 0 0; color: var(--slate); }

/* ---------- Sitewide continuous light scroll (Sokai's own palette) ----------
   Every page shares the same light crystal surface now (see `body`
   above), so plain `.section` already sits on it without needing a
   modifier. `.section--dark` — name kept for continuity with the
   homepage markup that references it, but it's a subtle translucent
   *light* wash now, not a dark one — is used on the homepage for extra
   depth across its long scroll. A fully solid fill would sit in front
   of (visually block) the fixed `.molecule-scene` canvas behind it,
   which needs to stay visible through every section. */
.section--dark {
  position: relative;
  z-index: 1;
  background: linear-gradient(180deg, rgba(244, 244, 244, 0.6) 0%, rgba(236, 238, 248, 0.6) 100%);
  color: var(--slate);
}
.section-num { font-size: 12px; margin-bottom: 14px; display: block; }

/* Faint vertical column-grid lines behind the dark sections — a fixed
   overlay so they read as a persistent blueprint guide while content
   scrolls past, the way the reference's own grid lines behave. */
.grid-lines {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.grid-lines__inner {
  max-width: var(--container);
  height: 100%;
  margin: 0 auto;
  position: relative;
  padding: 0 24px;
}
.grid-lines__inner span {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--line-on-dark);
}
.grid-lines__inner span:nth-child(1) { left: 0; }
.grid-lines__inner span:nth-child(2) { left: 25%; }
.grid-lines__inner span:nth-child(3) { left: 50%; }
.grid-lines__inner span:nth-child(4) { left: 75%; }
.grid-lines__inner span:nth-child(5) { right: 0; }

/* "On this page" sidebar nav — scroll-spy highlighted, homepage only,
   and only once the viewport has real margin outside the 1200px
   container to sit in without overlapping content. */
.page-nav {
  position: fixed;
  left: 40px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 30;
  display: none;
}
@media (min-width: 1440px) {
  .page-nav { display: block; }
}
.page-nav__label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(5, 16, 110, 0.4);
  margin-bottom: 14px;
}
.page-nav__list { display: flex; flex-direction: column; gap: 11px; }
.page-nav__list a {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: rgba(5, 16, 110, 0.55);
  transition: color 0.15s ease;
}
.page-nav__list a::before {
  content: '';
  width: 14px;
  height: 1px;
  background: rgba(5, 16, 110, 0.35);
  transition: width 0.2s ease, background-color 0.2s ease;
  flex-shrink: 0;
}
.page-nav__list a:hover { color: var(--navy); }
.page-nav__list a.is-active { color: var(--navy); }
.page-nav__list a.is-active::before { width: 22px; background: var(--spark); }

/* ---------- Trust / method row ---------- */
.trust-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 28px;
}
.trust-item {
  background: var(--card-on-dark);
  border: 1px solid var(--glass-border);
  border-radius: 14px;
  padding: 24px;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
/* Higher specificity than [data-reveal].is-visible's own transform:
   translateY(0) (same specificity otherwise, so source order would
   decide it) — this tilt needs to survive the reveal animation's final
   state, not get silently overridden by it. */
.trust-grid .trust-item:nth-child(odd) { transform: rotate(-0.5deg); }
.trust-grid .trust-item:nth-child(even) { transform: rotate(0.5deg); }
.trust-item__num {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--spark);
  margin-bottom: 10px;
  display: block;
}
.trust-item h3 {
  font-size: 19px;
  color: var(--slate);
  margin-bottom: 8px;
}
.trust-item p {
  font-size: 14.5px;
  color: var(--beaker);
  margin: 0;
}

/* ---------- Category filter ---------- */
.filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 40px;
}
.filter-chip {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 8px 14px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  color: var(--beaker);
  transition: border-color 0.15s ease, color 0.15s ease, background-color 0.15s ease;
}
.filter-chip.is-active {
  background: var(--sky);
  border-color: var(--sky);
  color: var(--white);
}
.filter-chip:hover:not(.is-active) { border-color: var(--sky); color: var(--sky); }

.shop-search {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}
.shop-search__input {
  width: 220px;
  max-width: 100%;
  padding: 10px 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--white);
  color: var(--slate);
  font-size: 14px;
}
.shop-search__input::placeholder { color: var(--beaker); }
.shop-search__input:focus-visible { outline: 2px solid var(--sky); outline-offset: 1px; }
.shop-search__btn { padding: 10px 18px; font-size: 13px; }

/* ---------- Product grid & card ---------- */
.product-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
}
.product-card {
  background: var(--card-on-dark);
  border: 1px solid var(--glass-border);
  border-radius: 14px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  height: 100%;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: box-shadow 0.15s ease, transform 0.15s ease, background-color 0.15s ease;
}
.product-card:hover {
  background: var(--card-on-dark-hover);
  box-shadow: 0 4px 24px rgba(255, 144, 165, 0.14), var(--shadow-card);
  transform: translateY(-3px);
}
.product-card__art {
  background: var(--swatch, var(--sky));
  color: #fff;
  height: 168px;
  flex-shrink: 0;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  position: relative;
  overflow: hidden;
}
.product-card__art::after {
  content: '';
  position: absolute;
  right: -30px;
  bottom: -30px;
  width: 120px;
  height: 120px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.08);
}
.product-card__hex {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  opacity: 0.8;
  align-self: flex-start;
  position: relative;
  z-index: 1;
}
.product-card__art-name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 22px;
  line-height: 1.15;
  position: relative;
  z-index: 1;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.product-card__body {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1;
}
.product-card__tagline {
  font-size: 14px;
  color: var(--beaker);
  flex: 1;
}
.product-card__specs {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--beaker);
  border-top: 1px solid var(--line);
  padding-top: 8px;
}
.product-card__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: auto;
  padding-top: 4px;
}
.product-card__price {
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 15px;
  color: var(--navy);
}

/* ---------- Product detail ---------- */
.product-detail {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 56px;
  align-items: start;
}
.product-detail__art {
  background: var(--swatch, var(--sky));
  color: #fff;
  border-radius: var(--radius);
  aspect-ratio: 4 / 5;
  padding: 28px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  position: sticky;
  top: 96px;
  overflow: hidden;
}
.product-detail__art::after {
  content: '';
  position: absolute;
  right: -60px;
  bottom: -60px;
  width: 220px;
  height: 220px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.07);
}
.product-detail__art-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(28px, 3vw, 40px);
  line-height: 1.1;
  position: relative;
  z-index: 1;
}
.product-detail__category {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  position: relative;
  z-index: 1;
}
.product-detail__price {
  font-family: var(--font-mono);
  font-size: 24px;
  font-weight: 600;
  color: var(--navy);
  margin: 18px 0 24px;
}
.qty-form {
  display: flex;
  gap: 12px;
  align-items: center;
  margin-bottom: 14px;
}
.variant-selector {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.variant-pill {
  position: relative;
  cursor: pointer;
}
.variant-pill input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  pointer-events: none;
}
.variant-pill span {
  display: inline-flex;
  align-items: center;
  padding: 9px 15px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--slate);
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.variant-pill:hover span { border-color: var(--sky); }
.variant-pill input:checked + span {
  background: var(--sky);
  border-color: var(--sky);
  color: var(--white);
}
.variant-pill input:focus-visible + span {
  outline: 2px solid var(--sky);
  outline-offset: 2px;
}
.qty-stepper {
  display: flex;
  align-items: center;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
}
.qty-stepper button {
  background: none;
  border: none;
  width: 36px;
  height: 44px;
  font-size: 16px;
  color: var(--slate);
}
.qty-stepper input {
  width: 40px;
  text-align: center;
  border: none;
  background: none;
  font-family: var(--font-mono);
  font-size: 15px;
  color: var(--slate);
}
.product-detail__disclaimer {
  font-size: 12px;
  color: var(--beaker);
  border-top: 1px solid var(--line);
  padding-top: 16px;
  margin-top: 24px;
}

/* ---------- Cart ---------- */
.cart-layout {
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 48px;
  align-items: start;
}
.cart-row {
  display: grid;
  grid-template-columns: 56px 1fr auto auto;
  gap: 16px;
  align-items: center;
  padding: 18px 0;
  border-bottom: 1px solid var(--line);
}
.cart-row__swatch {
  width: 56px;
  height: 56px;
  border-radius: var(--radius);
  background: var(--swatch, var(--sky));
}
.cart-row__name { font-weight: 600; color: var(--navy); }
.cart-row__meta {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--beaker);
}
.cart-row__price {
  font-family: var(--font-mono);
  text-align: right;
  min-width: 90px;
  color: var(--navy);
}
.cart-summary {
  background: var(--card-on-dark);
  border: 1px solid var(--glass-border);
  border-radius: 14px;
  padding: 24px;
  position: sticky;
  top: 96px;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.summary-row {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 14px;
  padding: 8px 0;
}
.summary-row--total {
  font-size: 17px;
  font-weight: 600;
  color: var(--navy);
  border-top: 1px solid var(--line);
  margin-top: 8px;
  padding-top: 14px;
}
.remove-link {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--beaker);
  text-decoration: underline;
  background: none;
  border: none;
  padding: 0;
}
.empty-state {
  text-align: center;
  padding: 96px 24px;
  color: var(--beaker);
}

/* ---------- Confirmation pages ---------- */
.confirm-panel {
  max-width: 560px;
  margin: 64px auto;
  text-align: center;
  padding: 0 24px;
}
.confirm-icon {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--sky);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 24px;
  font-family: var(--font-mono);
  font-size: 22px;
}

/* ---------- Footer ----------
   No margin-top — body is a continuous dark surface now (see `body`
   above), so a gap here just exposed bare --void between the last
   section and the footer's own gradient, reading as an unintentional
   empty band rather than a deliberate break. */
.site-footer {
  position: relative;
  z-index: 1;
  background: linear-gradient(160deg, var(--origin-navy) 0%, var(--origin-navy-2) 100%);
  color: var(--crystal);
}
.site-footer__inner {
  padding: 56px 24px 32px;
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 32px;
}
.site-footer .logo-full { filter: brightness(0) invert(1); height: 40px; margin-bottom: 12px; }
.site-footer h4 {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mist);
  margin-bottom: 14px;
}
.site-footer a, .site-footer li {
  font-size: 14px;
  color: rgba(244, 244, 244, 0.8);
  margin-bottom: 8px;
}
.site-footer a:hover { color: var(--white); }
.footer-bottom {
  border-top: 1px solid rgba(183, 203, 242, 0.15);
  padding: 20px 24px 32px;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  font-size: 12px;
  color: rgba(183, 203, 242, 0.6);
}
.footer-disclaimer {
  max-width: 640px;
  font-size: 12px;
  color: rgba(183, 203, 242, 0.6);
  line-height: 1.6;
}

/* ---------- Age / research-access gate ----------
   The one surface that stays a light card by design — it floats on the
   dark gradient body (views/age-gate.ejs sets that gradient inline, not
   through `body` in style.css), the same way the reference's own white
   "Start a project inquiry" button pops off its dark canvas. Colors here
   are deliberately hardcoded rather than routed through --line/--beaker/
   etc., since those tokens now mean "light-on-dark" everywhere else. */
.gate-card { color: var(--slate); }
.gate-card .eyebrow { color: var(--sky); }
.gate-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.gate-field-box {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  border: 1px solid rgba(5, 16, 110, 0.24);
  border-radius: var(--radius);
  padding: 16px;
  cursor: pointer;
  transition: border-color 0.15s ease;
}
.gate-field-box:hover { border-color: var(--sky); }
.gate-field-box input[type="checkbox"] {
  margin-top: 2px;
  width: 18px;
  height: 18px;
  accent-color: var(--navy);
  flex-shrink: 0;
}
.gate-label-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
}
.gate-required-tag {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.05em;
  color: var(--accent-amber);
}
.gate-select {
  width: 100%;
  border: 1px solid rgba(5, 16, 110, 0.24);
  border-radius: var(--radius);
  padding: 14px 16px;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  color: var(--slate);
  background: var(--white);
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M4 6l4 4 4-4' stroke='%234D495B' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 16px center;
  cursor: pointer;
}
.gate-select:focus-visible { outline: 2px solid var(--sky); outline-offset: 2px; }
.gate-select:invalid { color: var(--beaker-on-light, #4D495B); font-weight: 500; }
.gate-btn-primary {
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 13.5px;
}

/* ---------- Content pages (About / Privacy / Terms / Contact) ---------- */
/* Page-hero bands (About/Contact/Privacy/Terms) are light now too —
   only the footer and nav stay on dark navy as deliberate bookend
   accents (see the design-tokens comment at the top of this file). */
.page-hero {
  position: relative;
  overflow: hidden;
  background: linear-gradient(160deg, var(--crystal) 0%, var(--crystal-2) 100%);
  color: var(--slate);
  padding: 64px 0 56px;
}
.page-hero .container { position: relative; z-index: 1; }
.page-hero h1 { color: var(--navy); font-size: clamp(32px, 4vw, 46px); margin: 10px 0 0; max-width: 22ch; }
.page-hero p { color: var(--beaker); font-size: 16px; max-width: 52ch; margin: 16px 0 0; }

.prose { max-width: 720px; }
.prose h2 {
  font-size: 22px;
  color: var(--navy);
  margin: 40px 0 14px;
}
.prose h2:first-child { margin-top: 0; }
.prose p { font-size: 15.5px; color: var(--beaker); line-height: 1.7; margin-bottom: 16px; }
.prose ul { padding-left: 20px; margin-bottom: 16px; }
.prose li { font-size: 15.5px; color: var(--beaker); line-height: 1.7; margin-bottom: 8px; list-style: disc; }
.prose strong { color: var(--slate); }
.prose a { color: var(--sky); border-bottom: 1px solid rgba(33, 50, 208, 0.3); }
.prose a:hover { color: var(--spark); border-color: var(--spark); }
.prose .meta {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--beaker);
  margin-bottom: 32px;
}
.prose .legal-note {
  background: var(--crystal-2);
  border-left: 3px solid var(--spark);
  padding: 16px 20px;
  border-radius: var(--radius);
  font-size: 14px;
  color: var(--beaker);
  margin: 32px 0;
}

.about-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
  margin-top: 48px;
}
.about-card {
  background: var(--card-on-dark);
  border: 1px solid var(--glass-border);
  border-radius: 14px;
  padding: 24px;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.about-card__num {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--sky);
  display: block;
  margin-bottom: 12px;
}
.about-card h3 { font-size: 18px; color: var(--navy); margin-bottom: 8px; }
.about-card p { font-size: 14.5px; color: var(--beaker); margin: 0; }


/* ---------- Scroll reveal ---------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
[data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* ---------- Kinetic hero headline (single hero-level moment, by design) ---------- */
.kinetic-word {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.4em);
  animation: kinetic-word-in 0.7s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
@keyframes kinetic-word-in {
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .kinetic-word { opacity: 1; transform: none; animation: none; }
}

/* ---------- Hex-tag marquee band ---------- */
.marquee {
  position: relative;
  z-index: 1;
  background: rgba(12, 10, 74, 0.5);
  border-bottom: 1px solid var(--line-on-dark);
  overflow: hidden;
  padding: 14px 0;
}
.marquee__track {
  display: flex;
  width: max-content;
  gap: 48px;
  animation: marquee-scroll 32s linear infinite;
}
.marquee__item {
  font-family: var(--font-mono);
  font-size: 12.5px;
  letter-spacing: 0.06em;
  color: rgba(244, 244, 244, 0.55);
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
}
.marquee__item::after {
  content: '\2022';
  color: var(--spark);
  margin-left: 48px;
}
@keyframes marquee-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .marquee__track { animation: none; }
}

/* ---------- Stat counters (data-forward, not decorative) ---------- */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--glass-border);
  border: 1px solid var(--glass-border);
  border-radius: 14px;
  overflow: hidden;
}
.stat-item {
  background: var(--card-on-dark);
  padding: 32px 24px;
  text-align: left;
}
.stat-item__value {
  font-family: var(--font-mono);
  font-size: clamp(32px, 4vw, 44px);
  font-weight: 500;
  color: var(--navy);
  line-height: 1;
  margin-bottom: 10px;
}
.stat-item__label {
  font-size: 13.5px;
  color: var(--beaker);
}

/* ---------- Tactile crop-mark corners (technical/spec-sheet detail) ---------- */
.crop-marked { position: relative; }
.crop-marked::before,
.crop-marked::after {
  content: '';
  position: absolute;
  width: 14px;
  height: 14px;
  border: 1.5px solid var(--spark);
  opacity: 0.7;
  pointer-events: none;
}
.crop-marked::before { top: -1px; left: -1px; border-right: none; border-bottom: none; }
.crop-marked::after { bottom: -1px; right: -1px; border-left: none; border-top: none; }

/* ---------- Form fields (Checkout / Contact) ----------
   Replaces the old per-input inline styles (which hardcoded a white
   background — invisible now that every page is dark) with one reusable
   dark-glass input treatment. */
.form-grid { display: grid; gap: 16px; margin-bottom: 28px; }
.field { display: block; }
.field__label { display: block; margin-bottom: 6px; }
.field__hint { display: block; margin-top: 6px; font-size: 0.8125rem; color: var(--beaker); }
.field input[readonly] { background: var(--mist, #f4f5f7); color: var(--beaker); cursor: default; }
.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--white);
  color: var(--slate);
  font: inherit;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}
.field input::placeholder,
.field textarea::placeholder { color: var(--beaker); }
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: 2px solid var(--sky);
  outline-offset: 1px;
  border-color: var(--sky);
}
.field select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M4 6l4 4 4-4' stroke='%234D495B' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 36px;
  cursor: pointer;
}
.field select option { background: var(--white); color: var(--slate); }
.field textarea { resize: vertical; }
.field-row { display: grid; gap: 12px; }
.field-checkbox {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  font-size: 13px;
  color: var(--beaker);
}
.field-checkbox input { margin-top: 3px; accent-color: var(--sky); flex-shrink: 0; width: auto; }
.field-honeypot { position: absolute; left: -9999px; }

/* ---------- Notices (form success / error banners) ---------- */
.notice {
  border-radius: var(--radius);
  padding: 16px;
  margin-bottom: 24px;
  border: 1px solid;
}
.notice p, .notice li { margin: 0; font-size: 14px; }
.notice ul { list-style: disc; padding-left: 20px; }
.notice--error {
  background: rgba(192, 57, 43, 0.08);
  border-color: rgba(192, 57, 43, 0.3);
  color: var(--danger);
}
.notice--success {
  background: rgba(58, 138, 82, 0.08);
  border-color: rgba(58, 138, 82, 0.35);
  color: #2A6B41;
}

/* ---------- Numbered process/step list (homepage "How it's made") ---------- */
.step-list { border-top: 1px solid var(--glass-border); max-width: 640px; }
.step-row {
  display: flex;
  gap: 24px;
  padding: 22px 0;
  border-bottom: 1px solid var(--glass-border);
}
.step-row__num {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--spark);
  flex-shrink: 0;
  padding-top: 3px;
}
.step-row h3 { font-size: 18px; color: var(--slate); margin-bottom: 4px; }
.step-row p { font-size: 14.5px; color: var(--beaker); margin: 0; max-width: 52ch; }

/* ---------- FAQ accordion (homepage) ---------- */
.faq-list { border-top: 1px solid var(--glass-border); }
.faq-item { border-bottom: 1px solid var(--glass-border); }
.faq-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 20px 4px;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-size: 18px;
  color: var(--slate);
  transition: color 0.15s ease;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:hover { color: var(--navy); }
.faq-item__icon {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid var(--glass-border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--navy);
  transition: transform 0.2s ease, background-color 0.2s ease;
}
.faq-item[open] .faq-item__icon { background: var(--spark); color: var(--origin-navy); transform: rotate(45deg); }
.faq-item p {
  padding: 0 28px 22px 4px;
  color: var(--beaker);
  font-size: 14.5px;
  line-height: 1.7;
  max-width: 62ch;
}

/* ---------- Persistent 3D scene (homepage only) ----------
   public/js/molecule-scene.js renders into this fixed, full-viewport
   canvas — sitting behind every homepage section (z-index below
   .container content, above the plain --void body) so the same
   molecule stays on screen through the whole scroll and just changes
   camera pose per section, the way the reference's fixed 3D object
   does. `.hero__glow` (existing, image-based) is the static fallback
   drawn underneath in case WebGL/the CDN import never comes up. */
.molecule-scene {
  position: fixed;
  inset: 0;
  z-index: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 1.4s ease;
}
.molecule-scene.is-ready { opacity: 1; }
#molecule-scene-canvas { width: 100%; height: 100%; display: block; }
@media (max-width: 960px) {
  .molecule-scene { display: none; }
}

/* ---------- Responsive ---------- */
@media (max-width: 960px) {
  .hero__grid, .product-detail, .cart-layout, .trust-grid, .about-grid { grid-template-columns: 1fr; }
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
  .product-detail__art { position: static; }
  .product-grid { grid-template-columns: repeat(2, 1fr); }
  .nav-pill__links, .nav-pill__divider { display: none; }
  .site-footer__inner { grid-template-columns: 1fr 1fr; }
  .hero__molecule { display: none; }
  .hero__visual { display: none; }
  .hero__scrim { display: none; }
  .trust-grid { gap: 24px; }
}
@media (max-width: 640px) {
  .nav-pill__brand span { display: none; }
  .nav-pill { gap: 0; padding: 8px; }
}
@media (max-width: 560px) {
  .product-grid { grid-template-columns: 1fr; }
  .cart-row { grid-template-columns: 44px 1fr; row-gap: 8px; }
  .cart-row__price { grid-column: 2; text-align: left; }
  .site-footer__inner { grid-template-columns: 1fr; }
}
