/* ---- tokens.css ---- */
/* ============================================================
   Homeframe brand tokens.

   Lifted from Downloads/Home Frame Landing Pages (2).html so the built site and
   Elijah's After Effects comps share one source of truth. Recorded in prose in
   design-handoff.md section 6.

   These are the Homeframe brand, NOT the Command Center design language. The
   workspace greys apply to the admin panel only (rules.md).
   ============================================================ */

:root {
  /* -- blues ------------------------------------------------ */
  --base:        #062386;
  --navy:        #041a63;
  --blue:        #0a2fa8;
  --deep-top:    #071c55;
  --deep-bottom: #040e34;

  /* -- accent ----------------------------------------------- */
  --gold:        #ffc21e;
  --orange:      #ff8a1e;
  --accent:      linear-gradient(135deg, var(--gold), var(--orange));

  /* -- ink -------------------------------------------------- */
  --ink:         #f2f6ff;
  --ink-dim:     rgba(226, 236, 255, .62);
  --ink-faint:   rgba(226, 236, 255, .34);
  --ink-on-gold: #180a00;

  /* -- lines and surfaces ----------------------------------- */
  --rule:        rgba(255, 255, 255, .13);
  --rule-soft:   rgba(255, 255, 255, .07);
  --surface:     rgba(255, 255, 255, .045);
  --surface-2:   rgba(3, 12, 48, .86);

  /* The STUDIOS ribbon from the wordmark, sampled straight out of the logo PNG:
     a hot highlight along the top edge, the orange body falling to a deeper red
     at the bottom, and a dark lip underneath where the ribbon folds. */
  --ribbon: linear-gradient(180deg,
              #fb9b23 0%,
              #f2801c 16%,
              #ea5f07 50%,
              #dc4200 86%,
              #d03400 100%);
  --ribbon-lip:   rgba(124, 14, 0, .85);
  --ribbon-sheen: inset 0 1px 0 rgba(255, 219, 160, .6);
  --ribbon-cast:  0 16px 34px -14px rgba(190, 55, 0, .65);
  --ribbon-radius: clamp(9px, .7vw, 18px);

  --shadow-card: 0 34px 90px -28px rgba(0, 6, 32, .92),
                 0 8px 26px -12px rgba(0, 6, 32, .7);

  /* -- type ------------------------------------------------- *
   * Outfit, self-hosted. A geometric sans in the same lane as Altivo, under the
   * SIL Open Font License, so it can be served from this box with no vendor in
   * the request path. Altivo cannot be: Adobe Fonts covers commercial use but
   * web use only through Adobe's own hosted kit, which would tell Adobe which
   * investor opened the deck and when.
   *
   * ONE variable file covers every weight from 100 to 900. That matters for the
   * banner: the selected tab getting heavier is a real weight change within the
   * same typeface, not the browser faking bold or falling back to another font.
   *
   * If Altivo is ever licensed for self-hosting it drops in here and nothing
   * else changes. */
  --font: 'Outfit', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* Reverted 2026-08-29. Both rounded faces were tried on the Our Series header
     and neither was wanted: Fredoka read as a character in its own right, and
     Quicksand was Outfit with the corners off but too light at 700 against
     Outfit's 900. A typeface cannot be rounded by CSS — the terminals are drawn
     into the file — so this stays Outfit. Both files are kept in
     site/design-source/ if it is ever worth another look. */
  --font-display: var(--font);

  /* Banner scale. Everything in the banner derives from this, and the deck page
     needs it too, so it lives here rather than on .nav. */
  /* The banner scales with the viewport, and the FLOOR is what matters. At
     .82vw with an 11px minimum it hit that floor at about 1340px and stayed
     there, so on a laptop the banner was the same size as on a phone while the
     screen was three times wider — tiny, against a page that had grown. A
     steeper slope and a higher floor keep it in proportion on the way down. The
     21px ceiling is unchanged, so nothing about a large monitor moves. */
  --nav-size: clamp(13px, 1.25vw, 21px);
  /* The banner's resulting height: 1.7em padding-top + .8em padding-bottom +
     the logo, which is 5.6em wide at the mark's 1.409 aspect. */
  --nav-h: calc(var(--nav-size) * 6.474);

  /* -- rhythm ----------------------------------------------- */
  --ease:    cubic-bezier(.22, .61, .36, 1);
  /* For the carousel. Eases IN as well as out, so a slide leaves gently instead
     of snapping away, and the long tail means it settles rather than stops. */
  --ease-glide: cubic-bezier(.32, .01, .16, 1);
  /* Elijah's monitor is 3840 x 1440. The design was drawn at 1920, so every
     size below scales with the viewport instead of stopping at a 1920 cap —
     otherwise the layout sits as a small island in the middle of his screen,
     which is exactly what it did the first time. */
  --gutter:  clamp(18px, 3.4vw, 130px);
  --max:     min(74ch, 1600px);
  --max-wide: none;

  /* Reserved space so the fixed download button never covers the last line
     of a page, on top of the device's own safe area. */
  --fab-reserve: 108px;
}


@font-face {
  font-family: 'Outfit';
  src: url('/assets/outfit-var.6c18d579.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}


/* ---- base.css ---- */
/* ============================================================
   Base. Document-level styling only.

   SCAFFOLDING. This is a readable, on-brand baseline so the structure can be
   built and tested before Elijah's After Effects designs land. It is meant to be
   replaced by those designs, not defended.
   ============================================================ */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

body {
  font-family: var(--font);
  color: var(--ink);
  background: var(--base);
  min-height: 100vh;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  line-height: 1.6;
}

/* The gradient field is CSS, never an exported image: a JPG of this is two
   megabytes and bands visibly on an OLED phone, and cannot respond to viewport
   size. design-handoff.md section 1. */
body::before {
  content: '';
  position: fixed; inset: 0; z-index: -2;
  background:
    radial-gradient(122% 76% at 50% -14%, #1c4fd8 0%, rgba(28, 79, 216, 0) 58%),
    radial-gradient(86% 62% at 88% 20%, #0f3cbb 0%, rgba(15, 60, 187, 0) 62%),
    radial-gradient(98% 70% at 6% 76%, #072a8c 0%, rgba(7, 42, 140, 0) 64%),
    linear-gradient(176deg,
      var(--deep-top) 0%,
      var(--blue) 32%,
      #0b3099 56%,
      #071c5e 80%,
      var(--deep-bottom) 100%);
}
body::after {
  content: '';
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(120% 66% at 50% -8%, rgba(150, 190, 255, .13), transparent 60%),
    radial-gradient(78% 54% at 100% 14%, rgba(255, 138, 30, .05), transparent 66%);
}

/* ---- typography ------------------------------------------ */

h1, h2, h3 {
  font-weight: 900;
  letter-spacing: .045em;
  line-height: 1.08;
  text-transform: uppercase;
  text-wrap: balance;
}

p { max-width: 68ch; }
p + p { margin-top: 1em; }

a { color: var(--ink); }
a:focus-visible,
button:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
  border-radius: 4px;
}

b, strong { font-weight: 700; color: var(--ink); }

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

/* ---- never ship a browser-default control ---------------- *
 * A raw scrollbar renders as a white OS-native widget and breaks the design.
 * rules.md / workspace design rules. */
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: rgba(1, 8, 36, .45); }
::-webkit-scrollbar-thumb {
  background: linear-gradient(180deg, var(--gold), var(--orange));
  border-radius: 99px;
  border: 3px solid rgba(1, 8, 36, .45);
}
html { scrollbar-width: thin; scrollbar-color: var(--orange) rgba(1, 8, 36, .45); }

/* ---- skip link ------------------------------------------- */

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 12px 20px;
  background: var(--accent);
  color: var(--ink-on-gold);
  font-weight: 700;
  text-decoration: none;
  border-radius: 0 0 10px 0;
}
.skip:focus { left: 0; }

/* Present to assistive technology and to the document outline, absent visually.
   The homepage's title is the logo artwork, which is an image, so the heading
   that names the page lives here. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---- images ---------------------------------------------- */

img, video, svg { max-width: 100%; height: auto; display: block; }


/* ---- components.css ---- */
/* ============================================================
   Components. SCAFFOLDING — replaced by Elijah's designs.
   ============================================================ */

.nav__inner,
.foot__inner,
main {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* The banner is fixed on every page, so it occupies no layout space. Clearing
   it is the DEFAULT here rather than something each page remembers to do: a new
   page works without thinking about it, and the two pages that position their
   own first element opt out below. */
main {
  padding-block: clamp(28px, 5vw, 56px);
  margin-top: var(--nav-h);
}

/* Only the pages that actually carry the fixed download button reserve room for
   it. Reserving it everywhere just leaves a dead band at the bottom. */
.page-pitch main,
.page-tax main {
  padding-bottom: calc(var(--fab-reserve) + env(safe-area-inset-bottom, 0px));
}

/* ---- nav ------------------------------------------------- */

/* Built to Elijah's banner reference, 2026-08-28.
   Logo left, tabs beside it, nothing in the top right. The same bar on every
   page — fixed, over whatever is behind it, with its own band underneath.

   EVERYTHING here is derived from --nav-size, so the logo, the gaps, the bar
   height and the glow keep their proportions to the type at any screen width.
   The first attempt scaled the logo on its own and it ended up 314px wide on a
   3840 monitor, dwarfing the tabs. */

/* ONE definition, every page. There are deliberately no per-page variants of
   the banner: change it here and it changes everywhere. Pages differ only in
   what they put UNDER it, never in the bar itself.

   Fixed, so it follows the page down. Transparent, because the band below is
   ::before rather than a background on the bar — that lets the gradient run
   past the bottom of the bar and fade out, instead of ending on a hard edge. */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 60;
  background: none;
  border: 0;
}

/* The band. Colour sampled off Elijah's reference, where it reads rgb(3,18,74)
   and hides the picture completely at the very top. Height is set against the
   bar so the fade keeps its proportions at any screen size. */
.nav::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  /* Ends just over half a bar-height below the bar, so it stops eating into the
     picture. The solid part covers the bar itself and the fade is packed into
     what is left rather than trailing far down the page. */
  height: 170%;
  pointer-events: none;
  z-index: -1;
  background: linear-gradient(180deg,
    rgba(3, 18, 74, .78)  0%,
    rgba(3, 18, 74, .75)  30%,
    rgba(3, 18, 74, .68)  48%,
    rgba(3, 18, 74, .56)  60%,
    rgba(3, 18, 74, .41)  70%,
    rgba(3, 18, 74, .27)  79%,
    rgba(3, 18, 74, .15)  86%,
    rgba(3, 18, 74, .07)  92%,
    rgba(3, 18, 74, .02)  97%,
    rgba(3, 18, 74, 0)    100%);
}

.nav__inner {
  display: flex; align-items: center;
  /* Logo to tabs, and the bar pushed down off the top edge. */
  gap: calc(var(--nav-size) * 4);
  padding-block: calc(var(--nav-size) * 1.7) calc(var(--nav-size) * .8);
  flex-wrap: wrap;
}

.nav__logo { display: block; flex: 0 0 auto; line-height: 0; }
.nav__logo img {
  width: calc(var(--nav-size) * 5.6);
  height: auto;
  filter: drop-shadow(0 4px 14px rgba(0, 8, 40, .7));
}

.nav__links {
  display: flex; align-items: center;
  gap: calc(var(--nav-size) * 2.9);
  flex-wrap: wrap;
}

.nav__links a {
  position: relative;
  /* Two spans in one grid cell: an invisible always-900 copy that sets the
     width, and the visible label. The cell is therefore always as wide as the
     BOLD text, so selecting a tab thickens it in place and never nudges its
     neighbours along the bar. */
  display: inline-grid;
  align-items: center;
  /* Symmetric padding. The beam is absolutely positioned and reserves no space,
     so the labels stay vertically centred on the logo. */
  padding: calc(var(--nav-size) * .3) 0;
  /* line-height 1 strips the leading, so the gap between the label and the beam
     is the number below and not that number plus half a line box. */
  line-height: 1;
  font-size: var(--nav-size);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .9);
  text-decoration: none;
  /* The band is deliberately faint, so the labels carry a little of their own
     contrast rather than relying on it. */
  text-shadow: 0 1px 5px rgba(1, 8, 30, .55), 0 0 18px rgba(1, 8, 30, .35);
  transition: color .25s var(--ease), text-shadow .25s var(--ease);
}
.nav__links a > span { grid-area: 1 / 1; }
.tab__sizer { font-weight: 900; font-variation-settings: 'wght' 900; visibility: hidden; }
.tab__label {
  font-weight: 700;
  font-variation-settings: 'wght' 700;
  /* Outfit is a variable font, so weight is a number that can be animated rather
     than two separate faces to swap between. This covers hover and any change
     inside one page; moving between pages is covered by the view transition
     above. */
  transition: font-variation-settings .32s var(--ease), color .32s var(--ease);
}

.nav__links a:hover { color: #fff; }

/* ---- the selected tab ------------------------------------ *
 * The typeface does NOT change: Outfit is variable, so 700 to 900 moves along a
 * weight axis inside the same family. Nothing is faked bold and nothing falls
 * back to a different font. */

.nav__links a[aria-current='page'] {
  color: #fff;
  text-shadow:
    0 0 calc(var(--nav-size) * .28) rgba(255, 255, 255, .45),
    0 0 calc(var(--nav-size) * .8)  rgba(255, 178, 72, .62),
    0 0 calc(var(--nav-size) * 1.7) rgba(255, 140, 30, .45);
}
.nav__links a[aria-current='page'] .tab__label {
  font-weight: 900;
  font-variation-settings: 'wght' 900;
}

/* ---- the light beam -------------------------------------- *
 * An anamorphic lens streak, not an underline. The shape is what matters: thick
 * and white-hot at the centre, tapering to nothing at both ends, wrapped in a
 * soft warm bloom that tapers with it.
 *
 * It is built from four stacked ELLIPTICAL gradients rather than a rectangle
 * with a box-shadow. A rectangle has the same thickness end to end and its
 * shadow traces that rectangle, which is why the previous version read as a
 * flat light bar. An ellipse is thickest at its centre and thins toward its
 * edges for free, which is exactly the falloff a real streak has.
 *
 *   1  core      needle-thin, pure white
 *   2  inner     tight yellow-white flare hugging the core
 *   3  mid       the orange body of the glow
 *   4  outer     the wide, faint spill
 */
.nav__links a[aria-current='page']::before {
  content: '';
  position: absolute;
  left: 50%;
  top: calc(100% + var(--nav-size) * .1);
  /* 140% wide, with the CORE sized to 100/140 of it — so the bright streak is
     exactly as wide as the word above it while the bloom still has room to
     spill past the ends instead of being clipped square. */
  width: 140%;
  height: calc(var(--nav-size) * 3.4);
  transform: translate(-50%, -50%);
  pointer-events: none;
  background:
    radial-gradient(ellipse 36% 1.4% at 50% 50%,
      #ffffff 0%,
      rgba(255, 246, 224, .98) 28%,
      rgba(255, 205, 120, .6) 62%,
      rgba(255, 170, 60, 0) 100%),
    radial-gradient(ellipse 36% 4.2% at 50% 50%,
      rgba(255, 208, 130, .95) 0%,
      rgba(255, 158, 48, .72) 38%,
      rgba(255, 138, 30, 0) 100%),
    radial-gradient(ellipse 40% 14% at 50% 50%,
      rgba(255, 150, 38, .92) 0%,
      rgba(255, 133, 24, .48) 42%,
      rgba(255, 120, 16, 0) 80%),
    radial-gradient(ellipse 50% 44% at 50% 50%,
      rgba(255, 132, 24, .5) 0%,
      rgba(255, 118, 16, .18) 46%,
      rgba(255, 110, 12, 0) 78%);
}

/* ---- page head ------------------------------------------- */

.page-head { padding-block: clamp(36px, 6vw, 78px); display: grid; gap: 18px; }
.page-head__eyebrow {
  font-size: 11px; font-weight: 700; letter-spacing: .3em; text-transform: uppercase;
  color: var(--ink-faint);
}
.page-head__title {
  font-size: clamp(38px, 7vw, 88px);
  background: linear-gradient(178deg, #ffffff 34%, #bcd2ff 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.page-head__lede { font-size: clamp(15px, 1.5vw, 18px); color: var(--ink-dim); }

/* ---- sections -------------------------------------------- */

.section { padding-block: clamp(30px, 4.5vw, 62px); }
.section + .section { border-top: 1px solid var(--rule-soft); }
.section__title {
  font-size: clamp(19px, 2.3vw, 32px);
  margin-bottom: 18px;
}
.section__body { color: var(--ink-dim); font-size: clamp(14px, 1.2vw, 16.5px); }

/* ---- the ask table --------------------------------------- *
 * A real table, never an exported image. On a narrow screen it scrolls inside its
 * own container so the page itself never scrolls sideways. */

.table-wrap { margin-block: clamp(18px, 3vw, 34px); }
.table-scroll {
  overflow-x: auto;
  border: 1px solid var(--rule);
  border-radius: 14px;
  background: rgba(4, 14, 52, .55);
  -webkit-overflow-scrolling: touch;
}
.ask-table { border-collapse: collapse; width: 100%; min-width: 720px; font-size: 14px; }
/* The caption is the section title for its table, not a footnote about it, so
   it is sized and weighted like one. It was 11px and faint, which read as a
   label on the table rather than a heading over it. */
.ask-table__caption {
  caption-side: top;
  text-align: left;
  padding: clamp(16px, 1.3vw, 30px) clamp(16px, 1.2vw, 26px) clamp(12px, 1vw, 20px);
  font-family: var(--font-display);
  font-size: clamp(15px, 1.15vw, 30px);
  font-weight: 900;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #ffffff;
}
.ask-table th,
.ask-table td {
  padding: 12px 18px;
  text-align: right;
  border-bottom: 1px solid var(--rule-soft);
  white-space: nowrap;
}
.ask-table th:first-child,
.ask-table td:first-child { text-align: left; }
.ask-table thead th {
  font-size: 10px; font-weight: 700; letter-spacing: .22em; text-transform: uppercase;
  color: var(--ink-faint);
  background: rgba(3, 12, 48, .7);
  position: sticky; top: 0;
}
.ask-table td.is-primary { color: var(--ink); font-weight: 700; }
.ask-table tbody tr:hover { background: rgba(255, 255, 255, .03); }
.ask-table .is-total td {
  border-top: 1px solid var(--rule);
  border-bottom: 0;
  font-weight: 900;
  color: var(--ink);
}
.table-wrap__hint {
  margin-top: 10px;
  font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-faint);
}
@media (min-width: 900px) { .table-wrap__hint { display: none; } }

/* ---- the fixed download button --------------------------- *
 * Bottom right for the entire scroll. Never hidden, never collapsed to an icon,
 * never dependent on JavaScript. design-spec.md section 2. */

/* THE button. The wordmark's ribbon, and the only button style on the site:
   the download and the carousel's View full screen are the same object in two
   places, so they are one rule with two positions rather than two lookalikes
   that drift apart. */
.ribbon-button,
.download-fab {
  display: inline-flex; align-items: center; gap: .7em;
  padding: clamp(10px, .68vw, 16px) clamp(15px, 1.15vw, 27px);

  /* Square with rounded corners and the wordmark's ribbon, not a pill. */
  border: 0;
  border-radius: var(--ribbon-radius);
  border-bottom: max(3px, .22em) solid var(--ribbon-lip);

  background: var(--ribbon);
  color: #ffffff;
  font-family: inherit;
  font-size: clamp(10px, .58vw, 14px);
  font-weight: 900; letter-spacing: .1em; text-transform: uppercase;
  text-decoration: none;
  text-shadow: 0 2px 0 rgba(132, 26, 0, .4);

  box-shadow: var(--ribbon-sheen), var(--ribbon-cast), 0 4px 14px -4px rgba(0, 6, 32, .8);
  transition: transform .35s var(--ease), box-shadow .35s var(--ease), filter .35s var(--ease);
}
.download-fab {
  position: fixed;
  right: max(clamp(24px, 2.4vw, 64px), env(safe-area-inset-right, 0px));
  bottom: max(clamp(24px, 2.4vw, 64px), env(safe-area-inset-bottom, 0px));
  z-index: 80;
}

.ribbon-button:hover,
.download-fab:hover {
  transform: translateY(-2px);
  filter: brightness(1.06);
  box-shadow: var(--ribbon-sheen),
              0 22px 44px -14px rgba(190, 55, 0, .75),
              0 6px 18px -4px rgba(0, 6, 32, .85);
}
.ribbon-button__icon,
.download-fab__icon { font-size: 15px; line-height: 1; }

/* On a small screen it keeps its label. An icon-only button leaves an investor
   guessing what it does, which is the opposite of the point. */
@media (max-width: 460px) {
  .download-fab {
    left: max(20px, env(safe-area-inset-left, 0px));
    right: max(20px, env(safe-area-inset-right, 0px));
    justify-content: center;
    padding: 16px 18px;
    font-size: 12px;
  }
}

/* The footer was a placeholder bar and is gone. Elijah's own design replaces
   it; there is deliberately no CSS holding a shape for it. */


/* ---- hiding the page until the curtain can cover it ------- *
 *
 * intro.js adds this class to <html> synchronously, from the HEAD, before the
 * body has been parsed — so the very first paint is this colour and nothing
 * else. It comes off the instant the video has a frame, which is the instant
 * the curtain itself starts covering the page, so there is no moment where
 * either the site or a blank screen is on show.
 *
 * The colour is sampled from frame one of Elijah's export, which is fully
 * opaque: the curtains start closed. So this is not a stand-in for the animation,
 * it IS the animation's first frame, held until the video can take over.
 *
 * visibility, not opacity or display: it inherits, so one rule hides the whole
 * document, and unlike opacity a descendant can opt back OUT of it — which is
 * how the curtain itself stays visible while everything under it does not.
 *
 * With JavaScript off this class is never added and none of it applies. */

html.is-intro-pending { background-color: #061751; }
html.is-intro-pending body { visibility: hidden; }
html.is-intro-pending body .intro { visibility: visible; }

/* ---- the curtain intro ----------------------------------- *
 * pointer-events: none is the important line. The page underneath is live and
 * clickable from the first frame, so the curtain is never something anyone has
 * to wait out. */

.intro {
  position: fixed;
  inset: 0;
  z-index: 200;
  pointer-events: none;
  opacity: 1;
  transition: opacity .4s var(--ease);
}
.intro.is-leaving { opacity: 0; }

.intro__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;

  /* drop-shadow, NOT box-shadow. box-shadow traces the element's rectangle and
     would draw a frame around the whole viewport; drop-shadow follows the
     video's ALPHA, so the shadow is cast by the curtains themselves and falls
     into the gap as they part. That is the whole reason it reads as depth
     rather than as a video sitting on a page.

     One shadow, moderate blur: this is filtering a 2560-wide frame on every
     tick, and stacking two would cost twice as much for very little. */
  filter: drop-shadow(0 8px 38px rgba(1, 6, 26, .62));
}

/* Belt and braces: anyone who has asked for less motion never gets the element
   in the first place, but if that check is ever missed the CSS hides it too. */
@media (prefers-reduced-motion: reduce) {
  .intro { display: none; }
}


/* ---- pages.css ---- */
/* ============================================================
   Homepage — built to Elijah's design, 2026-08-28.

   Banner over a full-bleed hero, a fade at the top so the logo and tabs read
   against any frame of the video, a fade at the bottom carrying the hero into
   the blue, then the OUR SERIES rail as bare placeholder shapes.

   The blue field behind everything below the hero is an After Effects export,
   masked to the bottom fade defined here. Until it lands, --bg-fallback stands
   in so the layout can be judged.
   ============================================================ */

:root {
  /* The colour the hero fades INTO. It must match the top edge of the exported
     background exactly or a seam appears where the two meet. Sampled from the
     design; Elijah confirms it against his export. */
  --bg-top: #0e2b76;

  /* Height of the hero's bottom fade, as a fraction of the hero. This is the
     shape the background export is masked to. Kept short: a long fade eats the
     image and the design has the picture holding almost the whole frame. */
  --hero-fade-height: 34%;

  /* Rail geometry. Every card is the same height; the leading card is 16:9 and
     the rest are portrait, as in the design. Change these two lines to change
     the whole rail. */
  --rail-h: clamp(150px, 15.5vw, 620px);
  --rail-featured-aspect: 16 / 9;
  --rail-card-aspect: 7 / 10;

  /* The deck carousel below it. One slide large in the middle with its
     neighbours peeking in, so three numbers describe the whole thing. */
  /* Sized by whichever runs out first, WIDTH or HEIGHT. On a 3840-wide monitor a
     purely width-driven slide is taller than the window and the button under it
     is never on screen at the same time; on a short laptop the same number is
     fine. 70vh is the tallest a 16:9 slide can be and still leave room for the
     banner above it and the button below. */
  --slide-w: max(320px, min(62vw, 2300px, calc(70vh * 16 / 9)));
  --slide-h: calc(var(--slide-w) * 9 / 16);

  /* How far a neighbour's CENTRE sits from the middle slide's centre. It has to
     clear half of each: 0.5 for the active slide, plus half of a neighbour at
     --peek-scale (0.35), plus air. 0.85 is edge-to-edge with nothing between
     them, so 0.865 is about as tight as this goes before they touch. */
  --peek-shift: calc(var(--slide-w) * 0.865);
  --peek-scale: .7;
}

/* ---- full-bleed containers ------------------------------- *
 * The homepage is a full-bleed layout, not a centred reading column: the logo
 * sits near the left edge and the rail runs off the right. The other three
 * pages stay narrow, because they are documents to read. */

.nav__inner { max-width: none; }

.page-home main {
  max-width: none;
  /* The hero sits above main and starts at the top of the page, under the
     banner, so main must not be pushed down. */
  margin-top: 0;
  /* No top padding: the rail sits right up under the hero's fade, so OUR SERIES
     reads as part of the same field rather than a separate block below it. */
  padding-top: 0;
}

/* ---- the shell: banner over hero ------------------------- */

.shell { position: relative; }

/* ---- hero ------------------------------------------------ */

/* Sized by viewport HEIGHT, not by aspect ratio. On a 3840-wide monitor an
   aspect-driven hero either runs off the bottom of the screen or gets cropped
   into a letterbox slice; in the design it simply occupies the top ~two thirds
   of the window, which is what this does at any width. */
.hero {
  position: relative;
  width: 100%;
  height: clamp(340px, 78vh, 1500px);
  overflow: hidden;
  /* No background on the hero box itself. Anything opaque here would show
     through the masked fade and put back the seam the mask exists to remove. */
  background: transparent;
}

/* A phone in portrait gets a taller crop; a 2:1 letterbox is a sliver there. */
@media (max-width: 700px) {
  .hero { height: clamp(300px, 52vh, 560px); }
}

/* THE FADE, both ends.
 *
 * The hero image is MASKED at the top and the bottom rather than covered by
 * painted gradients, so what fills those bands is Elijah's own background
 * artwork rather than a colour picked to imitate it. That is the whole point:
 * the earlier top band was near-black rgba(3,10,30), which was visibly not the
 * same blue as the field it sat above.
 *
 * The stops are a SMOOTHSTEP curve at both ends, not a straight line. A linear
 * alpha ramp over a photograph reads as a hard edge - it sheds most of its
 * opacity through the middle of the ramp and then lingers, so the eye finds a
 * boundary. Smoothstep leaves 1.0 gently, falls fastest in the middle and lands
 * on 0 flat, which is what actually looks like a dissolve.
 *
 * The top is a wash rather than a cut-out: the mask bottoms out at 0.28 instead
 * of 0, so the band takes the artwork's colour while the picture still reads
 * through it. The bottom fade is the last 14% only.
 */
.hero__frame {
  position: absolute;
  inset: 0;
  -webkit-mask-image: linear-gradient(180deg,
    /* Top: the solid part is short and the RAMP is long, so it eases in rather
       than starting and finishing in the same breath. Percentages are scaled
       against the taller hero so the band lands at the same place on screen. */
    rgba(0, 0, 0, 0)     0%,
    rgba(0, 0, 0, 0)     1.8%,
    rgba(0, 0, 0, .027)  3.45%,
    rgba(0, 0, 0, .156)  5.1%,
    rgba(0, 0, 0, .34)   6.75%,
    rgba(0, 0, 0, .5)    8.4%,
    rgba(0, 0, 0, .66)   10.05%,
    rgba(0, 0, 0, .844)  11.7%,
    rgba(0, 0, 0, .973)  13.35%,
    rgba(0, 0, 0, 1)     15%,
    /* The picture, uninterrupted. */
    rgba(0, 0, 0, 1)     86%,
    /* Bottom: starts lower down the frame than before AND runs longer, so more
       of the image is on screen and the dissolve is not a snap. */
    rgba(0, 0, 0, .973)  87.75%,
    rgba(0, 0, 0, .844)  89.5%,
    rgba(0, 0, 0, .660)  91.25%,
    rgba(0, 0, 0, .5)    93%,
    rgba(0, 0, 0, .340)  94.75%,
    rgba(0, 0, 0, .156)  96.5%,
    rgba(0, 0, 0, .027)  98.25%,
    rgba(0, 0, 0, 0)     100%);
  mask-image: linear-gradient(180deg,
    /* Top: the solid part is short and the RAMP is long, so it eases in rather
       than starting and finishing in the same breath. Percentages are scaled
       against the taller hero so the band lands at the same place on screen. */
    rgba(0, 0, 0, 0)     0%,
    rgba(0, 0, 0, 0)     1.8%,
    rgba(0, 0, 0, .027)  3.45%,
    rgba(0, 0, 0, .156)  5.1%,
    rgba(0, 0, 0, .34)   6.75%,
    rgba(0, 0, 0, .5)    8.4%,
    rgba(0, 0, 0, .66)   10.05%,
    rgba(0, 0, 0, .844)  11.7%,
    rgba(0, 0, 0, .973)  13.35%,
    rgba(0, 0, 0, 1)     15%,
    /* The picture, uninterrupted. */
    rgba(0, 0, 0, 1)     86%,
    /* Bottom: starts lower down the frame than before AND runs longer, so more
       of the image is on screen and the dissolve is not a snap. */
    rgba(0, 0, 0, .973)  87.75%,
    rgba(0, 0, 0, .844)  89.5%,
    rgba(0, 0, 0, .660)  91.25%,
    rgba(0, 0, 0, .5)    93%,
    rgba(0, 0, 0, .340)  94.75%,
    rgba(0, 0, 0, .156)  96.5%,
    rgba(0, 0, 0, .027)  98.25%,
    rgba(0, 0, 0, 0)     100%);
}

.hero__media {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The source is 16:9 and this box is much wider than that on an ultrawide
     monitor, so `cover` crops top and bottom. Biasing upward keeps faces, titles
     and the top of the frame — the parts that carry the shot — rather than
     centring the crop and slicing heads off. */
  object-position: center 32%;
  display: block;
}

/* Marks the box as the pitch video's home until the file exists. Removed the
   moment site.json names a video file. */
.hero__placeholder-label {
  position: absolute;
  left: 50%; bottom: 18%;
  transform: translateX(-50%);
  margin: 0;
  padding: 10px 20px;
  border-radius: 99px;
  border: 1px solid rgba(255, 255, 255, .28);
  background: rgba(2, 9, 32, .55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  font-size: 11px; font-weight: 700; letter-spacing: .26em; text-transform: uppercase;
  color: rgba(255, 255, 255, .82);
  white-space: nowrap;
}

/* ---- the fades ------------------------------------------- *
 * Top: darkens the image under the banner so the logo and tabs always read.
 * Bottom: carries the hero into the blue below. The bottom one is the shape
 * Elijah masks the exported background to. */

/* There are deliberately NO painted fade overlays any more, at either end. The
   bottom one stopped dead at the hero's edge while still 40% opaque, and a
   semi-opaque layer that simply stops is a hard line. The top one was a
   near-black wash that never matched the background it sat above. The mask on
   .hero__frame replaces both. */

/* ---- the page field -------------------------------------- *
 * Everything below the hero sits on the exported blue. It repeats vertically,
 * so the export is a seamless vertical loop and the page can be any length.
 * --bg-image is set once the export lands. */

/* Elijah's export, and nothing on top of it.
   Earlier there were two extra radial layers standing in for a vignette. The
   artwork has its own — darker at the edges, brighter through the middle — so
   those are gone rather than doubled up on his. */
.page-home,
.page-pitch,
.page-series,
.page-ask,
.page-tax {
  background-color: var(--bg-deep);
  background-image: var(--bg-image);
  background-repeat: var(--bg-repeat);
  background-position: var(--bg-pos);
  background-size: var(--bg-size);
  /* The blend belongs to whichever background is active, which is why it is a
     variable and not a literal.
     
     It was `overlay, normal, normal, normal, normal` — one entry per layer of
     the CSS-generated version, where the leading `overlay` turned its noise
     layer into texture. The export has ONE layer, so that leading `overlay`
     landed on Elijah's artwork instead and blended it against the navy
     background-colour underneath. Overlay darkens everything below mid-grey, and
     every colour in a deep blue field is below mid-grey, so his gradient came out
     crushed and the wrong hue. It looked like a bad export. It was a leftover. */
  background-blend-mode: var(--bg-blend);
}

/* These pages paint their own field, so the generic one in base.css is off. */
.page-home::before, .page-home::after,
.page-pitch::before, .page-pitch::after,
.page-series::before, .page-series::after,
.page-ask::before, .page-ask::after,
.page-tax::before, .page-tax::after { content: none; }

:root {
  /* ============================================================
     THE FIELD behind Our Shows and the three money pages.
     ============================================================

     Drawn in CSS, not loaded as an image, and that is the point rather than a
     saving. Elijah's export is a fixed rectangle: to cover a page of any length
     it has to be tiled, and tiling a gradient means folding its two ends
     together, which averages them and flattens the thing you wanted. A CSS
     gradient has no size of its own. It is simply the page, at whatever height
     the page turns out to be, with no seam to hide and nothing to loop.

     Two rules it follows, both learned the hard way:

       - NO NOISE. An SVG turbulence layer was in here to fake texture and it
         read as dust on a screen.
       - NO SYMMETRIC VIGNETTE. Darkening both edges equally makes a page look
         lit from the middle, like a spotlight, instead of graded. The light here
         sits OFF centre and falls away unevenly, which is what Elijah's own
         artwork does.

     Colours are sampled from his deck: the blue runs from #143fb8 at the light
     down to #030d33 in the far corner.
     ============================================================ */

  /* Where the light sits. Each page moves it, further down this file, so four
     pages of the same field do not read as one long uniform wall. */
  --bg-x: 34%;
  --bg-y: 28%;

  /* The colour the page continues in below the gradient, and behind it while it
     paints. It is the mid tone rather than the darkest, so a slow paint never
     flashes something darker than the page it is about to become. */
  --bg-deep: #0a2a91;

  --bg-image:
    /* A darker band across the top, so the page starts deep and opens into the
       light rather than beginning at whatever brightness the light happens to
       fall at. It also gives the banner something consistent to sit on, since
       the banner is fixed and the light is not.
       
       The stops are a smoothstep, not a straight line: a linear alpha ramp over
       a gradient sheds most of its opacity through the middle and then lingers,
       which the eye finds as an edge. This leaves 1.0 gently and lands on 0
       flat. Same curve as the hero mask, for the same reason. */
    linear-gradient(180deg,
      rgba(3, 13, 51, .82)  0%,
      rgba(3, 13, 51, .80)  2%,
      rgba(3, 13, 51, .74)  5%,
      rgba(3, 13, 51, .62)  9%,
      rgba(3, 13, 51, .46) 13%,
      rgba(3, 13, 51, .30) 17%,
      rgba(3, 13, 51, .17) 21%,
      rgba(3, 13, 51, .07) 25%,
      rgba(3, 13, 51, .02) 29%,
      rgba(3, 13, 51, 0)   33%),

    /* A second, dimmer bloom from the opposite quarter. It keeps the falloff
       from being a clean radial — which reads as a spotlight — and it breaks up
       the long tonal ramp enough that 8-bit banding never gets a straight run to
       show itself in. Without noise, this is what does that job. */
    radial-gradient(85% 65% at calc(100% - var(--bg-x)) calc(100% - var(--bg-y)),
      rgba(26, 78, 214, .30) 0%,
      rgba(22, 66, 190, .16) 34%,
      rgba(18, 56, 165, .05) 60%,
      rgba(16, 50, 150, 0) 78%),

    /* The field itself. One light, placed off centre, falling to deep navy at
       the far corner. Stops are close together near the light and spread out
       into the shadow, because that is how light actually falls off and an even
       spacing reads as a printed ramp. */
    radial-gradient(125% 95% at var(--bg-x) var(--bg-y),
      #143fb8   0%,
      #1139ae   14%,
      #0e32a2   26%,
      #0b2b93   38%,
      #092480   50%,
      #071d6b   62%,
      #061755   73%,
      #051140   84%,
      #040e37   93%,
      #030d33  100%);

  --bg-size:   100% 100%;
  --bg-repeat: no-repeat;
  --bg-blend:  normal;
  --bg-pos:    0 0;
}

/* ---- OUR SERIES rail ------------------------------------- *
 * Placeholder shapes only, by instruction: no thumbnails, just where they go.
 * The track runs off the right edge to imply more, exactly as in the design. */

.rail {
  padding-block: clamp(2px, .3vw, 10px) clamp(30px, 4vw, 60px);
  margin-inline: calc(var(--gutter) * -1);
  padding-inline: var(--gutter);
}

.rail__heading {
  font-size: clamp(15px, 1.25vw, 46px);
  font-weight: 900;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #ffffff;
  margin-bottom: clamp(10px, 1.1vw, 18px);
}

.rail__track {
  display: flex;
  align-items: stretch;
  gap: clamp(8px, .75vw, 30px);
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x proximity;
  /* Let the last card run under the right gutter rather than stopping short. */
  margin-right: calc(var(--gutter) * -1);
  padding-right: var(--gutter);
  padding-bottom: 4px;
  scrollbar-width: none;
}
.rail__track::-webkit-scrollbar { display: none; }

.rail__card {
  flex: 0 0 auto;
  height: var(--rail-h);
  width: calc(var(--rail-h) * 0.7);
  aspect-ratio: var(--rail-card-aspect);
  border-radius: clamp(8px, .55vw, 26px);
  scroll-snap-align: start;

  /* Deliberately empty. This is where Elijah's exported artwork goes. */
  background:
    linear-gradient(160deg, rgba(255, 255, 255, .16), rgba(255, 255, 255, .05)),
    rgba(8, 28, 84, .5);
  border: 1px solid rgba(255, 255, 255, .18);
  box-shadow: 0 18px 40px -22px rgba(0, 6, 32, .9);
  transition: transform .45s var(--ease), border-color .45s var(--ease);
}
.rail__card:hover { transform: translateY(-5px); border-color: rgba(255, 180, 90, .4); }

.rail__card--featured {
  width: calc(var(--rail-h) * 16 / 9);
  aspect-ratio: var(--rail-featured-aspect);
}

/* ---- PITCH DECK carousel --------------------------------- *
 * One slide large in the middle, the ones either side of it peeking in, arrows,
 * and a 45 second auto-advance. Full bleed: the peeks are meant to run off both
 * edges of the screen so the deck reads as continuing past the frame.
 *
 * Position is a CLASS per slide (is-prev / is-active / is-next / is-far-*), set
 * by client/carousel.js. Nothing here is written by script, so every measurement
 * lives in this block and the served HTML carries no inline styles. */

.carousel {
  padding-block: clamp(10px, 1.2vw, 30px) clamp(40px, 5vw, 96px);
  margin-inline: calc(var(--gutter) * -1);
}

.carousel__stage {
  position: relative;
  height: var(--slide-h);
  /* Clips the peeks at the screen edges rather than widening the document. */
  overflow: hidden;
}

.carousel__slide,
.show-panel {
  margin: 0;
  position: absolute;
  top: 0;
  left: 50%;
  width: var(--slide-w);
  height: var(--slide-h);
  border-radius: clamp(8px, .55vw, 26px);
  overflow: hidden;
  background: rgba(4, 16, 58, .55);
  border: 1px solid rgba(255, 255, 255, .18);
  box-shadow: 0 30px 70px -30px rgba(0, 6, 32, .95);
  transform: translateX(-50%);
  /* transform and opacity ONLY. box-shadow was in this list, and it is not a
     composited property: animating it repaints a 2300px card on every frame,
     thirteen times over, which is what made the slide stutter. The shadow now
     simply stays put while the slide moves. */
  transition:
    transform .95s var(--ease-glide),
    opacity .95s var(--ease-glide);
}

.carousel__slide img,
.show-panel img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* The four positions. Everything further away parks just outside its neighbour
   and fades out, so a slide always arrives from the side it should. */
.carousel .is-active,
.rail--shows .is-active {
  transform: translateX(-50%) scale(1);
  opacity: 1;
  z-index: 2;
}
.carousel .is-prev,
.rail--shows .is-prev {
  transform: translateX(calc(-50% - var(--peek-shift))) scale(var(--peek-scale));
  opacity: .45;
  z-index: 1;
}
.carousel .is-next,
.rail--shows .is-next {
  transform: translateX(calc(-50% + var(--peek-shift))) scale(var(--peek-scale));
  opacity: .45;
  z-index: 1;
}
.carousel .is-far-left,
.rail--shows .is-far-left {
  transform: translateX(calc(-50% - var(--peek-shift) * 1.85)) scale(.6);
  opacity: 0;
  pointer-events: none;
}
.carousel .is-far-right,
.rail--shows .is-far-right {
  transform: translateX(calc(-50% + var(--peek-shift) * 1.85)) scale(.6);
  opacity: 0;
  pointer-events: none;
}

.carousel .is-prev:hover,
.carousel .is-next:hover,
.rail--shows .is-prev:hover,
.rail--shows .is-next:hover { opacity: .72; }

.carousel__arrow {
  position: absolute;
  top: 50%;
  z-index: 3;
  /* Centred ON the active slide's edge rather than parked at the screen edge, so
     the controls stay with the thing they control however wide the monitor is. */
  transform: translate(-50%, -50%);
  width: clamp(40px, 3.4vw, 112px);
  height: clamp(40px, 3.4vw, 112px);
  padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .26);
  background: rgba(4, 15, 50, .72);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: rgba(255, 255, 255, .92);
  cursor: pointer;
  box-shadow: 0 16px 40px -18px rgba(0, 6, 32, .95);
  transition:
    background .3s var(--ease),
    border-color .3s var(--ease),
    color .3s var(--ease),
    box-shadow .3s var(--ease),
    filter .3s var(--ease),
    transform .3s var(--ease);
}
.carousel__arrow--prev { left: calc(50% - var(--slide-w) / 2); }
.carousel__arrow--next { left: calc(50% + var(--slide-w) / 2); }

/* Touched, it becomes the same object as the View full screen button below it:
   the wordmark's ribbon gradient, its sheen along the top edge, its cast, and
   the dark lip where the ribbon folds — here as the border, since a circle has
   no bottom edge to fold over. One accent, one treatment. */
.carousel__arrow:hover,
.carousel__arrow:focus-visible {
  background: var(--ribbon);
  border-color: var(--ribbon-lip);
  color: #ffffff;
  box-shadow: var(--ribbon-sheen), var(--ribbon-cast), 0 4px 14px -4px rgba(0, 6, 32, .8);
  /* The translate has to be repeated: a bare scale() here would drop it and the
     button would jump to the corner it is positioned from. */
  transform: translate(-50%, -50%) scale(1.07);
}
.carousel__arrow:active {
  background: var(--ribbon);
  border-color: var(--ribbon-lip);
  color: #ffffff;
  filter: brightness(.94);
  transform: translate(-50%, -50%) scale(.97);
}

.carousel__chevron {
  width: 42%;
  height: 42%;
  display: block;
}

/* The arrows do nothing without the script, so they ship with the `hidden`
   attribute and carousel.js takes it off. Note the :not([hidden]) guard: putting
   a display value on the base rule would DEFEAT the attribute, since any display
   declaration overrides the one the browser gives [hidden]. That is also what
   keeps the previous arrow gone on slide 1, where carousel.js puts it back. */
.carousel__arrow:not([hidden]) {
  display: grid;
  place-items: center;
}

/* ---- the way through to the deck ------------------------- *
 * The only way out of the carousel, by instruction: the slides themselves do
 * not navigate. Same ribbon button as the deck page download, centred under the
 * strip where it reads as the end of the section. */



/* ---- no JavaScript --------------------------------------- *
 * Absolutely-positioned slides would pile up on top of each other, so without
 * the script the stage becomes an ordinary scrolling strip. Thirteen real links
 * into the deck page, in order, with no behaviour attached to any of them. */
.carousel:not(.is-live) .carousel__stage {
  display: flex;
  gap: clamp(10px, 1vw, 34px);
  height: auto;
  overflow-x: auto;
  padding-inline: var(--gutter);
  scrollbar-width: none;
}
.carousel:not(.is-live) .carousel__stage::-webkit-scrollbar { display: none; }
.carousel:not(.is-live) .carousel__slide {
  position: static;
  flex: 0 0 auto;
  transform: none;
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .carousel__slide { transition: none; }
}

/* ---- the two blocks on the home page ---------------------- *
 * Our Shows and Pitch Deck are the same object twice: a title, a carousel, a
 * button. Sharing the wrapper is what keeps them that way — style one and the
 * other follows, rather than two sets of rules drifting apart the first time
 * either is touched. */

.home-block {
  /* Tight at the top. The hero ends in a fade rather than an edge, so a large
     gap under it reads as the page having stopped rather than as breathing
     room. */
  padding-block: clamp(10px, 1.2vw, 30px) clamp(26px, 3vw, 68px);
}

/* A hairline between one block and the next, so Pitch Deck reads as its own
   section rather than as more of the shows above it. On the second block, not
   the first, so there is never a line under the hero. */
.home-block + .home-block {
  border-top: 1px solid rgba(255, 255, 255, .11);
}

.home-block__title {
  font-family: var(--font-display);
  font-size: clamp(26px, 3.2vw, 88px);
  font-weight: 900;
  letter-spacing: .04em;
  text-transform: uppercase;
  text-align: center;
  color: #ffffff;
  margin: 0 0 clamp(20px, 2.4vw, 52px);
  line-height: 1;
}

.home-block__actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(8px, .7vw, 14px);
  padding-top: clamp(22px, 2.4vw, 54px);
}

/* A button with nothing behind it yet. Held back rather than dressed up, and
   labelled underneath, because a placeholder that looks finished is one nobody
   notices before it ships. */
.ribbon-button.is-placeholder {
  filter: grayscale(.55) brightness(.72);
  cursor: not-allowed;
}
.ribbon-button.is-placeholder:hover {
  transform: none;
  filter: grayscale(.55) brightness(.72);
  box-shadow: var(--ribbon-sheen), var(--ribbon-cast), 0 4px 14px -4px rgba(0, 6, 32, .8);
}
.actions__note {
  margin: 0;
  font-size: clamp(10px, .66vw, 14px);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* ---- the shows rail --------------------------------------- *
 *
 * It IS the pitch deck carousel, pointed at the show artwork. Rather than a
 * second set of rules that look the same today and drift apart the first time
 * either is touched, the panels JOIN the carousel's selectors further down this
 * file — same size, same peek scale, same offsets, same arrows. There is one
 * carousel on this page, used twice. */

.rail--shows .rail__stage {
  position: relative;
  height: var(--slide-h);
  /* Pulled out to the full width of the window before clipping. `main` insets
     this page by a gutter, so without the negative margin the stage clipped the
     peeks a hundred-odd pixels in from each edge and they looked cut off rather
     than running off the screen. The deck carousel has done this from the start
     — the shows rail lost it when it was rebuilt. */
  margin-inline: calc(var(--gutter) * -1);
  overflow: hidden;
}

/* Without the script the stage is a plain scrolling row: absolutely positioned
   panels would otherwise pile on top of each other in the middle. */
.rail--shows:not(.is-live) .rail__stage {
  display: flex;
  gap: clamp(10px, 1vw, 34px);
  height: auto;
  overflow-x: auto;
  padding-inline: var(--gutter);
  scrollbar-width: none;
}
.rail--shows:not(.is-live) .rail__stage::-webkit-scrollbar { display: none; }
.rail--shows:not(.is-live) .show-panel {
  position: static;
  flex: 0 0 auto;
  transform: none;
  opacity: 1;
}

.show-panel {
  appearance: none;
  padding: 0;
  cursor: pointer;
}
.show-panel.is-active { cursor: default; }
.show-panel:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.show-panel:hover { border-color: rgba(255, 190, 110, .45); }

/* ---- homepage document below the rail -------------------- *
 * The pitch sections stay a readable width even though the rail is full bleed. */

.page-home .page-head,
.page-home .section {
  max-width: var(--max);
}


/* ============================================================
   Pitch deck page — the deck laid out vertically.
   ============================================================ */

.page-pitch main {
  max-width: none;
  /* The deck computes its own top spacing, banner height included. */
  margin-top: 0;
  /* The deck computes its own top spacing to centre slide one. main's default
     top padding sat on top of that and pushed everything down by exactly that
     much, which is why slide one was low and every slide after it was fine. */
  padding-top: 0;
}

.deck {
  width: 100%;
  max-width: var(--deck-w);
  margin-inline: auto;
  padding-block: clamp(18px, 2.6vw, 48px);
  display: grid;
  gap: clamp(18px, 2.2vw, 46px);
}

/* One slide, one tracked section. The source art is 1920 wide, so the container
   is capped near that: stretching a 1920 slide across a 3840 monitor doubles
   every pixel and the type on the slides goes soft. */
.slide {
  margin: 0;
  border-radius: clamp(8px, .55vw, 18px);
  overflow: hidden;
  background: rgba(4, 16, 54, .5);
  box-shadow: 0 26px 60px -30px rgba(0, 6, 32, .9);
  border: 1px solid rgba(255, 255, 255, .1);
}
.slide img {
  display: block;
  width: 100%;
  height: auto;
  /* Reserves the 16:9 box before the image arrives, so lazily loaded slides do
     not shunt the page around under the reader as they land. */
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.deck__end {
  display: grid;
  justify-items: center;
  gap: 12px;
  padding-block: clamp(30px, 5vw, 80px) clamp(10px, 2vw, 30px);
}

.deck__top {
  display: inline-flex; align-items: center; gap: .7em;
  padding: clamp(15px, 1.15vw, 26px) clamp(24px, 2vw, 46px);

  border: 0;
  border-radius: var(--ribbon-radius);
  border-bottom: max(3px, .22em) solid var(--ribbon-lip);

  background: var(--ribbon);
  color: #ffffff;
  font-size: clamp(12px, .78vw, 19px);
  font-weight: 900; letter-spacing: .1em; text-transform: uppercase;
  text-decoration: none;
  text-shadow: 0 2px 0 rgba(132, 26, 0, .4);

  box-shadow: var(--ribbon-sheen), var(--ribbon-cast);
  transition: transform .35s var(--ease), box-shadow .35s var(--ease), filter .35s var(--ease);
}
.deck__top:hover {
  transform: translateY(-3px);
  filter: brightness(1.06);
  box-shadow: var(--ribbon-sheen), 0 24px 48px -14px rgba(190, 55, 0, .78);
}
.deck__top-arrow { font-size: 1.2em; line-height: 1; }

.deck__end-note {
  font-size: clamp(10px, .62vw, 14px);
  font-weight: 700; letter-spacing: .24em; text-transform: uppercase;
  color: var(--ink-faint);
}


/* ---- deck scrolling -------------------------------------- *
 * Mandatory snap: a scroll moves to the next slide and centres it rather than
 * landing between two. Pure CSS, so this works with JavaScript disabled; the
 * only thing deck.js adds on top is the 45-second idle advance.
 *
 * The banner is sticky on this page. With mandatory snapping, a banner that
 * scrolls away at the top can become unreachable — scrolling up just snaps back
 * to slide one — so it stays put, and scroll-padding keeps it from covering the
 * slide it is centring. */

/* No scrollbar on the deck. The column of ticks down the left says where you are
   and takes you anywhere, which is everything the scrollbar was doing here and
   more, so the bar on the right is one more thing beside a full-screen picture
   for no gain. The page still scrolls by every other means: wheel, trackpad,
   arrow keys, Home and End, and the ticks themselves.
   
   Only on this page. Everywhere else the scrollbar is the sole indication that
   there is more below, and removing it there would hide the page from the
   reader. */
html.is-deck { scrollbar-width: none; }
html.is-deck::-webkit-scrollbar { width: 0; height: 0; display: none; }

html.is-deck {
  scroll-snap-type: y mandatory;
  scroll-padding-top: var(--nav-h);
}

/* deck.js adds this to <html> once it has taken the scroll over. Native snapping
   fights an animated scroll and the result stutters, so it goes off — but only
   when something is actually driving the scroll instead. With JavaScript off,
   blocked, or thrown, the class never appears and the rules above stand, which
   is the whole fallback.

   A class rather than a root.style write, so both halves of the decision are in
   this file and the build output contains no inline styles at all. */
html.is-deck.is-deck-enhanced {
  scroll-snap-type: none;
  scroll-behavior: auto;
}

html.is-deck.is-deck-enhanced .slide,
html.is-deck.is-deck-enhanced .deck__end {
  scroll-snap-align: none;
  scroll-snap-stop: normal;
}

/* The banner is fixed, so it takes no layout space and slide one would otherwise
   sit at the very top of the page on load — uncentred, unlike every slide after
   it, which the scroll controller centres properly.
   
   Rather than scripting a jump on load (which flashes, and does nothing with
   JavaScript off), the deck simply opens with enough padding that slide one is
   already centred in the space below the banner at scroll position zero:
   
       banner height + half of whatever is left over after the slide
   
   max() keeps it sane on a viewport too short to centre anything. */
/* A slide is sized by whichever runs out first, WIDTH or HEIGHT.
 *
 * It used to be width alone, and on a monitor that is wide but not tall — a
 * 1920x1080 panel with browser chrome eating a hundred pixels — a slide came out
 * taller than the space under the banner and simply could not be seen whole. The
 * reader has to scroll a slide to read a slide, which defeats the deck.
 *
 * The height term is the tallest 16:9 box that fits below the banner with a
 * little air, converted back to a width. Whichever of the three is smallest wins,
 * so the deck fits any monitor without a media query per size.
 *
 * --deck-slide-h, not --slide-h: that name belongs to the home carousel, and two
 * different slides sharing one variable is a trap for whoever edits next. */
.page-pitch .deck {
  --deck-air: clamp(24px, 7vh, 96px);
  --deck-w: min(
    2100px,
    calc(100vw - 2 * var(--gutter)),
    calc((100vh - var(--nav-h) - var(--deck-air)) * 16 / 9)
  );
  --deck-slide-h: calc(var(--deck-w) * 9 / 16);
  padding-top: max(
    clamp(18px, 2.6vw, 48px),
    calc(var(--nav-h) + (100vh - var(--nav-h) - var(--deck-slide-h)) / 2)
  );
}

.page-pitch .slide,
.page-pitch .deck__end {
  scroll-snap-align: center;
  scroll-snap-stop: always;
}

/* ---- where you are in the deck ---------------------------- *
 *
 * A vertical column down the LEFT edge, centred against the slide. Vertical
 * because the deck moves vertically: the ticks then run the same way the reader
 * does, and the mark that lights up is at the height of the slide it belongs to
 * rather than at a right angle to the motion. Left because the download sits
 * bottom right and the two must never compete — one is the thing to do, the
 * other is only where you are.
 *
 * Hidden until deck.js adds is-deck-enhanced, exactly like the carousel arrows.
 * Without the script the page still scrolls, and a counter that could not follow
 * the scroll would be worse than no counter. */

.deck__hud { display: none; }

html.is-deck-enhanced .deck__hud {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(10px, .9vw, 20px);
  position: fixed;
  left: max(clamp(20px, 1.9vw, 52px), env(safe-area-inset-left, 0px));
  /* Centred on the viewport rather than pinned to a corner: the slide it
     describes is centred too, so the eye finds them together. */
  top: 50%;
  transform: translateY(-50%);
  z-index: 80;
}

.deck__count {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(12px, .78vw, 19px);
  font-weight: 900;
  letter-spacing: .1em;
  color: var(--ink-dim);
  /* The number changes every slide, so it lines up on its digits rather than
     shifting the slash sideways between 9 and 10. */
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.deck__count-now { color: #ffffff; }
.deck__count-sep { opacity: .45; margin-inline: .3em; }

.deck__ticks {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(5px, .42vw, 11px);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* A real button, so it is focusable and works from the keyboard with nothing
   added. The padding is the click target and the ::before is the visible mark:
   a 3px target is a design that only works for people with a steady hand. */
.deck__tick {
  appearance: none;
  border: 0;
  padding: clamp(3px, .22vw, 5px) clamp(6px, .5vw, 12px);
  background: none;
  cursor: pointer;
  display: block;
}
.deck__tick::before {
  content: '';
  display: block;
  /* A horizontal dash in a vertical stack. The current one grows sideways, away
     from the column, so the stack itself never shifts as you move through it. */
  width: clamp(10px, .85vw, 22px);
  height: clamp(2px, .16vw, 4px);
  border-radius: 99px;
  background: rgba(255, 255, 255, .26);
  transition: background .3s var(--ease), width .3s var(--ease);
}
.deck__tick:hover::before { background: rgba(255, 255, 255, .55); }
.deck__tick.is-on::before {
  background: var(--accent);
  width: clamp(18px, 1.5vw, 38px);
  box-shadow: 0 0 clamp(6px, .5vw, 14px) rgba(255, 150, 40, .7);
}
.deck__tick:focus-visible::before {
  background: #ffffff;
  box-shadow: 0 0 0 2px rgba(255, 160, 50, .9);
}

@media (prefers-reduced-motion: reduce) {
  .deck__tick::before { transition: none; }
}

/* Someone who has asked for less motion gets the snapping without the glide. */
@media (prefers-reduced-motion: reduce) {
  html.is-deck { scroll-behavior: auto; }
}


/* ============================================================
   Our Series — the slate. One row per show: artwork on the left,
   title and logline on the right, running down the page.
   ============================================================ */

/* Capped and centred, so the whole slate sits in the middle of the screen with
   even margins either side. The writing inside it stays left aligned — the block
   is centred, not the text. Without the cap the rows started hard against the
   left gutter with a field of empty blue to the right on a wide monitor. */
.page-series main { max-width: min(1700px, 100%); }

/* Capped to what the content actually needs — the artwork column, the gap, and
   the logline's measure — then centred. The page container was already centred,
   but the rows stretched across all of it while the writing only filled the
   left half, so the whole block read as shoved against the left gutter with a
   field of empty blue beside it. Narrowing the block is what centres it; the
   text inside stays left aligned. */
.slate {
  display: grid;
  gap: clamp(40px, 5vw, 96px);
  padding-bottom: clamp(40px, 6vw, 110px);
  /* An explicit percentage of the VIEWPORT, then centred. Nothing intrinsic.
     `fit-content` looked right on first paint and then drifted back to the left
     on a resize or a reload: it derives the width from the content, and the
     content's own tracks were sized in vw and ch, so the answer changed
     depending on whether the webfont had loaded and in what order things
     resolved. A percentage has no such argument with itself — it is the same
     number every layout pass. */
  width: min(1400px, 78vw);
  max-width: 100%;
  margin-inline: auto;
}

.slate__group { display: grid; gap: clamp(16px, 1.8vw, 34px); }

/* Set like the banner: same face, same weight, same tracking. */
.slate__heading {
  font-size: clamp(13px, 1vw, 24px);
  font-weight: 900;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-faint);
  padding-bottom: clamp(10px, 1vw, 18px);
  border-bottom: 1px solid var(--rule-soft);
}

.slate__rows { display: grid; gap: clamp(20px, 2.2vw, 44px); }

.show {
  display: grid;
  /* Both columns are percentages of the block above, so the artwork's left edge
     and the text's right edge are always the same distance from their side of
     the screen, at any width. */
  grid-template-columns: 40% minmax(0, 1fr);
  gap: 4%;
  align-items: center;
}

/* One rule for both states: the empty box and the real artwork are the same
   shape, so a row does not move when its picture arrives. */
.show__art {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: clamp(10px, .8vw, 22px);
  border: 1px solid rgba(255, 255, 255, .18);
  box-shadow: 0 20px 44px -24px rgba(0, 6, 32, .9);
}

/* The placeholder fill only applies to the empty div, never behind a picture. */
div.show__art {
  background:
    linear-gradient(160deg, rgba(255, 255, 255, .16), rgba(255, 255, 255, .05)),
    rgba(8, 28, 84, .5);
}

.show__text { display: grid; gap: clamp(6px, .55vw, 12px); }

.show__title {
  font-size: clamp(24px, 2.7vw, 72px);
  font-weight: 900;
  letter-spacing: .04em;
  text-transform: uppercase;
  line-height: 1.1;
  color: #ffffff;
}

.show__subject {
  font-size: clamp(11px, .8vw, 21px);
  font-weight: 700;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.show__logline {
  font-size: clamp(13px, .95vw, 22px);
  line-height: 1.65;
  color: var(--ink-dim);
  /* No measure cap: the column is a fixed share of the block, so it already is
     the measure. Capping it again would leave dead space inside the column and
     put the imbalance back. */
}

/* On a phone the artwork goes above the writing rather than beside it: a 24vw
   thumbnail next to text is unreadable at 390px. */
@media (max-width: 720px) {
  .show { grid-template-columns: 1fr; gap: 14px; }
  .show__art { max-width: 460px; }
}


/* ---- centred page head with a beam divider --------------- *
 * Used on Our Series: title, the light beam, then the line. All centred as a
 * block and centre-aligned as text. Everything BELOW it stays left aligned. */

/* Trying the rounded display face here first, on Our Series only. If it works
   it moves up to a plain .page-head__title rule and covers every page. */
.page-head--centred {
  justify-items: center;
  text-align: center;
  /* Tight. The beam's box is mostly transparent padding, so the gap here is on
     top of that and the three elements drifted apart. The beam pulls itself back
     in with negative margins below. */
  gap: clamp(2px, .3vw, 10px);
}

.page-head--centred .page-head__title {
  font-weight: 900;
}

.page-head--centred .page-head__lede {
  font-size: clamp(15px, 1.5vw, 34px);
  font-weight: 800;
  color: #ffffff;
  /* One line. It is a single short sentence and breaking it in half reads as an
     accident rather than a decision. */
  max-width: none;
  white-space: nowrap;
  /* A cool glow rather than the beam's warm one, so it reads as its own light
     instead of spill from the streak above it. */
  text-shadow:
    0 0 .2em rgba(255, 255, 255, .35),
    0 0 .6em rgba(120, 180, 255, .62),
    0 0 1.4em rgba(60, 130, 255, .5);
}

/* The same anamorphic streak as the selected nav tab, at page scale. Four
   stacked ellipses rather than a bar with a shadow: an ellipse is thickest at
   its centre and thins to nothing at both ends on its own, which is the taper a
   real light streak has and a rectangle cannot fake. */
/* The box has to keep the nav beam's PROPORTIONS, not just its gradients. The
   ellipse sizes are percentages of this element, so stretching a short box out
   to 760px wide spread the same falloff across ten times the distance and the
   glow went thin and washed out. aspect-ratio locks the shape instead. */
.beam {
  position: relative;
  /* Sized against the VIEWPORT, not its container. It used to be 72% of whatever
     it sat inside, which meant a different beam on every page: inside the money
     pages' 74ch prose column it came out two thirds the height it has on Our
     Shows, and since the negative margins below cancel a fixed amount of dead
     space, the shorter box got over-pulled and the streak landed across the
     bottom of the title instead of under it. One beam, one size, everywhere. */
  width: min(820px, 72vw);
  aspect-ratio: 5 / 1;
  /* The 5:1 box is mostly transparent above and below the streak, so it claims
     far more vertical space than it shows. These pull that dead space back out
     rather than letting it push the title and the line apart. */
  margin-block: clamp(-72px, -5vw, -22px);
  pointer-events: none;

  /* Four stacked ellipses: white core, hot inner, orange body, outer bloom.
   *
   * This is the version that works, and it has now survived two attempts to
   * improve it. A linear colour ramp masked into a beam shape gave a genuine
   * left-to-right fade and looked thin and washed; offset ellipses of different
   * hues gave coloured blobs with a gap. The reason both failed is the same: the
   * thing that makes this read as light is that every layer shares one centre
   * and one colour, so the falloff is the only thing the eye has to follow.
   *
   * Solid orange, four layers, nothing else. A red tint off the left end was
   * tried and dropped the same minute. If anything is ever added here it goes at
   * the END of the stack so it paints behind these four, or it flattens the
   * core. */
  background:
    radial-gradient(ellipse 34% 1.3% at 50% 50%,
      #ffffff 0%,
      rgba(255, 248, 230, 1) 30%,
      rgba(255, 210, 130, .68) 64%,
      rgba(255, 175, 65, 0) 100%),
    radial-gradient(ellipse 35% 4% at 50% 50%,
      rgba(255, 214, 140, 1) 0%,
      rgba(255, 162, 52, .8) 38%,
      rgba(255, 140, 32, 0) 100%),
    radial-gradient(ellipse 39% 13% at 50% 50%,
      rgba(255, 152, 40, .95) 0%,
      rgba(255, 135, 26, .55) 42%,
      rgba(255, 122, 18, 0) 80%),
    radial-gradient(ellipse 50% 44% at 50% 50%,
      rgba(255, 134, 26, .58) 0%,
      rgba(255, 120, 18, .22) 46%,
      rgba(255, 112, 14, 0) 78%);
}

/* ---- sparks ---------------------------------------------- *
 * Faint embers coming off the line. Eighteen of them, placed once with a fixed
 * seed rather than at random on every build, so the beam looks the same on every
 * page and in every screenshot.
 *
 * Two rules make them read as sparks instead of dust, which is the failure mode:
 * they cluster tightly on the streak's line and spread further out only toward
 * the ends, the way embers actually leave a flame; and the further one sits from
 * the line the fainter it is. Dust is evenly scattered and evenly bright.
 *
 * Drawn on ::after so they sit above the glow, and the box is a little wider and
 * much taller than the beam so they are not clipped at the edges. */
.beam::after {
  content: '';
  position: absolute;
  inset: -34% -5%;
  pointer-events: none;
  background-repeat: no-repeat;
  background-image:
    radial-gradient(circle, rgba(255, 208, 140, 0.56) 0%, rgba(255, 208, 140, 0) 68%),
    radial-gradient(circle, rgba(255, 208, 140, 0.54) 0%, rgba(255, 208, 140, 0) 68%),
    radial-gradient(circle, rgba(255, 208, 140, 0.37) 0%, rgba(255, 208, 140, 0) 68%),
    radial-gradient(circle, rgba(255, 208, 140, 0.37) 0%, rgba(255, 208, 140, 0) 68%),
    radial-gradient(circle, rgba(255, 176, 84, 0.32) 0%, rgba(255, 176, 84, 0) 68%),
    radial-gradient(circle, rgba(255, 208, 140, 0.32) 0%, rgba(255, 208, 140, 0) 68%),
    radial-gradient(circle, rgba(255, 208, 140, 0.48) 0%, rgba(255, 208, 140, 0) 68%),
    radial-gradient(circle, rgba(255, 176, 84, 0.48) 0%, rgba(255, 176, 84, 0) 68%),
    radial-gradient(circle, rgba(255, 208, 140, 0.56) 0%, rgba(255, 208, 140, 0) 68%),
    radial-gradient(circle, rgba(255, 176, 84, 0.37) 0%, rgba(255, 176, 84, 0) 68%),
    radial-gradient(circle, rgba(255, 208, 140, 0.48) 0%, rgba(255, 208, 140, 0) 68%),
    radial-gradient(circle, rgba(255, 208, 140, 0.55) 0%, rgba(255, 208, 140, 0) 68%),
    radial-gradient(circle, rgba(255, 208, 140, 0.36) 0%, rgba(255, 208, 140, 0) 68%),
    radial-gradient(circle, rgba(255, 208, 140, 0.59) 0%, rgba(255, 208, 140, 0) 68%),
    radial-gradient(circle, rgba(255, 208, 140, 0.51) 0%, rgba(255, 208, 140, 0) 68%),
    radial-gradient(circle, rgba(255, 176, 84, 0.46) 0%, rgba(255, 176, 84, 0) 68%),
    radial-gradient(circle, rgba(255, 208, 140, 0.36) 0%, rgba(255, 208, 140, 0) 68%),
    radial-gradient(circle, rgba(255, 208, 140, 0.24) 0%, rgba(255, 208, 140, 0) 68%);
  background-size: 3.3px 3.3px, 1.9px 1.9px, 1.8px 1.8px, 2.8px 2.8px, 2.8px 2.8px, 2.6px 2.6px, 1.7px 1.7px, 2.5px 2.5px, 2.4px 2.4px, 3.1px 3.1px, 2.1px 2.1px, 3.1px 3.1px, 1.6px 1.6px, 3.4px 3.4px, 3.0px 3.0px, 3.3px 3.3px, 1.8px 1.8px, 2.6px 2.6px;
  background-position: 5.8% 51.8%, 11.2% 52.3%, 17.0% 57.0%, 19.6% 57.0%, 29.0% 58.4%, 30.2% 41.5%, 35.6% 46.1%, 41.9% 54.1%, 47.4% 51.7%, 55.0% 57.1%, 56.9% 45.9%, 64.2% 48.1%, 70.3% 57.5%, 75.3% 49.3%, 76.4% 53.2%, 81.7% 45.5%, 87.0% 42.5%, 95.4% 39.1%;
}


/* The tagline holds one line everywhere it fits. On a phone it cannot, and a
   line running off the side is worse than a break. */
@media (max-width: 640px) {
  .page-head--centred .page-head__lede { white-space: normal; max-width: 26ch; }
}

/* ---- a different crop per page ---------------------------- *
 * One asset, four framings. His field is a diagonal sweep with the bright band
 * running from the lower right up through the middle, so every position below
 * keeps that band in frame — the variation is which part of it you get, not
 * whether you get any. Landing a page in a dark corner is what made this look
 * wrong the first time. */

.page-series  { --bg-x: 30%; --bg-y: 24%; }
.page-ask     { --bg-x: 66%; --bg-y: 32%; }
.page-seed    { --bg-x: 40%; --bg-y: 58%; }
.page-tax     { --bg-x: 72%; --bg-y: 66%; }

/* ============================================================
   The money pages — Our Ask, Initial 500K Seed, GA Tax Credit.

   These three carry Elijah's budget sheets. They are documents to READ, so the
   prose keeps the narrow measure the rest of the site uses, but a five-column
   table squeezed into a reading column is unreadable and scrolls sideways with
   half the screen empty. So the column widens for the tables and the prose is
   pulled back in on its own.
   ============================================================ */

.page-ask main,
.page-tax main {
  max-width: min(1700px, 100%);
}

/* The head is CENTRED on all three money pages, but the lede is NOT the glowing
   one-line tagline that treatment carries on Our Shows. That styling exists for
   "Framing the world for the next generation" — five words, one line, a wordmark
   in prose. Here the lede is a full sentence explaining a budget, and at 34px
   with a glow behind it, it competes with the title instead of introducing it.
   Centred, ordinary weight, and a measure it can actually break on. */
/* More air around the beam here than on Our Shows. There the beam separates a
   title from a five-word tagline and wants to sit close; here it separates a
   title from a sentence, and the same tight spacing reads as crowding. The
   number is the beam's negative margin, which cancels the transparent padding
   in its 5:1 box — less negative is more gap. */
.page-ask .page-head .beam,
.page-tax .page-head .beam {
  margin-block: clamp(-56px, -3.5vw, -10px);
}

.page-ask .page-head--centred .page-head__lede,
.page-tax .page-head--centred .page-head__lede {
  font-size: clamp(15px, 1.3vw, 30px);
  font-weight: 600;
  color: var(--ink-dim);
  white-space: normal;
  max-width: 62ch;
  margin-inline: auto;
  text-shadow: none;
}

/* Prose keeps its measure. A line of text 1700px wide is a line nobody finishes.
   margin-inline: auto matters as much as the max-width: without it the capped
   block sits against the left gutter while the full-width tables below are
   centred, and the page reads as two columns that do not line up. */
.page-ask .page-head,
.page-tax .page-head,
.page-ask .section__body,
.page-tax .section__body {
  max-width: 74ch;
  margin-inline: auto;
}

/* ---- headline figures ------------------------------------ *
 * Three numbers across the top. The claim; the tables underneath are the
 * evidence. Text, never an exported graphic, so they can be selected, copied,
 * read aloud and searched. */

.figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: clamp(12px, 1.2vw, 28px);
  margin-block: clamp(22px, 3vw, 52px);
}

.figure {
  padding: clamp(18px, 1.6vw, 38px) clamp(18px, 1.6vw, 34px);
  border-radius: clamp(10px, .7vw, 20px);
  border: 1px solid rgba(255, 255, 255, .14);
  background: linear-gradient(165deg, rgba(255, 255, 255, .07), rgba(255, 255, 255, .02));
  box-shadow: 0 20px 44px -28px rgba(0, 6, 32, .95);
}

.figure__value {
  font-family: var(--font-display);
  font-size: clamp(28px, 2.6vw, 68px);
  font-weight: 900;
  line-height: 1.02;
  letter-spacing: -.01em;
  color: #ffffff;
  margin: 0 0 .35em;
  /* Figures are read down a column as much as across a row, so they line up on
     their digits rather than drifting with each number's own widths. */
  font-variant-numeric: tabular-nums;
}

/* The first figure on a page is the one the page exists to say. */
.figure:first-child .figure__value { color: var(--accent); }

.figure__label {
  margin: 0;
  font-size: clamp(11px, .72vw, 16px);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

/* ---- the tables ------------------------------------------ */

/* Money columns line up on their digits. Without this the thousands separators
   wander and a column of dollar figures cannot be compared down the page. */
.ask-table td,
.ask-table th { font-variant-numeric: tabular-nums; }

/* Each table is its own block with air around it, rather than three tables
   running together into one wall of numbers. */
.page-ask .section,
.page-tax .section {
  padding-block: clamp(10px, 1.2vw, 26px);
  border-top: 0;
}
