/* ==========================================================================
   GEOPHYSIS — The Governance Console
   --------------------------------------------------------------------------
   One stylesheet, no build step, no framework.

   The world: a physics facility's instrument panel in contemporary anodised
   metal and glass. Not a retro cockpit — no rivets, no brushed steel, no
   phosphor. Panels are milled and recessed; legends are engraved; lamps are
   glass with real bloom.

   The one colour rule that holds the whole thing together:
   CYAN IS LIVE STATE AND NOTHING ELSE. It is never a heading colour, never a
   decoration, never a gradient. If cyan appears, something is on.
   ========================================================================== */

/* ── Faces ───────────────────────────────────────────────────────────────
   Archivo carries a width axis (62–125), which is what does the engraving:
   legends run condensed and tracked, the master plate runs expanded. One
   file, two voices. Azeret Mono is for measurement only — never as a costume
   for "technical".                                                          */

@font-face {
  font-family: 'Archivo';
  src: url('/assets/fonts/archivo-var-latin.woff2') format('woff2-variations');
  font-weight: 300 800;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC,
                 U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Archivo';
  src: url('/assets/fonts/archivo-var-latin-ext.woff2') format('woff2-variations');
  font-weight: 300 800;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                 U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Azeret';
  src: url('/assets/fonts/azeret-var-latin.woff2') format('woff2-variations');
  font-weight: 300 600;
  font-style: normal;
  font-display: swap;
}

/* ── Tokens ───────────────────────────────────────────────────────────── */

:root {
  /* Housing and panels. Dark is not a category default here: the use scene is
     an instrument room, and every readable surface on a console is a lit
     legend on a dark anodised face. */
  --housing:    #04060D;
  --panel:      #0A1024;
  --panel-lift: #0C1430;
  --well:       #060A18;

  /* Milled edges. A panel seam is a dark groove with a light top lip — never
     a single flat 1px line. */
  --edge:       rgba(203, 216, 238, 0.12);
  --edge-soft:  rgba(203, 216, 238, 0.07);
  --edge-lip:   rgba(203, 216, 238, 0.22);
  --groove:     rgba(0, 0, 0, 0.55);

  /* Chrome type. Tinted from the panel hue, never neutral grey. */
  --chrome:     #D3DEF0;   /* 15.4:1 on panel */
  --chrome-2:   #8E9EBD;   /*  7.0:1 on panel */
  --chrome-3:   #7B8AAE;   /*  5.5:1 on panel — legend floor */

  --live:       #23A5EB;   /*  6.9:1 on panel */
  --live-glow:  rgba(35, 165, 235, 0.42);
  --live-haze:  rgba(35, 165, 235, 0.10);

  /* The shell every band aligns to — rail, plate, scale, bays, footer. It was
     1560px hard-coded in five places, which is 2.4x the 68ch measure: wide
     enough that every prose block sat at 46% of the band with dead space
     opposite it, and the page alternated between full-bleed panels and
     stranded half-width text. Derived rather than picked: a 68ch measure is
     ~662px, the target is for that to read as a deliberate column at ~55% of
     the band, so 662/0.55 + 112px of gutters lands here. */
  --shell: 1320px;

  --measure: 68ch;
  --gutter: clamp(1.25rem, 4vw, 3.5rem);
  --bay-y: clamp(4.5rem, 9vw, 8.5rem);
  --radius: 3px;          /* Milled panels have a small, hard corner. */

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ── Reset and base ──────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6.5rem;
}

body {
  margin: 0;
  background: var(--housing);
  color: var(--chrome);
  font-family: 'Archivo', system-ui, sans-serif;
  font-variation-settings: 'wdth' 100;
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.0625rem);
  line-height: 1.62;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, picture { max-width: 100%; display: block; }
ol, ul { margin: 0; padding: 0; list-style: none; }
p { margin: 0; }
sup { font-size: 0.66em; vertical-align: 0.42em; line-height: 0; }

/* ── Browser surfaces ─────────────────────────────────────────────────
   The parts nobody draws still belong to the design system.              */

::selection { background: var(--live); color: #02040A; }
html { scrollbar-color: #1B2647 var(--housing); scrollbar-width: thin; }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: var(--housing); }
::-webkit-scrollbar-thumb {
  background: #1B2647;
  border: 3px solid var(--housing);
  border-radius: 6px;
}
::-webkit-scrollbar-thumb:hover { background: #27355C; }

:focus-visible {
  outline: 2px solid var(--live);
  outline-offset: 3px;
  border-radius: 1px;
}

.sr, .skip:not(:focus) {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.skip:focus {
  position: fixed; z-index: 100; inset: 0.75rem auto auto 0.75rem;
  width: auto; height: auto; margin: 0; clip-path: none;
  padding: 0.7rem 1.1rem; background: var(--live); color: #02040A;
  font-weight: 700; text-decoration: none; border-radius: var(--radius);
}

/* ── Shared type roles ───────────────────────────────────────────────── */

/* The engraved legend: condensed, tracked small caps. Every label on the
   panel uses this one voice. */
.legend-face,
.rail__nav a, .readout__k, .ctl, .switch__tag, .app__band, .app__alt,
.mod__tag, .directory__h, .channel__k, .foot__say, .foot__desc,
.trajectory span, .triad span, .scale__axis, .sig__role, .plate__k {
  font-variation-settings: 'wdth' 86;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.155em;
  font-size: 0.6875rem;
  line-height: 1.35;
  color: var(--chrome-3);
}

/* Measurement voice. Data only — and a step index in a stated sequence is
   data, which is the only reason the cycle numerals are allowed to be mono. */
.readout__v, .scale__axis, .channel__v,
.cycle__s::before, .bus__q li::before {
  font-family: 'Azeret', ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  text-transform: none;
}

.h2 {
  margin: 0 0 1.5rem;
  font-variation-settings: 'wdth' 108;
  font-weight: 700;
  font-size: clamp(1.6rem, 1.1rem + 2.1vw, 2.6rem);
  line-height: 1.1;
  letter-spacing: -0.022em;
  text-wrap: balance;
  color: var(--chrome);
}

/* Sub-heading inside a bay. One clear step below .h2 in size and width axis,
   with more space above it than below — it opens a movement, it does not
   float between two. */
.h3 {
  margin: clamp(3rem, 6vw, 4.75rem) 0 1.15rem;
  font-variation-settings: 'wdth' 106;
  font-weight: 700;
  font-size: clamp(1.25rem, 1.05rem + 0.85vw, 1.75rem);
  line-height: 1.15;
  letter-spacing: -0.018em;
  text-wrap: balance;
  color: var(--chrome);
}

.prose { max-width: var(--measure); color: var(--chrome-2); }
.prose p + p { margin-top: 1.1rem; }
.prose--tight { font-size: 1.0625rem; }
.prose__stress {
  color: var(--chrome);
  font-variation-settings: 'wdth' 104;
  font-weight: 600;
}

/* ── The lamp ─────────────────────────────────────────────────────────
   A glass indicator sunk into the panel. Off, it is a dark well with a
   faint upper rim. Live, it blooms.                                      */

.lamp {
  --lamp: 9px;
  flex: 0 0 auto;
  display: inline-block;
  width: var(--lamp); height: var(--lamp);
  border-radius: 50%;
  background: #131C38;
  box-shadow:
    inset 0 1px 1.5px rgba(0, 0, 0, 0.9),
    inset 0 -1px 0 rgba(203, 216, 238, 0.10),
    0 0 0 1px rgba(0, 0, 0, 0.5);
  transition: background 0.45s var(--ease), box-shadow 0.45s var(--ease);
}
.lamp--live,
.is-live .lamp,
a:hover > .lamp, a:focus-visible > .lamp {
  background: var(--live);
  box-shadow:
    inset 0 1px 1.5px rgba(255, 255, 255, 0.45),
    0 0 0 1px rgba(35, 165, 235, 0.5),
    0 0 9px 1px var(--live-glow),
    0 0 22px 3px rgba(35, 165, 235, 0.20);
}

/* ── Rail ─────────────────────────────────────────────────────────────
   The console's top bar: mark, sections, live range readout, one control. */

.rail {
  position: sticky; top: 0; z-index: 50;
  background: rgba(6, 9, 20, 0.86);
  -webkit-backdrop-filter: blur(14px) saturate(1.3);
  backdrop-filter: blur(14px) saturate(1.3);
  border-bottom: 1px solid var(--groove);
  box-shadow: 0 1px 0 var(--edge-soft);
}
.rail__in {
  display: flex; align-items: center; gap: clamp(1rem, 3vw, 2.5rem);
  max-width: var(--shell); margin-inline: auto;
  padding: 0.7rem var(--gutter);
}

.mark { text-decoration: none; display: grid; gap: 1px; flex: 0 0 auto; }
.mark__name {
  font-variation-settings: 'wdth' 112;
  font-weight: 700;
  font-size: clamp(1rem, 0.9rem + 0.45vw, 1.2rem);
  letter-spacing: 0.055em;
  text-transform: uppercase;
  color: var(--chrome);
  line-height: 1;
}
.mark__say {
  font-family: 'Azeret', monospace;
  font-size: 0.5625rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--chrome-3);
  line-height: 1;
}

.rail__nav { display: none; gap: clamp(1rem, 2vw, 1.9rem); margin-left: auto; }
.rail__nav a {
  text-decoration: none;
  padding-block: 0.4rem;
  border-bottom: 1px solid transparent;
  transition: color 0.2s, border-color 0.2s;
}
.rail__nav a:hover, .rail__nav a:focus-visible { color: var(--chrome); border-bottom-color: var(--live); }

.rail__end { display: flex; align-items: center; gap: clamp(0.75rem, 2vw, 1.5rem); margin-left: auto; }
.rail__nav + .rail__end { margin-left: 0; }

.readout { display: none; text-align: right; line-height: 1.25; }
.readout__k { display: block; font-size: 0.5625rem; letter-spacing: 0.18em; }
.readout__v { display: block; font-size: 0.75rem; font-weight: 400; color: var(--chrome-2); }

/* The one control on the rail. A milled key with a lit lower lip. */
.ctl {
  --ctl-lip: rgba(35, 165, 235, 0.55);
  position: relative;
  display: inline-block;
  padding: 0.62rem 1.05rem;
  text-decoration: none;
  color: var(--chrome);
  background: linear-gradient(180deg, #16204a 0%, #0D1430 100%);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  box-shadow:
    inset 0 1px 0 var(--edge-lip),
    inset 0 -2px 0 -1px var(--ctl-lip),
    0 1px 2px rgba(0, 0, 0, 0.6);
  transition: background 0.25s var(--ease), box-shadow 0.25s var(--ease), color 0.2s;
  white-space: nowrap;
}
.ctl:hover, .ctl:focus-visible {
  --ctl-lip: var(--live);
  background: linear-gradient(180deg, #1B2861 0%, #101A44 100%);
  box-shadow:
    inset 0 1px 0 var(--edge-lip),
    inset 0 -2px 0 -1px var(--ctl-lip),
    0 0 16px -2px var(--live-glow),
    0 1px 2px rgba(0, 0, 0, 0.6);
}
.ctl:active { transform: translateY(1px); }

/* ── Master plate (hero) ─────────────────────────────────────────────── */

.plate {
  position: relative;
  isolation: isolate;
  border-bottom: 1px solid var(--groove);
  box-shadow: 0 1px 0 var(--edge-soft);
}

/* The field: your wallpaper, heavily attenuated and vignetted so it reads as
   ambient light inside the housing rather than as a space photograph. */
.plate__field {
  position: absolute; inset: 0; z-index: -1;
  --veil: radial-gradient(120% 90% at 68% 8%, rgba(10, 20, 54, 0) 0%, var(--housing) 78%);
  /* Portrait crop is the mobile-first default: a phone hero is tall, and
     serving it the 1920 landscape would cost 54 KB to then crop most away. */
  background-image: var(--veil), url('/assets/img/field-760.webp');
  background-size: cover, cover;
  background-position: center 22%;
  opacity: 0.5;
}
@media (min-width: 761px) {
  .plate__field { background-image: var(--veil), url('/assets/img/field-1200.webp'); }
}
@media (min-width: 1281px) {
  .plate__field { background-image: var(--veil), url('/assets/img/field-1920.webp'); }
}
.plate::after {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, rgba(4, 6, 13, 0.35) 0%, rgba(4, 6, 13, 0) 30%,
              rgba(4, 6, 13, 0.55) 78%, var(--housing) 100%);
  pointer-events: none;
}

.plate__in {
  display: grid;
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: center;
  max-width: var(--shell); margin-inline: auto;
  padding: clamp(3rem, 7vw, 6rem) var(--gutter) clamp(2.5rem, 5vw, 4rem);
}

/* A grid item defaults to a min-content floor, and this column's min-content
   is the word ELECTROMAGNETIC. Without min-width:0 that single word widens the
   whole column and pushes the page into horizontal scroll. */
.plate__in > * { min-width: 0; }
.plate__text { max-width: min(46ch, 100%); container-type: inline-size; }

/* The engraved title plate. Expanded caps at monumental scale is the whole
   move: it is a facility nameplate, not a marketing headline.

   The size ceiling is set by ELECTROMAGNETIC, the longest unbreakable word on
   the page. Rather than guess a viewport formula and be wrong between 768 and
   1024 — which is exactly what a first attempt did — the type is sized off its
   own column. Measured against the built page, the largest size at which the
   word stops overflowing is a constant 8.63% of the column width. 8.4cqw sits
   just under that at every width, so overflow here is structurally impossible
   rather than merely absent today.

   The vw clamp on the line above is the fallback for browsers without
   container query units. It is deliberately conservative: smaller than ideal
   everywhere, but overflowing nowhere. */
.legend {
  margin: 0;
  font-variation-settings: 'wdth' 106;
  font-weight: 700;
  font-size: clamp(1.55rem, 0.4rem + 3.2vw, 4.2rem);
  font-size: clamp(1.55rem, 8.4cqw, 4.4rem);
  line-height: 0.99;
  letter-spacing: -0.012em;
  text-transform: uppercase;
  text-wrap: balance;
  hyphens: auto;
  color: #E8EFFA;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.7);
}
.legend__sub {
  margin-top: clamp(1.1rem, 2.2vw, 1.7rem);
  max-width: 40ch;
  font-size: clamp(1.0625rem, 0.95rem + 0.6vw, 1.375rem);
  line-height: 1.45;
  color: var(--chrome-2);
  text-wrap: pretty;
}
.legend__note {
  margin-top: 1.35rem; padding-top: 1.1rem;
  border-top: 1px solid var(--edge);
  font-variation-settings: 'wdth' 88;
  font-weight: 600; font-size: 0.6875rem;
  letter-spacing: 0.155em; text-transform: uppercase;
  color: var(--chrome-3);
}

/* ── The signature (leadership page) ──────────────────────────────────
   An attribution, not a status. Deliberately no lamp: a lamp on this site
   means something is on, and a person is not a state — the same rule that
   keeps the home page's leadership panels dark.

   It is built from the two voices the channel strips already pair: the name
   in the panel's primary voice, the role in the engraved one. The hairline
   above it is the same seam `.legend__note` uses, so the plate closes the
   same way the master plate does. */
.sig {
  margin-top: clamp(1.75rem, 3.5vw, 2.5rem);
  padding-top: 1.15rem;
  border-top: 1px solid var(--edge);
  max-width: var(--measure);
}
.sig__name {
  display: block;
  font-variation-settings: 'wdth' 106;
  font-weight: 700; font-size: 1.0625rem;
  letter-spacing: -0.008em;
  color: var(--chrome);
}
.sig__role { display: block; margin-top: 0.4rem; }

/* The one link out of a bay and into the second page. A milled seam above it
   and a drawn arrow rather than a glyph — this page draws its own marks, the
   same way the trajectory draws rules instead of chevrons. Not a button: the
   rail already holds this page's one lit control, and a second one would spend
   the page's emphasis on navigation. */
.onward {
  margin-top: clamp(2rem, 4vw, 3rem);
  padding-top: 1.15rem;
  border-top: 1px solid var(--edge);
}
.onward a {
  display: inline-flex; align-items: center; gap: 0.85rem;
  font-variation-settings: 'wdth' 104;
  font-weight: 600;
  font-size: clamp(1rem, 0.95rem + 0.3vw, 1.125rem);
  color: var(--chrome-2);
  text-decoration: none;
  transition: color 0.2s var(--ease);
}
/* The rule is laid at its full extended length and scaled back at rest, rather
   than being laid short and widened on hover. Animating `width` would relayout
   the flex line on every frame — and because the rule is a flex item, that
   reflows the label beside it too. scaleX from a left origin is the same
   picture, composited, and the label never moves. */
.onward a::after {
  content: ''; flex: 0 0 auto;
  width: 34px; height: 1px;
  background: var(--chrome-3);
  transform: scaleX(0.647);          /* 22px of 34px at rest */
  transform-origin: left center;
  transition: transform 0.3s var(--ease), background-color 0.2s;
}
.onward a:hover, .onward a:focus-visible { color: var(--chrome); }
.onward a:hover::after, .onward a:focus-visible::after {
  transform: scaleX(1); background: var(--chrome-2);
}

/* The plate's standfirst. The master plate has no eyebrow and must not gain
   one — but this page's hero is a document rather than a nameplate, and a
   document is allowed to say what kind of document it is. Engraved voice,
   sitting above the title on the same optical rail as the rail's own
   legends. */
.plate__k { margin: 0 0 clamp(0.9rem, 2vw, 1.35rem); }

/* Prose continuing under the plate's standfirst needs the gap the standfirst
   itself gets from the title. Without it the two paragraphs butt together and
   the size change reads as a rendering fault rather than as a change of voice.
   Held to the same measure, so the block has one ragged edge and not two. */
.legend__sub + .prose { margin-top: clamp(1rem, 2vw, 1.35rem); max-width: 46ch; }

/* The rail entry for the page you are already on. Not cyan — cyan is live
   state, and "you are here" is not a state of the machine. It is marked by
   the same weight lift the hover uses, held permanently. */
.rail__nav a[aria-current='page'] {
  color: var(--chrome);
  border-bottom-color: var(--edge-lip);
}

/* The mark stands free. It was previously recessed behind a circular bezel,
   which read as a housing but clipped the outer wireframe against the rim and
   sank its edges into the dark radial behind it — the lattice lost definition
   exactly where it should be crispest.

   No ring, no well, no clipping. The only treatment is a cast shadow for
   depth plus a very low cyan bloom. Deliberately not a soft neon halo: that
   is the generic deep-tech floating orb this page is built to avoid, and the
   mark reads better hard-edged against the field than wrapped in glow. */
.orb {
  justify-self: center;
  width: min(408px, 80vw);
  aspect-ratio: 1;
}
.orb__hold {
  position: relative;
  height: 100%;
  display: grid; place-items: center;
}
.orb__hold img {
  width: 100%; height: 100%; object-fit: contain;
  filter:
    drop-shadow(0 20px 38px rgba(0, 0, 0, 0.62))
    drop-shadow(0 0 44px rgba(35, 165, 235, 0.12));
}

/* ── The spectrum scale ───────────────────────────────────────────────
   A real logarithmic axis, 10^-12 m to 10^3 m, at full tick density. The
   density is the point: it is the difference between a diagram and a
   decoration.                                                            */

.scale {
  max-width: var(--shell); margin-inline: auto;
  padding: 0 var(--gutter) clamp(2.5rem, 5vw, 4rem);
}

.scale__frame {
  /* One inset for the whole instrument. The tick field, band row, marker fan,
     axis labels and the draggable cursor all measure from this, which is what
     keeps the cursor landing exactly on the wavelength it reports. */
  --inset: clamp(0.5rem, 2vw, 1.25rem);
  position: relative;
  touch-action: pan-y;
  /* Selection is refused in CSS rather than by preventDefault(), because
     preventDefault() on a POINTER event only suppresses selection in Chromium.
     Firefox and WebKit consult the underlying mouse event, so on those engines
     a sweep across the axis would start selecting the band legends and drag a
     blue highlight along with the cursor. Nothing inside the frame is prose —
     it is a tick field, seven band labels and six axis legends — and the
     readout below, which IS worth selecting, is a sibling and unaffected. */
  -webkit-user-select: none; user-select: none;
  padding: 1.1rem 0 0.55rem;
  border-top: 1px solid var(--edge);
  border-bottom: 1px solid var(--edge);
  background:
    linear-gradient(180deg, rgba(12, 20, 48, 0.55) 0%, rgba(6, 10, 24, 0.75) 100%);
  box-shadow: inset 0 1px 0 var(--edge-lip), inset 0 -1px 0 var(--groove);
}

/* Tick field. JS lays 150 log-spaced ticks over this; the CSS field below is
   the no-JS floor so the axis is never empty. */
.scale__ticks {
  position: relative;
  height: 34px;
  margin-inline: var(--inset);
  background-image: repeating-linear-gradient(
    90deg,
    var(--edge-soft) 0 1px,
    transparent 1px 0.9%);
  background-position: bottom;
  background-size: 100% 12px;
  background-repeat: no-repeat;
}
/* Once JS has laid the true log-spaced ticks, the evenly-spaced CSS fallback
   would sit underneath them lying about the scale. Remove it. */
.scale__ticks.is-drawn { background-image: none; }
.scale__ticks i {
  position: absolute; bottom: 0;
  left: var(--x); width: 1px;
  height: var(--h);
  background: var(--tk, var(--edge));
  animation: tick-in 0.5s var(--ease) both;
  animation-delay: calc(var(--i) * 3.4ms);
}
@keyframes tick-in { from { opacity: 0; transform: scaleY(0.2); transform-origin: bottom; } }

.bands {
  position: relative;
  display: block;
  height: 30px;
  margin: 0.5rem var(--inset) 0;
}
.bands li {
  position: absolute;
  left: calc(var(--a) * 1%);
  width: calc((var(--b) - var(--a)) * 1%);
  height: 100%;
  border-left: 1px solid var(--edge);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.bands li:last-child { border-right: 1px solid var(--edge); }
.bands li span {
  font-variation-settings: 'wdth' 80;
  font-weight: 600; font-size: 0.625rem;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--chrome-3);
  white-space: nowrap;
}
/* γ is a symbol, not a word. uppercase would silently promote it to Γ, which
   is a different quantity. */
.bands li:first-child span { text-transform: none; font-size: 0.8125rem; }

/* Below 760px the long band names are wider than the bands physics gives them,
   and `overflow: hidden` was clipping MICROWAVE to "CROWAV". The abbreviations
   are the notation this audience already reads. The long form is not removed,
   only taken off-screen, so it still carries the accessible name. */
/* text-transform: none for the same reason as γ above — these are notation,
   not words. Uppercase promotes the micro sign µ to Greek capital Mu, turning
   "µW" (microwave) into "MW", which this audience reads as megawatt. */
.b-sm { display: none; }
.bands li .b-sm { text-transform: none; font-size: 0.6875rem; }
@media (max-width: 759px) {
  .bands li .b-lg {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap;
  }
  .bands li .b-sm { display: inline; }
  /* Nothing to abbreviate for γ, X, UV — they are already at their shortest. */
  .bands li:nth-child(-n+3) .b-lg { position: static; width: auto; height: auto;
    margin: 0; overflow: visible; clip-path: none; }
  /* The visible band is ~5px wide here, so its label stays screen-reader-only
     from the rule above. The cyan wash still marks it; a clipped glyph would
     only look like a rendering fault. */
}
/* The visible band is a sliver of the whole spectrum. That is a true and
   useful fact, so it is drawn true rather than widened for comfort. */
.bands__vis { background: linear-gradient(180deg, rgba(35,165,235,0.16), rgba(35,165,235,0)); }
.bands__vis span { color: var(--chrome-2); font-size: 0.5rem; letter-spacing: 0.06em; }
/* The visible band is 1.6% of the axis, so its cell is narrower than the word
   "Vis" and `overflow: hidden` was clipping it between 760px and 1380px. The
   cell keeps its true width — that sliver is the fact worth showing — and only
   the label is allowed outside it. Its neighbours' labels are centred in much
   wider cells, so nothing collides.

   The selector has to match the li: `.bands li` (0,1,1) sets overflow:hidden
   and outranks a bare `.bands__vis` (0,1,0). */
.bands li.bands__vis { overflow: visible; z-index: 1; }

/* Application markers. Hidden below 1000px, where the fan of labels cannot
   stay legible — each bay carries its own mini-scale instead, so the phone
   loses the picture but never the fact. */
.marks { display: none; }

.scale__axis {
  display: flex; justify-content: space-between;
  margin: 0.4rem var(--inset) 0;
  font-size: 0.5625rem; letter-spacing: 0.08em;
  color: #63719A;
}

/* ── The wavelength cursor ────────────────────────────────────────────
   The one thing on this instrument that moves. It is a cursor, not a
   label: the five application markers stay where physics puts them, and
   this is what the visitor drags. Position is a percentage along the same
   inset track the ticks use, so what it reads is where it sits.          */

.cursor {
  position: absolute;
  top: 0; bottom: 0;
  left: calc(var(--inset) + (100% - 2 * var(--inset)) * var(--p) / 100);
  width: 0;
  z-index: 3;
  pointer-events: none;
}
.cursor__stem {
  position: absolute;
  top: 0; bottom: 0; left: -1px;
  width: 2px;
  background: linear-gradient(180deg,
    var(--live) 0%, rgba(35, 165, 235, 0.75) 55%, rgba(35, 165, 235, 0.18) 100%);
  box-shadow: 0 0 12px var(--live-glow);
}
/* A milled tab, sized to the 44px touch target the pointer needs even though
   the tab reads as 26px of metal. */
/* Sized generously on purpose. The first build gave this a 26px tab and it was
   too easy to miss on a busy axis — the instrument looked inert because nobody
   found its handle. 56x38 of hit area, 38x24 of visible metal. */
.cursor__grip {
  position: absolute;
  top: -13px; left: 50%;
  transform: translateX(-50%);
  width: 56px; height: 38px;
  padding: 0;
  border: 0;
  background: none;
  cursor: grab;
  pointer-events: auto;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  /* A press-and-hold on the tab must grab it, not raise the iOS callout —
     which cancels the touch and drops the drag. */
  -webkit-touch-callout: none;
  -webkit-user-select: none; user-select: none;
}

/* A finger needs a larger target than a mouse does, so on touch pointers the
   hit area grows to 64x48 while the visible metal stays exactly where it was:
   the ::before and ::after offsets are re-based by the same amount the button's
   top moves, so nothing on screen shifts by a pixel. Only the invisible target
   grows, which is the entire point. */
@media (pointer: coarse) {
  .cursor__grip { top: -18px; width: 64px; height: 48px; }
  .cursor__grip::before { top: 10px; }
  .cursor__grip::after  { top: 16px; }
}
.cursor__grip::before {
  content: '';
  position: absolute;
  top: 5px; left: 50%;
  transform: translateX(-50%);
  width: 38px; height: 24px;
  border-radius: 2px;
  background: linear-gradient(180deg, #1D2E6B 0%, #0D1638 100%);
  border: 1px solid rgba(35, 165, 235, 0.65);
  box-shadow:
    inset 0 1px 0 rgba(203, 216, 238, 0.3),
    0 0 16px -2px var(--live-glow),
    0 2px 5px rgba(0, 0, 0, 0.75);
  transition: border-color 0.2s, box-shadow 0.25s var(--ease), transform 0.18s var(--ease);
}
/* Three milled flutes, so the tab reads as something meant to be gripped. */
.cursor__grip::after {
  content: '';
  position: absolute;
  top: 11px; left: 50%;
  transform: translateX(-50%);
  width: 13px; height: 11px;
  background-image: linear-gradient(90deg,
    var(--live) 0 1px, transparent 1px 4px,
    var(--live) 4px 5px, transparent 5px 8px,
    var(--live) 8px 9px, transparent 9px 12px,
    var(--live) 12px 13px);
  opacity: 0.9;
}
.cursor__grip:active::before { transform: translateX(-50%) scale(0.96); }

/* Breathes twice on arrival, then never again — `is-touched` is set by the
   first press or keypress. A hint that keeps pulsing is an animation; one that
   stops the moment it has been understood is an affordance. */
@keyframes grip-hint {
  0%, 100% { box-shadow: inset 0 1px 0 rgba(203,216,238,0.3), 0 0 16px -2px var(--live-glow), 0 2px 5px rgba(0,0,0,0.75); }
  50%      { box-shadow: inset 0 1px 0 rgba(203,216,238,0.45), 0 0 26px 2px var(--live-glow), 0 2px 5px rgba(0,0,0,0.75); }
}
.scale__frame:not(.is-touched) .cursor__grip::before {
  animation: grip-hint 1.9s var(--ease) 1.1s 2;
}
.cursor__grip:hover::before,
.cursor__grip:focus-visible::before {
  border-color: var(--live);
  box-shadow:
    inset 0 1px 0 rgba(203, 216, 238, 0.35),
    0 0 22px -1px var(--live-glow),
    0 2px 4px rgba(0, 0, 0, 0.7);
}
.cursor__grip:focus-visible { outline-offset: 1px; }
.is-dragging .cursor__grip { cursor: grabbing; }
/* While dragging, the cursor must not lag the finger. */
.cursor { transition: left 0.28s var(--ease); }
.is-dragging .cursor { transition: none; }
.scale__frame { cursor: crosshair; }

/* ── The readout ──────────────────────────────────────────────────────
   Real values computed from the cursor's wavelength against c and h.
   Nothing here is stored, sampled or invented.                          */

.probe {
  margin-top: 0.9rem;
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  background: linear-gradient(180deg, var(--panel-lift), var(--panel));
  box-shadow: inset 0 1px 0 var(--edge-lip);
}
.probe__row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  margin: 0;
  background: var(--groove);
}
.probe__cell {
  padding: 0.7rem 0.9rem;
  background: var(--panel);
}
.probe__cell dt {
  font-variation-settings: 'wdth' 86;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.155em;
  font-size: 0.5625rem;
  color: var(--chrome-3);
}
.probe__cell dd {
  margin: 0.28rem 0 0;
  font-family: 'Azeret', ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  font-size: 1.0625rem;
  font-weight: 500;
  line-height: 1.15;
  color: var(--chrome);
}
.probe__cell dd i {
  font-style: normal;
  font-size: 0.75rem;
  color: var(--chrome-2);
  margin-left: 0.1rem;
}
.probe__cell--band dd { font-family: 'Archivo', system-ui, sans-serif; font-weight: 600; }

.probe__gov {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem 0.85rem;
  padding: 0.75rem 0.9rem;
  border-top: 1px solid var(--groove);
  box-shadow: 0 1px 0 var(--edge-soft) inset;
}
.probe__gov-k {
  font-variation-settings: 'wdth' 86;
  font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.155em; font-size: 0.5625rem;
  color: var(--chrome-3);
}
.probe__gov-v { font-size: 0.9375rem; color: var(--chrome-2); }
/* Each application named in the readout is a live channel, so it is cyan —
   the same rule as every other lit thing on the page. */
.probe__gov-v b { font-weight: 600; color: var(--live); }
.probe__gov-v em { font-style: normal; color: var(--chrome-3); }

.scale__cap {
  max-width: 58ch;
  margin-top: 1.15rem;
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--chrome-2);
}
.scale__cap-hint { color: var(--chrome-3); }

/* ── Bays ─────────────────────────────────────────────────────────────
   Every section below the plate is a bay in the same housing: same ground,
   same seam, same inner width.                                           */

.bay {
  border-bottom: 1px solid var(--groove);
  box-shadow: 0 1px 0 var(--edge-soft);
  background: var(--housing);
}
.bay__in {
  max-width: var(--shell); margin-inline: auto;
  padding: var(--bay-y) var(--gutter);
}
.bay__lede {
  max-width: 62ch; margin: -0.5rem 0 2.5rem;
  font-size: clamp(1rem, 0.95rem + 0.35vw, 1.1875rem);
  color: var(--chrome-2);
}

.bay--mandate { background: linear-gradient(180deg, #05080F 0%, var(--housing) 100%); }
.bay--ggee { background: linear-gradient(180deg, var(--housing) 0%, #060A16 100%); }
.bay--horizon { background: linear-gradient(180deg, #060A16 0%, var(--housing) 100%); }

/* ── The switch: the thesis as a two-position control ────────────────── */

/* The control and the reasoning that justifies it, side by side on wide
   screens. The switch is given the slightly larger column: it is the thing
   being asserted, and the prose is the support. */
.thesis { display: grid; gap: clamp(1.75rem, 4vw, 2.75rem); }

.switch {
  display: grid; gap: 0;
  max-width: var(--measure);
  margin: 0;
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  background: linear-gradient(180deg, var(--panel-lift), var(--panel));
  box-shadow: inset 0 1px 0 var(--edge-lip), 0 18px 40px -30px #000;
  overflow: hidden;
}
.switch p {
  display: grid;
  grid-template-columns: 9px 1fr;
  align-items: baseline;
  gap: 0.5rem 0.95rem;
  padding: clamp(1.1rem, 2.4vw, 1.5rem) clamp(1.1rem, 2.6vw, 1.7rem);
}
.switch__off { border-bottom: 1px solid var(--groove); box-shadow: 0 1px 0 var(--edge-soft); }
.switch__off .switch__q { color: #6D7B9E; text-decoration: line-through; text-decoration-thickness: 1px; text-underline-offset: 0.2em; }
.switch__on { background: linear-gradient(90deg, var(--live-haze), transparent 62%); }
.switch__q {
  grid-column: 2;
  font-variation-settings: 'wdth' 104;
  font-weight: 600;
  font-size: clamp(1.0625rem, 0.9rem + 0.85vw, 1.5rem);
  line-height: 1.25;
  letter-spacing: -0.012em;
  color: var(--chrome);
  text-wrap: balance;
}
.switch__tag { grid-column: 2; }
.switch .lamp { grid-row: 1; align-self: center; margin-top: 0.4em; }

/* ── Applications: five bays, one scale, one ground ───────────────────
   Identical scale and identical ground is the whole discipline here: these
   compare, they do not compete. No featured tile, no varied sizes.        */

.apps {
  display: grid;
  gap: 1px;
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  background: var(--groove);
  overflow: hidden;
}
/* Channel strips, never a card grid. A same-size-card grid is the lazy
   container the craft floor refuses — but the real reason is the argument:
   these are channels on one console, so they read as rows on one face, at one
   scale, on one ground. Nothing is featured. They compare, they do not
   compete. The rack below uses the same layout for the same reason. */
.app {
  display: grid;
  gap: 0.55rem;
  padding: clamp(1.4rem, 2.8vw, 2.1rem) clamp(1.2rem, 2.6vw, 1.9rem);
  background: linear-gradient(180deg, var(--panel-lift) 0%, var(--panel) 100%);
  transition: background 0.35s var(--ease);
}
.app:hover, .app:focus-within, .app.is-live {
  background: linear-gradient(180deg, #131D46 0%, #0C1430 100%);
}
.app:hover .lamp, .app:focus-within .lamp, .app.is-live .lamp {
  background: var(--live);
  box-shadow:
    inset 0 1px 1.5px rgba(255, 255, 255, 0.45),
    0 0 0 1px rgba(35, 165, 235, 0.5),
    0 0 9px 1px var(--live-glow),
    0 0 22px 3px rgba(35, 165, 235, 0.20);
}
.app__name {
  margin: 0;
  font-variation-settings: 'wdth' 110;
  font-weight: 700;
  font-size: clamp(1.15rem, 1rem + 0.7vw, 1.5rem);
  letter-spacing: -0.014em;
  line-height: 1.15;
  color: var(--chrome);
}
/* The technology designation under the product name — SunSlinger under
   IntelliBrella, the acronym expansion under E.D.E.N. Engraved voice, so it
   reads as a plate stamped on the channel rather than as a second title.

   `display: block` swallows the space that precedes it in the markup, which is
   why that space is safe to keep — and it must be kept. Without it the
   heading's text stream reads "E.D.E.N.Enhanced Direct Energy Network", which
   is what a screen reader announces and what a copy-paste yields. */
.app__alt { display: block; margin-top: 0.45rem; }
.app__band {
  display: flex; align-items: center; gap: 0.6rem;
}
/* Each bay carries its own position on the same axis — so the phone, which
   cannot show the fanned labels on the master scale, still gets the fact. */
.app__mini {
  position: relative;
  flex: 1 1 auto;
  min-width: 48px;
  height: 7px;
  border-left: 1px solid var(--edge);
  border-right: 1px solid var(--edge);
  background: repeating-linear-gradient(90deg, var(--edge-soft) 0 1px, transparent 1px 4px);
}
.app__mini i {
  position: absolute; top: -2px; bottom: -2px;
  left: calc(var(--pos) * 1%);
  width: 2px; margin-left: -1px;
  background: var(--chrome-3);
  transition: background 0.35s var(--ease), box-shadow 0.35s var(--ease);
}
.app:hover .app__mini i, .app:focus-within .app__mini i, .app.is-live .app__mini i {
  background: var(--live);
  box-shadow: 0 0 8px var(--live-glow);
}
.app__body { color: var(--chrome-2); font-size: 0.9375rem; line-height: 1.58; max-width: 46ch; }

/* ── GGEE: six domains on one rack, feeding an orchestration bus ───────
   The rack is the .apps discipline applied to methodology — peers at one
   scale on one ground, because that is exactly what these six are. The
   asymmetry that carries information is vertical, not horizontal:
   everything on the rack routes down into the bus, which is the one layer
   Geophysis is actually building.                                        */

/* The claim the whole architecture rests on, so it is set as a statement
   rather than dropped into a paragraph. One hairline rule, no panel: this is
   speech, not an instrument reading. */
/* What GGEE is, beside why it is built that way. */
.overture { display: grid; gap: clamp(1.5rem, 3.5vw, 2.5rem); margin-bottom: clamp(2.5rem, 5vw, 3.5rem); }
.overture .bay__lede { margin: -0.5rem 0 0; }
.overture .creed { margin: 0; }

.creed {
  max-width: 58ch;
  margin: 0 0 2.75rem;
  padding-left: clamp(0.95rem, 2vw, 1.45rem);
  border-left: 1px solid var(--edge-lip);
  font-size: clamp(1.0625rem, 0.98rem + 0.42vw, 1.25rem);
  line-height: 1.5;
  color: var(--chrome-2);
  text-wrap: pretty;
}
.creed b {
  display: block;
  margin-top: 0.45rem;
  font-variation-settings: 'wdth' 104;
  font-weight: 600;
  color: var(--chrome);
}

.rack {
  display: grid; gap: 1px;
  background: var(--groove);
  border: 1px solid var(--edge); border-radius: var(--radius);
  overflow: hidden;
}
.mod {
  display: grid;
  gap: 0.5rem;
  padding: clamp(1.3rem, 2.6vw, 1.9rem) clamp(1.2rem, 2.6vw, 1.9rem);
  background: linear-gradient(180deg, var(--panel-lift), var(--panel));
}
/* Electromagnetic engineering is the domain the brief calls central, so it
   sits on a lifted ground. A lift, never cyan — cyan is live state, and a
   permanently-lit module would spend the page's one colour on emphasis. */
.mod--core { background: linear-gradient(180deg, #101940, #0A1128); }
.mod__name {
  margin: 0;
  font-variation-settings: 'wdth' 106;
  font-weight: 700; font-size: clamp(1.05rem, 0.98rem + 0.4vw, 1.3rem);
  letter-spacing: -0.012em; line-height: 1.2; color: var(--chrome);
}
.mod__tag { display: block; margin-top: 0.5rem; }
/* The methods are real designators, so they are set as a spec line: condensed
   and quiet, not tracked caps (too long to read) and not mono (they are
   names, not measurements). */
.mod__kit {
  font-variation-settings: 'wdth' 92;
  font-weight: 500;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--chrome-3);
}
.mod__body { color: var(--chrome-2); font-size: 0.9375rem; line-height: 1.58; max-width: 54ch; }

/* The bus carries the section's only lit rail, and with the same restraint as
   everywhere else: one cyan element, on the thing that integrates. The stub
   above it draws the route down from the rack instead of describing it. */
.bus {
  position: relative;
  margin-top: 2.5rem;
  padding: clamp(1.5rem, 3vw, 2.25rem) clamp(1.3rem, 2.6vw, 2rem);
  background: linear-gradient(180deg, #101940, #0A1128);
  border: 1px solid var(--edge); border-radius: var(--radius);
  box-shadow: inset 0 1px 0 var(--edge-lip);
}
.bus::before {
  content: ''; position: absolute; inset: 0 auto 0 0; width: 2px;
  background: linear-gradient(180deg, var(--live), rgba(35, 165, 235, 0.15));
  box-shadow: 0 0 14px var(--live-glow);
}
.bus::after {
  content: ''; position: absolute; left: 0; top: -2.5rem;
  width: 2px; height: 2.5rem;
  background: linear-gradient(180deg, transparent, var(--live));
}
.bus__name {
  margin: 0;
  font-variation-settings: 'wdth' 106;
  font-weight: 700; font-size: clamp(1.05rem, 0.98rem + 0.4vw, 1.3rem);
  letter-spacing: -0.012em; line-height: 1.2; color: var(--chrome);
}
.bus__lede {
  max-width: 56ch; margin-top: 0.8rem;
  font-size: 0.9375rem; line-height: 1.55; color: var(--chrome-2);
}
.bus__q { counter-reset: q; display: grid; margin-top: 1.5rem; }
.bus__q li {
  counter-increment: q;
  display: grid; grid-template-columns: 2.2rem minmax(0, 1fr);
  align-items: baseline;
  padding: 0.62rem 0;
  border-top: 1px solid rgba(203, 216, 238, 0.07);
  font-size: 0.9375rem; line-height: 1.5;
  color: var(--chrome-2);
}
.bus__q li::before { content: counter(q, decimal-leading-zero); font-size: 0.75rem; color: var(--chrome-3); }
.bus__note {
  max-width: 56ch; margin-top: 1.4rem;
  font-variation-settings: 'wdth' 104; font-weight: 600;
  font-size: 0.9375rem; line-height: 1.5; color: var(--chrome);
}

/* ── The cycle ────────────────────────────────────────────────────────
   Numbered because the sequence itself is the information, and closed
   because the claim is that it repeats. The return path down the left is
   the sentence "every successful cycle expands the library" drawn rather
   than asserted.                                                         */

/* Two up on wide screens: the statement on the left, the run of steps on the
   right. One column of eleven short lines stranded in a 1300px bay was the
   first build, and the dead half of the row read as an unfinished section. */
.ip { display: grid; gap: clamp(1.5rem, 3.5vw, 2.5rem); margin-top: clamp(3rem, 6vw, 4.75rem); }
.ip .h3 { margin-top: 0; }

.cycle {
  counter-reset: st;
  position: relative;
  max-width: 46ch;
  margin: 0;
  padding-left: 2.6rem;
}
.cycle::before {            /* the spine */
  content: ''; position: absolute;
  left: 1.6rem; top: 1.1rem; bottom: 1.1rem;
  width: 1px; background: var(--edge);
}
.cycle::after {             /* the return path, last step back to first */
  content: ''; position: absolute;
  left: 0.15rem; top: 1.1rem; bottom: 1.1rem;
  width: 1.45rem;
  border: 1px solid var(--edge);
  border-right: 0;
  border-radius: 2px 0 0 2px;
}
.cycle__s {
  counter-increment: st;
  position: relative;
  display: grid; grid-template-columns: 2.2rem minmax(0, 1fr);
  align-items: baseline;
  padding: 0.5rem 0;
  font-size: 0.9375rem; line-height: 1.5;
  color: var(--chrome-2);
}
.cycle__s::before { content: counter(st, decimal-leading-zero); font-size: 0.75rem; color: var(--chrome-3); }
.cycle__s::after {          /* the node, centred on the spine */
  content: ''; position: absolute;
  left: -1.125rem; top: 0.95rem;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--panel);
  box-shadow: 0 0 0 1px var(--edge-lip);
}
/* IP identification is the step the engine exists to reach. Marked by weight
   and a filled node — not by cyan, which on this page means something is on. */
.cycle__s--key {
  color: var(--chrome);
  font-variation-settings: 'wdth' 104;
  font-weight: 600;
}
.cycle__s--key::after { background: var(--chrome-2); box-shadow: 0 0 0 1px var(--chrome-3); }
.cycle__loop {
  max-width: 50ch; margin-top: 1.5rem;
  font-size: 0.9375rem; line-height: 1.55; color: var(--chrome-2);
}

/* ── Foundry ─────────────────────────────────────────────────────────── */

.foundry { display: grid; gap: clamp(2.25rem, 5vw, 4rem); }
.directory {
  align-self: start;
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  background: linear-gradient(180deg, var(--panel-lift), var(--panel));
  box-shadow: inset 0 1px 0 var(--edge-lip);
  overflow: hidden;
}
.directory__h {
  margin: 0; padding: 0.85rem 1.2rem;
  border-bottom: 1px solid var(--groove);
  box-shadow: 0 1px 0 var(--edge-soft);
  background: rgba(4, 6, 13, 0.4);
}
.directory__list { padding: 0.3rem 0; }
.directory__list li {
  display: flex; align-items: baseline; gap: 0.75rem;
  padding: 0.5rem 1.2rem;
  font-size: 0.9375rem;
  color: var(--chrome-2);
}
.directory__list li + li { border-top: 1px solid rgba(203, 216, 238, 0.05); }
.directory__list li::before {
  content: ''; flex: 0 0 auto; width: 14px; height: 1px;
  background: var(--chrome-3); transform: translateY(-0.35em);
}
/* The plate can also be an index. When its rows are links they keep the plate's
   voice and take the rail's underline on hover — the lead-in dash stays put, so
   a list of destinations and a list of facts read as the same component. */
.directory__list a {
  color: inherit; text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 0.2s, border-color 0.2s;
}
.directory__list a:hover, .directory__list a:focus-visible {
  color: var(--chrome); border-bottom-color: var(--edge-lip);
}

/* ── Horizon ──────────────────────────────────────────────────────────
   Same split as the foundry, and deliberately the same directory plate: the
   off-world requirements are a facility list, exactly like the licensing
   sectors, so they get the component that already exists rather than a new
   one invented to make the section feel different.                       */

/* The trajectory. Rules between the stops, not chevron glyphs — this page
   draws its own marks. */
.trajectory {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.55rem 1rem;
  margin-top: clamp(2rem, 4vw, 2.75rem);
}
.trajectory span { display: flex; align-items: center; gap: 1rem; color: var(--chrome-2); }
.trajectory span + span::before {
  content: ''; flex: 0 0 auto;
  width: 16px; height: 1px; background: var(--chrome-3);
}

/* Once there is room, the trajectory stops huddling at the left and spans its
   band as a measured scale: the stops are fixed and the rules between them
   stretch, so it reads as distance covered rather than as a row of labels.
   Below this it wraps, because five stops with stretched rules do not fit a
   phone without the rules collapsing to nothing. */
@media (min-width: 700px) {
  .trajectory { flex-wrap: nowrap; gap: 0; width: 100%; }
  .trajectory span { flex: 0 0 auto; gap: 0; }
  .trajectory span + span { flex: 1 1 auto; min-width: 0; }
  .trajectory span + span::before {
    flex: 1 1 auto;
    width: auto; min-width: 18px;
    margin-inline: clamp(0.85rem, 2.2vw, 1.75rem);
  }
}

/* The requirements run the full width of the bay as an engraved schedule,
   not as a second .directory plate — that component is in the very next bay,
   and repeating it would turn two arguments into one template. */
.reqs__k { margin: clamp(2.5rem, 5vw, 3.5rem) 0 0; }
.reqs {
  display: grid;
  margin-top: 0.9rem;
  border-top: 1px solid var(--edge);
}
.reqs li {
  display: flex; align-items: baseline; gap: 0.8rem;
  padding: 0.7rem 0;
  border-bottom: 1px solid rgba(203, 216, 238, 0.06);
  font-size: 0.9375rem;
  color: var(--chrome-2);
}
.reqs li::before {
  content: ''; flex: 0 0 auto; width: 14px; height: 1px;
  background: var(--chrome-3); transform: translateY(-0.35em);
}

/* ── Contact ─────────────────────────────────────────────────────────── */

.bay--contact { background: linear-gradient(180deg, #060A16 0%, #04060D 100%); border-bottom: 0; }
.call {
  margin: 0;
  max-width: 20ch;
  font-variation-settings: 'wdth' 112;
  font-weight: 700;
  font-size: clamp(1.85rem, 1.1rem + 3.2vw, 3.6rem);
  line-height: 1.02;
  letter-spacing: -0.022em;
  text-transform: uppercase;
  color: #E8EFFA;
  text-wrap: balance;
}
.call__sub {
  margin-top: 0.9rem;
  font-size: clamp(1.0625rem, 0.95rem + 0.55vw, 1.35rem);
  color: var(--chrome-2);
}
/* The closing statement and the one channel it points at. Stacked, the call
   ran to 55% of the band and the channel to 29%, leaving the last screen of
   the page mostly void — which read as unfinished rather than as restraint. */
.hail { display: grid; gap: clamp(2rem, 4vw, 3rem); }

.channel {
  margin-top: 0;
  max-width: 42ch;
  padding: clamp(1.1rem, 2.4vw, 1.5rem);
  border: 1px dashed rgba(203, 216, 238, 0.22);
  border-radius: var(--radius);
  background: rgba(10, 16, 36, 0.6);
}
.channel__k { display: flex; align-items: center; gap: 0.6rem; }
.channel__v {
  margin-top: 0.45rem;
  font-size: 1.0625rem; font-weight: 500; color: var(--chrome);
}
.channel__note {
  margin-top: 0.7rem; font-size: 0.8125rem; line-height: 1.5; color: var(--chrome-3);
  text-transform: none; letter-spacing: 0;
}

/* ── Footer ──────────────────────────────────────────────────────────── */

.foot { background: #02040A; border-top: 1px solid var(--groove); box-shadow: 0 -1px 0 var(--edge-soft); }
.foot__in { max-width: var(--shell); margin-inline: auto; padding: clamp(2.5rem, 5vw, 3.5rem) var(--gutter); display: grid; gap: 0.6rem; }
.foot__name {
  font-variation-settings: 'wdth' 110; font-weight: 700;
  font-size: 1rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--chrome);
}
.foot__say span { color: var(--chrome-2); }
/* The descriptor sits on the name line the way it does on the wordmark. */
.foot__desc { display: inline-block; margin-left: 0.85rem; vertical-align: 0.06em; }
.triad { display: flex; flex-wrap: wrap; gap: 0.45rem 1.6rem; margin-top: 0.4rem; }
.foot__legal { max-width: 62ch; font-size: 0.8125rem; line-height: 1.55; color: #63719A; }

/* ── Breakpoints ─────────────────────────────────────────────────────── */

@media (min-width: 560px) {
  .readout { display: block; }
  .foot__in { gap: 0.75rem; }
  .probe__row { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .probe__gov { padding-inline: 0.9rem; }
  .reqs { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(1.5rem, 4vw, 3rem); }
}

/* The seven orchestration questions pair up once each column can still hold a
   question on one or two lines. Below this they stack, because a two-column
   list of wrapped questions is harder to read than a single column of them. */
@media (min-width: 700px) {
  .bus__q {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: clamp(1.5rem, 3vw, 2.75rem);
  }
}

/* The plate splits at 900, not 760. Below that the text column is too narrow
   to carry the master legend beside the orb without the type collapsing. */
@media (min-width: 900px) {
  .plate__in { grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr); }
  .plate__text { max-width: none; }
  .orb { justify-self: end; }

  .app {
    grid-template-columns: minmax(7rem, 12rem) minmax(8rem, 13rem) minmax(0, 1fr);
    align-items: start;
    column-gap: clamp(1.25rem, 3vw, 2.75rem);
    row-gap: 0;
  }
  .app__body { max-width: 64ch; }

  /* Leadership reuses the channel panel but not its three-column split — there
     is no band and no mini-scale to fill the middle column, so the two roles
     sit side by side on the same ground instead. Equal width is the argument:
     neither role leads. */
  .crew { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .crew .app { grid-template-columns: none; row-gap: 0.6rem; }
  .crew .app__body { max-width: 48ch; }

  /* The rack takes the same three columns as the application channels: name,
     then designation, then description. Same discipline, same rhythm — the
     methodology reads as another face of the same console. */
  .mod {
    grid-template-columns: minmax(7rem, 12rem) minmax(9rem, 15rem) minmax(0, 1fr);
    align-items: start;
    column-gap: clamp(1.25rem, 3vw, 2.75rem);
    row-gap: 0;
  }
  .mod__body { max-width: 60ch; }

  /* A rack whose rows are a name and a description, with no designation
     between them. The GGEE domains have three parts because a computational
     domain has a name, a set of named methods, and a role; a portfolio
     competence has only the first and the last. Given the three-column rule
     anyway, the description drops into the 15rem designation column and sets
     itself in a gutter. Two columns is the honest count, so the name takes the
     width the missing column would have had. */
  .rack--pair .mod { grid-template-columns: minmax(9rem, 19rem) minmax(0, 1fr); }

  /* Nine requirements, three columns, three exact rows — no orphan cell. */
  .reqs { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (min-width: 1000px) {
  .rail__nav { display: flex; }
  .foundry { grid-template-columns: minmax(0, 1.4fr) minmax(0, 0.6fr); }

  .thesis {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    column-gap: clamp(2.5rem, 5vw, 4rem);
    align-items: start;
  }
  /* The prose sits optically level with the first question in the switch
     rather than with the panel's top edge. */
  .thesis .prose { padding-top: 0.35rem; }

  .hail {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    column-gap: clamp(2.5rem, 5vw, 4.5rem);
    align-items: center;
  }
  .channel { justify-self: end; max-width: 40ch; }

  .overture {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.95fr);
    column-gap: clamp(2.5rem, 5vw, 4rem);
    align-items: start;
  }

  /* The bus splits: the statement holds the left column, the seven questions
     take the right as a single unbroken run. Two short columns of questions
     under a half-width lede left the panel's right half empty. */
  .bus {
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    column-gap: clamp(2rem, 4vw, 3.5rem);
    align-items: start;
  }
  /* The rail and the routing stub are absolutely positioned, so they stay out
     of flow and never become grid items. */
  .bus__q {
    margin-top: 0;
    grid-template-columns: minmax(0, 1fr);
  }
  .bus__q li:first-child { border-top: 0; padding-top: 0; }

  .ip { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: clamp(2.5rem, 5vw, 5rem); align-items: start; }

  .marks {
    display: block; position: relative;
    height: 108px;
    margin: 0.35rem var(--inset) 0;
  }
  .pt { position: absolute; top: 0; left: calc(var(--x) * 1%); }

  /* Three label rows, joined to their true tick positions by leader lines.
     Three rather than one because the labels genuinely will not fit: the
     labels are centred on their positions and run ~13% of the axis wide,
     while IntelliBrella (36.8), SpectraDome (40.0) and GateKeeper (43.3) sit
     inside 6.5% of each other. The chart stacks rather than lying about where
     the applications sit. E.D.E.N. shares the top row — it is 33% clear. */
  .pt::before {
    content: ''; position: absolute; top: 0; left: 0;
    width: 1px; height: 15px; background: var(--edge-lip);
  }
  .pt--mid::before { height: 45px; }
  .pt--low::before { height: 75px; }

  .pt > a {
    position: absolute; top: 15px; left: 0;
    transform: translateX(-50%);
    /* These sit over a third of the axis and a sweep may start on one, so they
       must not begin a native link-drag or select their own text. */
    -webkit-user-drag: none;
    user-select: none; -webkit-user-select: none;
    display: flex; align-items: center; gap: 0.45rem;
    padding: 0.32rem 0.6rem;
    white-space: nowrap; text-decoration: none;
    border: 1px solid var(--edge);
    border-radius: var(--radius);
    background: linear-gradient(180deg, var(--panel-lift), var(--panel));
    box-shadow: inset 0 1px 0 var(--edge-soft);
    font-variation-settings: 'wdth' 90;
    font-weight: 600; font-size: 0.6875rem;
    letter-spacing: 0.11em; text-transform: uppercase;
    color: var(--chrome-2);
    transition: color 0.2s, border-color 0.2s, box-shadow 0.3s var(--ease);
  }
  .pt--mid > a { top: 45px; }
  .pt--low > a { top: 75px; }
  .pt .lamp { --lamp: 7px; }
  .pt > a:hover, .pt > a:focus-visible {
    color: var(--chrome);
    border-color: rgba(35, 165, 235, 0.55);
    box-shadow: inset 0 1px 0 var(--edge-soft), 0 0 18px -4px var(--live-glow);
  }
}

/* Arriving from a marker lights the bay you were sent to. Pure :target — it
   works with JavaScript switched off, which is the point of using it.

   `.is-probed` is the same lit state driven by the wavelength cursor: drag the
   cursor into a band and every application that governs there comes up, in the
   scale and in its bay at once. That is the "four expressions of one thesis"
   claim made demonstrable instead of merely asserted. */
.app:target,
.app.is-probed { background: linear-gradient(180deg, #131D46 0%, #0C1430 100%); }
.app:target .lamp,
.app.is-probed .lamp,
.pt.is-probed .lamp {
  background: var(--live);
  box-shadow:
    inset 0 1px 1.5px rgba(255, 255, 255, 0.45),
    0 0 0 1px rgba(35, 165, 235, 0.5),
    0 0 9px 1px var(--live-glow),
    0 0 22px 3px rgba(35, 165, 235, 0.20);
}
.app:target .app__mini i,
.app.is-probed .app__mini i { background: var(--live); box-shadow: 0 0 8px var(--live-glow); }
.pt.is-probed > a {
  color: var(--chrome);
  border-color: rgba(35, 165, 235, 0.55);
  box-shadow: inset 0 1px 0 var(--edge-soft), 0 0 18px -4px var(--live-glow);
}

/* Below 560px the master legend has to fit ELECTROMAGNETIC — fifteen
   characters — into roughly 280px. Narrowing the width axis to 96 buys back
   about 10% per character, which is the difference between the word fitting
   and the page scrolling sideways.

   Hyphenation is declared above but is not load-bearing: hyphenation
   dictionaries are absent in several rendering environments (headless
   Chromium among them), so the type is sized to fit unbroken and the hyphen
   is only ever a bonus. */
@media (max-width: 559px) {
  /* Narrowing the width axis to 96 buys back roughly 10% per character, which
     on a 320px phone is the difference between the word fitting and not. The
     measured fit ceiling at this width is 9.47% of the column. */
  .legend {
    font-variation-settings: 'wdth' 96;
    /* Capped at 2.35rem so the type does not visibly step down when the
       560px breakpoint swaps the width axis from 96 back to 106. */
    font-size: clamp(1.55rem, 0.1rem + 5.3vw, 2.35rem);
    font-size: clamp(1.55rem, 9.2cqw, 2.35rem);
  }
  .ctl { padding: 0.55rem 0.75rem; letter-spacing: 0.1em; }
  .ctl__long { display: none; }
}
.ctl__short { display: none; }
@media (max-width: 559px) { .ctl__short { display: inline; } }

/* Below 380px the mini-scale and the band legends get too tight. */
@media (max-width: 379px) {
  .app__mini { display: none; }
  .bands li span { font-size: 0.5rem; letter-spacing: 0.06em; }
  .mark__say { display: none; }
}

/* ── Motion ───────────────────────────────────────────────────────────
   One authored moment: the console powers up. Nothing is hidden to achieve
   it — the legend resolves out of soft focus, the tick field draws in, and
   lamps warm. Content is readable at every frame.                         */

.legend { animation: resolve 0.9s var(--ease) both; }
.legend__sub { animation: resolve 0.9s var(--ease) 0.12s both; }
@keyframes resolve {
  from { opacity: 0.25; filter: blur(7px); letter-spacing: 0.04em; }
  to   { opacity: 1; filter: blur(0); }
}

/* The mark settles into place rather than fading in — it is fully opaque the
   whole time. The bezel's warm-up keyframe went with the bezel. */
.orb__hold img { animation: settle 1.4s var(--ease) 0.15s both; }
@keyframes settle {
  from {
    transform: scale(0.955);
    filter: drop-shadow(0 6px 14px rgba(0, 0, 0, 0.5)) drop-shadow(0 0 0 rgba(35, 165, 235, 0));
  }
}

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