/**
 * SITE — shell, sections and components.
 *
 * Every colour, size, radius and duration below resolves through a token. The file is
 * organised by what a visitor meets in order: shell, hero, sections, cards, forms,
 * footer.
 */

/* ════════════════════════════════════════════════════════════════════════════
   LAYOUT PRIMITIVES
   ════════════════════════════════════════════════════════════════════════════ */

.shell {
  width: 100%;
  max-width: var(--wide);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.shell--narrow { max-width: 860px; }

.section {
  position: relative;
  padding-block: var(--section-y);
}

.section--sunken { background: var(--surface-sunken); }
.section--raised { background: var(--surface-raised); }

/* Section heads are centred by default; `--left` opts out for editorial pages. */
.section__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  text-align: center;
  max-width: 720px;
  margin-inline: auto;
  margin-bottom: var(--space-9);
}

.section__head--left {
  align-items: flex-start;
  text-align: left;
  margin-inline: 0;
}

.section__lede {
  font-size: var(--text-lg);
  color: var(--text-secondary);
  line-height: var(--leading-snug);
  max-width: 60ch;
}

/* The eyebrow carries the brand's structural-label treatment plus a gold tint. It is
   the one small type role allowed to use the accent, because it is never a paragraph. */
.eyebrow--accent { color: var(--accent-interactive); }

/* Bullet-separated eyebrow — "AI • SOFTWARE • RESEARCH". Separators are generated so
   the markup stays a plain list of words. */
.eyebrow--dotted { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.eyebrow--dotted > span + span::before {
  content: '•';
  margin-right: var(--space-2);
  opacity: 0.55;
}

/* A headline word set in the accent. Display-size only — at 3rem the gold clears
   contrast comfortably on both grounds. */
.text-accent { color: var(--accent-interactive); }

/* ════════════════════════════════════════════════════════════════════════════
   INDEXED SECTION BAND — the redesign's structural signature
   ════════════════════════════════════════════════════════════════════════════

   Every homepage section opens the same way: a mono index, the eyebrow, and the phase
   rule running to the edge of the shell. The rule — the one divider only this brand
   draws — stops being an occasional detail and becomes the spine of the page. One
   glance at any section band says Heliosync; that is the whole job.

   The index is mono because it is an ordinal, which is squarely inside the "numerals,
   ratios, IDs" rule. It is aria-hidden in markup: the order is already expressed by
   the document, and "zero one" read aloud before every heading is noise. */

.sec-head { margin-bottom: clamp(var(--space-8), 7vw, var(--space-9)); }

.sec-head__band { display: flex; align-items: center; gap: var(--space-4); }

.sec-head__index {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--accent-interactive);
  letter-spacing: 0.08em;
  flex: 0 0 auto;
}

.sec-head__band .eyebrow { flex: 0 0 auto; }

/* The rule fills whatever the band's text leaves. `width: auto` because the base
   class sets 100%, which inside flex would refuse to shrink. */
.sec-head__band .phase-rule { flex: 1 1 auto; width: auto; min-width: 48px; }

.sec-head__title {
  margin-top: var(--space-6);
  font-size: var(--text-4xl);
  letter-spacing: var(--track-4xl);
  line-height: var(--leading-displayTight);
  font-weight: var(--weight-displayHeavy);
  max-width: 22ch;
  text-wrap: balance;
}

/* Reuses .section__lede in markup so the scroll-linked text fill applies unchanged. */
.sec-head .section__lede { margin-top: var(--space-5); max-width: 58ch; }

/* ════════════════════════════════════════════════════════════════════════════
   ENTRANCE STAGE
   ════════════════════════════════════════════════════════════════════════════

   Hidden unless the head script has explicitly turned the sequence on. That polarity
   is the whole safety story: with JavaScript disabled the attribute stays "armed",
   this rule never matches, and the visitor gets the site immediately rather than a
   black cover with no way out.

   The stage carries the ground colour so there is no flash of content between first
   paint and the first canvas frame. The canvas then paints its own ground on the same
   clock as the particles, because fading a CSS background and a canvas on two
   different clocks is exactly where a sequence like this comes apart. */
.intro-stage { display: none; }

html[data-intro='on'] .intro-stage {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--surface-base);
  /* Input is handled on window with a one-shot listener that ends the sequence, so the
     stage itself never needs to intercept anything. */
  pointer-events: none;
}

html[data-intro='on'] .intro-stage canvas {
  width: 100%;
  height: 100%;
  display: block;
}

/* While the entrance is running the page must not scroll underneath it. */
html[data-intro='on'] { overflow: hidden; }

/* ════════════════════════════════════════════════════════════════════════════
   HEADER
   ════════════════════════════════════════════════════════════════════════════ */

.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  height: var(--header-h);
  display: flex;
  align-items: center;
  border-bottom: 1px solid transparent;
  transition:
    background-color var(--duration-normal) var(--ease-standard),
    border-color var(--duration-normal) var(--ease-standard),
    backdrop-filter var(--duration-normal) var(--ease-standard);
}

/* The header is transparent over the hero and acquires its ground once the page has
   scrolled past it — set by a scroll listener that only toggles one attribute. */
.site-header[data-scrolled='true'] {
  background: color-mix(in srgb, var(--surface-base) 82%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  backdrop-filter: blur(14px) saturate(1.4);
  border-bottom-color: var(--border-subtle);
}

@supports not (backdrop-filter: blur(1px)) {
  .site-header[data-scrolled='true'] { background: var(--surface-base); }
}

.site-header__inner {
  width: 100%;
  max-width: var(--wide);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--space-5);
}

.brand { display: inline-flex; align-items: center; gap: var(--space-3); }
.brand:focus-visible { outline-offset: 4px; }

/* ── The emblem ───────────────────────────────────────────────────────────────
   The logo reduced to geometry: sun rays, the crescent, the two-tone H, and the
   orbit carrying its dot. Inline SVG rather than an image file — it re-colours with
   the theme, stays sharp at any size and costs no request. */
.emblem { width: 2.15rem; height: 2.15rem; overflow: visible; flex: 0 0 auto; }
.emblem__rays { stroke: var(--accent-decorative); stroke-width: 2.4; stroke-linecap: round; opacity: 0.9; }
.emblem__crescent { fill: none; stroke: var(--accent-decorative); stroke-width: 4.5; stroke-linecap: round; }
.emblem__h-gold { fill: var(--accent-decorative); }
.emblem__h-sync { fill: var(--sync-base); }
.emblem__orbit { fill: none; stroke: var(--sync-base); stroke-width: 2.2; opacity: 0.85; }
.emblem__node { fill: var(--accent-decorative); }

/* The sun turns once, very slowly. At 48s it is below the threshold of noticing while
   watching and above it while glancing away and back — which is the intent. */
@media (prefers-reduced-motion: no-preference) {
  .emblem__rays { animation: emblem-spin 48s linear infinite; transform-origin: 50% 50%; }
  .emblem__orbit-group { animation: emblem-spin 26s linear infinite reverse; transform-origin: 50% 50%; }
}
@keyframes emblem-spin { to { transform: rotate(360deg); } }

/* ── Navigation ─────────────────────────────────────────────────────────────── */
.nav { display: flex; justify-content: center; }

.nav__list {
  display: flex;
  align-items: center;
  /* Tightened 2026-11-03 from clamp(16px, 2.2vw, 32px), when the ✳ toggle (34px)
     became the labelled edition switch (~145px). The header's three columns are
     packed to min-content above 1000px, so the room had to come from somewhere; six
     inter-item gaps at ~20px give it back without touching the type. */
  gap: clamp(var(--space-3), 1.5vw, calc(var(--space-4) + var(--space-1)));
}

.nav__link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding-block: var(--space-2);
  font-size: var(--text-sm);
  font-weight: var(--weight-bodyMedium);
  color: var(--text-secondary);
  white-space: nowrap;
  transition: color var(--duration-fast) var(--ease-standard);
}

.nav__link:hover { color: var(--text-primary); }

/* The active marker is the phase rule at nav scale: a short gold underline that grows
   from the centre rather than sliding in. */
.nav__link::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -2px;
  height: 1.5px;
  width: 0;
  background: var(--accent-decorative);
  transform: translateX(-50%);
  transition: width var(--duration-normal) var(--ease-standard);
}
.nav__link[aria-current='page'] { color: var(--accent-interactive); }
.nav__link[aria-current='page']::after { width: 22px; }

.nav__external { width: 11px; height: 11px; opacity: 0.75; flex: 0 0 auto; }

.header__actions { display: flex; align-items: center; gap: var(--space-3); justify-self: end; }

/* ── Edition switch ─────────────────────────────────────────────────────────
   "Cosmos | Horizon", replacing the ✳ theme toggle (2026-11-03). A segmented pill:
   one groove, two segments, the current one lit. The same shape as Horizon's own
   switch (.hz-edition) so a visitor crossing between editions finds it in the same
   place and the same form — only the material changes.

   On Cosmos the lit segment is gold on the glass tint with a gold hairline, never a
   solid gold fill: a filled gold capsule beside the Get in Touch pill would read as a
   second call to action, and this is a setting, not an offer. */
.edition-switch {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  height: 34px;
  padding: 3px;
  border: 1px solid var(--border-default);
  border-radius: 999px;
  font-size: var(--text-xs);
  font-weight: var(--weight-bodyMedium);
  letter-spacing: 0.02em;
  line-height: 1;
  white-space: nowrap;
}
.edition-switch__item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0 9px;
  border-radius: 999px;
  color: var(--text-secondary);
  transition: color var(--duration-fast) var(--ease-standard),
              background-color var(--duration-fast) var(--ease-standard);
}
.edition-switch__item[aria-current] {
  color: var(--accent-interactive);
  background: var(--glass-tint);
  box-shadow: inset 0 0 0 1px var(--border-accent);
}
/* The dot is the logo's synchronised oscillator at its smallest — the same gold node
   the mega menu uses to mark "this one is real". */
.edition-switch__item[aria-current]::before {
  content: '';
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--accent-decorative);
  box-shadow: 0 0 6px var(--accent-glow);
}
a.edition-switch__item:hover { color: var(--text-primary); background: var(--surface-glass); }
/* Rounded to the segment, not the default small radius: a square ring on a capsule
   looks like a rendering fault. */
a.edition-switch__item:focus-visible { outline-offset: 1px; border-radius: 999px; }

/* ── Mobile menu button ─────────────────────────────────────────────────────── */
.nav-toggle {
  display: none;
  width: 38px; height: 38px;
  place-items: center;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: transparent;
  cursor: pointer;
}
.nav-toggle__bars { position: relative; width: 16px; height: 10px; }
.nav-toggle__bars span {
  position: absolute; left: 0;
  width: 100%; height: 1.5px;
  background: var(--text-primary);
  transition: transform var(--duration-normal) var(--ease-standard),
              opacity var(--duration-fast) var(--ease-standard);
}
.nav-toggle__bars span:nth-child(1) { top: 0; }
.nav-toggle__bars span:nth-child(2) { bottom: 0; }
.nav-toggle[aria-expanded='true'] .nav-toggle__bars span:nth-child(1) { transform: translateY(4.25px) rotate(45deg); }
.nav-toggle[aria-expanded='true'] .nav-toggle__bars span:nth-child(2) { transform: translateY(-4.25px) rotate(-45deg); }

/* ════════════════════════════════════════════════════════════════════════════
   BUTTONS
   ════════════════════════════════════════════════════════════════════════════ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: 13px 24px;
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-bodyMedium);
  letter-spacing: 0.01em;
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
}

/* Primary is a metal rather than a flat fill: a two-stop gold that reads as a machined
   surface catching light. This is the only gradient on the site, and it is doing a
   material job rather than a decorative one. */
.btn--primary {
  background: linear-gradient(140deg, #E8CE7A 0%, var(--accent-solid) 46%, #B8942B 100%);
  color: #0B0B0E;
  border-color: color-mix(in srgb, var(--accent-solid) 70%, transparent);
  box-shadow: 0 1px 0 0 rgb(255 255 255 / 0.28) inset;
}
.btn--primary:hover { filter: brightness(1.06); }

.btn--ghost {
  background: transparent;
  color: var(--text-primary);
  border-color: var(--border-interactive);
}
.btn--ghost:hover { border-color: var(--accent-interactive); color: var(--accent-interactive); }

/* The header CTA is the one pill on the site — small enough that the radius reads as a
   deliberate exception rather than as the house style. */
.btn--pill { border-radius: 999px; padding: 10px 20px; font-size: var(--text-sm); }

/* The hero and the closing CTA carry the page's two display moments; their controls
   scale with them so the composition stays in proportion. */
.btn--lg { padding: 16px 30px; font-size: var(--text-base); }

.btn__arrow { width: 12px; height: 12px; flex: 0 0 auto; }

/* ════════════════════════════════════════════════════════════════════════════
   HERO
   ════════════════════════════════════════════════════════════════════════════ */

.hero {
  position: relative;
  min-height: min(100svh, 980px);
  display: flex;
  align-items: center;
  padding-top: calc(var(--header-h) + var(--space-8));
  padding-bottom: var(--space-7);
  overflow: hidden;
  isolation: isolate;
}

/* One stage rather than a two-column grid. The old 50/50 split capped the headline at
   half a shell, which is why nothing on the page ever felt big. Now the headline owns
   the full shell width and the field hangs behind its right edge — scale over
   symmetry, with the copy always painting above the atmosphere. */
.hero__stage { position: relative; width: 100%; }

.hero__content { position: relative; z-index: 2; }

.hero__title {
  margin-top: var(--space-5);
  font-size: var(--text-hero);
  letter-spacing: var(--track-hero);
  line-height: var(--leading-displayHero);
}

.hero__lede {
  margin-top: var(--space-6);
  font-size: var(--text-lg);
  color: var(--text-secondary);
  max-width: 44ch;
  line-height: var(--leading-snug);
}

.hero__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-7); }

/* ── Hero foot — verified figures as instrumentation ─────────────────────────
   No icons. A number beside a line icon reads as a marketing feature; a display-weight
   number over a tracked caps label under the phase rule reads as a measurement. Same
   figures, different register. */
.hero__foot { position: relative; z-index: 2; margin-top: clamp(var(--space-8), 9vh, var(--space-9)); }

.hero__foot > .phase-rule { margin-bottom: 0; }

.hero__stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0;
}

.stat { padding: var(--space-5) var(--space-4) 0 0; }
.stat + .stat { padding-left: var(--space-5); border-left: 1px solid var(--border-subtle); }

.stat__value {
  font-family: var(--font-display);
  font-weight: var(--weight-displayHeavy);
  font-size: var(--text-2xl);
  letter-spacing: var(--track-2xl);
  line-height: 1;
  color: var(--text-primary);
}
.stat__label {
  margin-top: var(--space-2);
  font-size: var(--text-2xs);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-muted);
  line-height: 1.4;
}

/* ── The coherence field ────────────────────────────────────────────────────── */

/* Legacy two-column composition — still the right layout for inner pages
   (Digital Human), where the field shares a grid with the page head. */
.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr);
  align-items: center;
  gap: var(--space-8);
  width: 100%;
}

.hero__field {
  position: relative;
  aspect-ratio: 1 / 1;
  width: 100%;
  max-width: 620px;
  justify-self: end;
}

/* Homepage stage: absolutely placed behind the headline's right edge. Positioned with
   inset + auto margins rather than a translate, because [data-depth] owns `transform`
   — a positioning translate here would be overwritten by the parallax animation. */
.hero__stage > .hero__field {
  position: absolute;
  z-index: 0;
  inset: 0 max(-6vw, -84px) 0 auto;
  margin-block: auto;
  height: min(56vh, 44vw, 640px);
  width: auto;
  max-width: none;
}

/* The canvas is decorative and aria-hidden. It carries no text and no information that
   is not also stated in the copy beside it. */
/* ── Horizon ground wash ──────────────────────────────────────────────────────
   A flat light fill is what makes a light theme feel like an unstyled document: on
   Cosmos the eye reads depth from the field, the bloom and the glows lifting out of
   black, and none of that machinery has an equivalent here — light does not lift out
   of light.

   So depth is painted instead, and on the Platinum ground it is painted as light on
   metal: one cool highlight from the upper right where the hero field sits, and one
   deeper settle at the bottom, as though the sheet were lit from a single high source.
   Both are within ~3% of the base colour — invisible as colour, present as form. The
   copper appears only in the highlight, at a fifth of the strength of the steel, so
   the page keeps a trace of the brand's warmth without turning cream again.

   Fixed attachment: it is the room the page moves through, not a texture that scrolls
   with it. Cosmos is deliberately excluded — it already has three systems doing this
   job, and a fourth gradient there only muddies black. */
:root[data-theme='horizon'] body {
  background-image:
    radial-gradient(ellipse 95% 62% at 78% -12%, rgb(255 255 255 / 0.55), transparent 62%),
    radial-gradient(ellipse 70% 46% at 84% -4%, rgb(158 120 31 / 0.045), transparent 64%),
    radial-gradient(ellipse 120% 72% at 18% 110%, rgb(40 52 68 / 0.055), transparent 64%);
  background-attachment: fixed;
  background-repeat: no-repeat;
}

.field-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  mix-blend-mode: var(--field-blend);

  /* The quantum field fills its whole box — unlike the sphere it replaced, which was
     self-limiting because a projected sphere simply ends. A field that ends at the
     canvas rectangle reads as a cropped screenshot: four hard edges no other element
     on the page has. The mask returns the vignette the geometry no longer provides.

     Elliptical rather than circular, and slightly over-sized (68%/72% against a square
     box), so the fade completes exactly at the box edge. `closest-side` is load-bearing: the
     default farthest-corner ending shape puts the transparent stop outside the element,
     which leaves the mask ~85% opaque where it meets the edge — the hard rectangle
     survives, just fainter. Measured, not assumed. */
  -webkit-mask-image: radial-gradient(ellipse closest-side at 50% 50%, #000 0%, #000 54%, rgba(0, 0, 0, 0.42) 78%, transparent 100%);
          mask-image: radial-gradient(ellipse closest-side at 50% 50%, #000 0%, #000 54%, rgba(0, 0, 0, 0.42) 78%, transparent 100%);
}

/* The static fallback is the same composition and needs the same frame treatment, or
   the no-JS view gains an edge the live view does not have. */
.field-static {
  -webkit-mask-image: radial-gradient(ellipse closest-side at 50% 50%, #000 0%, #000 54%, rgba(0, 0, 0, 0.42) 78%, transparent 100%);
          mask-image: radial-gradient(ellipse closest-side at 50% 50%, #000 0%, #000 54%, rgba(0, 0, 0, 0.42) 78%, transparent 100%);
}

/* A static SVG of the same geometry sits underneath and is what a visitor sees when
   JavaScript is off, when WebGL is unavailable, or when reduced motion is requested.
   The canvas covers it when it starts, so there is never a flash of both. */
.field-static { position: absolute; inset: 0; opacity: 0.9; }
html[data-field='live'] .field-static { display: none; }

/* Ambient bloom behind the field. Radial, low-alpha, decorative — the one place a
   glow is permitted, because it stands in for the light the particles emit. */
.hero__bloom {
  position: absolute;
  inset: -22%;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(circle at 58% 46%, var(--accent-glow) 0%, transparent 60%);
  opacity: 0.75;
}

/* ── Site-wide particle atmosphere ──────────────────────────────────────────── */
/* One fixed canvas behind the whole document, drawn at very low density. It is the
   quietest possible statement of the same motif and it is never in front of text. */
.atmosphere {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.5;
}
.wp-site-blocks { position: relative; z-index: 1; }

/* ── Film grain ─────────────────────────────────────────────────────────────
   A static noise tile at a few percent opacity over the whole page, so the ground
   reads as material rather than as empty pixels. Inline SVG turbulence — no request,
   no animation, ~350 bytes. Sits above the header as film sits above everything;
   at this opacity it textures without ever obscuring. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 150;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 220px 220px;
  opacity: var(--grain-opacity);
  mix-blend-mode: overlay;
}

@media print { body::after { display: none; } }

/* ── Scroll cue ─────────────────────────────────────────────────────────────── */
.scroll-cue {
  position: absolute;
  left: 50%;
  bottom: var(--space-6);
  transform: translateX(-50%);
  display: grid;
  place-items: center;
  width: 24px; height: 38px;
  border: 1px solid var(--border-interactive);
  border-radius: 999px;
  opacity: 0.6;
}
.scroll-cue::after {
  content: '';
  width: 3px; height: 6px;
  border-radius: 999px;
  background: var(--accent-decorative);
  transform: translateY(-6px);
}
@media (prefers-reduced-motion: no-preference) {
  .scroll-cue::after { animation: cue-drift 2.4s var(--ease-standard) infinite; }
}
@keyframes cue-drift {
  0%, 100% { transform: translateY(-6px); opacity: 0; }
  30%      { opacity: 1; }
  70%      { transform: translateY(6px); opacity: 0; }
}

/* ════════════════════════════════════════════════════════════════════════════
   CARDS
   ════════════════════════════════════════════════════════════════════════════ */

.grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); }

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-6);
  background: var(--surface-raised);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  overflow: hidden;
  text-decoration: none;
  color: inherit;
}

/* The icon well: a hairline square with the glyph inside. Square rather than circular
   because the whole system's radius language is tight, and a circle here would be the
   only fully round element on the page. */
.card__icon {
  display: grid;
  place-items: center;
  width: 46px; height: 46px;
  border: 1px solid var(--border-accent);
  border-radius: var(--radius-md);
  color: var(--accent-decorative);
  background: color-mix(in srgb, var(--accent-decorative) 7%, transparent);
  flex: 0 0 auto;
}
.card__icon svg { width: 20px; height: 20px; }

.card__title { font-size: var(--text-xl); letter-spacing: var(--track-xl); }
.card__body { color: var(--text-secondary); font-size: var(--text-sm); }
.card__body p + p { margin-top: var(--space-3); }

.card__foot { margin-top: auto; padding-top: var(--space-2); display: flex; align-items: center; gap: var(--space-3); }

.card__arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--accent-interactive);
}
.card__arrow .arrow { width: 15px; height: 11px; }

/* Safety net. heliosync_icon() emits a viewBox-only SVG and base.css makes svg a block
   at max-width:100%, so an arrow outside a sizing wrapper stretches to fill its parent —
   a card-wide glyph. Zero specificity: every contextual size above and below still wins. */
:where(svg.arrow) { width: 1em; height: 1em; flex: 0 0 auto; }

/* Status pill on a product card. Text-sized, hairline, no fill — a label, not a badge. */
.status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border: 1px solid var(--border-default);
  border-radius: 999px;
  font-size: var(--text-2xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.status::before {
  content: '';
  width: 5px; height: 5px;
  border-radius: 999px;
  background: currentColor;
}
.status[data-state='live']        { color: var(--success); border-color: color-mix(in srgb, var(--success) 40%, transparent); }
.status[data-state='development'] { color: var(--accent-interactive); border-color: var(--border-accent); }
.status[data-state='research']    { color: var(--info); border-color: color-mix(in srgb, var(--info) 40%, transparent); }
.status[data-state='planned']     { color: var(--text-muted); }

/* ── Product card (2026-08 redesign) ─────────────────────────────────────────
   The icon well is retired here. A hairline square holding a generic line glyph is the
   most interchangeable element a technology site can carry; the product's name at
   display weight, its category, and its honest status do more work with less. */
.card--product { padding: var(--space-7); gap: var(--space-5); }

.card__top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
}

.card__name {
  font-size: var(--text-2xl);
  letter-spacing: var(--track-2xl);
  font-weight: var(--weight-displayHeavy);
  line-height: var(--leading-display);
}

/* ════════════════════════════════════════════════════════════════════════════
   THE DISCIPLINE LEDGER — an index, not a menu
   ════════════════════════════════════════════════════════════════════════════

   Replaces the four icon cards. Full-width numbered rows read as the contents page of
   a technical document — which is what a four-discipline structure actually is. Hover
   is the brand signature doing the talking: the row lifts its material 1.2°, the rim
   light tracks the pointer, and the row's coherence bar locks platinum → gold. */

.ledger { border-top: 1px solid var(--border-subtle); }

.ledger__row {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: 'index main meta';
  align-items: center;
  gap: clamp(var(--space-5), 4vw, var(--space-8));
  padding: clamp(var(--space-6), 4.5vw, var(--space-7)) var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
  color: inherit;
  text-decoration: none;
}

.ledger__index {
  grid-area: index;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--accent-interactive);
  min-width: 3ch;
}

.ledger__main { grid-area: main; }

.ledger__title {
  font-size: var(--text-2xl);
  letter-spacing: var(--track-2xl);
  font-weight: var(--weight-display);
  transition: color var(--duration-fast) var(--ease-standard);
}

/* ════════════════════════════════════════════════════════════════════════════
   SECTOR MENU — the Products panel
   ════════════════════════════════════════════════════════════════════════════

   Anchored to the header rather than to the nav item: a panel hanging off a
   centred nav item would sit wherever that item happens to fall, and the item
   moves as the nav wraps. Pinned to the header's own bottom edge it lands in the
   same place every time, which is what makes it read as part of the chrome.

   It borrows the header's glass treatment so it reads as the header extending
   downward rather than as a card floating over the page. */
.nav__item--mega { position: static; }

.mega {
  position: absolute;
  inset-inline: 0;
  top: 100%;
  z-index: 90;
  background: color-mix(in srgb, var(--surface-raised) 94%, transparent);
  -webkit-backdrop-filter: blur(18px) saturate(1.3);
  backdrop-filter: blur(18px) saturate(1.3);
  border-bottom: 1px solid var(--border-subtle);
  box-shadow: var(--elevation-3);
  /* Opens downward from the header edge. transform only — animating height would
     relayout the whole panel every frame. */
  transform-origin: top center;
  animation: mega-in var(--duration-fast) var(--ease-entrance) both;
}

@supports not (backdrop-filter: blur(1px)) {
  .mega { background: var(--surface-raised); }
}

@keyframes mega-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

.mega__inner {
  width: 100%;
  max-width: var(--wide);
  margin-inline: auto;
  padding: clamp(var(--space-6), 4vw, var(--space-8)) var(--gutter);
  display: grid;
  grid-template-columns: minmax(200px, 1fr) 2.4fr;
  gap: clamp(var(--space-6), 5vw, var(--space-9));
}

.mega__lead-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: var(--weight-displayHeavy);
  letter-spacing: var(--track-xl);
  color: var(--text-primary);
}

.mega__lead-link .arrow { transition: transform var(--duration-fast) var(--ease-standard); }
.mega__lead-link:hover .arrow { transform: translateX(3px); }

.mega__note {
  margin-top: var(--space-4);
  font-size: var(--text-sm);
  line-height: var(--leading-body);
  color: var(--text-muted);
  max-width: 30ch;
}

.mega__chev { width: 18px; height: 18px; flex: 0 0 auto; transition: transform var(--duration-fast) var(--ease-standard); }
.mega__lead-link:hover .mega__chev { transform: translateX(3px); }

/* ── The sector index (2026-09-13) ───────────────────────────────────────────
   Replaces the plain word list, in the nav panel and on the Products page. Each sector
   is a quiet card — gold glyph, name, the built marker, a chevron — because the index is
   the catalogue's front door and twelve bare words read as a footnote.

   Hover is four small moves at once rather than one large one: 2px of lift, the border
   tinting gold, a faint gold under-glow, and the chevron stepping 3px right. No tilt —
   [data-hover='lift'] is for large surfaces, and 1.2° on a 54px-tall tile reads as a
   wobble. Every glyph is explicitly sized: an unsized SVG in this theme stretches to fill
   its container, which is exactly how the giant arrow on the old sector cards happened. */
.sector-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 250px), 1fr));
  gap: var(--space-3);
}
.sector-grid--mega { margin-top: var(--space-4); grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 1180px) { .sector-grid--mega { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.sector-card {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 54px;
  padding: 12px var(--space-4);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background-color: color-mix(in srgb, var(--text-primary) 2.5%, var(--surface-raised));
  color: var(--text-secondary);
  text-decoration: none;
  transition:
    transform var(--duration-normal) var(--ease-standard),
    border-color var(--duration-normal) var(--ease-standard),
    background-color var(--duration-normal) var(--ease-standard),
    box-shadow var(--duration-normal) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard);
}
.sector-card__icon {
  width: 22px; height: 22px;
  flex: 0 0 auto;
  color: var(--accent-decorative);
  opacity: 0.78;
  transition: opacity var(--duration-fast) var(--ease-standard);
}
.sector-card__name { flex: 0 1 auto; min-width: 0; font-size: var(--text-base); line-height: 1.25; }
.sector-card__chev {
  width: 14px; height: 14px;
  flex: 0 0 auto;
  margin-left: auto;
  color: var(--text-muted);
  transition: transform var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard);
}

.sector-card:hover,
.sector-card:focus-visible {
  transform: translateY(-2px);
  border-color: var(--border-accent);
  background-color: color-mix(in srgb, var(--accent-decorative) 5%, var(--surface-raised));
  box-shadow: 0 12px 30px -16px var(--accent-glow), var(--elevation-1);
  color: var(--text-primary);
}
.sector-card:hover .sector-card__icon,
.sector-card:focus-visible .sector-card__icon { opacity: 1; }
.sector-card:hover .sector-card__chev,
.sector-card:focus-visible .sector-card__chev { transform: translateX(3px); color: var(--accent-interactive); }
.sector-card[aria-current='page'] { border-color: var(--border-accent); color: var(--text-primary); }

@media (prefers-reduced-motion: reduce) {
  .sector-card:hover, .sector-card:focus-visible,
  .sector-card:hover .sector-card__chev, .sector-card:focus-visible .sector-card__chev { transform: none; }
}

/* ── Sector page head ─────────────────────────────────────────────────────────
   Breadcrumb and the way back on one bar, then the title beside its tagline card. */
.sector-head__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.crumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.crumbs li { display: inline-flex; align-items: center; gap: var(--space-2); }
.crumbs a { color: var(--text-secondary); transition: color var(--duration-fast) var(--ease-standard); }
.crumbs a:hover, .crumbs a:focus-visible { color: var(--accent-interactive); }
.crumbs__sep { width: 12px; height: 12px; flex: 0 0 auto; color: var(--text-muted); }
.crumbs [aria-current='page'] { color: var(--text-primary); }

.sector-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  transition: color var(--duration-fast) var(--ease-standard);
}
.sector-back svg { width: 14px; height: 14px; flex: 0 0 auto; transition: transform var(--duration-fast) var(--ease-standard); }
.sector-back:hover, .sector-back:focus-visible { color: var(--accent-interactive); }
.sector-back:hover svg { transform: translateX(-3px); }

.sector-head__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: clamp(var(--space-6), 5vw, var(--space-9));
  align-items: end;
  margin-top: var(--space-6);
}
.sector-head .page-head__title { margin-top: 0; max-width: 16ch; }

.sector-tag {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  width: min(100%, 360px);
  padding: var(--space-5) var(--space-6);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-xl);
  background-color: color-mix(in srgb, var(--surface-raised) 82%, transparent);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
.sector-tag__icon {
  display: grid;
  place-items: center;
  width: 52px; height: 52px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent-decorative) 10%, transparent);
  color: var(--accent-decorative);
}
.sector-tag__icon svg { width: 24px; height: 24px; }
.sector-tag__text { margin: 0; font-size: var(--text-base); line-height: var(--leading-snug); color: var(--text-secondary); }
.sector-tag__text span { display: block; }

@media (max-width: 860px) {
  .sector-head__grid { grid-template-columns: 1fr; align-items: start; }
  .sector-tag { justify-self: start; }
}

/* ── Sector switcher ──────────────────────────────────────────────────────────
   Every sector, one tap away, at the top of every sector page — so moving from
   Education to Healthcare never means going back first. Wraps on wide screens; scrolls
   sideways on a phone, where twelve wrapped chips would push the page down a screen. */
.sector-switch { border-block: 1px solid var(--border-subtle); }
.sector-switch__inner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding-block: var(--space-4);
}
.sector-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 13px;
  border: 1px solid var(--border-subtle);
  border-radius: 999px;
  font-size: var(--text-2xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--text-muted);
  transition:
    color var(--duration-fast) var(--ease-standard),
    border-color var(--duration-fast) var(--ease-standard),
    background-color var(--duration-fast) var(--ease-standard);
}
.sector-chip:hover, .sector-chip:focus-visible { color: var(--text-primary); border-color: var(--border-accent); }
.sector-chip[aria-current='page'] {
  color: var(--accent-interactive);
  border-color: var(--border-accent);
  background-color: color-mix(in srgb, var(--accent-decorative) 8%, transparent);
}
@media (max-width: 720px) {
  .sector-switch__inner { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .sector-switch__inner::-webkit-scrollbar { display: none; }
}

/* The one mark separating the three sectors that have something from the nine that
   do not. Small, and explained by the legend underneath — an unexplained dot would
   be decoration, and this one is load-bearing. */
.mega__dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent-interactive);
  flex: 0 0 auto;
}

.mega__legend {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border-subtle);
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* Below the nav's collapse width the mobile panel owns the screen; the sector list
   would overlay its own links, so it never opens there (also enforced in site.js). */
@media (max-width: 1000px) {
  .mega { display: none !important; }
}

/* ════════════════════════════════════════════════════════════════════════════
   CHAIN — how the four pillars feed each other
   ════════════════════════════════════════════════════════════════════════════

   Sits directly under the pillar ledger and answers the question that list
   provokes: why is one company doing all four. Each row is a pair of indices and
   the sentence that links them, so it reads as a derivation rather than a second
   list — the ledger above already named everything, and repeating the names here
   would make this look like a summary instead of an argument.

   The last link points backwards (04 → 03), closing the loop. That is deliberate
   and is the whole point of the block: this is not a pipeline with an end, it is
   a cycle where the research feeds the entity that motivated the research. */
.chain {
  margin-top: clamp(var(--space-8), 7vw, var(--space-9));
  padding-top: var(--space-7);
  border-top: 1px solid var(--border-subtle);
  display: grid;
  gap: var(--space-5);
}

.chain__label { margin-bottom: var(--space-2); }

.chain__link {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(var(--space-4), 3vw, var(--space-6));
  align-items: baseline;
  padding-block: var(--space-3);
}

/* Mono, because these are identifiers pointing at numbered rows above — squarely
   inside this brand's "numerals, ratios, IDs" rule for the mono face. */
.chain__pair {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.chain__node { color: var(--accent-interactive); }

/* The arrow is the only element here that carries the accent at full strength on
   Cosmos; it is the thing the block is about. */
.chain__arrow { color: var(--text-muted); transition: color var(--duration-normal) var(--ease-standard); }
.chain__link:hover .chain__arrow { color: var(--accent-interactive); }

.chain__body {
  color: var(--text-secondary);
  line-height: var(--leading-body);
  max-width: 62ch;
  margin: 0;
}

/* The closing line is the company's philosophy in one sentence. Set at lede scale
   so it reads as a conclusion drawn from the four rows above it, not as a fifth row. */
.chain__close {
  margin-top: var(--space-5);
  padding-top: var(--space-6);
  border-top: 1px solid var(--border-subtle);
  font-size: var(--text-lg);
  line-height: var(--leading-snug);
  color: var(--text-primary);
  max-width: 66ch;
  text-wrap: pretty;
}

@media (max-width: 640px) {
  .chain__link { grid-template-columns: 1fr; gap: var(--space-2); }
  .chain__close { font-size: var(--text-base); }
}

/* ════════════════════════════════════════════════════════════════════════════
   PREMISE — the problem, then what is being built for it
   ════════════════════════════════════════════════════════════════════════════

   Added 2026-08-07. Three of the company's four lines of work are ahead of their
   own product, so the page cannot lead with a result. It leads with the reason
   instead: the left column states what is wrong today, the right states what is
   being built for it. That is an argument a reader can check, where a capability
   list is only an assertion.

   Two columns rather than stacked paragraphs, because the pairing IS the content —
   read side by side the problem and the answer are one statement; read one under
   the other they are two. It folds to one column below 860px, where side-by-side
   would leave both columns too narrow to hold a sentence.

   The rule between them is the brand's phase rule turned vertical: it belongs to
   the same family as every other divider on the site rather than introducing a new
   one, and it makes the pairing structural rather than merely adjacent. */
.section--premise { padding-block: clamp(var(--space-8), 8vw, var(--space-10)); }

.premise {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(var(--space-6), 5vw, var(--space-9));
  align-items: start;
  position: relative;
}

/* The divider. A pseudo-element rather than a border on a column, so it can inset
   from both ends and fade — a full-height hairline reads as a table, not a seam. */
@media (min-width: 861px) {
  .premise::before {
    content: '';
    position: absolute;
    inset-block: 4%;
    left: calc(50% - clamp(var(--space-3), 2.5vw, var(--space-5)));
    width: 1px;
    background: linear-gradient(
      to bottom,
      transparent,
      var(--border-default) 18%,
      var(--border-default) 82%,
      transparent
    );
  }
}

.premise__col > .eyebrow { margin-bottom: var(--space-4); }

/* The problem sits in the muted role and the answer in the primary one, so the
   emphasis falls on what is being done about it rather than on the complaint. */
.premise__problem {
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--text-muted);
  max-width: 46ch;
}

.premise__answer {
  font-size: var(--text-lg);
  line-height: var(--leading-snug);
  color: var(--text-primary);
  max-width: 46ch;
}

/* A continuation sentence: same voice, one step back, so a two-paragraph answer
   does not read as two competing claims. */
.premise__answer--tail {
  margin-top: var(--space-4);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--text-secondary);
}

/* Inside an existing panel (the StudioNoir band) the pair has less room, so it
   stacks and drops the divider. */
.premise--stacked { grid-template-columns: 1fr; gap: var(--space-6); margin-top: var(--space-7); }
.premise--stacked::before { display: none; }

@media (max-width: 860px) {
  .premise { grid-template-columns: 1fr; gap: var(--space-6); }
  .premise__answer { font-size: var(--text-base); }
}

/* The problem line. Set below the title and above the claim, in the muted role and one
   step down the scale, so a row reads as an argument — this is broken, here is what we
   are building — rather than as a heading with a description under it. Muted rather
   than secondary because it must clearly rank below the sentence that follows it; on
   both themes it is the token tuned against the darkest ground small type ever sits on. */
.ledger__problem {
  margin-top: var(--space-2);
  max-width: 62ch;
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
  color: var(--text-muted);
}

/* With a problem line present the claim needs its own separation, and it carries the
   emphasis of the pair. */
.ledger__problem + .ledger__body { margin-top: var(--space-3); color: var(--text-secondary); }

.ledger__body {
  margin-top: var(--space-2);
  color: var(--text-secondary);
  font-size: var(--text-base);
  max-width: 56ch;
}

.ledger__meta {
  grid-area: meta;
  display: grid;
  justify-items: end;
  gap: var(--space-3);
}

.ledger__arrow { display: inline-flex; color: var(--accent-interactive); }
.ledger__arrow .arrow { width: 18px; height: 14px; }

@media (hover: hover) and (pointer: fine) {
  .ledger__row:hover .ledger__title,
  .ledger__row:focus-within .ledger__title { color: var(--accent-interactive); }
}

/* ════════════════════════════════════════════════════════════════════════════
   COHERENCE READOUT — the about panel's designed artifact
   ════════════════════════════════════════════════════════════════════════════

   Replaces a filler graphic. Four discipline channels, each carrying a coherence bar
   at rest (platinum, drifting). Hovering the panel locks every channel at once — the
   four-disciplines-one-system claim, demonstrated instead of stated. */

.readout {
  display: grid;
  gap: var(--space-6);
  padding: clamp(var(--space-6), 4vw, var(--space-8));
  background: var(--surface-sunken);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-xl);
}

.readout__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-4);
}

.readout__row { display: grid; gap: var(--space-3); }

.readout__line {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
}

.readout__name {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-lg);
  letter-spacing: -0.01em;
}

/* Channel IDs and counts are mono because they are IDs and counts. */
.readout__ch {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--text-muted);
  margin-left: auto;
}

.readout__line .cbar { flex: 0 0 auto; }

/* The statement pull in the about copy — the one sentence that most sounds like this
   company, set so it cannot be skimmed past. */
.about__pull {
  margin-top: var(--space-6);
  padding-left: var(--space-5);
  border-left: 2px solid var(--accent-decorative);
  font-family: var(--font-display);
  font-weight: var(--weight-displaySoft);
  font-size: var(--text-xl);
  letter-spacing: var(--track-xl);
  line-height: var(--leading-snug);
  max-width: 32ch;
}

/* ════════════════════════════════════════════════════════════════════════════
   STUDIONOIR MONOLITH
   ════════════════════════════════════════════════════════════════════════════

   Still a generated composition rather than a screenshot — but a designed one: deeper
   ground, vignette, and a slow sheen that passes like light over lacquer. The literal
   white in the sheen is a material highlight, same precedent as the button's metal. */

/* Compound selector on purpose: .panel__media sets `background` as a shorthand later
   in this file, and at equal specificity source order would erase the vignette. */
.panel__media.noir-panel {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(circle at 50% 42%,
      color-mix(in srgb, var(--accent-decorative) 10%, transparent), transparent 64%),
    var(--surface-sunken);
}

@media (prefers-reduced-motion: no-preference) {
  .noir-panel::after {
    content: '';
    position: absolute;
    inset: -40%;
    pointer-events: none;
    background: linear-gradient(115deg,
      transparent 44%, rgb(255 255 255 / 0.05) 50%, transparent 56%);
    animation: noir-sheen 9s var(--ease-standard) infinite;
  }
}
@keyframes noir-sheen {
  0%, 55%  { transform: translate3d(-46%, 0, 0); }
  85%, 100% { transform: translate3d(46%, 0, 0); }
}

.noir-mark { position: relative; text-align: center; padding: var(--space-6); }

.noir-mark__line {
  font-family: var(--font-display);
  font-weight: var(--weight-displayHeavy);
  font-size: var(--text-3xl);
  letter-spacing: 0.2em;
  line-height: 1.08;
  color: var(--text-primary);
  /* Wide tracking pads the right edge by one full letterspace; nudge back to centre. */
  margin-right: -0.2em;
}
.noir-mark__line--accent { color: var(--accent-interactive); }

/* ════════════════════════════════════════════════════════════════════════════
   RESEARCH — ghost numerals
   ════════════════════════════════════════════════════════════════════════════

   Two programmes, each opened by its ordinal at display scale in a faint gold. The
   numeral is decoration over structure the document already states, so it carries no
   contrast obligation and is aria-hidden in markup. */

.research-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(var(--space-5), 5vw, var(--space-8));
  align-items: start;
  padding-block: var(--space-8);
  border-top: 1px solid var(--border-subtle);
}
.research-item:last-of-type { border-bottom: 1px solid var(--border-subtle); }

.research-item__index {
  font-family: var(--font-mono);
  font-size: var(--text-ghost);
  line-height: 0.8;
  letter-spacing: -0.04em;
  color: color-mix(in srgb, var(--accent-decorative) 28%, transparent);
}

.research-item__title { font-size: var(--text-2xl); letter-spacing: var(--track-2xl); }

.research-item__body {
  margin-top: var(--space-4);
  color: var(--text-secondary);
  max-width: 58ch;
}

/* ════════════════════════════════════════════════════════════════════════════
   TENETS — the principles, compact
   ════════════════════════════════════════════════════════════════════════════

   Deliberately quieter than Research: the page needs rhythm, and five standards in a
   tight grid against two programmes at ghost scale is the contrast that provides it. */

.tenets {
  display: grid;
  /* 300px, not 320: at a 768px viewport the scrollbar leaves ~677px of shell, and a
     320px minimum drops the grid to one column exactly where two fit comfortably. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: var(--space-7) var(--space-7);
}

.tenet { border-top: 1px solid var(--border-default); padding-top: var(--space-5); }

.tenet__index {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--accent-interactive);
}

.tenet__title { font-size: var(--text-lg); margin-top: var(--space-3); }

.tenet__body {
  margin-top: var(--space-2);
  color: var(--text-secondary);
  font-size: var(--text-sm);
  max-width: 44ch;
}

/* ════════════════════════════════════════════════════════════════════════════
   METRICS — verified audience figures
   ════════════════════════════════════════════════════════════════════════════

   Large, quiet, and separated by the phase rule rather than boxed. A number in a card
   with a border reads as a marketing tile; a number sitting in space with a hairline
   under it reads as a fact. Same figures, different register. */

.metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
  gap: var(--space-6);
  margin-top: var(--space-8);
}

.metric { padding-top: var(--space-4); border-top: 1px solid var(--border-accent); }

.metric__value {
  font-family: var(--font-display);
  font-weight: var(--weight-displayHeavy);
  font-size: var(--text-3xl);
  letter-spacing: var(--track-3xl);
  line-height: 1;
  color: var(--accent-interactive);
}

.metric__label {
  margin-top: var(--space-3);
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

/* ════════════════════════════════════════════════════════════════════════════
   NOTICE — the honesty block
   ════════════════════════════════════════════════════════════════════════════

   Used where the page has to state plainly what does NOT exist. Deliberately given a
   tinted ground and an accent edge so it cannot be skimmed past: a reader who skips it
   and reads the roadmap as a feature list is the precise failure these pages are built
   to avoid, and tense alone does not survive skimming. */

.notice {
  padding: var(--space-6) var(--space-7);
  background: color-mix(in srgb, var(--accent-decorative) 6%, var(--surface-raised));
  border: 1px solid var(--border-accent);
  border-left-width: 3px;
  border-radius: var(--radius-lg);
}
.notice p { max-width: 66ch; }

/* A card icon well carrying a numeral rather than a glyph — used for ordered
   architecture stages, where a generic icon would say less than the position does. */
.card__icon--num {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--accent-interactive);
  letter-spacing: 0;
}

/* ════════════════════════════════════════════════════════════════════════════
   FEATURE PANEL — a two-column block with media on one side
   ════════════════════════════════════════════════════════════════════════════ */

.panel {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr));
  gap: clamp(var(--space-6), 5vw, var(--space-9));
  align-items: center;
}
.panel--reverse .panel__media { order: -1; }

.panel__media {
  position: relative;
  aspect-ratio: 4 / 3;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-xl);
  background: var(--surface-raised);
  overflow: hidden;
  display: grid;
  place-items: center;
}
.panel__media img { width: 100%; height: 100%; object-fit: cover; }

/* Placeholder state — visible, labelled, and obviously not final. Better than a stock
   photograph, which would be a lie about what exists. */
.placeholder {
  display: grid;
  place-items: center;
  gap: var(--space-3);
  padding: var(--space-6);
  text-align: center;
  color: var(--text-muted);
  background-image:
    repeating-linear-gradient(45deg,
      color-mix(in srgb, var(--border-default) 55%, transparent) 0 1px,
      transparent 1px 11px);
}
.placeholder__label { font-size: var(--text-2xs); letter-spacing: var(--track-label); text-transform: uppercase; }

/* Portrait media — a 9:16 clip inside a panel that otherwise runs 4:3. Capped in
   width so the media column does not tower over the copy sitting beside it. */
.panel__media--portrait {
  aspect-ratio: 9 / 16;
  width: 100%;
  max-width: 340px;
  margin-inline: auto;
}
.panel__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* The credit sits on the frame rather than under it. Shanaya is StudioNoir's
   character, and the attribution has to survive the section being screenshotted —
   under the frame it would be cropped off, which is how misattribution starts. */
.panel__credit {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding: var(--space-6) var(--space-4) var(--space-3);
  font-size: var(--text-2xs);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  text-align: center;
  color: var(--text-secondary);
  background: linear-gradient(
    to top,
    color-mix(in srgb, var(--surface-raised) 94%, transparent),
    transparent);
}

/* ════════════════════════════════════════════════════════════════════════════
   PRINCIPLES / NUMBERED LIST
   ════════════════════════════════════════════════════════════════════════════ */

.principle {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-5);
  padding-block: var(--space-6);
  border-top: 1px solid var(--border-subtle);
}
.principle:last-child { border-bottom: 1px solid var(--border-subtle); }

.principle__index {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--accent-interactive);
  padding-top: 0.35em;
  min-width: 3ch;
}
.principle__title { font-size: var(--text-xl); margin-bottom: var(--space-2); }
.principle__body { color: var(--text-secondary); max-width: 62ch; }

/* ════════════════════════════════════════════════════════════════════════════
   TIMELINE
   ════════════════════════════════════════════════════════════════════════════ */

.timeline { position: relative; padding-left: var(--space-6); }
.timeline::before {
  content: '';
  position: absolute;
  left: 3px; top: 8px; bottom: 8px;
  width: 1px;
  background: linear-gradient(var(--border-accent), transparent);
}
.timeline__item { position: relative; padding-bottom: var(--space-7); }
.timeline__item::before {
  content: '';
  position: absolute;
  left: calc(var(--space-6) * -1);
  top: 8px;
  width: 7px; height: 7px;
  border-radius: 999px;
  background: var(--accent-decorative);
}
.timeline__date { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--accent-interactive); }
.timeline__title { font-size: var(--text-lg); margin-top: var(--space-1); }
.timeline__body { color: var(--text-secondary); font-size: var(--text-sm); margin-top: var(--space-2); max-width: 60ch; }

/* ════════════════════════════════════════════════════════════════════════════
   CTA BAND
   ════════════════════════════════════════════════════════════════════════════ */

.cta-band {
  position: relative;
  text-align: center;
  padding-block: clamp(var(--space-9), 12vw, var(--space-11));
  overflow: hidden;
}
.cta-band::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 120%, var(--accent-glow) 0%, transparent 62%);
  opacity: 0.9;
}
.cta-band > * { position: relative; }

/* The closing display moment, bracketing the page with the hero. */
.cta-band__rule { max-width: 320px; margin-inline: auto; margin-bottom: var(--space-6); }
.cta-band__title {
  font-size: var(--text-5xl);
  letter-spacing: var(--track-5xl);
  line-height: var(--leading-displayTight);
  max-width: 14ch;
  margin-inline: auto;
}
.cta-band__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); justify-content: center; margin-top: var(--space-7); }

/* ════════════════════════════════════════════════════════════════════════════
   CONTACT / SUPPORT
   ════════════════════════════════════════════════════════════════════════════ */

.contact-list { display: grid; gap: var(--space-5); }
.contact-list dt { font-size: var(--text-xs); letter-spacing: var(--track-label); text-transform: uppercase; color: var(--text-muted); margin-bottom: var(--space-1); }
.contact-list dd { font-size: var(--text-base); color: var(--text-primary); }
.contact-list a { color: var(--accent-interactive); }
.contact-list a:hover { color: var(--accent-hover); }

/* ════════════════════════════════════════════════════════════════════════════
   FORMS
   ════════════════════════════════════════════════════════════════════════════ */

.form { display: grid; gap: var(--space-5); }

.field { display: grid; gap: var(--space-2); }

.field label {
  font-size: var(--text-xs);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-muted);
}

.field input,
.field textarea,
.field select {
  width: 100%;
  padding: 12px 14px;
  background: var(--surface-sunken);
  /* border-interactive, not border-default: this outline IS the affordance, so it is
     held to 3:1 per WCAG 1.4.11. If you cannot see the edge of a text field, you
     cannot tell where to type. */
  border: 1px solid var(--border-interactive);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-size: var(--text-sm);
  transition: border-color var(--duration-fast) var(--ease-standard);
}

.field textarea { resize: vertical; min-height: 120px; line-height: var(--leading-body); }

.field input:hover,
.field textarea:hover,
.field select:hover { border-color: var(--border-strong); }

.field input:focus,
.field textarea:focus,
.field select:focus { border-color: var(--accent-interactive); }

/* The native arrow is drawn in the OS accent colour and cannot be themed. Replacing it
   with a background image keeps the control consistent across both grounds. */
.field select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 18px) center, calc(100% - 13px) center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 38px;
}

.field ::placeholder { color: var(--text-muted); opacity: 1; }

/* ════════════════════════════════════════════════════════════════════════════
   PAGE HEADER (inner pages)
   ════════════════════════════════════════════════════════════════════════════ */

.page-head {
  position: relative;
  padding-top: calc(var(--header-h) + clamp(var(--space-7), 7vw, var(--space-9)));
  padding-bottom: clamp(var(--space-6), 5vw, var(--space-8));
  overflow: hidden;
  isolation: isolate;
}

/* Inner pages have no coherence field, so without this they open on flat black and
   read as a different, cheaper site than the homepage. The bloom is the hero's
   atmosphere at a fraction of the strength — enough to carry the same light. */
.page-head::before {
  content: '';
  position: absolute;
  inset: -60% -10% auto -10%;
  height: 190%;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(ellipse 55% 45% at 76% 26%, var(--accent-glow) 0%, transparent 64%);
  opacity: 0.55;
}

/* A second, much wider wash from the opposite corner. One gradient alone reads as a
   spotlight; two crossing at different scales read as ambient light in a room. */
.page-head::after {
  content: '';
  position: absolute;
  inset: auto -20% -40% -20%;
  height: 120%;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(ellipse 70% 60% at 18% 88%, var(--accent-glow) 0%, transparent 70%);
  opacity: 0.22;
}
.page-head__title {
  font-size: var(--text-4xl);
  letter-spacing: var(--track-4xl);
  line-height: var(--leading-displayTight);
  max-width: 18ch;
  margin-top: var(--space-4);
}
.page-head__lede { margin-top: var(--space-5); font-size: var(--text-lg); color: var(--text-secondary); max-width: 58ch; line-height: var(--leading-snug); }

/* ════════════════════════════════════════════════════════════════════════════
   FOOTER
   ════════════════════════════════════════════════════════════════════════════ */

.site-footer { border-top: 1px solid var(--border-subtle); padding-block: var(--space-9) var(--space-6); background: var(--surface-sunken); }

/* The brand band: the site signs off at scale, above the link grid. */
.footer__brand { display: grid; gap: var(--space-6); margin-bottom: var(--space-8); }

.footer__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--space-8) var(--space-6);
}
/* These were <h5> under a page whose last section heading is an <h2>, which is a
   two-level skip and a WCAG 1.3.1 failure. They are <h2> now — inside the contentinfo
   landmark, so they scope sensibly and screen-reader users get them in the heading list
   for navigation. The visual treatment is unchanged; only the level moved. */
.footer__heading {
  font-size: var(--text-xs);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-muted);
  font-family: var(--font-body);
  font-weight: var(--weight-bodyMedium);
  line-height: var(--leading-body);
  margin-bottom: var(--space-4);
}
.footer__links { display: grid; gap: var(--space-3); }
.footer__links a { color: var(--text-secondary); font-size: var(--text-sm); transition: color var(--duration-fast) var(--ease-standard); }
.footer__links a:hover { color: var(--accent-interactive); }
.footer__strap { margin-top: var(--space-4); color: var(--text-muted); font-size: var(--text-sm); max-width: 34ch; }

.footer__base {
  margin-top: var(--space-8);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border-subtle);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  justify-content: space-between;
  align-items: center;
  color: var(--text-muted);
  font-size: var(--text-xs);
}

/* ════════════════════════════════════════════════════════════════════════════
   RESPONSIVE
   ════════════════════════════════════════════════════════════════════════════ */

/* Nav collapses at 1000px — the point at which seven items plus a CTA stop fitting
   without shrinking type below the body scale. */
@media (max-width: 1000px) {
  .site-header__inner { grid-template-columns: auto 1fr; }
  .nav-toggle { display: grid; }
  .header__actions .btn--pill { display: none; }

  .nav {
    position: fixed;
    inset: var(--header-h) 0 auto 0;
    display: block;
    padding: var(--space-6) var(--gutter) var(--space-8);
    background: var(--surface-overlay);
    border-bottom: 1px solid var(--border-subtle);
    box-shadow: var(--elevation-3);
    /* clip-path rather than height: it animates on the compositor and needs no
       measurement of the panel's natural height. */
    clip-path: inset(0 0 100% 0);
    transition: clip-path var(--duration-normal) var(--ease-standard);
  }
  .nav[data-open='true'] { clip-path: inset(0 0 0 0); }
  .nav[data-open='false'] { pointer-events: none; }

  .nav__list { flex-direction: column; align-items: stretch; gap: 0; }
  .nav__link { justify-content: space-between; padding-block: var(--space-4); font-size: var(--text-lg); border-bottom: 1px solid var(--border-subtle); }
  .nav__link::after { display: none; }
  .nav__cta { margin-top: var(--space-6); display: flex; }
  .nav__cta .btn { width: 100%; }
}

@media (min-width: 1001px) { .nav__cta { display: none; } }

/* Between the collapse and 1280px, logo + seven items + the edition switch + the CTA do
   not fit one line (the CTA already ran past the gutter here before the switch existed).
   The header CTA steps aside, exactly as it does below 1000px; Support Us in the nav
   still leads to the same place. */
@media (min-width: 1001px) and (max-width: 1279px) {
  .header__actions .btn--pill { display: none; }
}

/* The field leaves the overlap and returns to the flow before it would sit on top of
   wrapping headline text. */
@media (max-width: 900px) {
  .hero { min-height: 0; padding-top: calc(var(--header-h) + var(--space-7)); }
  .hero__grid { grid-template-columns: 1fr; gap: var(--space-7); }

  /* Copy first, field second — the field is atmosphere; it does not outrank the
     sentence that says what the page is. Smaller here too: at 460px it was the whole
     screen on a phone, which reads as a loading state rather than as a hero. */
  .hero__field {
    max-width: min(360px, 74vw);
    margin-inline: auto;
    justify-self: center;
  }
  .hero__stage > .hero__field {
    position: relative;
    inset: auto;
    margin: var(--space-7) auto 0;
    height: auto;
    width: min(340px, 72vw);
  }
  .scroll-cue { display: none; }
  .panel--reverse .panel__media { order: 0; }

  /* The ledger folds: index and coherence bar share the top line, the title and body
     run full width beneath. The arrow goes — the whole row is the affordance. */
  .ledger__row {
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas:
      'index meta'
      'main  main';
    align-items: baseline;
    row-gap: var(--space-4);
  }
  .ledger__meta { justify-items: start; justify-self: end; }
  .ledger__arrow { display: none; }

  .research-item { grid-template-columns: minmax(0, 1fr); row-gap: var(--space-3); }
}

@media (max-width: 620px) {
  .edition-switch__item { padding: 0 8px; }
  .edition-switch__item[aria-current]::before { display: none; }
  /* Logo, switch and menu button share one line down to a 360px phone: the switch
     gives up its dot (the lit segment still says which is current) and the header
     closes its gaps a step. */
  .site-header__inner { column-gap: var(--space-3); }
  .header__actions { gap: var(--space-2); }
  .hero__stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat { padding-top: var(--space-5); }
  .stat:nth-child(odd) { border-left: 0; padding-left: 0; }
  .stat:nth-child(even) { padding-left: var(--space-5); }
  .hero__actions .btn { flex: 1 1 100%; }
  .footer__grid { grid-template-columns: 1fr 1fr; }
  .footer__col:first-child { grid-column: 1 / -1; }
}

/* The narrowest phones (360-380px): one more notch, or the wordmark's tracking runs
   into the switch. */
@media (max-width: 380px) {
  .brand { gap: var(--space-2); }
  .edition-switch { padding: 2px; letter-spacing: 0; }
  .edition-switch__item { padding: 0 6px; }
}

/* ── The section objects (2026-09-24) ──────────────────────────────────────────
   Blender-built 3D objects beside section headings, in page heads, in the homepage's product
   cards and behind the closing band. heliosync_obj3d() prints the slot, scene3d.js draws it.
   The Blender still shows until the live object is ready, and for good without WebGL, without
   JavaScript, or under reduced motion. Decorative: aria-hidden, never over text. */
.obj3d {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  pointer-events: none;
}
.obj3d__still,
.obj3d__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.obj3d__still {
  object-fit: contain;
  transition: opacity var(--duration-slow) var(--ease-standard);
}
.obj3d__canvas {
  opacity: 0;
  transition: opacity var(--duration-slow) var(--ease-standard);
}
.obj3d[data-live] .obj3d__canvas { opacity: 1; }
.obj3d[data-live] .obj3d__still { opacity: 0; }

/* Beside a section heading or a page title: the empty upper right of the section, lined up
   with the content column's right edge. The section's content stacks above it. */
.section > .obj3d--head,
.page-head > .obj3d--head {
  position: absolute;
  z-index: 0;
  top: clamp(var(--space-6), 5vw, var(--space-8));
  right: max(var(--gutter), calc((100% - var(--wide)) / 2 + var(--gutter)));
  width: clamp(280px, 30vw, 470px);
}
.page-head > .obj3d--head {
  top: calc(var(--header-h) + var(--space-4));
  width: clamp(240px, 25vw, 400px);   /* page titles run wider than section headings */
}
/* A section with a narrow column (research) has only its margin free: a smaller object, in it */
.section > .obj3d--side {
  position: absolute;
  z-index: 0;
  top: clamp(var(--space-6), 5vw, var(--space-8));
  right: var(--space-3);
  width: clamp(200px, 19vw, 290px);
}
.section:has(> .obj3d--side) > .shell { position: relative; z-index: 1; }
.section:has(> .obj3d--head) > .shell,
.page-head:has(> .obj3d--head) > .shell { position: relative; z-index: 1; }

/* In a product card, between its tags and its name */
.obj3d--card {
  width: 100%;
  aspect-ratio: 16 / 10;
  max-height: 210px;
  margin: var(--space-2) 0 var(--space-1);
}

/* Behind the closing band's title, quieter than anything in front of it */
.cta-band > .obj3d--backdrop {
  position: absolute;
  z-index: 0;
  left: 50%;
  top: 50%;
  width: min(80vw, 720px);
  transform: translate(-50%, -50%);
  opacity: 0.3;
}
.cta-band > .shell { position: relative; z-index: 1; }

/* A page's figure column (the Digital Human page) */
.obj3d--figure {
  width: 100%;
  max-width: 540px;
  margin-inline: auto;
}

/* Narrow screens: the object moves above the heading instead of beside it */
@media (max-width: 900px) {
  .section > .obj3d--head,
  .section > .obj3d--side,
  .page-head > .obj3d--head {
    position: relative;
    top: auto;
    right: auto;
    width: min(78%, 380px);
    margin: 0 auto calc(-1 * var(--space-4));
  }
  .page-head > .obj3d--head { margin-top: calc(var(--header-h) + var(--space-3)); margin-bottom: 0; }
}

@media print {
  .obj3d { display: none !important; }
}

/* ── Print ─────────────────────────────────────────────────────────────────── */
@media print {
  .site-header, .atmosphere, .hero__field, .scroll-cue, .cta-band { display: none !important; }
  body { background: #fff; color: #000; }
}
