/* ===== restyled home page =====
   Everything sits on a 14px cell grid: gutters, padding and section spacing are
   all multiples of --cell, so the layout lines up with the 9px block field the
   hero canvas paints behind it.

   Structure, top to bottom:
     .hhead   the bar — name on the left, nav on the right
     #hero-kv the block field, fixed behind everything
     .intro   the two paragraphs, revealed a line at a time */

:root {
  --paper: #FFFFFF;
  --ink: #0A0A0A;
  --muted: #8b8b8b;
  --line: rgba(10, 10, 10, .12);
  --cell: 14px;
  --gutter: 56px;
  --maxw: 1176px;
  --font: "aktiv-grotesk", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
@media (max-width: 680px) { :root { --gutter: 28px; } }   /* 2 cells on mobile */

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html { overscroll-behavior: none; }
body {
  margin: 0;
  overscroll-behavior: none;
  background: var(--paper);
  color: var(--ink);
  overflow-x: hidden;
  font-family: var(--font);
  font-weight: 400;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; }

/* Visible to screen readers only — names controls that read as bare icons. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ===== hero ===== */
/* Fixed and behind everything. The bar above it carries a solid white
   background, so the field is masked out from under the name and nav. */
#hero-kv { position: fixed; inset: 0; width: 100%; height: 100%; display: block; z-index: 0; pointer-events: none; }

.hero { position: relative; min-height: 100vh; background: transparent; z-index: 1; }

.hhead { position: relative; z-index: 5; background: #fff; padding: 0 var(--gutter); }
/* Hairline under the bar, drawn on from the left as the page loads. */
.hhead::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: var(--line); transform-origin: left; transform: scaleX(0);
  animation: lineGrowX .9s cubic-bezier(.16, 1, .3, 1) .5s both;
}
.hhead .hgrid {
  max-width: var(--maxw); margin: 0 auto;
  padding: calc(var(--cell) * 2) 0 calc(var(--cell) * 2 + 2px);
  display: grid; grid-template-columns: 1fr; gap: calc(var(--cell) * 3);
  align-items: stretch;
}
@media (min-width: 900px) { .hhead .hgrid { grid-template-columns: 1.6fr 1fr; } }

.hhead .hl {
  margin: 0; align-self: start; font-weight: 400; text-transform: uppercase;
  font-size: clamp(32px, 5.2vw, 82px); line-height: 0.92; letter-spacing: -0.035em;
}

/* Each line is a window with the text sliding up into it. The steps() timing is
   what makes the movement read as mechanical rather than smooth. */
.hhead .ln { display: block; overflow: hidden; padding-bottom: .08em; margin-bottom: -.08em; }
.hhead .ln > span { display: block; transform: translateY(115%); animation: heroLine .95s steps(6) both; }
.hhead .hl .ln:nth-child(1) > span { animation-delay: .10s; }
.hhead .hl .ln:nth-child(2) > span { animation-delay: .21s; }
/* On every page but Home the name is a link back to Home; it should read as the
   plain wordmark, never an underlined link. (Home has no <a> here.) */
.hhead .hl a { display: block; text-decoration: none; color: inherit; }

@keyframes heroLine { from { transform: translateY(115%); } to { transform: translateY(0); } }
@keyframes lineGrowX { to { transform: scaleX(1); } }
@keyframes lineGrowY { to { transform: scaleY(1); } }

.hhead .hcol { position: relative; display: flex; flex-direction: column; justify-content: flex-start; gap: calc(var(--cell) * 2); }
@media (min-width: 900px) {
  .hhead .hcol { padding-left: calc(var(--cell) * 3); }
  /* Vertical rule between the name and the nav, drawn top-down on load. */
  .hhead .hcol::before {
    content: ""; position: absolute; left: 0;
    top: calc(var(--cell) * -2); bottom: calc(var(--cell) * -2); width: 1px;
    background: var(--line); transform-origin: top; transform: scaleY(0);
    animation: lineGrowY .85s cubic-bezier(.16, 1, .3, 1) .42s both;
  }
}

/* ===== nav ===== */
/* Sits where the reference put its strapline: same type treatment, one link per
   line, stacked to fill the column. */
.hnav { display: flex; flex-direction: column; gap: calc(var(--cell) * 0.5); }
.hnav a {
  display: block; text-decoration: none; text-transform: uppercase;
  font-size: clamp(13px, 1.45vw, 20px); line-height: 1.18; letter-spacing: -0.01em;
  position: relative; width: max-content;
  animation: heroLine .95s steps(6) both;
}
.hnav a:nth-child(1) { animation-delay: .36s; }
.hnav a:nth-child(2) { animation-delay: .44s; }
/* Underline grows from the left on hover — the same gesture as the load lines. */
.hnav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
  background: currentColor; transform: scaleX(0); transform-origin: left;
  transition: transform .3s cubic-bezier(.16, 1, .3, 1);
}
.hnav a:hover::after, .hnav a:focus-visible::after { transform: scaleX(1); }

/* ===== Finance dropdown ===== */
/* The row holds the link and the caret button side by side; the menu hangs below
   it, out of flow so opening it never pushes the nav around. */
.hnav-group { position: relative; }
.hnav-row { display: flex; align-items: baseline; gap: 6px; }
.hnav-toggle {
  font: inherit; padding: 0; margin: 0; border: 0; background: none; color: inherit;
  cursor: pointer; line-height: 1; display: flex; align-items: center;
  animation: heroLine .95s steps(6) .44s both;
}
.hnav-caret { width: 10px; height: 6px; display: block; transition: transform .25s cubic-bezier(.16, 1, .3, 1); }
.hnav-group.is-open .hnav-caret { transform: rotate(180deg); }

.hnav-menu {
  list-style: none; margin: 8px 0 0; padding: 0;
  position: absolute; top: 100%; left: 0; z-index: 6; min-width: 12ch;
  background: #fff; border: 1px solid var(--line);
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity .2s ease, transform .2s cubic-bezier(.16, 1, .3, 1), visibility .2s;
}
.hnav-menu li + li { border-top: 1px solid var(--line); }
.hnav-menu a {
  display: block; width: auto; padding: 9px 14px;
  font-size: 13px; letter-spacing: .01em; animation: none;
}
.hnav-menu a::after { display: none; }        /* the row highlight replaces the underline */
.hnav-menu a:hover, .hnav-menu a:focus-visible { background: #f4f4f4; }

.hnav-group.is-open .hnav-menu { opacity: 1; visibility: visible; transform: translateY(0); }
/* Hover-to-open, pointer devices only — on touch the caret button is the way in. */
@media (hover: hover) and (pointer: fine) {
  .hnav-group:hover .hnav-menu { opacity: 1; visibility: visible; transform: translateY(0); }
  .hnav-group:hover .hnav-caret { transform: rotate(180deg); }
}

/* ===== intro ===== */
/* Pulled up under the hero. The hero is a full 100vh but its field frays out at
   around 73% of that, so without this the copy starts a quarter of a screen
   below where the blocks actually stop, reading as a gap rather than a break. */
.intro { position: relative; z-index: 2; margin-top: -24vh; padding: calc(var(--cell) * 4) var(--gutter) 0; }

/* Optional page title above the lead paragraphs (the dashboard uses one; the
   home page has none). Same display treatment as the hero name. */
.intro-title {
  margin: 0 0 calc(var(--cell) * 2.5);
  font-weight: 400; text-transform: uppercase;
  font-size: clamp(32px, 5.2vw, 82px); line-height: 0.92; letter-spacing: -0.035em;
}
.intro .wrap { max-width: var(--maxw); margin: 0 auto; }
/* Hidden until the script has split it into lines, so the unsplit paragraph
   never flashes on screen first. */
.intro .lead {
  font-size: clamp(26px, 3.4vw, 46px); line-height: 1.06; letter-spacing: -.02em;
  font-weight: 400; margin: 0; max-width: none; opacity: 0;
}
.intro .lead + .lead { margin-top: calc(var(--cell) * 2.5); }
.intro .lead.ready { opacity: 1; }
/* Inline links in the copy: underlined so they read as links, in the ink colour.
   The offset is kept small so the underline stays inside the .ln clip window
   (which has only .06em of padding below the text) rather than being cut off. */
.intro .lead a {
  color: inherit; text-decoration: underline;
  text-decoration-thickness: 1px; text-underline-offset: 0.09em;
  transition: opacity .2s ease;
}
.intro .lead a:hover, .intro .lead a:focus-visible { opacity: 0.55; }
/* Social line under the bio — a .lead so it reveals and keeps its links, sized
   down and given extra air above so it reads as a quiet footer, not body copy. */
.intro .lead.lead--meta {
  margin-top: calc(var(--cell) * 4);
  font-size: clamp(16px, 1.7vw, 21px); letter-spacing: 0; line-height: 1.2;
}
.intro .lead .ln { display: block; overflow: hidden; padding-bottom: .06em; margin-bottom: -.06em; }
.intro .lead .ln > span { display: block; transform: translateY(115%); transition: transform .85s steps(6); }
.intro .lead.in .ln > span { transform: translateY(0); }

/* ===== outro =====
   Closes the page the way the hero opens it: the same block field, the other
   photo, frayed edge at the top instead of the bottom. It has no content of its
   own — the height is what gives the field somewhere to live. */
.outro { position: relative; z-index: 1; height: 90vh; margin-top: calc(var(--cell) * 6); }

/* ===== writings page =====
   The restyled bar and block field dropped on top of the existing writings
   layout. That layout keeps its own grid — --landing-max is 1760px, much wider
   than the hero's 1176px --maxw — so the bar is refitted to the list's grid
   rather than the other way round. The nav has to line up with the list; the
   comments in style.css are explicit that these two must not drift apart. */
.writings-page .hhead { padding: 0; }
.writings-page .hhead .hgrid {
  max-width: var(--landing-max);
  padding: calc(var(--cell) * 2) var(--photo-inset) calc(var(--cell) * 2 + 2px) var(--page-pad-l);
}
/* The name is a link here (this is not the home page), so drop the link styling
   and let the two .ln windows keep doing the work. */
/* Lift the list up under the field's frayed edge, the same move the home page's
   intro makes, for the same reason. z-index keeps it above the fixed canvas. */
.writings-page .wr {
  position: relative; z-index: 2;
  margin-top: -22vh;
  padding-top: calc(var(--cell) * 4);
  /* Now that the index is a short list, give it a generous, viewport-scaled
     bottom so the page closes deliberately instead of cutting off just under
     the last row (the shared .wr bottom padding is only 72px). */
  padding-bottom: clamp(6rem, 18vh, 12rem);
}

/* Match the home page's display treatment. The typeface was already identical
   on both pages — Aktiv Grotesk, same stack — so it is the case and the
   tracking, not the font, that made them read as different. */
.writings-page .wr-title { text-transform: uppercase; letter-spacing: -0.035em; }

/* ===== companies page =====
   Same hero bar + block field as the other pages, dropped on top of the
   existing sectors layout. That layout keeps its own 1760px grid, so the bar is
   refitted to it — the nav must line up with the intro and the card rows. */
.companies-page .hhead { padding: 0; }
.companies-page .hhead .hgrid {
  max-width: var(--landing-max);
  padding: calc(var(--cell) * 2) var(--photo-inset) calc(var(--cell) * 2 + 2px) var(--page-pad-l);
}
/* The page content sits above the fixed canvas, which repaints a white
   background every frame and would otherwise cover the cards. z-index 1 clears
   the canvas (z-index 0); the faint grid still shows through behind them. */
.companies-page .sectors-intro,
.companies-page #sectors { position: relative; z-index: 1; }

/* The Next-in-Finance CTA that used to sit between the last carousel and the
   field is gone, so drop the field's top margin — the last sector band's own
   bottom padding is now the whole gap, which sits the field just under the
   final card row. (The global .outro margin still applies on the home page.) */
.companies-page .outro { margin-top: 0; }

/* Lift the intro up under the field's frayed edge, and drop the big top padding
   that used to clear the old fixed nav — the nav now lives in the bar above. */
.companies-page .sectors-intro {
  margin-top: -22vh;
  padding-top: calc(var(--cell) * 4);
}

/* "Change the fonts to match the home page font." The title, deck and cards were
   already on Aktiv Grotesk; these three still used a monospace face the home
   page has nowhere — the card index numbers, the carousel arrows, and the
   Next-in-Finance CTA. Redefining the token for this page moves them all onto
   Aktiv Grotesk without touching each rule. */
.companies-page { --gf-mono: "aktiv-grotesk", "Helvetica Neue", Arial, sans-serif; }

/* ===== essay (an individual reading page under Essays) =====
   No block field — this is a page for reading. The nav bar sits at the top on
   its own (no full-height .hero wrapper), then the essay in a centred box that
   matches the nav's width, with the text itself capped to a comfortable measure
   and left-aligned to the same gutter as the nav name. */
/* Sits above the fixed block-field canvas (z-index 0) and is pulled up under the
   field's frayed edge, the same move the home intro makes. */
.essay-page .essay {
  position: relative; z-index: 1;
  max-width: var(--maxw);
  margin-inline: auto; margin-top: -22vh;
  padding: calc(var(--cell) * 4) var(--gutter) calc(var(--cell) * 10);
}
.essay-page .essay > * { max-width: 42rem; }   /* reading measure, left-aligned */

.essay-head { margin-bottom: calc(var(--cell) * 3.5); }
.essay-meta {
  margin: 0 0 calc(var(--cell) * 1.5);
  font-size: 14px; letter-spacing: .01em; color: var(--ink);
}
.essay-title {
  margin: 0;
  font-size: clamp(34px, 5vw, 64px); font-weight: 400;
  line-height: 1.02; letter-spacing: -0.03em;
}
.essay-body { font-size: clamp(17px, 1.2vw, 19px); line-height: 1.65; }
.essay-body p { margin: 0 0 1.4em; }
.essay-body p:last-child { margin-bottom: 0; }
/* Inline reference links in an essay: underlined, in the ink colour. */
.essay-body a {
  color: inherit; text-decoration: underline;
  text-decoration-thickness: 1px; text-underline-offset: 0.14em;
  transition: opacity .2s ease;
}
.essay-body a:hover, .essay-body a:focus-visible { opacity: 0.55; }
/* Numbered / bulleted lists inside an essay. */
.essay-body ol, .essay-body ul { margin: 1.5em 0; padding-left: 1.5em; }
.essay-body li { margin: 0 0 0.7em; padding-left: 0.3em; }
.essay-body li:last-child { margin-bottom: 0; }

/* Quiet "back to the index" link under the essay. */
.essay-back {
  display: inline-block; margin-top: calc(var(--cell) * 5);
  font-size: 14px; text-decoration: none; color: var(--muted);
  transition: color .2s ease;
}
.essay-back:hover, .essay-back:focus-visible { color: var(--ink); }

/* ===== manifesto page =====
   No block field and no page title — the bar sits at the top and the text opens
   the page directly. The hero collapses to just the bar's height, and the intro
   drops the -24vh pull (which only exists to tuck copy under a field's frayed
   edge on the pages that have one). */
.manifesto-page .hero { min-height: 0; }
.manifesto-page .intro { margin-top: 0; }
/* The system scene's scroll stage. Empty by design apart from the sticky
   headline — its height is the scroll distance the whole scene takes. The
   first ~30% of it is pure float (see js/hero-field.js), which is what puts
   drifting blocks on the landing screen with the assembly still to come. */
.manifesto-page .mnet { position: relative; height: 340vh; }
/* The scene's headline: sticks to the top of the viewport while the system
   assembles below it. The band it sits in stays white because the field's
   geometry keeps all rails and nodes in the lower part of the screen, and
   data-pxsafe keeps stray blocks off the text itself. */
.manifesto-page .mnet-head {
  position: sticky; top: 0; z-index: 2;
  height: 30vh;
  display: flex; align-items: center; justify-content: center;
  padding: 0 var(--gutter);
  /* Invisible until the system assembles — js/hero-field.js drives opacity
     from the scene's scroll progress, so the words appear with the structure. */
  opacity: 0;
}
.manifesto-page .mnet-head p {
  margin: 0; max-width: 34ch; text-align: center;
  font-size: clamp(22px, 2.6vw, 40px); line-height: 1.15; letter-spacing: -.02em;
}

/* ===== the evidence: three block-built charts, one at a time ===== */
.manifesto-page .mcharts { position: relative; height: 680vh; }
.manifesto-page .mcharts-head {
  position: sticky; top: 0; z-index: 2;
  height: 30vh;
  display: flex; align-items: center; justify-content: center;
  padding: 0 var(--gutter); text-align: center;
}
/* The three captions are stacked in the same slot; js/hero-field.js drives
   each one's opacity so it rides with its chart. */
.manifesto-page .mchart-cap { position: absolute; max-width: 46ch; opacity: 0; }
.manifesto-page .mchart-cap h2 {
  margin: 0 0 8px; font-weight: 400;
  font-size: clamp(22px, 2.6vw, 40px); line-height: 1.1; letter-spacing: -.02em;
}
.manifesto-page .mchart-cap p {
  margin: 0; font-size: clamp(13px, 1.1vw, 17px); line-height: 1.4; color: var(--muted);
}

@media (prefers-reduced-motion: reduce) {
  .hhead .ln > span, .hnav a, .hnav-toggle { animation: none; transform: none; }
  .hhead::after { animation: none; transform: scaleX(1); }
  .hhead .hcol::before { animation: none; transform: scaleY(1); }
  .intro .lead .ln > span { transition: none; transform: none; }
}
