/* ==========================================================================
   Obstoon — art direction layer
   --------------------------------------------------------------------------
   Loaded after interior.css. This layer owns the *dimensional* visual
   identities: the home ecosystem core, per-page hero objects, and the
   material language (light, edge, depth shadow) they share.

   Everything here is CSS 3D, SVG and pseudo-elements. No frameworks, no
   canvas, no external assets.

   House rules held throughout:
   - no generic glowing spheres or abstract orbs
   - no placeholder rectangles standing in for a focal object
   - no fake product UI, no invented platform or feature claims
   - depth must be legible: front / mid / back planes are always distinct
   ========================================================================== */

/* ---- Material tokens ---------------------------------------------------- */

/* Dark is the default set. Light is *not* an inversion: it is a frosted
   ceramic-and-glass system on cool paper stock, lit from above, with shorter
   and bluer shadows. Both are art-directed so the objects keep their form. */
:root,
[data-theme="dark"] {
  --ad-bg-0: #0d1426;
  --ad-bg-1: #0a1020;
  --ad-bg-2: #070c18;

  --ad-face-1: #131c33;
  --ad-face-2: #0b1223;
  --ad-face-3: #070c18;
  --ad-face-4: #1b2540;
  --ad-face-5: #080d18;

  --ad-top-1: #33456e;
  --ad-top-2: #1b2542;

  --ad-side-1: #101a30;
  --ad-side-2: #0a1120;

  --ad-sat-1: #16203a;
  --ad-metal-1: #2a3550;
  --ad-metal-2: #223050;

  /* channel colours, mixed to the alpha each surface needs */
  --ad-lift: #ffffff;   /* specular highlight, top-facing edges */
  --ad-shade: #000000;  /* occlusion inside a form, cast shadows */
  --ad-line: #96beff;   /* cool borders, grid lines, mesh */
  --ad-glow: #78c8ff;   /* emissive seams, seams, glow */
  --ad-panel: #0c1220;  /* floating panels over the scene */

  /* Lighting rig for the home object. A blue-white key and an indigo fill give
     the form a direction of light without a warm cast, so the faces read as lit
     rather than tinted and the frame never drifts toward amber. */
  --ad-key: #cfe1ff;    /* cool key light, upper right */
  --ad-key-2: #9a86ff;  /* indigo fill, lower left */
  --ad-seam: #9fd4ff;   /* seam and edge lines on the object */
}

[data-theme="light"] {
  /* Light mode reads as glazed ceramic: near-white faces, distinctly cooler
     side planes so the form still turns, and shadows tinted blue rather than
     neutral grey. Kept off pure white so surfaces stay separated. */
  --ad-bg-0: #ffffff;
  --ad-bg-1: #f4f7fc;
  --ad-bg-2: #dee6f1;

  --ad-face-1: #ffffff;
  --ad-face-2: #f3f7fc;
  --ad-face-3: #dde5f0;
  --ad-face-4: #fbfcfe;
  --ad-face-5: #d6dfec;

  --ad-top-1: #ffffff;
  --ad-top-2: #e8eff8;

  --ad-side-1: #d3ddec;
  --ad-side-2: #b9c6d9;

  --ad-sat-1: #ffffff;
  --ad-metal-1: #c8d4e5;
  --ad-metal-2: #d7e0ee;

  --ad-lift: #ffffff;
  --ad-shade: #1b3358;
  --ad-line: #2c5da3;
  --ad-glow: #2f66c8;
  --ad-panel: #ffffff;

  /* Light mode is lit separately, not inverted: the key is stronger and cooler
     because it has to read against white, and the seams go darker since a pale
     line on white disappears. Blue-white key with an indigo fill keeps the page
     cool neutral rather than beige. */
  --ad-key: #cfe0ff;
  --ad-key-2: #8b93ef;
  --ad-seam: #1f4f96;
}

/* ---- Shared material ---------------------------------------------------- */

/* Rim light: a lit top edge plus a cool bounce along the bottom. Used on every
   dimensional surface so objects read as one material system rather than a set
   of unrelated illustrations. */
.mat-lit {
  position: relative;
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--ad-lift) 14%, transparent),
    inset 0 -1px 0 color-mix(in srgb, var(--ad-line) 7%, transparent),
    inset 1px 0 0 color-mix(in srgb, var(--ad-lift) 5%, transparent),
    var(--shadow-md);
}

/* Depth shadow cast onto whatever is behind/below. */
.mat-casts {
  filter: drop-shadow(0 26px 34px color-mix(in srgb, var(--ad-shade) 50%, transparent));
}

/* --------------------------------------------------------------------------
   1. HOME — the Obstoon aperture
   --------------------------------------------------------------------------
   The home hero is the ecosystem, not a product. The mark is a dimensional
   aperture: four stacked annuli give it real thickness, a conic rim light and
   a beveled bore give it material, and the three product modules sit on one
   shared orbit, each plugged into a port on the rim. One object, one system.

   Hierarchy is explicit rather than implied: the ring is the primary form, the
   Speech / Library / Tracker modules are secondary, the orbit markers, ports and
   depth planes are tertiary. Every element is sized against the mark, so the
   hierarchy holds at every viewport instead of collapsing on small screens.
   -------------------------------------------------------------------------- */

.core-scene {
  position: relative;
  width: 100%;
  max-width: 40rem;
  margin-inline: auto;
  perspective: 1500px;
  perspective-origin: 50% 44%;
  aspect-ratio: 1 / 0.98;
}

.core-space {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transform: rotateX(var(--scene-rx, 0deg)) rotateY(var(--scene-ry, 0deg));
  transition: transform var(--dur-5) var(--ease-out);
}

.core-space > * {
  position: absolute;
  transform-style: preserve-3d;
}

/* -- back plane: graded atmosphere. Two light pools plus an occlusion pool,
      so the mark sits in a lit volume rather than on a flat field. The pools
      mirror the rig (key upper-right, indigo fill lower-left) so the haze and
      the ring face are lit by the same source. Kept quiet: the wash supports
      the face, it does not compete with it. -- */
.core-haze {
  inset: -6%;
  background:
    radial-gradient(44% 38% at 72% 26%, color-mix(in srgb, var(--ad-key) 16%, transparent), transparent 70%),
    radial-gradient(46% 44% at 26% 72%, color-mix(in srgb, var(--ad-key-2) 16%, transparent), transparent 72%),
    radial-gradient(58% 46% at 50% 98%, color-mix(in srgb, var(--ad-shade) 32%, transparent), transparent 76%);
  filter: blur(12px);
  transform: translate3d(calc(var(--px, 0) * 1px), calc(var(--py, 0) * 1px), -260px);
}

/* -- mid-back plane: the floor grid, deliberately quiet. It is a depth cue,
      not a texture: half the previous line weight, a wider cell, a faster
      falloff and a lower opacity, so the mark and the orbit carry the frame's
      detail instead of competing with a wall of lines. -- */
.core-grid {
  inset: 54% -4% -14% -4%;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--ad-line) 7%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--ad-line) 5%, transparent) 1px, transparent 1px);
  background-size: 4.6rem 4.6rem;
  transform: translate3d(calc(var(--px, 0) * 1px), calc(var(--py, 0) * 1px), -120px) rotateX(76deg);
  transform-origin: 50% 0;
  mask-image: linear-gradient(to bottom, rgb(0 0 0 / 0.5), transparent 60%);
  opacity: 0.36;
}

/* -- contact shadow, so the mark stands on the floor. A tighter, darker core
      under the annulus plus a wider soft skirt: the object reads as heavy on
      the plane instead of hovering inside a glow. -- */
.core-contact {
  left: 50%;
  bottom: 13%;
  width: 66%;
  height: 14%;
  transform: translate(-50%, 0) translate3d(calc(var(--px, 0) * 1px), calc(var(--py, 0) * 1px), -40px) rotateX(76deg);
  background:
    radial-gradient(38% 42% at 50% 50%, color-mix(in srgb, var(--ad-shade) 92%, transparent), transparent 64%),
    radial-gradient(60% 60% at 50% 50%, color-mix(in srgb, var(--ad-shade) 46%, transparent), transparent 72%);
  filter: blur(9px);
}

/* -- the mark -- */
.core {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  transform: translate3d(calc(var(--px, 0) * 1px), calc(var(--py, 0) * 1px), 0);
}

.core__body {
  --hole: 35%;
  position: relative;
  width: min(60%, 19rem);
  aspect-ratio: 1 / 1;
  transform-style: preserve-3d;
  /* Slightly deeper turn than before: just enough more side-wall that the
     stacked annuli read as a physical thickness instead of a flat disc. The
     hole stays circular, so the object still sits face-on. */
  transform: rotateX(11deg) rotateY(-18deg);
}

/* Thickness. Four annuli at four depths: because the body is turned, each
   layer shows past the one in front of it along the far edge, and the
   progressively darker fills read as a wall rather than as a stack of rings. */
.core__ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  -webkit-mask-image: radial-gradient(circle at 50% 50%, transparent 0 var(--hole), #000 calc(var(--hole) + 0.4%));
  mask-image: radial-gradient(circle at 50% 50%, transparent 0 var(--hole), #000 calc(var(--hole) + 0.4%));
}

/* The far wall catches a little key light on its top-right shoulder, which is
   what separates the back plane from the void behind it. */
.core__ring--back {
  transform: translateZ(-60px) scale(1.12);
  background:
    radial-gradient(64% 64% at 74% 22%, color-mix(in srgb, var(--ad-key) 16%, transparent), transparent 62%),
    color-mix(in srgb, var(--ad-shade) 78%, var(--ad-face-3));
}

/* The side wall itself: a columnar shade that turns the wall into a surface
   rather than a darker ring, with the key raking down its length. */
.core__ring--wall {
  transform: translateZ(-44px) scale(1.075);
  background:
    radial-gradient(60% 90% at 78% 8%, color-mix(in srgb, var(--ad-key) 22%, transparent), transparent 60%),
    linear-gradient(118deg, color-mix(in srgb, var(--ad-shade) 44%, var(--ad-face-3)) 0%, var(--ad-face-3) 58%, var(--ad-shade) 130%);
}

.core__ring--mid {
  transform: translateZ(-26px) scale(1.04);
  background: linear-gradient(150deg, var(--ad-face-4) 0%, var(--ad-face-2) 54%, var(--ad-face-3) 100%);
  /* a lit top edge on the mid step, so the wall reads in stages, not as one
     recessed blob */
  box-shadow:
    inset 0 2px 0 color-mix(in srgb, var(--ad-lift) 12%, transparent),
    inset 0 -3px 6px color-mix(in srgb, var(--ad-shade) 30%, transparent);
}

/* The working face: the key lands on one shoulder with a tight falloff, a
   cooler fill answers from the opposite side, and the base value ramp runs
   top-left to bottom-right. The inset shadows are the bevel that separates the
   face from the wall behind it. */
.core__ring--front {
  transform: translateZ(-8px);
  background:
    radial-gradient(58% 58% at 74% 22%, color-mix(in srgb, var(--ad-key) 40%, transparent), transparent 66%),
    radial-gradient(62% 62% at 22% 86%, color-mix(in srgb, var(--ad-key-2) 30%, transparent), transparent 70%),
    linear-gradient(148deg, var(--ad-face-1) 0%, var(--ad-face-2) 52%, var(--ad-face-3) 100%);
  box-shadow:
    inset 0 3px 0 color-mix(in srgb, var(--ad-lift) 13%, transparent),
    inset 0 -5px 10px color-mix(in srgb, var(--ad-shade) 34%, transparent),
    inset -3px 0 6px color-mix(in srgb, var(--ad-key-2) 12%, transparent);
}

/* Rim light: a conic highlight confined to a slightly thicker outer band, so
   the turning edge is described by light rather than by an outline. The top
   segment is tightened so the bright reads as gloss on the shoulder and dies
   before the lower-left fill takes over. */
.core__rim {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(
    from 205deg,
    rgb(255 255 255 / 0.78),
    rgb(255 255 255 / 0.07) 18%,
    rgb(255 255 255 / 0) 42%,
    rgb(255 255 255 / 0.18) 68%,
    rgb(255 255 255 / 0.66) 92%,
    rgb(255 255 255 / 0.78)
  );
  -webkit-mask-image: radial-gradient(circle at 50% 50%, transparent 0 68.2%, #000 68.8% 71.8%, transparent 72.6%);
  mask-image: radial-gradient(circle at 50% 50%, transparent 0 68.2%, #000 68.8% 71.8%, transparent 72.6%);
  transform: translateZ(-7px);
  pointer-events: none;
}

/* The outer contour. A crisp circle at the full radius: in Dark mode the ring
   already separates by value against the glow, but in Light mode a white face
   on a pale blue field only differed by 0.04 L*, which is why the mark went
   ghost-like there. This line is what makes the aperture read at either theme. */
.core__edge {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--ad-seam) 80%, transparent);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--ad-lift) 30%, transparent),
    0 14px 30px color-mix(in srgb, var(--ad-shade) 40%, transparent);
  transform: translateZ(-6px);
  pointer-events: none;
}

/* The bore itself. Nothing in Dark mode: there the hole is the lit part of the
   frame and reads on its own. In Light mode the section below shades it. */
.core__bore {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: transparent;
  transform: translateZ(-7px);
  pointer-events: none;
}

/* The bore: a lit bevel where the inner edge turns into the hole. A tighter
   white catch at the inner lip plus a deeper occlusion right inside it gives
   the aperture a machined rim instead of a flat donut edge. */
.core__bevel {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 50%,
    transparent 0 35.3%,
    rgb(255 255 255 / 0.62) 36.2%,
    rgb(0 0 0 / 0.5) 39.4%,
    transparent 44%);
  transform: translateZ(-7px);
  pointer-events: none;
}

/* The shared orbit. Every product module sits on it, which is what makes the
   three of them read as one system instead of three floating decorations. */
.core__orbit {
  position: absolute;
  inset: -17%;
  border-radius: 50%;
  border: 1px dashed color-mix(in srgb, var(--ad-line) 22%, transparent);
  transform: translateZ(-12px);
}

/* Tertiary accents: small markers at the midpoints between modules, so the
   orbit reads as measured rather than as a stray circle. Held in the imprint
   range: brighter than the dashed rule but without a neon halo. */
.core__orbit i {
  position: absolute;
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 0.1rem;
  background: color-mix(in srgb, var(--ad-line) 52%, transparent);
  box-shadow: 0 0 8px color-mix(in srgb, var(--ad-glow) 28%, transparent);
  transform: translate(-50%, -50%) rotate(45deg);
}

.core__orbit i:nth-child(1) { left: 55.2%; top: 0.5%; }
.core__orbit i:nth-child(2) { left: 98.5%; top: 61.5%; }
.core__orbit i:nth-child(3) { left: 14%;   top: 84.5%; }

/* Ports and tethers: each module is plugged into the rim, not merely placed
   near it. A tether is exactly the gap between rim and orbit, rotated onto the
   module's angle, so the line lands on both ends without any measured maths. */
.core__port {
  position: absolute;
  width: 0.58rem;
  height: 0.58rem;
  border-radius: 50%;
  background: var(--port);
  box-shadow:
    0 0 0 3px color-mix(in srgb, var(--ad-face-2) 82%, transparent),
    0 0 14px var(--port);
  transform: translate(-50%, -50%) translateZ(-6px);
}

.core__port--speech  { left: 9%;    top: 21.3%; --port: var(--ink-speech); }
.core__port--library { left: 92.4%; top: 23.5%; --port: var(--ink-library); }
.core__port--tracker { left: 76.5%; top: 92.4%; --port: var(--ink-tracker); }

.core__tether {
  position: absolute;
  width: 1px;
  height: 17%;
  transform-origin: 0 0;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--ad-line) 58%, transparent),
    color-mix(in srgb, var(--ad-line) 16%, transparent));
}

.core__tether--speech  { left: 9%;    top: 21.3%; transform: rotate(-235deg); }
.core__tether--library { left: 92.4%; top: 23.5%; transform: rotate(-122deg); }
.core__tether--tracker { left: 76.5%; top: 92.4%; transform: rotate(-32deg); }

/* -- SECONDARY: the three product modules.

      Sizing is a percentage of the mark, not a viewport clamp, so the modules
      stay proportionally smaller than the ring at every width. Previously the
      satellites were sized in vw and drifted out of the hierarchy on large
      screens and out of frame on small ones. -- */
.sat {
  position: absolute;
  transform-style: preserve-3d;
}

.sat__body {
  position: relative;
  width: 100%;
  border: 1px solid color-mix(in srgb, var(--ad-line) 24%, transparent);
  border-radius: 0.7rem;
  background: linear-gradient(160deg, var(--ad-sat-1) 0%, var(--ad-side-2) 100%);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--ad-lift) 14%, transparent),
    0 18px 30px color-mix(in srgb, var(--ad-shade) 48%, transparent);
  overflow: hidden;
}

.sat__name {
  position: absolute;
  top: calc(100% + 0.34rem);
  left: 50%;
  margin: 0;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: var(--text-3xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-soft);
  white-space: nowrap;
}

/* Speech: a live voice fragment. Concentric arc bands read as a waveform seen
   end-on, not as an orb. */
.sat--voice {
  left: -4.9%;
  top: 11.6%;
  width: 30%;
  transform: translate(-50%, -50%) translateZ(54px);
}

.sat--voice .sat__body {
  aspect-ratio: 1 / 1;
  padding: 0.5rem;
  display: grid;
  place-items: center;
}

.voice-arcs {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
}

.voice-arcs i {
  position: absolute;
  border: 1.5px solid var(--ink-speech);
  border-radius: 50%;
  border-bottom-color: transparent;
  border-right-color: transparent;
  transform: rotate(-45deg);
}

.voice-arcs i:nth-child(1) { width: 34%; height: 34%; opacity: 0.95; }
.voice-arcs i:nth-child(2) { width: 56%; height: 56%; opacity: 0.6; }
.voice-arcs i:nth-child(3) { width: 78%; height: 78%; opacity: 0.32; }
.voice-arcs i:nth-child(4) { width: 96%; height: 96%; opacity: 0.16; }

.voice-arcs::after {
  content: "";
  width: 16%;
  height: 16%;
  border-radius: 50%;
  background: var(--ink-speech);
  box-shadow: 0 0 12px var(--ink-speech);
}

/* Library: a catalogued document block with visible leaves. */
.sat--doc {
  left: 106.8%;
  top: 14.5%;
  width: 26%;
  transform: translate(-50%, -50%) translateZ(20px);
}

.sat--doc .sat__body {
  aspect-ratio: 4 / 5;
  padding: 0.45rem;
  display: grid;
  align-content: start;
  gap: 0.22rem;
}

.doc-leaf {
  height: 0.28rem;
  border-radius: 1px;
  background: color-mix(in srgb, var(--ad-line) 34%, transparent);
}

.doc-leaf:nth-child(1) { width: 72%; background: var(--ink-library); height: 0.42rem; }
.doc-leaf:nth-child(2) { width: 100%; }
.doc-leaf:nth-child(3) { width: 88%; }
.doc-leaf:nth-child(4) { width: 64%; }
.doc-leaf:nth-child(5) { width: 92%; }

/* Tracker: a compact progress path. A dashed ascent, three milestone nodes
   (the middle one lit), and a small certificate tag on the rim. Reads as
   "journey → milestones → certificate" at a glance. */
.sat--tracker {
  left: 85.5%;
  top: 106.8%;
  width: 34%;
  transform: translate(-50%, -50%) translateZ(76px);
}

.sat--tracker .sat__body {
  aspect-ratio: 16 / 7;
  padding: 0.5rem 0.55rem;
}

.trk-rail {
  position: absolute;
  inset-inline: 14%;
  top: 50%;
  height: 1px;
  background: repeating-linear-gradient(
    90deg,
    color-mix(in srgb, var(--ad-line) 55%, transparent) 0 4px,
    transparent 4px 8px
  );
}

.trk-node {
  position: absolute;
  left: var(--x, 50%);
  top: 50%;
  width: 0.34rem;
  height: 0.34rem;
  border: 1.5px solid var(--ink-tracker);
  background: var(--surface);
  transform: translate(-50%, -50%) rotate(45deg);
  box-shadow: 0 0 8px color-mix(in srgb, var(--ink-tracker) 45%, transparent);
}

.trk-node--on {
  background: var(--ink-tracker);
}

.trk-node--off {
  border-style: dashed;
  opacity: 0.55;
}

.trk-tag {
  position: absolute;
  right: 14%;
  top: 16%;
  font-family: var(--font-mono);
  font-size: 0.5rem;
  letter-spacing: 0.1em;
  color: var(--ink-tracker);
}

/* --------------------------------------------------------------------------
   2. SPEECH — voice geometry
   --------------------------------------------------------------------------
   Replaces the previous abstract orb. The hero object is a dimensional
   microphone built from a capsule body, a mesh grille and a stand, wrapped in
   stacked waveform planes. It states SPEECH at a glance and is not a sphere.
   -------------------------------------------------------------------------- */

.mic {
  position: relative;
  /* The product hero field is a 16/10 box with overflow:hidden. Sizing the
     scene by height keeps the whole object on screen at every width instead
     of cropping the stand and the lower waveform. */
  height: 100%;
  width: auto;
  max-width: 100%;
  max-height: 100%;
  aspect-ratio: 1 / 1;
  margin-inline: auto;
  perspective: 1400px;
  perspective-origin: 50% 46%;
}

.mic__space {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transform: rotateX(var(--scene-rx, 0deg)) rotateY(var(--scene-ry, 0deg));
  transition: transform var(--dur-5) var(--ease-out);
  display: grid;
  place-items: center;
}

.mic__space > * {
  position: absolute;
  transform-style: preserve-3d;
}

/* Waveform planes behind the mic: a real bar array, with each bar pushed to
   its own Z so the array has depth instead of being a flat silhouette. */
.mic__wave {
  left: 50%;
  top: 50%;
  width: 122%;
  height: 58%;
  transform: translate(-50%, -50%) translateZ(-90px);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(1px, 0.35vw, 3px);
  opacity: 0.9;
}

.mic__wave i {
  width: clamp(2px, 0.4vw, 3.5px);
  height: var(--h, 40%);
  border-radius: 2px;
  background: linear-gradient(180deg, var(--ink-speech), color-mix(in srgb, var(--ad-glow) 12%, transparent));
  transform: translateZ(var(--z, 0px));
  box-shadow: 0 0 8px color-mix(in srgb, var(--ink-speech) 26%, transparent);
}

/* Second waveform plane, rotated as a back wall behind the first. */
.mic__wall {
  left: 50%;
  top: 50%;
  width: 118%;
  height: 46%;
  transform: translate(-50%, -50%) translateZ(-150px) rotateY(-14deg);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(1px, 0.5vw, 4px);
  opacity: 0.32;
  filter: blur(1px);
}

.mic__wall i {
  width: 2px;
  height: var(--h, 30%);
  background: color-mix(in srgb, var(--ad-line) 60%, transparent);
}

/* Ground plane so the stand has a surface to sit on. */
.mic__floor {
  inset: 78% -4% -9% -4%;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--ad-line) 12%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--ad-line) 10%, transparent) 1px, transparent 1px);
  background-size: 2.4rem 2.4rem;
  transform: translateZ(-60px) rotateX(76deg);
  transform-origin: 50% 0;
  mask-image: linear-gradient(to bottom, rgb(0 0 0 / 0.8), transparent 80%);
}

.mic__shadow {
  left: 50%;
  bottom: 12%;
  width: 40%;
  height: 8%;
  transform: translate(-50%, 0) translateZ(-30px) rotateX(76deg);
  background: radial-gradient(50% 50% at 50% 50%, color-mix(in srgb, var(--ad-shade) 70%, transparent), transparent 72%);
  filter: blur(8px);
}

/* The capsule. Body + grille + stand are separate rotated planes. */
.mic__rig {
  position: relative;
  width: 42%;
  aspect-ratio: 1 / 2.05;
  transform-style: preserve-3d;
  transform: translateZ(40px) rotateY(-14deg);
}

.mic__body {
  position: absolute;
  inset: 0 0 26% 0;
  border-radius: 999px 999px 46% 46% / 999px 999px 34% 34%;
  border: 1px solid color-mix(in srgb, var(--ad-line) 28%, transparent);
  background:
    radial-gradient(80% 46% at 30% 12%, color-mix(in srgb, var(--ad-lift) 20%, transparent), transparent 58%),
    linear-gradient(168deg, var(--ad-face-4) 0%, var(--ad-side-1) 46%, var(--ad-side-2) 100%);
  box-shadow:
    inset 0 2px 0 color-mix(in srgb, var(--ad-lift) 22%, transparent),
    inset -14px 0 26px color-mix(in srgb, var(--ad-shade) 40%, transparent),
    0 28px 50px color-mix(in srgb, var(--ad-shade) 55%, transparent);
  overflow: hidden;
}

/* Grille: crossed mesh, so the head reads as a microphone. */
.mic__grille {
  position: absolute;
  inset: 4% 6% 52% 6%;
  border-radius: 999px 999px 40% 40%;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--ad-line) 42%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--ad-line) 42%, transparent) 1px, transparent 1px);
  background-size: 0.42rem 0.42rem;
  mask-image: radial-gradient(70% 70% at 50% 34%, #000 40%, transparent 78%);
  opacity: 0.72;
}

/* Collar between grille and body. */
.mic__collar {
  position: absolute;
  inset: 46% 12% auto 12%;
  height: 5%;
  border-radius: 999px;
  background: linear-gradient(180deg, var(--ad-metal-1) 0%, var(--ad-sat-1) 100%);
  box-shadow: 0 1px 0 color-mix(in srgb, var(--ad-line) 30%, transparent);
}

/* Stem + base, angled into the same 3D space. */
.mic__stem {
  position: absolute;
  inset: 72% 46% 12% 46%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--ad-side-2), var(--ad-metal-1) 42%, var(--ad-side-1));
  box-shadow: inset 1px 0 0 color-mix(in srgb, var(--ad-line) 22%, transparent);
  transform: translateZ(-14px);
}

.mic__base {
  position: absolute;
  inset: auto 22% 4% 22%;
  height: 8%;
  border-radius: 999px;
  background: linear-gradient(180deg, var(--ad-metal-2) 0%, var(--ad-side-2) 100%);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--ad-line) 30%, transparent),
    0 20px 30px color-mix(in srgb, var(--ad-shade) 50%, transparent);
  transform: translateZ(-6px);
}

/* Capture ring: an arc band that sits in front of the grille and catches the
   key light. This is the accent highlight. */
.mic__ring {
  position: absolute;
  inset: 2% 2% 50% 2%;
  border-radius: 999px 999px 46% 46%;
  border: 1.5px solid var(--ink-speech);
  border-bottom-color: transparent;
  opacity: 0.7;
  filter: drop-shadow(0 0 10px color-mix(in srgb, var(--ink-speech) 60%, transparent));
  transform: translateZ(22px);
}

/* Speech fragments orbiting the mic — short quoted lines, which is what the
   product actually does. */
.mic__frag {
  position: absolute;
  padding: 0.4rem 0.7rem;
  border: 1px solid color-mix(in srgb, var(--ad-line) 24%, transparent);
  border-radius: 0.5rem;
  background: color-mix(in srgb, var(--ad-panel) 86%, transparent);
  box-shadow: 0 12px 22px color-mix(in srgb, var(--ad-shade) 40%, transparent), inset 0 1px 0 color-mix(in srgb, var(--ad-lift) 10%, transparent);
  font-size: var(--text-3xs);
  color: var(--text-soft);
  white-space: nowrap;
  max-width: 12rem;
  overflow: hidden;
  text-overflow: ellipsis;
}

.mic__frag--a { top: 12%; left: -2%; transform: translateZ(120px); }
.mic__frag--b { top: 30%; right: -4%; transform: translateZ(60px); }
.mic__frag--c { bottom: 20%; left: -6%; transform: translateZ(150px); }

.mic__frag b {
  color: var(--ink-speech);
  font-weight: 600;
  margin-right: 0.3rem;
}

/* --------------------------------------------------------------------------
   3. LIBRARY — dimensional archive
   --------------------------------------------------------------------------
   Curated knowledge, not file storage. A stack of catalogued volumes seen in
   perspective, each leaf a real plane, with subject tabs and an availability
   spine.
   -------------------------------------------------------------------------- */

.archive {
  position: relative;
  height: 100%;
  width: auto;
  max-width: 100%;
  max-height: 100%;
  aspect-ratio: 1 / 1;
  margin-inline: auto;
  perspective: 1500px;
  perspective-origin: 50% 44%;
}

.archive__space {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transform: rotateX(var(--scene-rx, 0deg)) rotateY(var(--scene-ry, 0deg));
  transition: transform var(--dur-5) var(--ease-out);
  display: grid;
  place-items: center;
}

.archive__space > * {
  position: absolute;
  transform-style: preserve-3d;
}

/* Catalogued volumes: each volume is a separate plane pushed back in Z and
   stepped across, so the stack has real depth instead of being one flat card. */
.volumes {
  position: relative;
  width: 62%;
  aspect-ratio: 5 / 6;
  transform-style: preserve-3d;
  transform: rotateX(6deg) rotateY(-15deg);
}

.volume {
  position: absolute;
  inset: 0;
  border: 1px solid color-mix(in srgb, var(--ad-line) 20%, transparent);
  border-radius: 0.5rem;
  background: linear-gradient(160deg, var(--ad-sat-1) 0%, var(--ad-face-2) 58%, var(--ad-face-5) 100%);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--ad-lift) 13%, transparent),
    inset 0 -14px 24px color-mix(in srgb, var(--ad-shade) 36%, transparent),
    0 22px 40px color-mix(in srgb, var(--ad-shade) 48%, transparent);
  transform: translate3d(
    calc(var(--dx, 0) * var(--stack-scale, 1)),
    calc(var(--dy, 0) * var(--stack-scale, 1)),
    calc(var(--dz, 0) * var(--stack-scale, 1))
  );
  overflow: hidden;
}

/* Subject tab on each spine: the cataloguing read. */
.volume::before {
  content: attr(data-subject);
  position: absolute;
  top: 0.55rem;
  left: 0.6rem;
  font-family: var(--font-mono);
  font-size: 0.56rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-library);
  opacity: 0.9;
}

/* Availability spine down the left edge. */
.volume::after {
  content: "";
  position: absolute;
  inset-block: 0;
  left: 0;
  width: 3px;
  background: var(--avail, var(--ink-library));
  opacity: 0.85;
}

/* Text block on the front-most volume only. */
.volume__text {
  position: absolute;
  inset: 2.1rem 0.7rem 0.7rem 1rem;
  display: grid;
  gap: 0.28rem;
  align-content: start;
}

.volume__text i {
  height: 0.22rem;
  border-radius: 1px;
  background: color-mix(in srgb, var(--ad-line) 26%, transparent);
}

.volume__text i:nth-child(1) { width: 62%; height: 0.34rem; background: color-mix(in srgb, var(--ad-line) 40%, transparent); }
.volume__text i:nth-child(2) { width: 100%; }
.volume__text i:nth-child(3) { width: 92%; }
.volume__text i:nth-child(4) { width: 78%; }
.volume__text i:nth-child(5) { width: 96%; }
.volume__text i:nth-child(6) { width: 54%; }

/* Index card floating free of the stack: the catalogue made visible. */
.archive__card {
  top: 8%;
  right: 2%;
  width: 34%;
  aspect-ratio: 5 / 4;
  padding: 0.55rem;
  border: 1px solid color-mix(in srgb, var(--ad-line) 26%, transparent);
  border-radius: 0.5rem;
  background: color-mix(in srgb, var(--ad-panel) 90%, transparent);
  box-shadow: 0 16px 30px color-mix(in srgb, var(--ad-shade) 46%, transparent), inset 0 1px 0 color-mix(in srgb, var(--ad-lift) 12%, transparent);
  transform: translateZ(170px) rotateZ(4deg);
  display: grid;
  gap: 0.22rem;
  align-content: start;
}

.archive__card i {
  height: 0.2rem;
  border-radius: 1px;
  background: color-mix(in srgb, var(--ad-line) 30%, transparent);
}

.archive__card i:nth-child(1) { width: 70%; background: var(--ink-library); height: 0.32rem; }
.archive__card i:nth-child(2) { width: 100%; }
.archive__card i:nth-child(3) { width: 84%; }
.archive__card i:nth-child(4) { width: 92%; }

/* Subject rail on the left: spatial organisation, not a filter chip row. */
.archive__rail {
  left: 1%;
  top: 50%;
  width: 20%;
  display: grid;
  gap: 0.34rem;
  transform: translateZ(60px) translateY(-50%);
}

.archive__rail span {
  display: flex;
  align-items: center;
  gap: 0.34rem;
  font-family: var(--font-mono);
  font-size: 0.54rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.archive__rail span::before {
  content: "";
  width: 0.3rem;
  height: 0.3rem;
  border-radius: 50%;
  background: var(--c, var(--accent));
  flex: none;
}

.archive__floor {
  inset: 78% -4% -10% -4%;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--ad-line) 12%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--ad-line) 10%, transparent) 1px, transparent 1px);
  background-size: 2.6rem 2.6rem;
  transform: translateZ(-100px) rotateX(76deg);
  transform-origin: 50% 0;
  mask-image: linear-gradient(to bottom, rgb(0 0 0 / 0.85), transparent 80%);
}

/* --------------------------------------------------------------------------
   4. TRACKER — progress path scene
   --------------------------------------------------------------------------
   The planned product is represented with an honest, structural visual: an
   ascending route with milestone nodes, a progress ring, level markers and
   certificate/profile layers. It states "study → progress → certificates →
   profile" as a dimensional story. Nothing here implies a working dashboard:
   the route is drawn to ~60% and the guides are dashed. No data, no UI.
   -------------------------------------------------------------------------- */

.trackpath {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  perspective: 1600px;
  perspective-origin: 50% 44%;
}

.trackpath__space {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transform: rotateX(var(--scene-rx, 0deg)) rotateY(var(--scene-ry, 0deg));
  transition: transform var(--dur-5) var(--ease-out);
  display: grid;
  place-items: center;
}

.trackpath__space > * {
  position: absolute;
  transform-style: preserve-3d;
}

/* Ground plane the route stands on. */
.trackpath__floor {
  inset: 74% -6% -12% -6%;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--ad-line) 10%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--ad-line) 8%, transparent) 1px, transparent 1px);
  background-size: 2.6rem 2.6rem;
  transform: translateZ(-140px) rotateX(74deg);
  transform-origin: 50% 0;
  mask-image: linear-gradient(to bottom, rgb(0 0 0 / 0.8), transparent 82%);
}

/* The route drawing: full planned journey (dashed) and the designed portion
   (solid, indigo) that fills in as the scene reveals. */
.trackpath__route {
  left: 50%;
  top: 50%;
  width: 74%;
  transform: translate(-50%, -50%) translateZ(30px);
  overflow: visible;
}

.trackpath__route svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

/* The product-page hero field styles every svg as a full-bleed overlay; the
   route drawing must flow inside its own box instead. */
.page-hero__field .trackpath__route svg {
  position: static;
  width: 100%;
  height: auto;
}

.route-zone,
.route-done {
  fill: none;
  stroke-linecap: round;
}

.route-zone {
  stroke: var(--border-strong);
  stroke-width: 1.5;
  stroke-dasharray: 2 6;
}

.route-done {
  stroke: var(--ink-tracker);
  stroke-width: 2.5;
  stroke-dasharray: 700;
  stroke-dashoffset: 700;
  filter: drop-shadow(0 0 7px color-mix(in srgb, var(--ink-tracker) 48%, transparent));
}

.is-inview .route-done {
  animation: route-fill 1.6s var(--ease-out) var(--reveal-delay, 0s) forwards;
}

@keyframes route-fill {
  to {
    stroke-dashoffset: 0;
  }
}

/* Progress ring: the one completed, measurable moment. */
.trackpath__ring {
  display: none;
}

/* Milestone diamonds mounted on the route. --x/--y are percentages of the
   route box, authored in the markup at the same points as the SVG path. */
.trackpath__node {
  position: absolute;
  width: 0.6rem;
  height: 0.6rem;
  border: 1.5px solid color-mix(in srgb, var(--ink-tracker) 75%, transparent);
  background: var(--surface);
  transform: translate(-50%, -50%) rotate(45deg);
  box-shadow: 0 0 12px color-mix(in srgb, var(--ink-tracker) 42%, transparent);
}

.trackpath__node--done {
  background: var(--ink-tracker);
  border-color: var(--ink-tracker);
}

.trackpath__node--future {
  border-style: dashed;
  opacity: 0.6;
}

.trackpath__node--done::after {
  content: "";
  position: absolute;
  inset: 34%;
  background: radial-gradient(circle, var(--obj-hot), var(--ob-gold) 55%, transparent);
  filter: blur(1px);
}

/* Level markers beside the nodes: the CEFR scale without claiming data. */
.trackpath__tag {
  position: absolute;
  font-family: var(--font-mono);
  font-size: clamp(0.5rem, 1.1vw, 0.62rem);
  letter-spacing: 0.1em;
  color: var(--text-faint);
  white-space: nowrap;
}

/* Certificate layer: a folded paper card with a seal, on its own depth plane.
   A concept object, not a live record. */
.trackpath__cert {
  left: 74%;
  top: 10%;
  width: clamp(3.4rem, 11vw, 6.2rem);
  aspect-ratio: 3 / 4;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-2xs);
  background: linear-gradient(160deg, var(--surface-3), color-mix(in srgb, var(--surface) 82%, var(--ob-indigo)));
  box-shadow:
    var(--shadow-md),
    var(--shadow-lg),
    0 2px 0 color-mix(in srgb, var(--ink-tracker) 24%, transparent);
  transform: translateZ(70px) rotateY(-12deg) rotate(4deg);
}

.trackpath__cert::before {
  content: "";
  position: absolute;
  inset-inline: 18%;
  top: 26%;
  height: 3px;
  border-radius: 2px;
  background: var(--ink-tracker);
  box-shadow:
    0 10px 0 color-mix(in srgb, var(--ink-tracker) 50%, transparent),
    0 20px 0 color-mix(in srgb, var(--ink-tracker) 26%, transparent);
}

.trackpath__cert::after {
  content: "";
  position: absolute;
  right: 12%;
  bottom: 12%;
  width: 30%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 36% 30%, var(--obj-hot), var(--ob-gold) 58%, color-mix(in srgb, var(--ob-gold) 55%, transparent));
  opacity: 0.92;
  box-shadow: 0 1px 0 rgb(255 255 255 / 0.6);
}

/* A ghost "profile" card in the back, and the dashed Future CV outline far
   ahead of the drawn route — both planned, neither available. */
.trackpath__profile {
  left: 10%;
  top: 6%;
  width: clamp(2.6rem, 8vw, 4.4rem);
  aspect-ratio: 3 / 4;
  border: 1px solid var(--ad-line);
  border-radius: var(--radius-xs);
  background: color-mix(in srgb, var(--ad-face-3) 56%, transparent);
  transform: translateZ(120px) rotateY(10deg);
  opacity: 0.75;
  backdrop-filter: blur(1px);
  box-shadow: var(--shadow-sm), inset 0 1px 0 color-mix(in srgb, #fff 18%, transparent);
}

.trackpath__profile::before {
  content: "";
  position: absolute;
  inset-inline: 22%;
  top: 20%;
  width: 34%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: color-mix(in srgb, var(--ink-tracker) 40%, transparent);
}

.trackpath__profile::after {
  content: "";
  position: absolute;
  inset-inline: 22%;
  top: 44%;
  bottom: 34%;
  border-radius: 76% 76% 0 0;
  background: color-mix(in srgb, var(--ink-tracker) 28%, transparent);
}

.trackpath__cv {
  left: 72%;
  top: 58%;
  width: clamp(3rem, 9vw, 5rem);
  aspect-ratio: 4 / 3;
  border: 1.5px dashed var(--ad-line-strong);
  border-radius: var(--radius-2xs);
  transform: translateZ(12px) rotateY(6deg);
  opacity: 0.8;
  box-shadow: var(--shadow-xs);
}

.trackpath__cv::before {
  content: "CV";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.18em;
  color: var(--text-faint);
}

/* --------------------------------------------------------------------------
   4c. HOME ECOSYSTEM — one space, two distinct objects
   --------------------------------------------------------------------------
   The grid was already asymmetric (Speech spans both rows in the wide column),
   but both items were opaque bordered cards, which is what made the section
   read as two equal rectangles. Here the card framing is dissolved: the tint
   wash and a hairline carry the form, each panel is tilted into a shared
   perspective space at a different depth, and one shared floor ties the two
   objects together. No content, no extra cards.
   -------------------------------------------------------------------------- */

.ecosystem {
  position: relative;
  perspective: 1700px;
  perspective-origin: 50% 34%;
  isolation: isolate;
  /* the tilted floor plane bleeds past the section; clip it on the inline axis
     so it cannot extend the document. `clip` rather than `hidden` so it stays
     out of the scroll-container business and leaves overflow-y visible. */
  overflow-x: clip;
}

/* The shared space the two objects sit in. */
.ecosystem::before {
  content: "";
  position: absolute;
  inset: -6% -4% -10% -4%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(52% 44% at 22% 18%, color-mix(in srgb, var(--ink-speech) 10%, transparent), transparent 70%),
    radial-gradient(48% 46% at 82% 68%, color-mix(in srgb, var(--ink-library) 9%, transparent), transparent 72%),
    radial-gradient(40% 40% at 78% 92%, color-mix(in srgb, var(--ink-tracker) 10%, transparent), transparent 72%);
  filter: blur(10px);
}

/* shared floor, so the two panels read as standing in one room */
.ecosystem::after {
  content: "";
  position: absolute;
  inset: 62% 0 -14% 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--ad-line) 11%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--ad-line) 9%, transparent) 1px, transparent 1px);
  background-size: 3.4rem 3.4rem;
  transform: rotateX(76deg);
  transform-origin: 50% 0;
  mask-image: linear-gradient(to bottom, rgb(0 0 0 / 0.7), transparent 84%);
}

.ecosystem__item {
  background: transparent;
  border-color: color-mix(in srgb, var(--ad-line) 16%, transparent);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--ad-lift) 10%, transparent),
    0 26px 46px color-mix(in srgb, var(--ad-shade) 34%, transparent);
  transform: rotateX(5deg) translateZ(var(--eco-z, 0px));
  transform-style: preserve-3d;
  backdrop-filter: blur(2px);
}

/* the two panels sit at different depths, so they are not one flat pair */
.ecosystem__item--speech { --eco-z: 46px; }
.ecosystem__item--library { --eco-z: 0px; }

/* the wash carries the product identity now that the fill is gone */
.ecosystem__item::after {
  opacity: 0.96;
  background:
    radial-gradient(84% 64% at 10% 0%,
      color-mix(in srgb, var(--ink-speech) 26%, transparent) 0%,
      transparent 64%),
    linear-gradient(180deg,
      color-mix(in srgb, var(--ad-face-4) 62%, transparent) 0%,
      color-mix(in srgb, var(--ad-face-2) 42%, transparent) 100%);
}

.ecosystem__item--library::after {
  background:
    radial-gradient(94% 90% at 100% 4%,
      color-mix(in srgb, var(--ink-library) 24%, transparent) 0%,
      transparent 66%),
    linear-gradient(200deg,
      color-mix(in srgb, var(--ad-face-4) 58%, transparent) 0%,
      color-mix(in srgb, var(--ad-face-2) 40%, transparent) 100%);
}

.ecosystem__item--tracker { --eco-z: -20px; }

.ecosystem__item--tracker::after {
  background:
    radial-gradient(88% 92% at 90% 96%,
      color-mix(in srgb, var(--ink-tracker) 26%, transparent) 0%,
      transparent 68%),
    linear-gradient(200deg,
      color-mix(in srgb, var(--ad-face-4) 56%, transparent) 0%,
      color-mix(in srgb, var(--ad-face-2) 40%, transparent) 100%);
}

/* visuals get depth instead of sitting flat on the panel */
.ecosystem__visual {
  transform-style: preserve-3d;
  transform: translateZ(24px);
}

.vis-wave__bars {
  transform-style: preserve-3d;
}

.vis-docs__stack {
  transform-style: preserve-3d;
  transform: rotateX(4deg) rotateY(-9deg);
}

.vis-docs__sheet {
  transform-style: preserve-3d;
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--ad-lift) 12%, transparent),
    0 14px 24px color-mix(in srgb, var(--ad-shade) 32%, transparent);
}

@media (max-width: 62rem) {
  .ecosystem {
    perspective: none;
  }

  .ecosystem__item {
    transform: none;
  }

  .ecosystem__visual,
  .vis-docs__stack {
    transform: none;
  }

  .ecosystem::after {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   4d. HEADER — presence and a legible SUN <-> MOON control
   --------------------------------------------------------------------------
   The header already had a tracked uppercase wordmark, a gradient diamond mark
   and a scaleX nav underline, so nothing is rebuilt here. What was missing was
   material: the mark was a flat gradient chip, and the switch track gave no
   hint which end was which. The mark is now a small lit solid with a top face
   and a cast shadow, and the switch carries a soft light on the active end.

   The switch keeps its existing button, aria-label, aria-pressed, title and
   focus ring -- only the surface treatment is added.
   -------------------------------------------------------------------------- */

.brand {
  letter-spacing: 0.16em;
  text-shadow: 0 1px 0 color-mix(in srgb, var(--ad-shade) 24%, transparent);
}

/* The Obstoon mark: a lit solid rather than a flat chip. */
.brand__dot {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  background:
    linear-gradient(150deg,
      color-mix(in srgb, var(--accent) 92%, #fff) 0%,
      var(--accent) 42%,
      var(--accent-2) 100%);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, #fff 62%, transparent),
    inset 0 -1px 0 color-mix(in srgb, var(--ad-shade) 30%, transparent),
    0 0 10px color-mix(in srgb, var(--accent) 42%, transparent),
    0 2px 5px color-mix(in srgb, var(--ad-shade) 40%, transparent);
  transform: translateY(-1px) rotate(45deg) scale(1.04);
  transition: box-shadow var(--dur-3) var(--ease-out),
    transform var(--dur-3) var(--ease-out);
}

.brand:hover .brand__dot {
  transform: translateY(-1px) rotate(45deg) scale(1.14);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, #fff 70%, transparent),
    0 0 16px color-mix(in srgb, var(--accent) 62%, transparent),
    0 3px 7px color-mix(in srgb, var(--ad-shade) 46%, transparent);
}

/* Current-page underline gets a lit edge so the active item is unmistakable
   without relying on colour alone. */
.site-nav__link[aria-current="page"]::after {
  height: 2px;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--accent) 70%, transparent),
    var(--accent), var(--accent-2));
  box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 46%, transparent);
}

/* SUN <-> MOON: the track shows a soft light at the end that is live. */
.theme-switch {
  --switch-w: 66px;
  height: 36px;
  background:
    linear-gradient(90deg,
      color-mix(in srgb, #f7c948 12%, transparent) 0%,
      transparent 46%,
      transparent 54%,
      color-mix(in srgb, #8ea6d8 14%, transparent) 100%),
    var(--surface-inset);
  border-color: color-mix(in srgb, var(--ad-line) 20%, transparent);
  box-shadow: inset 0 1px 2px color-mix(in srgb, var(--ad-shade) 26%, transparent);
}

.theme-switch__thumb {
  background: linear-gradient(150deg,
    color-mix(in srgb, var(--accent) 78%, #fff) 0%,
    var(--accent) 44%,
    color-mix(in srgb, var(--accent-2) 78%, var(--accent)) 100%);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, #fff 58%, transparent),
    0 0 14px color-mix(in srgb, var(--accent) 44%, transparent),
    0 2px 6px color-mix(in srgb, var(--ad-shade) 42%, transparent);
}

.theme-switch__opt svg {
  width: 17px;
  height: 17px;
}

/* --------------------------------------------------------------------------
   4e. LIGHT AND CHROMA — the mark is lit, not tinted
   --------------------------------------------------------------------------
   The aperture's material is defined in section 1. This block carries the
   frame-level light around it.

   The key light is cool in both themes. It used to be an amber (#ffd8a6 dark,
   #ffab4d light) laid over the page at up to 88% alpha, which is where the
   warm beige and orange came from in Light mode: a saturated warm hue at that
   strength over a white field dominates the frame. The rig is now a blue-white
   key with an indigo fill in both themes, so the two themes differ in value
   rather than in temperature, and Light mode reads as cool neutral white with
   restrained violet rather than as paper.
   -------------------------------------------------------------------------- */


/* Light mode: the face was white on white with no ramp, so the annulus read as
   a flat disc. It now carries a base value ramp from near-white top-left to a
   light blue-grey bottom-right, a blue-white key on the shoulder and a broader
   indigo fill opposite, which is what gives the ring its turn. */
[data-theme="light"] .core__ring--front {
  background:
    radial-gradient(74% 74% at 76% 18%, color-mix(in srgb, var(--ad-key) 78%, transparent), transparent 64%),
    radial-gradient(72% 72% at 22% 86%, color-mix(in srgb, var(--ad-key-2) 52%, transparent), transparent 70%),
    linear-gradient(148deg, #fdfefe 0%, #eef3fb 44%, #c9d7ec 100%);
}

[data-theme="light"] .core__edge {
  border-color: color-mix(in srgb, var(--ad-seam) 92%, transparent);
  box-shadow: 0 16px 34px color-mix(in srgb, var(--ad-shade) 30%, transparent);
}

/* Light mode: the bore shows the page, which is the same value as the face, so
   the hole needs its own depth. A shaded disc painted behind the front annulus
   and clipped to the bore gives the aperture something to look into. Scoped to
   Light only, because in Dark the bore is already the lit part of the frame. */
[data-theme="light"] .core__bore {
  background: radial-gradient(circle at 50% 50%,
    color-mix(in srgb, var(--ad-shade) 34%, transparent) 0 26%,
    color-mix(in srgb, var(--ad-shade) 22%, transparent) 31%,
    transparent 35%);
}

/* Light mode: the pale field needs less atmosphere, not less structure. Each
   haze layer is cut by about a third so the page, the grid, the cards and the
   objects step apart instead of merging through a soft blue veil. The palette
   stays cool-white; nothing goes warm. */
[data-theme="light"] .core-haze {
  background:
    radial-gradient(44% 38% at 72% 26%, color-mix(in srgb, var(--ad-key) 11%, transparent), transparent 70%),
    radial-gradient(46% 44% at 26% 72%, color-mix(in srgb, var(--ad-key-2) 11%, transparent), transparent 72%),
    radial-gradient(58% 46% at 50% 98%, color-mix(in srgb, var(--ad-shade) 20%, transparent), transparent 76%);
  filter: blur(8px);
}

[data-theme="light"] .hero__glow {
  background:
    repeating-linear-gradient(
      90deg,
      color-mix(in srgb, var(--ad-seam) 12%, transparent) 0 1px,
      transparent 1px 72px
    ),
    repeating-linear-gradient(
      0deg,
      color-mix(in srgb, var(--ad-seam) 9%, transparent) 0 1px,
      transparent 1px 72px
    ),
    radial-gradient(
      50% 48% at 66% 30%,
      color-mix(in srgb, var(--ad-key) 34%, transparent) 0%,
      color-mix(in srgb, var(--ad-key) 22%, transparent) 40%,
      transparent 76%
    ),
    radial-gradient(
      42% 40% at 22% 78%,
      color-mix(in srgb, var(--ad-key-2) 24%, transparent) 0%,
      color-mix(in srgb, var(--ad-key-2) 10%, transparent) 50%,
      transparent 80%
    ),
    radial-gradient(
      58% 36% at 58% 62%,
      color-mix(in srgb, var(--ad-line) 8%, transparent) 0%,
      transparent 74%
    );
  mask-image: radial-gradient(122% 100% at 54% 36%, #000 52%, transparent 98%);
  -webkit-mask-image: radial-gradient(122% 100% at 54% 36%, #000 52%, transparent 98%);
}

[data-theme="light"] .ecosystem::before {
  background:
    radial-gradient(52% 44% at 22% 18%, color-mix(in srgb, var(--ink-speech) 7%, transparent), transparent 70%),
    radial-gradient(48% 46% at 82% 68%, color-mix(in srgb, var(--ink-library) 6%, transparent), transparent 72%),
    radial-gradient(40% 40% at 78% 92%, color-mix(in srgb, var(--ink-tracker) 7%, transparent), transparent 72%);
  filter: blur(10px);
}
/* The luminous field behind the home object.
   A broad pool of key light on the right where the object stands, a cooler
   fill low on the left, and a mask held open just long enough for both to
   survive. After review the alphas and reach were pulled back: the haze had
   crept past "frame value range" into a bloom that competed with the copy
   column, so the stops are now roughly two-thirds of what they were and the
   key radius is tighter. The frame still carries a lit direction, but the text
   and the ring carry the peaks. */
.hero__glow {
  background:
    repeating-linear-gradient(
      90deg,
      color-mix(in srgb, var(--ad-seam) 18%, transparent) 0 1px,
      transparent 1px 72px
    ),
    repeating-linear-gradient(
      0deg,
      color-mix(in srgb, var(--ad-seam) 13%, transparent) 0 1px,
      transparent 1px 72px
    ),
    /* key light: wide, high, on the object's side, but held below bloom so the
       wash sits behind the object and the copy rather than over them. */
    radial-gradient(
      54% 52% at 66% 30%,
      color-mix(in srgb, var(--ad-key) 54%, transparent) 0%,
      color-mix(in srgb, var(--ad-key) 40%, transparent) 38%,
      color-mix(in srgb, var(--ad-key) 12%, transparent) 62%,
      transparent 82%
    ),
    /* cool fill, low and opposite, so the field has a direction */
    radial-gradient(
      44% 42% at 22% 78%,
      color-mix(in srgb, var(--ad-key-2) 40%, transparent) 0%,
      color-mix(in srgb, var(--ad-key-2) 14%, transparent) 48%,
      transparent 80%
    ),
    /* a wide, low pool under the object so it stands in light */
    radial-gradient(
      60% 38% at 58% 62%,
      color-mix(in srgb, var(--ad-line) 12%, transparent) 0%,
      transparent 74%
    ),
    linear-gradient(
      180deg,
      transparent 0%,
      transparent 68%,
      color-mix(in srgb, var(--obj-1) 12%, transparent) 86%,
      transparent 100%
    );
  mask-image: radial-gradient(128% 102% at 54% 36%, #000 56%, transparent 98%);
  -webkit-mask-image: radial-gradient(128% 102% at 54% 36%, #000 56%, transparent 98%);
}

/* Ruled detail on the object's side of the frame.
   The hero's edge density was almost entirely coming from the text column, so
   the left half carried roughly twice the detail of the right and the frame
   read as left-weighted. The object itself is smooth by construction -- it is
   built from soft gradients -- so the right half needed line work of its own.

   Ruled lines and a measure rule are the right motif here rather than more
   geometry on the slab: this is a study product, and ruled paper is already
   the brand's own language. The mask fades them in from the centre so they
   never crowd the copy. After review the field's density was pulled back hard:
   the tick column had moved toward HUD territory, so the rules are lighter and
   wider-set -- still present as imprint, no longer reading as a texture. */
.hero-visual::before {
  content: "";
  position: absolute;
  inset: 3% -3% 3% 2%;
  pointer-events: none;
  background:
    /* the measure rule: a lighter tick column down the right edge */
    repeating-linear-gradient(180deg,
      color-mix(in srgb, var(--ad-seam) 38%, transparent) 0 1px,
      transparent 1px 11px),
    /* ruled lines */
    repeating-linear-gradient(0deg,
      color-mix(in srgb, var(--ad-seam) 16%, transparent) 0 1px,
      transparent 1px 16px),
    repeating-linear-gradient(90deg,
      color-mix(in srgb, var(--ad-seam) 14%, transparent) 0 1px,
      transparent 1px 36px);
  mask-image: linear-gradient(90deg, transparent 0%, #000 30%, #000 90%, transparent 100%);
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 30%, #000 90%, transparent 100%);
  opacity: 0.36;
}

/* Keep the ruled field off the object itself -- it is depth cue for the space
   around the slab, not a texture on it. */
.hero-visual > * {
  position: relative;
}

/* --------------------------------------------------------------------------
   5. Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 64rem) {
  .core-scene {
    max-width: 32rem;
  }
}

/* Mobile. The mark was nearly full-bleed at 390px and the hero ran well past
   the first screen. The scene is now sized below the measure of the text
   column, so the copy leads, the object follows, and the whole composition
   lands inside the first viewport rather than straddling two. */
@media (max-width: 48rem) {
  .core-scene {
    max-width: 20rem;
  }

  /* Cut mobile hero haze slightly so content/background separate better. */
  .core-haze {
    filter: blur(8px);
    background:
      radial-gradient(44% 38% at 72% 26%, color-mix(in srgb, var(--ad-key) 10%, transparent), transparent 70%),
      radial-gradient(46% 44% at 26% 72%, color-mix(in srgb, var(--ad-key-2) 10%, transparent), transparent 72%),
      radial-gradient(58% 46% at 50% 98%, color-mix(in srgb, var(--ad-shade) 20%, transparent), transparent 76%);
  }

  .hero__glow {
    mask-image: radial-gradient(116% 98% at 54% 36%, #000 52%, transparent 98%);
    -webkit-mask-image: radial-gradient(116% 98% at 54% 36%, #000 52%, transparent 98%);
  }

  /* The stack of eyebrow, headline, lead, two buttons and two chips was
     pushing the mark past the first screen. Tightening the vertical rhythm
     buys it back without dropping any of it. */
  .hero {
    padding-block-start: clamp(1.75rem, 6vw, 2.5rem);
  }

  .hero__content {
    gap: clamp(0.75rem, 2.6vw, 1.05rem);
  }

  .hero__grid {
    gap: clamp(1.75rem, 4vw, 2.5rem);
  }

  .hero__meta {
    gap: 0.35rem;
  }

  .hero__meta .chip {
    font-size: var(--text-2xs);
    padding: 0.3rem 0.6rem;
  }

  /* The 5-volume stack is taller than the field box at this width, so the
     step is scaled down rather than allowed to bleed out of frame. */
  .archive {
    --stack-scale: 0.36;
  }

  .volumes {
    width: 54%;
  }

  /* Pointer 3D is dropped rather than faked with a wrong resting angle. */
  .core-space,
  .mic__space,
  .archive__space {
    transform: rotateX(4deg);
  }

  /* The modules keep their position on the orbit and lose only their
     stand-off depth, so the composition survives without pointer parallax.
     The -50% centre offset has to stay: it is what puts each module on its
     point of the orbit rather than at its corner. */
  .sat--voice,
  .sat--doc,
  .sat--wave {
    transform: translate(-50%, -50%);
  }

  .mic__frag--a,
  .mic__frag--b,
  .mic__frag--c {
    transform: translateZ(0);
    max-width: 8rem;
  }

  .archive__card {
    transform: translateZ(0) rotateZ(3deg);
  }

  /* Tighter vertical spacing between related scene motifs on tracker only, per
     the "home + tracker scene spacing" QC item. */
  .trackpath__cert {
    top: 8%;
  }

  .trackpath__profile {
    top: 4%;
  }

  .trackpath__cv {
    top: 54%;
  }
}

@media (max-width: 29.99rem) {
  .core-scene {
    max-width: 15.5rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .core-space,
  .mic__space,
  .archive__space,
  .trackpath__space {
    transform: none;
  }
}