/* ============================================================ tokens ==== */
/*
 * Two themes, declared as sibling attribute blocks on <html data-theme>. This
 * is the convention the four OpCo sites already use; `body.light-mode` and
 * public/opco-tokens.css are older mechanisms that nothing live links.
 *
 * Four tokens exist purely to survive the flip:
 *   --on-gold   text sitting ON a gold fill. It is NOT "the page background",
 *               which is what --ink was wrongly doing in four places.
 *   --gold-ink  gold used AS text. The documented light gold #A88B3D measures
 *               2.7:1 on the documented cream, so text needs its own darker value.
 *   --gold-dim  had the gold RGB baked in, so it never tracked --gold.
 *   --panel-2   was declared and never used; it is now the quote surface.
 */
:root,
:root[data-theme="dark"] {
  color-scheme: dark;

  /* A cool graphite ground, deliberately not the purple-black of the
     incumbent page. Gold stays: it is brand equity, not a design choice. */
  --ink:        #0A0C10;
  --ink-2:      #0D1016;
  --panel:      #11151C;
  --panel-2:    #161B24;
  --hair:       rgba(255,255,255,0.070);
  --hair-2:     rgba(255,255,255,0.115);
  --hair-3:     rgba(255,255,255,0.20);
  /* Interactive boundaries need 3:1 of their own (WCAG 1.4.11); the hairlines
     above are structural rules and are allowed to stay quiet. */
  --edge:       rgba(255,255,255,0.36);

  --cta-gold:   #C8A55A;
  --gold:       #C8A55A;
  --gold-ink:   #C8A55A;
  --gold-hi:    #E4C57F;
  --gold-dim:   rgba(200,165,90,0.14);
  --on-gold:    #0A0C10;

  --studios:    #CF7468;
  --digital:    #A87FD4;
  --labs:       #5B9E7B;
  --systems:    #6A8FCC;
  /* The same four at full strength, and deliberately never redefined for the
     light theme: they are for surfaces that are dark whatever the page is,
     like the register's photo cards. */
  --studios-lit: #CF7468;
  --digital-lit: #A87FD4;
  --labs-lit:    #5B9E7B;
  --systems-lit: #6A8FCC;

  --text:       #E9EBEF;
  --text-mid:   #939CAB;
  /* 5.62:1 at worst on panel-2, and 4.70 on the bare ink where the page's
     gold glow and the pointer's both peak, so the mono labels and eyebrows
     this token carries clear WCAG AA as small text anywhere. #7C8694 fell to
     3.92 under the two glows; #626B79 measured 3.4:1. */
  --text-low:   #8A94A2;

  --nav-glass:   rgba(10,12,16,0.36);
  --panel-glass: rgba(10,12,16,0.96);
  --veil-a:      rgba(10,12,16,0.97);
  --veil-b:      rgba(10,12,16,0.91);
  --veil-c:      rgba(10,12,16,0.56);
  --veil-d:      rgba(10,12,16,0.12);
  --ground-1:    #0B0E13;
  --ground-2:    #090B0F;
  --ground-glow: rgba(200,165,90,0.11);
  --ground-cool: rgba(106,143,204,0.07);
  --glow-gold:   rgba(200,165,90,0.10);
  --glow-cool:   rgba(106,143,204,0.055);
  --glow-warm:   rgba(207,116,104,0.045);
  /* Contains var(--ink), so it is substituted where it is declared. Any
     block that redefines --ink must redeclare --cell too, or the cell
     keeps the ink of the scope it was written in. */
  --cell:        color-mix(in srgb, var(--ink) 96%, transparent);
  --chart-grid:  rgba(255,255,255,0.09);
  --chart-mute:  #4E5663;

  /* Pointer. The dot is the page's text colour, so it reads on the ground it
     is standing on. The glow is capped at the alpha where the quietest text
     on the bare ground still clears 4.5 with the page's own gold glow stacked
     under it: --text-low measures 4.70 there, which leaves very little room,
     so 0.10 is a ceiling not a taste. */
  --cur-ink:     #E9EBEF;
  --cur-glow:    rgba(200,165,90,0.10);
  /* Over a gold glass band the dot takes the band's own gold-white. */
  --cur-band:    #F7E0A4;

  /* The gold bands' own tokens live in the band itself ("gold glass bands"
     below), redefined per theme, so nothing here describes a band. */

  --shell:      1420px;
  --gutter:     clamp(1.15rem, 3.6vw, 3.25rem);
  --rail:       clamp(2.6rem, 6vw, 6.5rem);

  --f-display:  'Onest', system-ui, -apple-system, sans-serif;
  --f-body:     'Lexend', system-ui, -apple-system, sans-serif;
  --f-mono:     'Fragment Mono', ui-monospace, 'SF Mono', monospace;
  --f-quote:    'Newsreader', Georgia, serif;

  --ease:       cubic-bezier(0.22, 0.68, 0.24, 1);

  /* The projects section is ported 1:1 from anuragbains.com V3 and its rules
     read that site's token names. They are aliases of this site's tokens, so
     the rules stay a straight copy and every colour is still the HoldCo's.
     Redeclared in the light block, like --cell. */
  --ground:      var(--ink);
  --raised:      var(--panel);
  --card:        var(--panel-2);
  --signal:      var(--gold);
  --signal-ink:  var(--gold-ink);
  --on-signal:   var(--on-gold);
  --shot-frame:  var(--hair-2);
  /* The shelf is dark in both themes, so its frame is too: the shelf's own
     paper, so the frame never flashes before the scene paints. */
  --shelf-paper: #0A0C10;
}

/*
 * Light. Every value below was measured, not picked: each accent is the
 * brand hue walked down until it clears 4.5:1 against all four light
 * surfaces. The brand doc's own light gold (#A88B3D) is kept, but only as a
 * FILL, because as text it measures 2.7:1.
 */
:root[data-theme="light"] {
  color-scheme: light;

  --ink:        #EDE9E0;
  --ink-2:      #E4DFD3;
  --panel:      #DED8CC;
  --panel-2:    #D8D2C5;
  --hair:       rgba(26,26,46,0.115);
  --hair-2:     rgba(26,26,46,0.18);
  --hair-3:     rgba(26,26,46,0.34);
  --edge:       rgba(26,26,46,0.52);

  --cta-gold:   #A88B3D;
  --gold:       #A88B3D;
  --gold-ink:   #6B5830;
  --gold-hi:    #5A4A28;
  --gold-dim:   rgba(168,139,61,0.20);
  --on-gold:    #0A0C10;

  --studios:    #854B43;
  --digital:    #695085;
  --labs:       #39634D;
  --systems:    #445B82;

  --text:       #1A1A2E;
  --text-mid:   #4A4A64;
  --text-low:   #54546A;

  --nav-glass:   rgba(237,233,224,0.39);
  --panel-glass: rgba(237,233,224,0.96);
  --veil-a:      rgba(237,233,224,0.97);
  --veil-b:      rgba(237,233,224,0.91);
  --veil-c:      rgba(237,233,224,0.58);
  --veil-d:      rgba(237,233,224,0.14);
  --ground-1:    #F3F0E9;
  --ground-2:    #E7E2D7;
  --ground-glow: rgba(168,139,61,0.16);
  --ground-cool: rgba(68,91,130,0.09);
  --glow-gold:   rgba(168,139,61,0.16);
  --glow-cool:   rgba(68,91,130,0.075);
  --glow-warm:   rgba(133,75,67,0.06);
  /* Cream has more headroom than the dark ground: the binding text here is
     --gold-ink at 5.66, so the pool can be twice as strong and still land at
     4.75 under its own brightest point. */
  --cur-ink:     #1A1A2E;
  --cur-glow:    rgba(168,139,61,0.20);
  --cur-band:    #2E2410;
  --cell:        color-mix(in srgb, var(--ink) 96%, transparent);
  --chart-grid:  rgba(26,26,46,0.13);
  --chart-mute:  #8E8A80;

  --ground:      var(--ink);
  --raised:      var(--panel);
  --card:        var(--panel-2);
  --signal:      var(--gold);
  --signal-ink:  var(--gold-ink);
  --on-signal:   var(--on-gold);
  --shot-frame:  var(--hair-2);
  --shelf-paper: #0A0C10;
}

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

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* [hidden] has to beat every display declaration in this sheet. Without it the
   project modal's link, hidden for a project with no link, still lays out as
   an empty gold bar. (From anuragbains.com V3, with the rest of the port.) */
[hidden] { display: none !important; }
/* A visitor who has gone away (site.js's idle gate, two minutes without input)
   gets a still page, and so does anything scrolled out of view: site.js marks
   each [data-offscreen-pause] container .is-off while it is off screen.
   !important because an `animation:` shorthand resets the play state. */
html[data-idle] *, html[data-idle] *::before, html[data-idle] *::after { animation-play-state: paused !important; }
.is-off, .is-off *, .is-off *::before, .is-off *::after { animation-play-state: paused !important; }
/* The project modal holds the page still behind it. */
body.is-locked { overflow: hidden; }

/*
 * The body is not a flat colour. Three very wide, very low-opacity radials
 * sit behind everything at fixed position, so the page reads as lit rather
 * than printed, and the gold has somewhere to come from.
 */
body::before {
  content: '';
  position: fixed; inset: 0; z-index: -10; pointer-events: none;
  /* Promoted to its own compositor layer. Without this a fixed, full-viewport
     three-radial gradient is repainted on every scroll frame, which on a
     machine without GPU acceleration is enough to starve the header's
     animation loop entirely. */
  transform: translateZ(0);
  will-change: transform;
  background:
    radial-gradient(58% 42% at 78% 8%,  var(--glow-gold), transparent 62%),
    radial-gradient(52% 40% at 12% 44%, var(--glow-cool), transparent 66%),
    radial-gradient(64% 46% at 62% 92%, var(--glow-warm), transparent 64%);
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--text);
  font-family: var(--f-body);
  font-weight: 300;
  font-size: clamp(0.925rem, 0.88rem + 0.2vw, 1.02rem);
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

h1, h2, h3, h4 {
  font-family: var(--f-display);
  font-weight: 800;
  letter-spacing: -0.032em;
  line-height: 1.03;
  margin: 0;
  text-wrap: balance;
}

p { margin: 0; }
a { color: inherit; }

::selection { background: var(--gold); color: var(--on-gold); }

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

.skip {
  position: absolute; left: 0.5rem; top: -4rem; z-index: 200;
  background: var(--gold); color: var(--on-gold);
  padding: 0.6rem 1rem; font-family: var(--f-mono); font-size: 0.7rem;
  text-decoration: none; transition: top 0.18s var(--ease);
}
.skip:focus { top: 0.5rem; }

.sr {
  position: absolute; width: 1px; height: 1px; padding: 0;
  margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ========================================================= the frame ==== */
/*
 * The whole page sits inside one measured frame: two hairline rails, corner
 * brackets at every section join, and a mono index in the left gutter. It is
 * the organising idea of this version, and the reason nothing here needs a
 * card to look contained.
 */
.shell {
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--gutter);
  position: relative;
}

/*
 * Bands run edge to edge; only their content is held to the shell measure.
 * --shell-pad reproduces exactly what .shell used to do (centre at --shell,
 * never closer to the edge than --gutter) but as padding on a full-width
 * element, so a band's background reaches both edges of the viewport.
 */
.bands { width: 100%; }

.band {
  --band-pad: clamp(1rem, 3.2vw, 3rem);
  --shell-pad: max(var(--gutter), calc((100% - var(--shell)) / 2 + var(--gutter)));
  position: relative;
  border-top: 1px solid var(--hair);
  padding-block: clamp(4rem, 9vw, 8.5rem);
  padding-inline: calc(var(--shell-pad) + var(--band-pad));
}

/* Section index sits in the rail, aligned to the first baseline of the head. */
.band > .index {
  font-family: var(--f-mono);
  font-size: 0.72rem;
  color: var(--gold-ink);
  letter-spacing: 0.08em;
  display: block;
  margin-bottom: 1.6rem;
}
@media (min-width: 1080px) {
  .band { padding-left: calc(var(--shell-pad) + var(--rail)); }
  .band > .index {
    position: absolute;
    left: calc(var(--shell-pad) + var(--band-pad));
    top: clamp(4rem, 9vw, 8.5rem);
    margin: 0;
  }
}

.eyebrow {
  font-family: var(--f-mono);
  font-size: 0.72rem;
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--text-low);
  display: block;
  margin-bottom: 1.15rem;
}

.h-lg { font-size: clamp(2.05rem, 1.35rem + 3.1vw, 3.85rem); }
.h-md { font-size: clamp(1.45rem, 1.1rem + 1.5vw, 2.15rem); }
.h-sm { font-size: clamp(1.05rem, 0.95rem + 0.5vw, 1.3rem); letter-spacing: -0.02em; }

.lede {
  color: var(--text-mid);
  max-width: 60ch;
  font-size: clamp(1rem, 0.94rem + 0.3vw, 1.14rem);
  line-height: 1.72;
  margin-top: 1.5rem;
}

.head-split {
  display: grid;
  gap: clamp(1.5rem, 4vw, 4rem);
  align-items: end;
}
@media (min-width: 960px) {
  .head-split { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); }
  .head-split .lede { margin-top: 0; }
}
/* A second paragraph under a lede, in the same column. */
.lede.lede-2, .head-split .lede.lede-2 { margin-top: 1rem; }

/* ============================================================== nav ===== */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  background: var(--nav-glass);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  border-bottom: 1px solid var(--hair);
}

.nav-in {
  max-width: var(--shell);
  margin-inline: auto;
  padding: 0 var(--gutter);
  height: 62px;
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vw, 2.5rem);
}

.mark {
  display: flex; align-items: center; gap: 0.6rem;
  text-decoration: none; margin-right: auto; flex-shrink: 0;
  min-height: 44px;  /* WCAG 2.5.8: the glyph is 20px, the target must not be */
  flex-wrap: nowrap; white-space: nowrap;
}
.mark img { width: 26px; height: auto; display: block; }
/* The logo file is white artwork. Inverting is exact for a monochrome mark
   and costs one filter rather than a second request. */
:root[data-theme="light"] .mark img { filter: invert(1); }
.mark span {
  font-family: var(--f-display); font-weight: 800;
  font-size: 0.755rem; letter-spacing: 0.2em; text-transform: uppercase;
}
/* Below 520px the bar has to carry the mark, the theme toggle, the CTA and the
   menu button. The wordmark is the one that can shed its text and still be
   understood, because the logo stays. */
@media (max-width: 520px) {
  .mark span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .nav-in { gap: 0.6rem; }
  .nav-cta { padding-inline: 0.8rem; letter-spacing: 0.1em; }
}

.nav-links { display: none; gap: clamp(1rem, 2.2vw, 1.9rem); }
@media (min-width: 900px) { .nav-links { display: flex; } }
.nav-links a {
  font-family: var(--f-mono);
  font-size: 0.72rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--text-mid);
  text-decoration: none;
  padding-block: 0.4rem;
  border-bottom: 1px solid transparent;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.nav-links a:hover, .nav-links a[aria-current="true"] {
  color: var(--text); border-bottom-color: var(--gold);
}

.nav-toggle {
  display: inline-flex; flex-direction: column; justify-content: center; gap: 4px;
  width: 44px; height: 44px; padding: 0 10px;
  background: transparent; border: 1px solid var(--edge); cursor: pointer;
  transition: border-color 0.2s var(--ease);
}
.nav-toggle:hover { border-color: var(--gold); }
.nav-toggle span { display: block; height: 1px; background: var(--text); transition: transform 0.24s var(--ease), opacity 0.18s var(--ease); }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }
@media (min-width: 900px) { .nav-toggle { display: none; } }

.nav-panel {
  border-top: 1px solid var(--hair);
  background: var(--panel-glass);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
}
.nav-panel[hidden] { display: none; }
.nav-panel ul {
  list-style: none; margin: 0;
  padding: 0.5rem var(--gutter) 1.1rem;
  max-width: var(--shell); margin-inline: auto;
}
.nav-panel a {
  display: block; padding: 0.85rem 0;
  border-bottom: 1px solid var(--hair);
  font-family: var(--f-mono); font-size: 0.72rem; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--text-mid); text-decoration: none;
}
.nav-panel a:hover, .nav-panel a:focus-visible { color: var(--gold-hi); }
.nav-panel a[data-opco] { display: flex; align-items: center; gap: 0.7rem; }
@media (min-width: 900px) { .nav-panel { display: none; } }

/* Theme toggle. Same construction as the four OpCo sites: one button, both
   icons in the DOM, CSS picks which is visible from the root attribute. */
.theme-toggle {
  width: 44px; height: 44px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; color: var(--text-mid);
  border: 1px solid var(--edge); cursor: pointer;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease), background 0.2s var(--ease);
}
.theme-toggle:hover { color: var(--gold-ink); border-color: var(--gold); background: var(--gold-dim); }
.theme-toggle svg { width: 16px; height: 16px; pointer-events: none; display: none; }
:root[data-theme="dark"]  .theme-toggle .icon-sun  { display: block; }
:root[data-theme="light"] .theme-toggle .icon-moon { display: block; }

.nav-cta {
  font-family: var(--f-mono);
  font-size: 0.72rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--on-gold);
  background: var(--cta-gold);
  text-decoration: none;
  padding: 0.62rem 1.05rem;
  min-height: 40px; display: inline-flex; align-items: center;
  border: 1px solid var(--cta-gold);
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
  white-space: nowrap;
}
.nav-cta:hover { background: transparent; color: var(--gold-hi); }
.nav-cta:active { transform: translateY(1px); }

/* ============================================================= hero ===== */
.hero {
  position: relative;
  min-height: min(94svh, 900px);
  display: flex;
  align-items: flex-end;
  padding-top: 62px;
  overflow: clip;
  isolation: isolate;
}

/* A complete composition even with zero JavaScript and no WebGL: the canvas
   only ever adds to this, it is never the thing holding the header up. */
.hero-ground {
  position: absolute; inset: 0; z-index: -3;
  background:
    radial-gradient(72% 58% at 74% 42%, var(--ground-glow), transparent 68%),
    radial-gradient(46% 40% at 18% 12%, var(--ground-cool), transparent 70%),
    linear-gradient(180deg, var(--ground-1) 0%, var(--ink) 62%, var(--ground-2) 100%);
}

.hero-scene { position: absolute; inset: 0; z-index: -2; }
.hero-scene canvas { width: 100%; height: 100%; display: block; }

/* Keeps type legible over whatever the scene is doing behind it. */
.hero-veil {
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(92deg, var(--veil-a) 0%, var(--veil-b) 30%, var(--veil-c) 47%, var(--veil-d) 68%, transparent 85%),
    linear-gradient(0deg, var(--ink) 1%, transparent 34%);
}
@media (max-width: 899px) {
  .hero-veil { background: linear-gradient(0deg, var(--ink) 16%, var(--veil-b) 56%, var(--veil-c) 100%); }
}

.hero-in {
  position: relative;
  width: 100%;
  padding-block: clamp(2.5rem, 7vw, 5rem);
}

.hero-meta {
  font-family: var(--f-mono);
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-low);
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.55rem 0.9rem;
  margin-bottom: clamp(1.5rem, 4vw, 2.4rem);
}
.hero-meta b { color: var(--gold-ink); font-weight: 400; }
/* Decoration, and marked as such: the slashes repeat spacing the eye already
   has, they are read out as "slash" by a screen reader if left in the tree,
   and at 1.79:1 they would fail 1.4.3 as text. */
.hero-meta i { font-style: normal; color: var(--hair-3); }

h1 {
  font-size: clamp(2.5rem, 1.25rem + 5.6vw, 5.4rem);
  max-width: 17ch;
  letter-spacing: -0.042em;
}
h1 .soft { color: var(--text-mid); font-weight: 300; }

.hero-sub {
  margin-top: clamp(1.4rem, 3vw, 2rem);
  max-width: 54ch;
  color: var(--text-mid);
  font-size: clamp(0.98rem, 0.92rem + 0.32vw, 1.14rem);
}

.hero-acts {
  display: flex; flex-wrap: wrap; gap: 0.8rem;
  margin-top: clamp(1.8rem, 4vw, 2.6rem);
}

.btn {
  font-family: var(--f-mono);
  font-size: 0.685rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 0.88rem 1.5rem;
  min-height: 44px;
  border: 1px solid var(--gold);
  display: inline-flex; align-items: center; gap: 0.6rem;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), transform 0.12s var(--ease);
}
.btn-solid { background: var(--gold); color: var(--on-gold); }
.btn-solid:hover { background: var(--gold-hi); border-color: var(--gold-hi); }
.btn-ghost { background: transparent; color: var(--text); border-color: var(--edge); }
.btn-ghost:hover { border-color: var(--gold); color: var(--gold-hi); }
.btn:active { transform: translateY(1px); }

/* --- scene switcher ---
   Three headers were built so they can be judged side by side, so the
   control is a real part of the page rather than a hidden dev flag. */
.scene-pick {
  margin-top: clamp(2.2rem, 5vw, 3.4rem);
  border-top: 1px solid var(--hair);
  padding-top: 1rem;
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.5rem 1rem;
}
.scene-pick > .label {
  font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--text-low);
}
.scene-opts { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.scene-opt {
  font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.11em;
  text-transform: uppercase;
  background: transparent; color: var(--text-mid);
  border: 1px solid var(--edge); padding: 0.5rem 0.9rem;
  min-height: 44px; cursor: pointer;
  display: inline-flex; align-items: center; gap: 0.5rem;
  transition: color 0.18s var(--ease), border-color 0.18s var(--ease), background 0.18s var(--ease);
}
.scene-opt::before {
  content: ''; width: 5px; height: 5px; border-radius: 50%;
  background: var(--hair-3); transition: background 0.18s var(--ease);
}
.scene-opt:hover { color: var(--text); border-color: var(--hair-2); }
.scene-opt[aria-pressed="true"] {
  color: var(--gold-hi); border-color: var(--gold); background: var(--gold-dim);
}
.scene-opt[aria-pressed="true"]::before { background: var(--gold); }
.scene-note {
  font-family: var(--f-mono); font-size: 0.7rem; color: var(--text-low);
  letter-spacing: 0.04em;
}

/* ====================================================== orb labels ====== */
/*
 * One label per orbiting node in the structure scene, positioned per frame by
 * the scene itself. The layer sits ABOVE the veil, unlike the canvas, or the
 * veil would paint straight over it.
 */
.hero-labels { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.hero-labels[hidden] { display: none; }

.scene-label {
  position: absolute; top: 0; left: 0;
  display: flex; align-items: baseline; gap: 0.5rem;
  transform: translate3d(0, 0, 0);
  will-change: transform;
  /* Hidden until the scene has projected it. Parking it thousands of pixels
     off-canvas instead put a phantom box in the page's geometry. */
  visibility: hidden;
  padding: 0.3rem 0.55rem;
  background: color-mix(in srgb, var(--ink) 66%, transparent);
  border: 1px solid var(--hair-2);
  border-left: 2px solid var(--label-color, var(--gold));
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.35s var(--ease);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  /* the node is the anchor, so hang the plate off it rather than centring.
     The horizontal offset is applied in JS so the plate can flip to the left
     of its node when it would otherwise run off the right edge. */
  margin: -0.9rem 0 0 0;
}
.scene-label.is-placed { visibility: visible; }
.scene-label i {
  font-style: normal; font-family: var(--f-mono);
  font-size: 0.685rem; letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--label-color, var(--gold-ink));
}
.scene-label b {
  font-family: var(--f-mono); font-weight: 400;
  font-size: 0.7rem; letter-spacing: 0.06em;
  color: var(--text);
}
@media (prefers-reduced-motion: reduce) {
  .scene-label { transition: none; }
}

/* =========================================================== specs ====== */
/*
 * This band was an auto-scrolling ticker. A marquee hides half its content at
 * any moment and moves for attention rather than for meaning, so the same
 * facts are now a fixed specification strip: everything readable at once, at
 * rest, which is what a register is supposed to be.
 */
.specs {
  border-top: 1px solid var(--hair);
  border-bottom: 1px solid var(--hair);
  background: color-mix(in srgb, var(--ink-2) 96%, transparent);
  padding-inline: var(--gutter);
}
.specs-in {
  max-width: var(--shell); margin-inline: auto;
  display: grid; gap: 1px;
  /* the gap colour is the rule between cells, so it must not extend into
     the gutter or it paints two grey blocks at the page edges */
  background: var(--hair);
}
@media (min-width: 620px) { .specs-in { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .specs-in { grid-template-columns: repeat(5, 1fr); } }

.specs-in > div {
  background: color-mix(in srgb, var(--ink-2) 96%, transparent);
  padding: 1rem clamp(0.9rem, 1.8vw, 1.5rem) 1.1rem;
  display: grid; gap: 0.4rem;
}
.specs dt {
  font-family: var(--f-mono); font-size: 0.7rem;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--text-low);
}
.specs dd {
  margin: 0; font-size: 0.875rem; color: var(--text);
  line-height: 1.45;
}

/* ======================================================= structure ====== */
.rail {
  margin-top: clamp(2.6rem, 6vw, 4.5rem);
  display: grid;
  gap: 1px;
  background: var(--hair);
  border-block: 1px solid var(--hair);
}
@media (min-width: 780px) { .rail { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1180px) { .rail { grid-template-columns: repeat(4, 1fr); } }

.rail-cell {
  background: var(--cell);
  padding: clamp(1.5rem, 2.6vw, 2.1rem) clamp(1.25rem, 2.2vw, 1.8rem) clamp(1.7rem, 3vw, 2.3rem);
  position: relative;
  transition: background 0.25s var(--ease);
}
.rail-cell:hover { background: var(--panel); }
.rail-cell::before {
  content: '';
  position: absolute; left: 0; top: 0; height: 2px; width: 100%;
  background: var(--accent);
  transform: scaleX(0.16); transform-origin: left;
  transition: transform 0.4s var(--ease);
}
.rail-cell:hover::before { transform: scaleX(1); }

.rail-code {
  font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.15em;
  color: var(--accent); display: flex; align-items: center; gap: 0.5rem;
}
.rail-code::after { content: ''; flex: 1; height: 1px; background: var(--hair); }

.rail-name {
  font-family: var(--f-display); font-weight: 800;
  font-size: clamp(1.1rem, 1rem + 0.5vw, 1.32rem);
  letter-spacing: -0.025em;
  margin: 1.1rem 0 0.5rem;
}
.rail-disc {
  font-family: var(--f-mono); font-size: 0.7rem;
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--text-low);
}
.rail-body { color: var(--text-mid); font-size: 0.9rem; margin-top: 1rem; }


/* =========================================================== charts ===== */
/*
 * Every chart here is authored so that --p: 1 is the finished, correct chart.
 * The scroll scrub only walks --p from 0 to 1 over a truth that is already in
 * the DOM, so with JavaScript off, or with reduced motion, the reader still
 * gets the real figures. No chart library, no canvas: the numbers are text.
 */
.chart-note {
  font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.06em;
  color: var(--text-low); margin-top: 1rem;
}
.chart-note b { color: var(--gold-ink); font-weight: 400; }

.figures { display: grid; gap: 1px; background: var(--hair); border-block: 1px solid var(--hair); margin-top: clamp(2.4rem, 5vw, 3.6rem); }
@media (min-width: 560px) { .figures { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .figures { grid-template-columns: repeat(4, 1fr); } }

/* The term precedes its definition in the DOM, as a definition list
   requires; the number is lifted above it visually. */
.figure {
  background: var(--cell);
  padding: clamp(1.3rem, 2.6vw, 1.9rem) clamp(1.1rem, 2vw, 1.5rem) clamp(1.5rem, 3vw, 2rem);
  display: flex; flex-direction: column;
}
.figure .figure-n { order: -1; }
.figure-n {
  display: block;
  font-family: var(--f-display); font-weight: 800;
  font-size: clamp(2.4rem, 1.6rem + 2.6vw, 3.6rem);
  line-height: 1; letter-spacing: -0.045em; color: var(--gold-ink);
  font-variant-numeric: proportional-nums;
}
.figure-n.is-counting { font-variant-numeric: tabular-nums; }
.figure-l { margin: 0.75rem 0 0; font-size: 0.88rem; color: var(--text-mid); }
.figure-s { margin: 0.4rem 0 0; font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.08em; color: var(--text-low); }

/* --- the money chart: a stacked comparison against one solid bar --- */
.cost { margin-top: clamp(2.4rem, 5vw, 3.6rem); }
.cost-row {
  display: grid; gap: 0.5rem 1.25rem; align-items: center;
  padding-block: clamp(1rem, 2vw, 1.4rem);
  border-top: 1px solid var(--hair);
}
@media (min-width: 780px) { .cost-row { grid-template-columns: 12rem minmax(0, 1fr) 5.5rem; } }
.cost-row:last-of-type { border-bottom: 1px solid var(--hair); }

.cost-label { font-size: 0.94rem; color: var(--text-mid); }
.is-lead .cost-label { color: var(--text); font-weight: 500; }

.cost-track { display: flex; gap: 2px; height: 22px; }
.seg {
  position: relative; overflow: hidden;
  width: calc(var(--w) * 1%);
  background: var(--chart-mute);
  transform: scaleX(var(--p, 1)); transform-origin: left;
  transition: transform 0.05s linear;
}
.seg:last-child { border-radius: 0 2px 2px 0; }
.is-lead .seg { background: var(--gold); }
.seg-label {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}
.cost-total {
  font-family: var(--f-mono); font-size: 0.92rem; color: var(--text);
  font-variant-numeric: tabular-nums;
}
@media (min-width: 780px) { .cost-total { text-align: right; } }
.is-lead .cost-total { color: var(--gold-ink); }

.cost-key { display: flex; flex-wrap: wrap; gap: 0.5rem 1.4rem; margin-top: 1.1rem; }
.cost-key span {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.05em; color: var(--text-low);
}
.cost-key i { width: 10px; height: 10px; background: var(--chart-mute); }
.cost-key .lead i { background: var(--gold); }

.cost-delta {
  margin-top: 1.4rem; font-size: clamp(1.02rem, 0.94rem + 0.4vw, 1.22rem);
  color: var(--text);
}
.cost-delta b { color: var(--gold-ink); font-weight: 600; }

/* --- the relationship model --- */
.model { margin-top: clamp(2.4rem, 5vw, 3.6rem); display: grid; gap: 1px; background: var(--hair); border: 1px solid var(--hair); }
@media (min-width: 820px) { .model { grid-template-columns: 1fr 1fr; } }
.model-half { background: var(--cell); padding: clamp(1.4rem, 3vw, 2.2rem); }
.model-half h3 { font-size: clamp(1rem, 0.95rem + 0.3vw, 1.15rem); font-weight: 600; }
.model-half > p { color: var(--text-mid); font-size: 0.9rem; margin-top: 0.6rem; }
.model svg { width: 100%; height: auto; margin-top: 1.4rem; display: block; }
.model .edge {
  stroke: var(--chart-mute); stroke-width: 1.5; fill: none;
  stroke-dasharray: var(--len); stroke-dashoffset: calc(var(--len) - var(--len) * var(--p, 1));
}
.model .edge-lead { stroke: var(--gold); stroke-width: 2; }
/* An unfilled node is a hole in the card it sits on, so it takes the card
   surface, not the page ground. On a reversed band those differ. */
.model .node { fill: var(--cell); stroke: var(--edge); stroke-width: 1.5; }
.model .node-you { fill: var(--text); stroke: none; }
.model .node-lead { fill: var(--gold); stroke: none; }
.model text {
  font-family: var(--f-mono); font-size: 11px; letter-spacing: 0.05em;
  fill: var(--text-low); text-anchor: middle;
}
.model-count {
  margin-top: 1.1rem; font-family: var(--f-mono); font-size: 0.72rem;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-low);
}
.model-count b { color: var(--text); font-weight: 400; }

/* --- the numbers, always reachable --- */
.numbers { margin-top: 1.6rem; }
.numbers > summary {
  font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.11em;
  text-transform: uppercase; color: var(--text-mid); cursor: pointer;
  padding: 0.7rem 0; min-height: 44px; display: flex; align-items: center;
}
.numbers > summary:hover { color: var(--gold-ink); }
.numbers table { border-collapse: collapse; width: 100%; max-width: 44rem; margin-top: 0.5rem; }
.numbers caption { text-align: left; font-size: 0.8rem; color: var(--text-low); padding-bottom: 0.6rem; }
.numbers th, .numbers td {
  text-align: left; padding: 0.55rem 1rem 0.55rem 0;
  border-bottom: 1px solid var(--hair); font-size: 0.85rem;
}
.numbers th { font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-low); font-weight: 400; }
.numbers td { color: var(--text-mid); }
.numbers td:last-child { font-family: var(--f-mono); color: var(--text); font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  .seg, .model .edge { transition: none; }
}

/* ============================================================ route ===== */
.route { margin-top: clamp(2.8rem, 6vw, 4.5rem); position: relative; }

/* One continuous spine over the per-step track, scaled by scroll progress.
   Defaults to 1 so it reads as a finished rule with no script at all. */
.route-spine {
  position: absolute; left: 5px; top: 1.5rem; bottom: 2.4rem; width: 1px;
  background: var(--gold); transform-origin: top;
  transform: scaleY(var(--route-p, 1));
  pointer-events: none;
}

.step {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0 clamp(1.1rem, 2.6vw, 2.2rem);
  padding-bottom: clamp(1.9rem, 3.4vw, 2.9rem);
  position: relative;
}
@media (min-width: 1080px) {
  .step { grid-template-columns: auto minmax(0, 1fr) minmax(10rem, 16rem); align-items: start; }
}
/* the spine: one continuous line the steps hang from */
.step::before {
  content: '';
  position: absolute;
  left: 5px; top: 1.5rem; bottom: -0.4rem;
  width: 1px; background: var(--hair);
}
.step:last-child::before { display: none; }

.step-dot {
  width: 11px; height: 11px; margin-top: 0.45rem;
  border: 1px solid var(--hair-3);
  border-radius: 50%;
  background: var(--ink);
  position: relative; z-index: 1;
  transition: background 0.3s var(--ease), border-color 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.step[data-owner] .step-dot { border-color: var(--accent); }
.step.in .step-dot { background: var(--accent, var(--gold)); box-shadow: 0 0 0 4px rgba(200,165,90,0.09); }

.step-code {
  font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.14em;
  color: var(--text-low);
}
.step-title {
  font-family: var(--f-display); font-weight: 600;
  font-size: clamp(1.02rem, 0.95rem + 0.4vw, 1.22rem);
  letter-spacing: -0.02em;
  margin: 0.35rem 0 0.45rem;
}
.step-owner {
  font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--accent, var(--text-low));
  grid-column: 2; margin-top: 0.55rem;
  display: flex; align-items: baseline; gap: 0.55rem;
}
.step-owner::before {
  content: ''; width: 14px; height: 1px; background: currentColor; opacity: 0.6;
  transform: translateY(-0.28em);
}
@media (min-width: 1080px) {
  /* On wide screens the owner becomes a ledger column with its own rule, so
     the width the ladder does not use is doing work rather than sitting empty. */
  .step-owner {
    grid-column: 3; grid-row: 1; margin-top: 0;
    align-self: stretch; align-items: flex-start;
    justify-content: flex-end; text-align: right;
    border-left: 1px solid var(--hair);
    padding: 0.5rem 0 0 1.5rem;
  }
  .step-owner::before { order: 2; transform: translateY(0.42em); }
}
.step-body { color: var(--text-mid); font-size: 0.92rem; max-width: 62ch; }

/* ========================================================= companies ==== */
/*
 * The register: four equal photo cards, one per company (owner, 2026-09-24:
 * the four text rows took 1,877px and showed no marks and no photography).
 * Equal on purpose, because the lede says none of them outranks another.
 *
 * A card is dark in both themes, because its ground is a photograph, so it
 * carries its own ink instead of the page's. Hover and focus-within do the
 * same thing: the photograph comes up from muted to full colour and leans
 * toward the pointer, the company's hue runs the length of the top edge, a
 * light follows the pointer, and the body rises to show the services. Every
 * change is a transform or an opacity; nothing loops.
 */
.opcos {
  list-style: none; margin: clamp(2.4rem, 5vw, 3.8rem) 0 0; padding: 0;
  display: grid; gap: clamp(0.7rem, 1.3vw, 1.05rem);
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
@media (max-width: 1099.98px) { .opcos { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* A phone gets one swipeable row: each card at 82% of the width, so the next
   one shows at the edge and says there is more. The row bleeds to the screen
   edges and snaps each card to the band's own margin. */
@media (max-width: 639.98px) {
  .opcos {
    --edge-pad: calc(var(--shell-pad) + var(--band-pad));
    grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: 82%;
    overflow-x: auto; overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory; scroll-padding-inline: var(--edge-pad);
    margin-inline: calc(-1 * var(--edge-pad)); padding: 0.25rem var(--edge-pad) 0.5rem;
    scrollbar-width: none;
  }
  .opcos::-webkit-scrollbar { display: none; }
  .opco { scroll-snap-align: start; }
}

.opco { perspective: 1100px; }
.opco[data-reveal] { transition-delay: calc(var(--i, 0) * 80ms); }

.opco-card {
  --card-ink: #F3F0E8;
  --card-mid: #D8D4CA;
  --card-low: #B4AFA3;
  position: relative; isolation: isolate; overflow: hidden;
  aspect-ratio: 3 / 4;
  background: #0D1016;
  color: var(--card-ink);
  outline: 1px solid rgba(255, 255, 255, 0.08); outline-offset: -1px;
  box-shadow: 0 34px 64px -44px rgba(0, 0, 0, 0.85), 0 3px 12px -6px rgba(0, 0, 0, 0.45);
  transform: rotateX(calc(var(--py, 0) * -3.5deg)) rotateY(calc(var(--px, 0) * 4.5deg));
  transition: transform 0.7s var(--ease);
}
@media (max-width: 639.98px) { .opco-card { aspect-ratio: 4 / 5; } }

/* The photograph: muted and darkened at rest, full colour under the hand. The
   grey layer desaturates it through a blend mode, so the change is an opacity. */
.opco-shot { position: absolute; inset: 0; z-index: 0; isolation: isolate; }
.opco-shot picture, .opco-shot img { display: block; width: 100%; height: 100%; }
.opco-shot img {
  object-fit: cover;
  transform: scale(1.08) translate3d(calc(var(--px, 0) * -9px), calc(var(--py, 0) * -9px), 0);
  transition: transform 1.2s var(--ease);
}
.opco-shot::before {
  content: ''; position: absolute; inset: 0; z-index: 1;
  background: #808080; mix-blend-mode: saturation; opacity: 0.62;
  transition: opacity 0.9s var(--ease);
}
.opco-shot::after {
  content: ''; position: absolute; inset: 0; z-index: 2;
  background:
    linear-gradient(to top, rgba(7, 8, 11, 0.96) 0%, rgba(7, 8, 11, 0.78) 30%, rgba(7, 8, 11, 0.18) 62%, rgba(7, 8, 11, 0.42) 100%);
}
/* A second, deeper veil for the risen body, faded in rather than repainted. */
.opco-card::before {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(to top, rgba(7, 8, 11, 0.9) 0%, rgba(7, 8, 11, 0.55) 50%, transparent 78%);
  opacity: 0; transition: opacity 0.6s var(--ease);
}
/* The company's hue along the top edge: a stub at rest, the full width in use. */
.opco-card::after {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 2px; z-index: 4;
  background: var(--accent);
  transform: scaleX(0.16); transform-origin: left;
  transition: transform 0.55s var(--ease);
}
/* The light the pointer carries across the photograph. */
.opco-glow {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: radial-gradient(22rem circle at calc(50% + var(--px, 0) * 50%) calc(50% + var(--py, 0) * 50%),
    color-mix(in srgb, var(--accent) 26%, transparent), transparent 62%);
  mix-blend-mode: screen; opacity: 0;
  transition: opacity 0.6s var(--ease);
}

.opco-top {
  position: absolute; z-index: 3; top: 0; left: 0; right: 0;
  display: flex; align-items: center; gap: 0.7rem;
  padding: clamp(0.9rem, 1.4vw, 1.15rem) clamp(0.9rem, 1.4vw, 1.15rem) 2.2rem;
  /* A scrim for the label: at full colour a bright sky sits right behind it. */
  background: linear-gradient(180deg, rgba(7, 8, 11, 0.62), rgba(7, 8, 11, 0.3) 62%, transparent);
}
.opco-mark {
  width: 46px; height: 46px; flex: none;
  display: grid; place-items: center;
  background: rgba(10, 12, 16, 0.46);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
  backdrop-filter: blur(10px) saturate(140%);
  outline: 1px solid rgba(255, 255, 255, 0.16); outline-offset: -1px;
  transition: outline-color 0.4s var(--ease);
}
.opco-mark img { width: 40px; height: 40px; display: block; }
/* The card is dark in both themes, so it always wears the light artwork. */
.opco-mark .for-light { display: none !important; }
.opco-mark .for-dark { display: block !important; }
.opco-code {
  font-family: var(--f-mono); font-size: 0.68rem; letter-spacing: 0.15em;
  text-transform: uppercase; color: var(--card-mid);
  display: flex; flex-direction: column; gap: 0.15rem; line-height: 1.25;
}
.opco-code span { color: var(--card-ink); }

.opco-body {
  position: absolute; z-index: 3; left: 0; right: 0; bottom: 0;
  padding: clamp(1rem, 1.6vw, 1.3rem) clamp(0.95rem, 1.5vw, 1.25rem) clamp(1.05rem, 1.7vw, 1.35rem);
  transform: translate3d(0, var(--lift, 0px), 0);
  transition: transform 0.7s var(--ease);
}
/* Risen, the body floats on frosted glass: a photograph brought to full
   colour can put a bright sky or a white page right behind the type, and
   the pane keeps it readable whatever the picture does. */
.opco-body::before {
  content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  /* Dense enough to hold 4.5:1 in front of the brightest thing in any of the
     four photographs (the lit end of the Systems aisle); the blur still lets
     the picture's colour through. */
  background: linear-gradient(to top, rgba(7, 8, 11, 0.93), rgba(7, 8, 11, 0.87));
  -webkit-backdrop-filter: blur(16px) saturate(125%);
  backdrop-filter: blur(16px) saturate(125%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
  opacity: 0; transition: opacity 0.5s var(--ease);
}
.opco:hover .opco-body::before,
.opco:focus-within .opco-body::before { opacity: 1; }
.opco-name {
  font-family: var(--f-display); font-weight: 800;
  font-size: clamp(1.3rem, 1.05rem + 0.8vw, 1.72rem); letter-spacing: -0.035em;
  line-height: 1.04; color: var(--card-ink);
}
.opco-line { margin-top: 0.5rem; font-size: 0.86rem; line-height: 1.5; color: var(--card-mid); }
.opco-more { padding-top: 0.95rem; opacity: 0; transition: opacity 0.45s var(--ease); }
.opco-services { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.34rem; }
.opco-services li {
  font-family: var(--f-mono); font-size: 0.68rem; letter-spacing: 0.05em; line-height: 1.4;
  color: var(--card-mid); padding-left: 0.95rem; position: relative;
}
.opco-services li::before {
  content: ''; position: absolute; left: 0; top: 0.62em; width: 5px; height: 1px;
  background: var(--accent-hi, var(--accent));
}
.opco-visit {
  margin-top: 0.95rem; display: inline-flex; align-items: center; gap: 0.45rem;
  font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.08em;
  color: var(--card-ink); text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 70%, transparent);
  padding-bottom: 0.2rem;
}
.opco-visit span { transition: transform 0.3s var(--ease); display: inline-block; }
/* The whole card is a link. The body is positioned, so a stretched link inside
   it could only cover the body; this pointer-only twin of the site link covers
   the card itself. */
.opco-hit { position: absolute; inset: 0; z-index: 5; }
.opco-visit:focus-visible { outline: none; }
.opco-card:has(.opco-visit:focus-visible) { outline: 2px solid var(--gold-hi); outline-offset: 3px; }

.opco:hover .opco-card::after,
.opco:focus-within .opco-card::after { transform: scaleX(1); }
.opco:hover .opco-shot::before,
.opco:focus-within .opco-shot::before { opacity: 0; }
.opco:hover .opco-shot img,
.opco:focus-within .opco-shot img { transform: scale(1.13) translate3d(calc(var(--px, 0) * -14px), calc(var(--py, 0) * -14px), 0); }
.opco:hover .opco-card::before,
.opco:focus-within .opco-card::before { opacity: 1; }
.opco:hover .opco-glow { opacity: 1; }
.opco:hover .opco-body,
.opco:focus-within .opco-body { transform: none; }
.opco:hover .opco-more,
.opco:focus-within .opco-more { opacity: 1; transition-delay: 0.12s; }
.opco:hover .opco-mark,
.opco:focus-within .opco-mark { outline-color: color-mix(in srgb, var(--accent) 80%, transparent); }
.opco:hover .opco-visit span { transform: translate(2px, -2px); }
.opco-card:active { transform: scale(0.992); }

/* No hover, no hidden content: on touch screens the services always show,
   the photograph is at full colour, and nothing tilts. */
@media (hover: none), (pointer: coarse) {
  .opco-body { transform: none; }
  .opco-more { opacity: 1; }
  .opco-shot::before { opacity: 0.2; }
  .opco-card::before { opacity: 1; }
  .opco-card::after { transform: scaleX(1); }
  .opco-card { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .opco-card, .opco-shot img, .opco-body, .opco-more, .opco-card::after,
  .opco-shot::before, .opco-card::before, .opco-glow { transition: none; }
  .opco-card { transform: none; }
  .opco-shot img { transform: scale(1.04); }
}

.co-visit {
  font-family: var(--f-mono); font-size: 0.72rem; letter-spacing: 0.13em;
  text-transform: uppercase; text-decoration: none;
  color: var(--text); white-space: nowrap;
  border: 1px solid var(--edge); padding: 0.72rem 1.1rem; min-height: 44px;
  display: inline-flex; align-items: center; gap: 0.55rem;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease), background 0.2s var(--ease);
}
.co-visit:hover { border-color: var(--accent); color: var(--accent); background: rgba(255,255,255,0.02); }
.co-visit span { transition: transform 0.2s var(--ease); }
.co-visit:hover span { transform: translate(2px, -2px); }

/* ======================================================== engagement ==== */
.engage {
  margin-top: clamp(2.6rem, 6vw, 4.5rem);
  display: grid; gap: 1px; background: var(--hair);
  border: 1px solid var(--hair);
}
@media (min-width: 1000px) { .engage { grid-template-columns: minmax(0, 1.06fr) minmax(0, 0.94fr); } }

.engage-side { background: color-mix(in srgb, var(--panel) 96%, transparent); padding: clamp(1.7rem, 3.4vw, 2.8rem); }
.engage-list { background: color-mix(in srgb, var(--ink-2) 96%, transparent); padding: clamp(1.7rem, 3.4vw, 2.8rem); }

.quote {
  font-family: var(--f-quote);
  font-style: italic; font-weight: 300;
  font-size: clamp(1.32rem, 1.05rem + 1.15vw, 1.85rem);
  line-height: 1.35; letter-spacing: -0.01em;
  color: var(--text);
  margin: 0 0 1.3rem;
}

.dims { list-style: none; margin: 1.4rem 0 0; padding: 0; counter-reset: dim; }
.dims li {
  counter-increment: dim;
  display: grid; grid-template-columns: 2.4rem minmax(0, 1fr); gap: 0.6rem;
  padding: 0.72rem 0;
  border-top: 1px solid var(--hair);
  font-size: 0.9rem; color: var(--text-mid);
}
.dims li::before {
  content: counter(dim, decimal-leading-zero);
  font-family: var(--f-mono); font-size: 0.7rem; color: var(--gold-ink);
  letter-spacing: 0.08em; padding-top: 0.22em;
}

/* ========================================================= inquiries ==== */
.form-wrap {
  margin-top: clamp(2.6rem, 6vw, 4.5rem);
  display: grid; gap: clamp(1.6rem, 4vw, 3.2rem);
}
@media (min-width: 1000px) { .form-wrap { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); } }

.reg { list-style: none; margin: 1.6rem 0 0; padding: 0; }
.reg li {
  display: flex; justify-content: space-between; align-items: center; gap: 1rem;
  border-top: 1px solid var(--hair);
  font-family: var(--f-mono); font-size: 0.72rem; letter-spacing: 0.06em;
}
.reg li span:first-child { padding-block: 0.72rem; }
.reg li a { display: inline-flex; align-items: center; min-height: 30px; }
.reg li span:first-child { color: var(--text-mid); text-transform: uppercase; letter-spacing: 0.12em; }
.reg li a { color: var(--gold-ink); text-decoration: none; }
.reg li a:hover { color: var(--gold-hi); text-decoration: underline; text-underline-offset: 3px; }

form { display: grid; gap: 1px; background: var(--hair); border: 1px solid var(--hair); }
.field { background: var(--ink-2); padding: 1rem clamp(1rem, 2vw, 1.4rem) 1.1rem; }
@media (min-width: 640px) { .pair { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--hair); } }

.field label {
  display: block;
  font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.15em;
  text-transform: uppercase; color: var(--text-low); margin-bottom: 0.55rem;
}
.field input, .field select, .field textarea {
  width: 100%; background: transparent; border: 0; padding: 0;
  color: var(--text); font-family: var(--f-body); font-size: 0.95rem; font-weight: 300;
  line-height: 1.6; min-height: 30px;  /* WCAG 2.5.8 target size */
}
.field select { color: var(--text-mid); }
.field select option { background: var(--panel); color: var(--text); }
.field textarea { resize: vertical; min-height: 5.5rem; }
.field input:focus, .field select:focus, .field textarea:focus { outline: 0; }
.field:focus-within { background: var(--panel); box-shadow: inset 2px 0 0 var(--gold); }
.field ::placeholder { color: var(--text-low); opacity: 1; }

.form-foot {
  background: var(--ink-2); padding: 1.1rem clamp(1rem, 2vw, 1.4rem);
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem;
}
.form-note { font-family: var(--f-mono); font-size: 0.7rem; color: var(--text-low); letter-spacing: 0.05em; }
button.btn { cursor: pointer; font-family: var(--f-mono); }

/* =========================================================== footer ===== */
footer { border-top: 1px solid var(--hair); background: var(--ink-2); }
.foot-in {
  max-width: var(--shell); margin-inline: auto;
  padding: clamp(2.4rem, 5vw, 3.6rem) var(--gutter) clamp(1.6rem, 3vw, 2.2rem);
  display: grid; gap: clamp(1.6rem, 4vw, 3rem);
}
@media (min-width: 820px) { .foot-in { grid-template-columns: minmax(0, 1.1fr) repeat(2, minmax(0, 0.8fr)); } }

.foot-head {
  font-family: var(--f-mono); font-weight: 400; font-size: 0.7rem;
  letter-spacing: 0.17em; text-transform: uppercase; color: var(--text-low);
  margin-bottom: 1rem;
}
.foot-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.55rem; }
.foot-col a {
  font-size: 0.86rem; color: var(--text-mid); text-decoration: none;
  display: inline-block; padding-block: 0.2rem;  /* clears the 24px target minimum */
  transition: color 0.18s var(--ease);
}
.foot-col a:hover { color: var(--gold-hi); }
/* The four company links wear their own colour, with a bar that fills on
   hover so the colour is a label rather than decoration. */
.foot-col a[data-opco] {
  color: var(--opco);
  display: flex; align-items: baseline; gap: 0.6rem;
}
/* Aligned by the flex baseline rather than a hand-tuned offset, so it stays
   put when the link's padding or line-height changes. */
.foot-col a[data-opco]::before {
  content: ''; flex: none;
  width: 5px; height: 5px; background: var(--opco);
  transform: translateY(-0.15em);
  transition: transform 0.22s var(--ease);
}
.foot-col a[data-opco]:hover { color: var(--opco); }
.foot-col a[data-opco]:hover::before { transform: translateY(-0.15em) scale(1.7); }
.foot-brand { font-size: 0.88rem; color: var(--text-mid); max-width: 34ch; margin-top: 0.9rem; }

.foot-bar {
  border-top: 1px solid var(--hair);
  max-width: var(--shell); margin-inline: auto;
  padding: 1.1rem var(--gutter) 1.6rem;
  display: flex; flex-wrap: wrap; gap: 0.6rem 1.4rem; justify-content: space-between;
  font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.09em; color: var(--text-low);
}
.foot-bar a { color: var(--text-low); text-decoration: none; display: inline-block; padding-block: 0.4rem; }
.foot-bar a:hover { color: var(--gold-ink); }


/* ================================================== companies menu ====== */
/*
 * Hover on a fine pointer, click everywhere else. The button is a real
 * <button aria-expanded>, so it works from the keyboard and on touch, and the
 * hover is only an accelerator layered on top.
 */
.nav-group { position: relative; display: none; }
@media (min-width: 900px) { .nav-group { display: block; } }

.nav-group-btn {
  display: inline-flex; align-items: center; gap: 0.45rem;
  font-family: var(--f-mono); font-size: 0.72rem;
  letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--text-mid); background: transparent; border: 0;
  padding: 0.4rem 0; min-height: 44px; cursor: pointer;
  border-bottom: 1px solid transparent;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.nav-group-btn:hover, .nav-group-btn[aria-expanded="true"] { color: var(--text); border-bottom-color: var(--gold); }
.nav-group-btn svg { width: 9px; height: 9px; transition: transform 0.22s var(--ease); }
.nav-group-btn[aria-expanded="true"] svg { transform: rotate(180deg); }

.nav-group-menu {
  position: absolute; top: calc(100% + 0.55rem); left: 50%;
  transform: translateX(-50%) translateY(-6px);
  min-width: 15rem; padding: 0.4rem;
  background: var(--panel-glass);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  border: 1px solid var(--hair-2);
  box-shadow: 0 18px 44px rgba(0,0,0,0.34), 0 2px 8px rgba(0,0,0,0.2);
  opacity: 0; visibility: hidden;
  transition: opacity 0.2s var(--ease), transform 0.2s var(--ease), visibility 0.2s;
  z-index: 60;
}
.nav-group:hover .nav-group-menu,
.nav-group-btn[aria-expanded="true"] + .nav-group-menu,
.nav-group-menu:focus-within {
  opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0);
}
/* A pointer that cannot hover must not get the hover-open, or the menu
   latches open after a tap. */
@media (hover: none) {
  .nav-group:hover .nav-group-menu { opacity: 0; visibility: hidden; }
  .nav-group-btn[aria-expanded="true"] + .nav-group-menu { opacity: 1; visibility: visible; }
}

.nav-group-menu a {
  display: flex; align-items: center; gap: 0.6rem;
  padding: 0.62rem 0.7rem; min-height: 44px;
  text-decoration: none; border-left: 2px solid var(--opco, var(--gold));
  transition: background 0.16s var(--ease);
}
.nav-group-menu a:hover { background: var(--gold-dim); }
.nav-group-menu a b {
  font-family: var(--f-display); font-weight: 600; font-size: 0.82rem;
  letter-spacing: -0.01em; color: var(--opco, var(--text));
}
.nav-group-menu a i {
  font-style: normal; font-family: var(--f-mono);
  font-size: 0.685rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-low); margin-left: auto;
}

/* ============================================== gold glass bands ======= */
/*
 * The gold bands (owner, 2026-09-24: "just gold opaque colour ... make these
 * translucent so they look premium and not cheap"). A band is no longer a flat
 * gold fill. It is gold GLASS, built in four layers:
 *
 *   .band-light   a warm light moving behind the pane: a ThreeUI scene adapted
 *                 in scenes.js (CodexBand), over a CSS composition that is the
 *                 finished band before, and without, any script or WebGL
 *   ::before      the pane itself: a translucent gold tint and a fine grain
 *   ::after       the two lips of the pane catching the light, brightest where
 *                 the light is, along the top and bottom edges
 *   tiles         the content floats on frosted glass with a gilded edge
 *
 * Dark theme: smoked gold glass with gold-white type. Light theme: pale gold
 * glass with bronze-black type. Every token is still redefined inside the band
 * rather than per element, so anything dropped into a band is correct by
 * default. The light is capped in the shader so the quietest type here keeps
 * 4.5:1 over the brightest pixel the scene can draw behind content; only the
 * lips, where there is no type, may run brighter.
 */
.band-reverse {
  --glass:        rgba(10, 8, 4, 0.34);
  --glass-2:      rgba(26, 20, 10, 0.46);
  --glass-edge-a: rgba(247, 224, 164, 0.62);
  --glass-edge-b: rgba(247, 224, 164, 0.09);
  --glass-sheen:  inset 0 1px 0 rgba(255, 240, 205, 0.10);
  --glass-shade:  0 34px 70px -44px rgba(0, 0, 0, 0.9), 0 2px 12px -6px rgba(0, 0, 0, 0.55);
  --glass-spot:   rgba(247, 224, 164, 0.10);
  --lip:          rgba(247, 224, 164, 0.85);
  --lip-glow:     rgba(247, 224, 164, 0.20);

  --ink: #110E09;
  --ink-2: #110E09;
  --panel: var(--glass-2);
  --panel-2: var(--glass-2);
  --cell: var(--glass);
  /* An SVG node is a hole in the tile it sits on; a translucent fill would show
     the line behind it, so holes take this opaque stand-in for the tile. */
  --cell-solid: #17130C;
  --text: #F7F2E6;
  --text-mid: #E2D8C1;
  --text-low: #D3C7AB;
  --gold: #E0BD72;
  --gold-ink: #EFD08A;
  --gold-hi: #F7E0A4;
  --gold-dim: rgba(239, 208, 138, 0.12);
  --on-gold: #110E09;
  --hair: rgba(239, 208, 138, 0.15);
  --hair-2: rgba(239, 208, 138, 0.24);
  --hair-3: rgba(239, 208, 138, 0.34);
  --edge: rgba(239, 208, 138, 0.55);
  --chart-mute: #6B5A36;
  --chart-grid: rgba(239, 208, 138, 0.14);
  --numeral: linear-gradient(180deg, #FFF3D2 0%, #EFD08A 46%, #BD9443 100%);

  position: relative;
  isolation: isolate;
  background: var(--ink);
  color: var(--text);
  border-top: 0;
}
:root[data-theme="light"] .band-reverse {
  --glass:        rgba(255, 252, 243, 0.40);
  --glass-2:      rgba(255, 252, 243, 0.56);
  --glass-edge-a: rgba(255, 255, 255, 0.95);
  --glass-edge-b: rgba(110, 86, 34, 0.16);
  --glass-sheen:  inset 0 1px 0 rgba(255, 255, 255, 0.7);
  --glass-shade:  0 24px 50px -38px rgba(92, 70, 24, 0.3), 0 2px 8px -6px rgba(92, 70, 24, 0.18);
  --glass-spot:   rgba(255, 255, 255, 0.34);
  --lip:          rgba(255, 251, 238, 0.95);
  --lip-glow:     rgba(255, 246, 222, 0.55);

  --ink: #E4D3A6;
  --ink-2: #E4D3A6;
  --cell-solid: #EFE3C3;
  --text: #17130B;
  --text-mid: #3A3122;
  --text-low: #433820;
  --gold: #8A6A26;
  --gold-ink: #4E3C12;
  --gold-hi: #45360F;
  --gold-dim: rgba(90, 71, 25, 0.10);
  --on-gold: #F7EEDA;
  --hair: rgba(74, 58, 22, 0.16);
  --hair-2: rgba(74, 58, 22, 0.24);
  --hair-3: rgba(74, 58, 22, 0.34);
  --edge: rgba(74, 58, 22, 0.55);
  --chart-mute: #B09760;
  --chart-grid: rgba(74, 58, 22, 0.14);
  --numeral: linear-gradient(180deg, #7A5F27 0%, #54421A 55%, #33270C 100%);
}

/* Layer one: the light, and the composition it sits on. With no script, no
   WebGL or reduced motion this is the band, so it is finished on its own:
   light rising from the lower lip, a softer light falling from the upper. */
.band-reverse > .band-light {
  position: absolute; inset: 0; z-index: 0; pointer-events: none; overflow: hidden;
  background:
    radial-gradient(95% 42% at 50% 104%, rgba(224, 189, 114, 0.34), transparent 72%),
    radial-gradient(60% 30% at 20% -6%, rgba(224, 189, 114, 0.18), transparent 70%),
    linear-gradient(180deg, #17130B, #110E09 38%, #110E09 70%, #1B160D);
}
:root[data-theme="light"] .band-reverse > .band-light {
  background:
    radial-gradient(95% 42% at 50% 104%, rgba(138, 106, 38, 0.30), transparent 72%),
    radial-gradient(60% 30% at 20% -6%, rgba(138, 106, 38, 0.16), transparent 70%),
    linear-gradient(180deg, #DDC996, #E4D3A6 38%, #E4D3A6 70%, #D8C38D);
}
.band-light canvas {
  position: absolute; inset: 0; width: 100%; height: 100%; display: block;
  opacity: 0; transition: opacity 1.1s var(--ease);
}
.band-light canvas.is-lit { opacity: 1; }

/* Layer two: the pane. A thin gold tint at each edge and a grain, so the glass
   reads as a material rather than a colour. The grain is one static SVG tile. */
.band-reverse::before {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    linear-gradient(180deg, rgba(255, 236, 190, 0.035), transparent 11%, transparent 90%, rgba(255, 236, 190, 0.03)),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 0.92 0 0 0 0 0.78 0 0 0 0.05 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
}

/* Layer three: the lips of the pane, bright at the centre where the light
   meets them and fading to nothing at the sides. */
.band-reverse::after {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    linear-gradient(90deg, transparent, var(--lip) 50%, transparent) top / 100% 1px no-repeat,
    radial-gradient(42% 100% at 50% 0%, var(--lip-glow), transparent) top / 100% 22px no-repeat,
    linear-gradient(90deg, transparent, var(--lip) 50%, transparent) bottom / 100% 1px no-repeat,
    radial-gradient(42% 100% at 50% 100%, var(--lip-glow), transparent) bottom / 100% 22px no-repeat;
}

.band-reverse > :not(.band-light):not(.index) { position: relative; z-index: 2; }
.band-reverse > .index { z-index: 2; color: var(--gold-ink); }
@media (max-width: 1079.98px) { .band-reverse > .index { position: relative; } }

/* Layer four: the tiles. Frosted glass with a gilded edge (a masked gradient,
   because a border cannot fade), a sheen along the top, a shadow that sits
   them above the pane, and a light that follows the pointer across them. The
   hairline grids become separated tiles: a 1px gap of hair behind translucent
   cells would tint every cell, which is why the cells used to be opaque. */
.band-reverse .figures,
.band-reverse .model,
.band-reverse .rail,
.band-reverse .engage {
  background: transparent; border: 0;
  gap: clamp(0.6rem, 1.1vw, 0.95rem);
}
.band-reverse .figure,
.band-reverse .model-half,
.band-reverse .rail-cell,
.band-reverse .cost,
.band-reverse .tiers,
.band-reverse .engage-side,
.band-reverse .engage-list {
  position: relative;
  background:
    radial-gradient(18rem circle at var(--mx, 50%) var(--my, -30%), var(--glass-spot), transparent 64%),
    linear-gradient(180deg, var(--glass-2), var(--glass));
  box-shadow: var(--glass-sheen), var(--glass-shade);
  -webkit-backdrop-filter: blur(18px) saturate(135%);
  backdrop-filter: blur(18px) saturate(135%);
  transition: transform 0.45s var(--ease);
}
.band-reverse .figure::after,
.band-reverse .model-half::after,
.band-reverse .rail-cell::after,
.band-reverse .cost::after,
.band-reverse .tiers::after,
.band-reverse .engage-side::after,
.band-reverse .engage-list::after {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  padding: 1px;
  background: linear-gradient(152deg, var(--glass-edge-a), var(--glass-edge-b) 32%, var(--glass-edge-b) 68%, color-mix(in srgb, var(--glass-edge-a) 50%, transparent));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  opacity: 0.75; transition: opacity 0.45s var(--ease);
}
.band-reverse .figure:hover,
.band-reverse .model-half:hover,
.band-reverse .rail-cell:hover { transform: translateY(-3px); }
.band-reverse .figure:hover::after,
.band-reverse .model-half:hover::after,
.band-reverse .rail-cell:hover::after,
.band-reverse .cost:hover::after,
.band-reverse .tiers:hover::after,
.band-reverse .engage-side:hover::after,
.band-reverse .engage-list:hover::after { opacity: 1; }
.band-reverse .cost { margin-inline: 0; padding: clamp(1.3rem, 3vw, 2.3rem); }
.band-reverse .tiers { border-top: 0; padding: 0 clamp(1.1rem, 2.6vw, 2.1rem); }
.band-reverse .tier:last-child { border-bottom: 0; }
.band-reverse .model .node:not(.node-you):not(.node-lead) { fill: var(--cell-solid); }
.band-reverse .rail-code { color: var(--text-mid); }
.band-reverse .figure-n,
.band-reverse .tier-price b {
  background: var(--numeral);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}
/* A browser without backdrop-filter gets a denser tile instead of a clear one. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .band-reverse { --glass: rgba(18, 14, 8, 0.82); --glass-2: rgba(28, 22, 12, 0.86); }
  :root[data-theme="light"] .band-reverse { --glass: rgba(246, 238, 216, 0.9); --glass-2: rgba(250, 244, 228, 0.92); }
}
@media (prefers-reduced-motion: reduce) {
  .band-reverse .figure, .band-reverse .model-half, .band-reverse .rail-cell,
  .band-reverse .cost, .band-reverse .tiers, .band-reverse .engage-side,
  .band-reverse .engage-list { transition: none; transform: none !important; }
  .band-light canvas { transition: none; }
}

/* Buttons keep their meaning on the glass: gold fill, dark label. */
.band-reverse .btn-solid { background: var(--gold-ink); color: var(--on-gold); border-color: var(--gold-ink); }
.band-reverse .btn-solid:hover { background: transparent; color: var(--gold-ink); }
.band-reverse .btn-ghost { color: var(--text); border-color: var(--edge); }
.band-reverse .btn-ghost:hover { border-color: var(--gold-ink); color: var(--gold-ink); }



/* ============================================================ icons ===== */
/*
 * One line-icon family, 20x20 at stroke 1.5, sized to sit on the same optical
 * weight as the mono label beside it. Icons never appear alone: every one has
 * text next to it, so none of them has to be understood on its own.
 */
.ico, .rule-ico { flex: none; vertical-align: -0.18em; }
.rule-ico { width: 26px; height: 26px; }

/*
 * The four companies' own marks (2026-09-24), wherever a company is named
 * with a mark beside it: the Companies menu, the about page's pillars and
 * the pricing floors. Both artworks ship, and the theme picks the one drawn
 * for its ground, the way the four OpCo sites do. Each file carries its own
 * padding, so the image is drawn a little larger than its box.
 */
.for-light { display: none; }
:root[data-theme="light"] .for-dark { display: none; }
:root[data-theme="light"] .for-light { display: block; }
.menu-mark, .rail-mark, .floor-mark {
  flex: none; display: inline-grid; place-items: center; overflow: visible;
}
.menu-mark { width: 20px; height: 20px; }
.menu-mark img { width: 26px; height: 26px; }
.rail-mark { width: 24px; height: 24px; }
.rail-mark img { width: 30px; height: 30px; }
.floor-mark { width: 22px; height: 22px; margin-right: 0.55rem; }
.floor-mark img { width: 28px; height: 28px; }

/* ====================================================== nav additions === */
.nav-panel-head {
  font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.17em;
  text-transform: uppercase; color: var(--text-low);
  padding: 1.1rem 0 0.35rem;
}
.hero-note { margin-top: clamp(1.6rem, 4vw, 2.4rem); }

/* ====================================================== rule cards ====== */
.rules {
  margin-top: clamp(2.4rem, 5vw, 3.6rem);
  display: grid; gap: 1px; background: var(--hair);
  border-block: 1px solid var(--hair);
}
@media (min-width: 900px) { .rules { grid-template-columns: repeat(3, 1fr); } }
.rule-card { background: var(--cell); padding: clamp(1.4rem, 3vw, 2.1rem); }
.rule-n { color: var(--gold-ink); margin-bottom: 1.1rem; }
.rule-card h3 { margin-bottom: 0.6rem; }
.rule-card p { color: var(--text-mid); font-size: 0.92rem; }

/* =========================================================== tiers ====== */
.tiers { margin-top: clamp(2.4rem, 5vw, 3.6rem); border-top: 1px solid var(--hair); }
.tier {
  display: grid; gap: 0.5rem 1.5rem; align-items: baseline;
  padding-block: clamp(1.3rem, 2.6vw, 1.9rem);
  border-bottom: 1px solid var(--hair);
}
@media (min-width: 900px) { .tier { grid-template-columns: minmax(0, 15rem) minmax(0, 1fr) minmax(0, 10rem); } }
.tier-name { font-size: clamp(1.05rem, 1rem + 0.4vw, 1.24rem); font-weight: 600; letter-spacing: -0.02em; }
.tier-note { font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.07em; color: var(--text-low); margin-top: 0.4rem; }
.tier-draws { color: var(--text-mid); font-size: 0.92rem; }
.tier-price { display: flex; flex-direction: column; gap: 0.25rem; }
@media (min-width: 900px) { .tier-price { text-align: right; } }
.tier-price i {
  font-style: normal; font-family: var(--f-mono); font-size: 0.685rem;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-low);
}
.tier-price b {
  font-family: var(--f-display); font-weight: 800;
  font-size: clamp(1.3rem, 1.1rem + 0.9vw, 1.75rem);
  letter-spacing: -0.035em; color: var(--gold-ink);
  font-variant-numeric: tabular-nums;
}

/* ========================================================== floors ====== */
.floors { margin-top: clamp(2.4rem, 5vw, 3.6rem); display: grid; gap: 1px; background: var(--hair); border: 1px solid var(--hair); }
@media (min-width: 760px) { .floors { grid-template-columns: repeat(2, 1fr); } }
/* The unit and price cells do not wrap, so four columns need real room. At
   1280 they were forcing the grid past the shell. */
@media (min-width: 1400px) { .floors { grid-template-columns: repeat(4, 1fr); } }
.floor {
  background: var(--cell); padding: clamp(1.3rem, 2.4vw, 1.7rem);
  display: flex; flex-direction: column; gap: 1rem;
  border-top: 2px solid var(--accent);
}
.floor-code {
  display: flex; align-items: center;
  font-family: var(--f-mono); font-size: 0.72rem; letter-spacing: 0.09em;
  color: var(--accent);
}
.floor-table { border-collapse: collapse; width: 100%; }
.floor-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.floor-table td {
  padding: 0.5rem 0; border-bottom: 1px solid var(--hair);
  font-size: 0.83rem; color: var(--text-mid); vertical-align: baseline;
}
.floor-table td:nth-child(2) {
  font-family: var(--f-mono); font-size: 0.685rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-low); padding-inline: 0.6rem;
  white-space: nowrap;
}
.floor-table td:last-child {
  font-family: var(--f-mono); font-size: 0.76rem; color: var(--text);
  text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums;
}
.floor .co-visit { margin-top: auto; align-self: flex-start; }

/* ========================================================= projects ===== */
/*
 * Ported 1:1 from anuragbains.com V3 assets/css/site.css ("04 projects:
 * fanned stacks", "the modal", "projects: the bar, and the shelf view"). The
 * rules are copied unchanged and read that site's token names, which are
 * aliased to this site's tokens in both theme blocks at the top, so the port
 * stays a straight copy and every colour is still the HoldCo's. The one edit
 * inside the copied rules: the shelf frame's paper is a token, not a hex.
 * The HoldCo additions follow the copy, marked as such.
 */
/* --- 04 projects: fanned stacks ------------------------------------------ */
.pfilter { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: clamp(1.8rem, 4vw, 2.6rem); }
.pfilter button {
  font-family: var(--f-mono); font-size: 0.70rem; letter-spacing: 0.05em; text-transform: uppercase;
  background: transparent; color: var(--text-mid); border: 1px solid var(--hair-2);
  padding: 0.5rem 0.9rem; min-height: 38px; cursor: pointer;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease), background 0.2s var(--ease);
}
.pfilter button:hover { color: var(--text); border-color: var(--edge); }
.pfilter button[aria-pressed="true"] { color: var(--on-signal); background: var(--signal); border-color: var(--signal); }

.pgrid { display: grid; gap: clamp(1.2rem, 2.6vw, 1.9rem); }
@media (min-width: 720px)  { .pgrid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .pgrid { grid-template-columns: repeat(3, 1fr); } }

.pcard {
  --co: var(--signal);
  --co-ink: var(--signal-ink);
  display: flex; flex-direction: column; text-align: left; cursor: pointer;
  background: var(--card); border: 1px solid var(--hair); border-top: 2px solid var(--co);
  padding: 0; overflow: hidden; font: inherit; color: inherit;
  transition: background 0.3s var(--ease), transform 0.35s var(--ease);
}
.pcard:hover { background: var(--raised); transform: translateY(-3px); }
.pcard[hidden] { display: none; }

/* the fan. hero shot in front, two behind, splayed */
.fan {
  /* A fixed height, so a portrait phone fan and a landscape site fan leave the
     title and meta on the same line across the whole grid. Without it the row
     with Dream Codex in it sits noticeably lower than its neighbours. */
  height: clamp(14rem, 26vw, 18.5rem);
  /*
   * The row must be DEFINITE, not auto. `.fan` has a fixed height, but its
   * single implicit row was auto-sized, and an auto row is indefinite - so a
   * percentage height or max-height on the images resolved to nothing and the
   * portrait phone laid out at its full intrinsic height, two thirds of it
   * outside the box. minmax(0, 1fr) hands the row the container's real height.
   */
  display: grid; grid-template-rows: minmax(0, 1fr);
  place-items: center; position: relative; overflow: hidden;
  padding: clamp(1.2rem, 2.6vw, 1.8rem) 1rem 0;
  background: radial-gradient(120% 90% at 50% 0%, color-mix(in srgb, var(--co) 14%, transparent), transparent 70%);
}
.fan img {
  grid-area: 1 / 1; display: block;
  /*
   * max-height is what actually keeps a shot inside the fan. Every image now
   * carries width/height attributes for layout stability, and with those
   * present a percentage height on the portrait rule stopped resolving against
   * the fan and fell back to the attribute-implied size: the Dream phone laid
   * out 620px tall inside a 256px box, so `overflow: hidden` cropped away
   * two thirds of it.
   */
  max-width: 100%; max-height: 100%;
  object-fit: contain; object-position: center;
  border: 1px solid var(--shot-frame); transform-origin: 50% 92%;
  transition: transform 0.42s var(--ease);
}
.fan--wide img { width: min(78%, 20rem); height: auto; aspect-ratio: 1440 / 900; }
/*
 * Portrait: fit the height, let the width follow, never exceed the box. A phone
 * shown whole is narrow, so the tall fan gives back the top padding a landscape
 * shot needs - the fan height stays uniform across the grid either way, which
 * is what keeps every card's title on the same line.
 */
.fan--tall { padding-top: 0.5rem; }
.fan--tall img { width: auto; height: 100%; aspect-ratio: 629 / 1400; }
/* Painted back to front in the markup, so the hero shot is last and sits on
   top without a z-index war. */
.fan .fan-2 { transform: translateX(-16%) rotate(-7deg); filter: saturate(0.85) brightness(0.82); }
.fan .fan-1 { transform: translateX(16%)  rotate(7deg);  filter: saturate(0.85) brightness(0.82); }
.fan .fan-0 { transform: translateY(-2%); }
.pcard:hover .fan .fan-2 { transform: translateX(-23%) rotate(-11deg); }
.pcard:hover .fan .fan-1 { transform: translateX(23%)  rotate(11deg); }
.pcard:hover .fan .fan-0 { transform: translateY(-6%); }
@media (prefers-reduced-motion: reduce) {
  .fan img { transition: none; }
  .pcard:hover .fan img, .pcard:hover { transform: none; }
}

.pcard-meta { display: flex; justify-content: space-between; gap: 1rem; padding: clamp(1.2rem, 2.6vw, 1.6rem) clamp(1.2rem, 2.6vw, 1.6rem) 0; font-family: var(--f-mono); font-size: 0.70rem; letter-spacing: 0.07em; text-transform: uppercase; }
.pcard-kind { color: var(--co-ink); }
.pcard-year { color: var(--text-low); }
.pcard-body { padding: 0.8rem clamp(1.2rem, 2.6vw, 1.6rem) 0; }
.pcard-name { display: block; font-family: var(--f-display); font-weight: 700; font-size: clamp(1.2rem, 1.1rem + 0.4vw, 1.45rem); letter-spacing: -0.025em; }
.pcard-blurb { display: block; margin-top: 0.55rem; color: var(--text-mid); font-size: 0.92rem; line-height: 1.5; }
.pcard-more {
  margin-top: auto; padding: 1.2rem clamp(1.2rem, 2.6vw, 1.6rem) clamp(1.2rem, 2.6vw, 1.5rem);
  font-family: var(--f-mono); font-size: 0.70rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-low); display: flex; align-items: center; gap: 0.45rem; transition: color 0.2s var(--ease);
}
.pcard-more::after { content: '\2192'; transition: transform 0.25s var(--ease); }
.pcard:hover .pcard-more { color: var(--co-ink); }
.pcard:hover .pcard-more::after { transform: translateX(4px); }

/* --- the modal ---------------------------------------------------------- */
.modal { position: fixed; inset: 0; z-index: 200; display: grid; place-items: center; padding: clamp(0.75rem, 3vw, 2rem); }
.modal[hidden] { display: none; }
.modal-scrim { position: absolute; inset: 0; background: color-mix(in srgb, var(--ground) 86%, transparent); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); border: 0; padding: 0; cursor: pointer; }
.modal-box {
  --co: var(--signal);
  --co-ink: var(--signal-ink);
  position: relative; width: min(1040px, 100%); max-height: min(92svh, 900px);
  background: var(--ground); border: 1px solid var(--hair-2); border-top: 2px solid var(--co);
  overflow: auto; display: grid;
}
@media (min-width: 900px) { .modal-box { grid-template-columns: 1.25fr 1fr; } }
.modal-close {
  position: absolute; right: 0.6rem; top: 0.6rem; z-index: 3;
  width: 40px; height: 40px; display: grid; place-items: center; cursor: pointer;
  background: color-mix(in srgb, var(--ground) 80%, transparent); color: var(--text); border: 1px solid var(--hair-2);
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease);
}
.modal-close:hover { background: var(--signal); color: var(--on-signal); border-color: var(--signal); }
.modal-close svg { width: 16px; height: 16px; }

.gal { position: relative; background: var(--raised); display: flex; flex-direction: column; }
/* On a phone the gallery is stacked above the copy, so it needs a ratio of its
   own. Side by side it should instead fill whatever height the copy column
   ends up being, or the picture floats in a pool of empty ground. */
.gal-stage { position: relative; aspect-ratio: 16 / 10; overflow: hidden; }
.modal-box[data-tall="true"] .gal-stage { aspect-ratio: 629 / 1400; }
@media (min-width: 900px) {
  .gal-stage, .modal-box[data-tall="true"] .gal-stage { aspect-ratio: auto; flex: 1; min-height: 22rem; }
}
.slide { position: absolute; inset: 0; margin: 0; opacity: 0; transition: opacity 0.65s var(--ease); }
.slide.is-on { opacity: 1; }
.slide img { width: 100%; height: 100%; object-fit: contain; object-position: center; background: var(--ground); }

.gal-bar { flex: none; display: flex; align-items: center; gap: 0.7rem; padding: 0.7rem 0.9rem; border-top: 1px solid var(--hair); }
.gdots { display: flex; gap: 0.3rem; flex: 1; }
.gdot { width: 26px; height: 24px; padding: 0; background: transparent; border: 0; cursor: pointer; position: relative; }
.gdot::after { content: ''; position: absolute; left: 0; right: 0; top: 50%; height: 2px; background: var(--hair-2); transition: background 0.25s var(--ease); }
.gdot.is-on::after { background: var(--signal); }
.gcount { font-family: var(--f-mono); font-size: 0.70rem; color: var(--text-low); letter-spacing: 0.06em; }
.gnav { display: flex; gap: 0.3rem; }
.gnav button { width: 36px; height: 36px; display: grid; place-items: center; cursor: pointer; background: transparent; border: 1px solid var(--hair-2); color: var(--text-mid); transition: color 0.2s var(--ease), border-color 0.2s var(--ease); }
.gnav button:hover { color: var(--text); border-color: var(--edge); }
.gnav svg { width: 14px; height: 14px; }

.modal-copy { padding: clamp(1.4rem, 3.4vw, 2.4rem); display: flex; flex-direction: column; gap: 1rem; }
.modal-kind { font-family: var(--f-mono); font-size: 0.70rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--co-ink); }
.modal-copy h3 { font-size: clamp(1.6rem, 1.3rem + 1.2vw, 2.3rem); }
.modal-copy p { color: var(--text-mid); font-size: 0.98rem; }
.modal-status { font-family: var(--f-mono); font-size: 0.70rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-low); border: 1px solid var(--hair-2); padding: 0.35rem 0.6rem; align-self: flex-start; }
.modal-facts { display: grid; gap: 0.7rem; margin-top: auto; padding-top: 1rem; border-top: 1px solid var(--hair); }
.modal-fact { display: flex; justify-content: space-between; gap: 1rem; font-size: 0.88rem; }
.modal-fact dt { font-family: var(--f-mono); font-size: 0.70rem; letter-spacing: 0.07em; text-transform: uppercase; color: var(--text-low); margin: 0; }
.modal-fact dd { margin: 0; text-align: right; }
.modal-stack { display: flex; flex-wrap: wrap; gap: 0.35rem; justify-content: flex-end; }
.modal-stack span { font-family: var(--f-mono); font-size: 0.70rem; color: var(--text-mid); border: 1px solid var(--hair-2); padding: 0.24rem 0.5rem; }

/* --- projects: the bar, and the shelf view ------------------------------ */
.pbar { display: flex; flex-wrap: wrap; gap: 1rem; align-items: center; justify-content: space-between; margin-bottom: clamp(1.8rem, 4vw, 2.6rem); }
.pview { display: flex; gap: 0.4rem; flex: none; }
.pview button {
  font-family: var(--f-mono); font-size: 0.70rem; letter-spacing: 0.05em; text-transform: uppercase;
  background: transparent; color: var(--text-mid); border: 1px solid var(--hair-2);
  padding: 0.5rem 0.9rem; min-height: 38px; cursor: pointer;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease), background 0.2s var(--ease);
}
.pview button:hover { color: var(--text); border-color: var(--edge); }
.pview button[aria-pressed="true"] { color: var(--on-signal); background: var(--signal); border-color: var(--signal); }

/*
 * The shelf. This is ThreeUI's Complete Shelf, a real Three.js scene with lit
 * board geometry and rendered covers, so it lives in its own document under
 * assets/shelf/ and mounts here in an iframe rather than being inlined: it
 * carries its own r165 runtime and its own canvas sizing, and keeping it
 * sandboxed means a WebGL context loss in the shelf cannot take the hero's
 * raymarcher down with it.
 *
 * The frame needs a DEFINITE height. The scene sizes its drawing buffer from
 * its own viewport, and an auto-height iframe collapses to the 150px default,
 * which is what a canvas with nothing to measure against reports.
 */
.shelf { padding-top: clamp(1rem, 3vw, 2rem); }
.shelf[hidden] { display: none; }
.shelf-frame {
  display: block; width: 100%; border: 1px solid var(--hair-2); border-radius: 4px;
  /*
   * Tall enough to open a book in. The reader panel stacks a title, a deck,
   * four metadata fields, the page-flip row and two buttons: 590px for the
   * longest volume. At the old 46rem ceiling the flip controls fell off the
   * bottom of the frame and the visitor had to scroll the host page to turn a
   * page, which is the one thing the reader is for.
   */
  height: clamp(34rem, 86vh, 54rem);
  background: var(--shelf-paper);   /* the shelf's own paper, so the frame never flashes light */
  color-scheme: dark;
}
.shelf-note {
  font-family: var(--f-mono); font-size: 0.70rem; letter-spacing: 0.05em;
  color: var(--text-low); margin-top: 0.8rem; text-transform: uppercase;
}
@media (max-width: 700px) { .shelf-frame { height: clamp(30rem, 78vh, 40rem); } }

/* an art-only project card: the diagram fills the frame instead of a fan */
.fan--art { padding: 0; }
.fan--art .fan-art { width: 100%; height: 100%; object-fit: cover; object-position: center; border: 0; }

/* --- projects: HoldCo additions ------------------------------------------ */
/* The gallery's cross-fade is motion nobody asked for. In anuragbains this
   sits inside its reveal block's reduced-motion rule. */
@media (prefers-reduced-motion: reduce) { .slide { transition: none; } }
/* The HoldCo band head has no bottom margin of its own, so the bar takes the
   gap every other band's content takes below its head. */
.pbar { margin-top: clamp(2.4rem, 5vw, 3.6rem); }
/* A press answers like .btn does here. The copied rules give each control
   its hover and the sheet's :focus-visible ring; this adds the active state. */
.pfilter button:active, .pview button:active, .gnav button:active,
.modal-close:active { transform: translateY(1px); }
.pcard:active { transform: translateY(-1px); }
/* State markers need 3:1 (WCAG 1.4.11). The idle gallery dots take the
   control edge (3.2:1 on --raised in both themes, up from 1.4), and in the
   light theme the fill-only gold (2.3:1 as a marker) gives way to the text
   gold: the current dot 4.83:1, and a pressed chip's border 5.66:1 on the
   page. In the dark theme the two golds are the same value. */
.gdot::after { background: var(--edge); }
.gdot.is-on::after { background: var(--signal-ink); }
:root[data-theme="light"] .pfilter button[aria-pressed="true"],
:root[data-theme="light"] .pview button[aria-pressed="true"] { border-color: var(--signal-ink); }
/* Side by side, a long body scrolls inside its own column instead of pushing
   the gallery's pause and arrows out of the box (Dream Codex at 1280x800:
   Lexend at this line height runs 28px past the cap). 3px is the box's top
   and bottom border. projects.js resets this scroll on every open. */
@media (min-width: 900px) {
  .modal-copy { max-height: calc(min(92svh, 900px) - 3px); overflow-y: auto; overscroll-behavior: contain; }
}


/* ============================================================ drift ===== */
/*
 * The brand-drift model. Both tracks draw themselves in on the section's --p
 * scrub, and both are correct and complete at --p: 1 with no script at all.
 */
.drift { margin-top: clamp(2.4rem, 5vw, 3.6rem); }
.drift svg { width: 100%; height: auto; display: block; overflow: visible; }

.dr-line {
  fill: none; stroke: var(--chart-mute); stroke-width: 2.4;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 700; stroke-dashoffset: calc(700 - 700 * var(--p, 1));
}
.dr-line--lead { stroke: var(--gold); }
/* a wide, faint copy of the lead line so it glows without a filter */
.dr-line--lead + .dr-node { filter: none; }

.dr-ref {
  stroke: var(--hair-2); stroke-width: 1; stroke-dasharray: 3 5;
}
.dr-wedge {
  fill: var(--chart-mute); opacity: calc(0.2 * var(--p, 1));
}
.dr-node {
  fill: var(--ink); stroke: var(--chart-mute); stroke-width: 2;
  opacity: var(--p, 1);
}
.dr-node--lead { stroke: var(--gold); }

.dr-lane {
  font-family: var(--f-mono); font-size: 12px; letter-spacing: 0.09em;
  text-transform: uppercase; fill: var(--text-low);
}
.dr-end {
  font-family: var(--f-mono); font-size: 12px; letter-spacing: 0.08em;
  fill: var(--chart-mute); text-anchor: end;
}
.dr-end--lead { fill: var(--gold-ink); }
.dr-axis {
  font-family: var(--f-mono); font-size: 11px; letter-spacing: 0.1em;
  text-transform: uppercase; fill: var(--text-low);
}
.dr-axis--end { text-anchor: end; }

/* ====================================================== touchpoints ===== */
.touchpoints {
  margin-top: clamp(2.4rem, 5vw, 3.6rem);
  display: grid; gap: clamp(1.4rem, 3vw, 2.4rem);
}
@media (min-width: 960px) { .touchpoints { grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); align-items: start; } }
.tp-head p { color: var(--text-mid); font-size: 0.92rem; margin-top: 0.7rem; }

.tp-rows { border-top: 1px solid var(--hair); }
.tp-row {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem 1rem;
  justify-content: space-between;
  padding: 0.95rem 0 0.95rem 1rem;
  border-bottom: 1px solid var(--hair);
  border-left: 2px solid var(--accent);
  /* each row arrives as the section scrubs, so the list assembles */
  opacity: calc(0.25 + 0.75 * var(--p, 1));
  transform: translateX(calc((1 - var(--p, 1)) * -8px));
}
.tp-what { font-size: 0.94rem; }
.tp-who {
  font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--accent);
}

/*
 * The preview (2026-09-24): a photograph of the surface the pointer is on.
 * All six are stacked in one frame and cross-fade, the arriving one settling
 * from a slight zoom. The first shows on arrival; a tap does what hover does.
 * The rows are the content, the photographs are illustration, so the frame is
 * hidden from assistive technology and the rows stay plain text.
 */
.tp-view {
  position: relative; overflow: hidden; isolation: isolate;
  margin: clamp(1.3rem, 2.6vw, 2rem) 0 0;
  aspect-ratio: 3 / 2;
  background: #0D1016;
  box-shadow: 0 30px 60px -42px rgba(0, 0, 0, 0.8);
}
.tp-view::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 2px; z-index: 3;
  background: var(--accent); transition: background-color 0.5s var(--ease);
}
.tp-view::after {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(to top, rgba(7, 8, 11, 0.86) 0%, rgba(7, 8, 11, 0.2) 38%, transparent 60%);
}
.tp-shot {
  position: absolute; inset: 0; display: block;
  opacity: 0; transform: scale(1.06);
  transition: opacity 0.7s var(--ease), transform 1.4s var(--ease);
}
.tp-shot.is-on { opacity: 1; transform: none; }
.tp-shot img { display: block; width: 100%; height: 100%; object-fit: cover; }
.tp-cap {
  position: absolute; z-index: 2; left: 0; right: 0; bottom: 0;
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.3rem 1rem;
  padding: 0.9rem 1rem 0.95rem 1.2rem;
  color: #F3F0E8;
}
.tp-cap b { font-weight: 400; font-size: 0.9rem; }
.tp-cap span {
  font-family: var(--f-mono); font-size: 0.68rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: #CBC7BD;
}
.tp-row { cursor: default; transition: background-color 0.3s var(--ease); }
.tp-row .tp-what { transition: transform 0.35s var(--ease), color 0.3s var(--ease); }
.tp-row.is-active { background: linear-gradient(90deg, color-mix(in srgb, var(--accent) 13%, transparent), transparent 70%); }
.tp-row.is-active .tp-what { transform: translateX(6px); color: var(--text); }
@media (hover: none), (pointer: coarse) { .tp-row { cursor: pointer; } }
@media (max-width: 959.98px) { .tp-view { margin-bottom: 0.4rem; } }

@media (prefers-reduced-motion: reduce) {
  .tp-row { opacity: 1; transform: none; }
  .tp-shot, .tp-row .tp-what { transition: none; }
  .tp-shot { transform: none; }
}

/* ======================================================= principles ===== */
/*
 * Six cells on a hairline grid. The numeral is the visual: oversized, set in
 * the outline of the display face, sitting behind the icon so the eye reads
 * the count before the words. Everything moves on transform and opacity.
 */
.principles {
  margin-top: clamp(2.4rem, 5vw, 3.6rem);
  display: grid; gap: 1px; background: var(--hair);
  border: 1px solid var(--hair);
}
@media (min-width: 700px)  { .principles { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .principles { grid-template-columns: repeat(3, 1fr); } }

.principle {
  position: relative; overflow: hidden;
  background: var(--cell);
  padding: clamp(1.6rem, 3vw, 2.3rem) clamp(1.3rem, 2.4vw, 1.9rem) clamp(1.9rem, 3.4vw, 2.6rem);
  transition: background 0.35s var(--ease);
}
.principle:hover { background: var(--panel); }

/* the outlined numeral, bled off the top right corner */
.principle-n {
  position: absolute; top: -0.32em; right: -0.06em;
  font-family: var(--f-display); font-weight: 800;
  font-size: clamp(5.5rem, 4rem + 5vw, 8rem); line-height: 1;
  letter-spacing: -0.06em;
  color: transparent;
  -webkit-text-stroke: 1px var(--hair-3);
  pointer-events: none;
  transition: transform 0.5s var(--ease), -webkit-text-stroke-color 0.4s var(--ease);
}
.principle:hover .principle-n {
  transform: translate(-2%, 3%);
  -webkit-text-stroke-color: var(--gold);
}

.principle-ico {
  position: relative; z-index: 1;
  display: inline-flex; color: var(--gold-ink);
  transition: color 0.3s var(--ease), transform 0.4s var(--ease);
}
.principle-ico .ico { width: 26px; height: 26px; }
.principle:hover .principle-ico { transform: translateY(-2px); }

.principle-title {
  position: relative; z-index: 1;
  font-family: var(--f-display); font-weight: 800;
  font-size: clamp(1.08rem, 1rem + 0.5vw, 1.28rem); letter-spacing: -0.028em;
  margin: 1.1rem 0 0.6rem;
}
/* a rule that draws itself in as the cell is entered */
.principle-title::after {
  content: ''; display: block; height: 1px; width: 2.2rem;
  background: var(--gold); margin-top: 0.75rem;
  transform: scaleX(0.45); transform-origin: left;
  transition: transform 0.45s var(--ease);
}
.principle:hover .principle-title::after { transform: scaleX(1); }

.principle-body {
  position: relative; z-index: 1;
  color: var(--text-mid); font-size: 0.9rem;
}

@media (prefers-reduced-motion: reduce) {
  .principle-n, .principle-ico, .principle-title::after { transition: none; }
  .principle-title::after { transform: scaleX(1); }
}

/* ========================================================== founder ===== */
.founder {
  margin-top: clamp(2.4rem, 5vw, 3.6rem);
  display: grid; gap: clamp(1.6rem, 4vw, 3rem);
  align-items: start;
}
@media (min-width: 820px) {
  .founder { grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr); }
}
.founder-photo { margin: 0; position: relative; }
.founder-photo img {
  display: block; width: 100%; height: auto;
  /* Cropped to a portrait card. The source is a full-length 502x900 frame and
     at that ratio it drove the whole section past two screens. */
  aspect-ratio: 4 / 5; object-fit: cover; object-position: 50% 22%;
  border: 1px solid var(--hair-2);
  /* the gold sits behind the photo rather than on it */
  box-shadow: 0 24px 60px rgba(0,0,0,0.42);
  filter: saturate(0.94) contrast(1.02);
}
/* a thin keyline offset behind the frame, in the house gold */
.founder-photo::after {
  content: ''; position: absolute; inset: 14px -14px -14px 14px; z-index: -1;
  border: 1px solid var(--gold); opacity: 0.5; pointer-events: none;
}
.founder-body { display: flex; flex-direction: column; }
.founder-name {
  font-family: var(--f-display); font-weight: 800;
  font-size: clamp(1.3rem, 1.1rem + 0.9vw, 1.7rem); letter-spacing: -0.035em;
}
.founder-role {
  font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--gold-ink); margin-top: 0.35rem;
}
.founder-body .quote { margin: 1.6rem 0 1.2rem; }
.founder-body p:not(.quote):not(.founder-name):not(.founder-role) {
  color: var(--text-mid); font-size: 0.94rem;
}
.founder-body p + p:not(.quote) { margin-top: 0.9rem; }

/* ========================================================== phases ====== */
.phases { margin-top: clamp(2.4rem, 5vw, 3.6rem); display: grid; gap: 1px; background: var(--hair); border: 1px solid var(--hair); }
@media (min-width: 860px) { .phases { grid-template-columns: repeat(3, 1fr); } }
.phase { background: var(--cell); padding: clamp(1.4rem, 2.8vw, 2rem); }
.phase > h3 { font-size: 1.1rem; margin-bottom: 0.35rem; }
.phase > p { color: var(--text-low); font-size: 0.85rem; margin-bottom: 1.4rem; }
.phase ol { list-style: none; padding: 0; margin: 0; display: grid; gap: 1.1rem; }
.phase li > b { display: block; font-weight: 600; font-size: 0.94rem; }
.phase li > span { display: block; color: var(--text-mid); font-size: 0.87rem; margin-top: 0.2rem; }
.phase li > .who {
  font-family: var(--f-mono); font-size: 0.7rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--e, var(--text-low)); margin-top: 0.35rem;
}

/* ========================================================== reveals ===== */
/*
 * The hidden start state is gated on .js, which only a running script sets.
 * Without it every [data-reveal] block would be permanently invisible to a
 * reader with scripting off, which is the whole page.
 */
.js [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 14px, 0);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}
.js [data-reveal].in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; transform: none; transition: none; }
  .step.in .step-dot { box-shadow: none; }
}


/* ========================================================== pointer ===== */
/*
 * The dot cursor carried over from the portfolio: a small solid dot that
 * follows the pointer on a lag and opens into a ring over anything clickable.
 * Same geometry as that site (9px dot, 46px ring, 1.4px stroke) so the two
 * properties feel like one hand, with this site's tokens instead of that
 * site's. Everything here is built by JS, so with scripting off the native
 * cursor is untouched.
 */
@media (hover: hover) and (pointer: fine) {
  html.cur, html.cur a, html.cur button, html.cur [role="button"],
  html.cur summary, html.cur label, html.cur input, html.cur select,
  html.cur textarea { cursor: none; }
}

/*
 * The dot is a zero-size anchor carrying two children: the 9px core and the
 * 46px ring. The portfolio animates one element's width and height between
 * those two sizes; here the two are stacked and cross-faded with transform,
 * which looks the same and asks for no layout on a page already running a
 * WebGL loop.
 */
.cur-dot {
  position: fixed; top: 0; left: 0; width: 0; height: 0;
  pointer-events: none; z-index: 9999;
  opacity: 0;
  /* Left and top stay at zero: the position is a transform, so moving the
     cursor never touches layout. */
  transform: translate3d(0, 0, 0);
  transition: opacity 0.3s var(--ease);
  will-change: transform;
}
.cur-dot.is-on { opacity: 1; }

.cur-dot i {
  position: absolute; top: 0; left: 0; display: block; border-radius: 50%;
  transition: transform 0.26s var(--ease), opacity 0.26s var(--ease),
              background-color 0.3s var(--ease), border-color 0.3s var(--ease);
}
.cur-core { width: 9px;  height: 9px;  margin: -4.5px 0 0 -4.5px; background: var(--cur-ink); }
.cur-ring { width: 46px; height: 46px; margin: -23px 0 0 -23px;
            border: 1.4px solid var(--cur-ink); transform: scale(0.2); opacity: 0; }

.cur-dot.is-open .cur-core { transform: scale(0); opacity: 0; }
.cur-dot.is-open .cur-ring { transform: scale(1); opacity: 1; }

/* Over a gold glass band the pointer takes the band's own type colour: gold
   white on the smoked dark glass, deep bronze on the pale light glass. */
.cur-dot.on-gold .cur-core { background: var(--cur-band); }
.cur-dot.on-gold .cur-ring { border-color: var(--cur-band); }

/*
 * The light the pointer carries. It sits at -9: behind every section, above
 * the fixed ambience at -10. That is deliberate. Over content it would veil
 * text and cost measured contrast; behind it, it lights the ground the text
 * is printed on and the reversed bands and the header keep their own light.
 *
 * It is a fixed-size square moved only by transform, never a repositioned
 * full-viewport gradient: that layer is composited once and the pointer
 * never repaints it.
 */
.cur-glow {
  position: fixed; top: 0; left: 0;
  width: 44rem; height: 44rem; margin: -22rem 0 0 -22rem;
  pointer-events: none; z-index: -9;
  opacity: 0;
  /* The peak is capped by contrast, so presence is bought by holding that
     peak across the inner fifth rather than by raising it. */
  background: radial-gradient(closest-side,
              var(--cur-glow) 0%, var(--cur-glow) 19%, transparent 76%);
  /* The negative margin already centres it, so the transform carries the
     position and nothing else. */
  transform: translate3d(0, 0, 0);
  transition: opacity 0.45s var(--ease);
  will-change: transform;
}
.cur-glow.is-on { opacity: 1; }

@media (hover: none), (pointer: coarse) {
  .cur-dot, .cur-glow { display: none !important; }
  html.cur, html.cur * { cursor: auto !important; }
}
/* A light pool that chases the pointer is exactly the kind of motion this
   setting is asking to be spared. The dot stays: it is a cursor, not an
   animation, and it snaps rather than trails. */
@media (prefers-reduced-motion: reduce) {
  .cur-glow { display: none !important; }
  .cur-dot { transition: opacity 0.3s linear; }
}

/* ============================================================ legal ===== */
/*
 * The four legal pages: V1's text, verbatim, in V3's chrome since V3 went live
 * (2026-09-24). A reading page, one measured column, with the few classes the
 * text carries from V1: .legal-title, .legal-updated, .legal-intro, .note,
 * .permissions-table and .status-on / .status-off. --text-hi is V1's token,
 * still named by two inline styles inside the text, so it is aliased here
 * rather than the text edited.
 */
.legal-band { padding-top: calc(62px + clamp(3rem, 7vw, 6rem)); border-top: 0; }
.legal { --text-hi: var(--text); max-width: 46rem; }
.legal-title { font-size: clamp(2.2rem, 1.6rem + 2.6vw, 3.6rem); }
.legal-updated {
  margin-top: 1rem; font-family: var(--f-mono); font-size: 0.72rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-low);
}
.legal .legal-intro {
  margin-top: 1.6rem; font-size: clamp(1.02rem, 0.96rem + 0.3vw, 1.14rem);
  line-height: 1.72; color: var(--text-mid);
}
.legal h2 {
  font-size: clamp(1.25rem, 1.1rem + 0.6vw, 1.55rem); letter-spacing: -0.02em;
  margin: 2.8rem 0 0.9rem; padding-top: 1.4rem; border-top: 1px solid var(--hair);
}
.legal h3 { font-size: 1.04rem; font-weight: 600; letter-spacing: -0.01em; margin: 1.6rem 0 0.5rem; }
.legal p { color: var(--text-mid); margin-top: 0.9rem; }
.legal ul, .legal ol { color: var(--text-mid); margin: 0.9rem 0 0; padding-left: 1.2rem; }
.legal li { margin-top: 0.45rem; }
.legal li::marker { color: var(--gold-ink); }
.legal strong { color: var(--text); font-weight: 400; }
.legal a {
  color: var(--gold-ink); text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: color-mix(in srgb, var(--gold-ink) 45%, transparent);
  transition: color 0.2s var(--ease), text-decoration-color 0.2s var(--ease);
}
.legal a:hover { color: var(--gold-hi); text-decoration-color: var(--gold-hi); }
.legal code { font-family: var(--f-mono); font-size: 0.85em; padding: 0.08em 0.35em; background: var(--panel-2); }
.legal .note {
  margin-top: 1.4rem; padding: 1.1rem 1.25rem;
  background: var(--panel); border-left: 2px solid var(--gold);
  color: var(--text-mid); font-size: 0.94rem;
}
.legal .note p:first-child { margin-top: 0; }
.permissions-table { width: 100%; border-collapse: collapse; margin-top: 1.4rem; font-size: 0.9rem; }
.permissions-table th {
  text-align: left; font-family: var(--f-mono); font-size: 0.7rem; font-weight: 400;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-low);
  padding: 0.7rem 0.9rem 0.7rem 0; border-bottom: 1px solid var(--hair-2);
}
.permissions-table td {
  padding: 0.8rem 0.9rem 0.8rem 0; border-bottom: 1px solid var(--hair);
  color: var(--text-mid); vertical-align: top;
}
.permissions-table tr:last-child td { border-bottom: 0; }
.permissions-table td:first-child { color: var(--text); }
.status-on, .status-off {
  display: inline-block; white-space: nowrap; padding: 0.2rem 0.5rem;
  font-family: var(--f-mono); font-size: 0.64rem; letter-spacing: 0.12em; text-transform: uppercase;
}
.status-on { color: var(--on-gold); background: var(--gold); }
.status-off { color: var(--text-low); outline: 1px solid var(--edge); outline-offset: -1px; }
@media (min-width: 640px) { .permissions-table td:first-child { white-space: nowrap; } }
