/* =====================================================================
   ZON — Colors & Type foundations
   Core tokens for the ZON brand system.
   ===================================================================== */

/* -------- Fonts -------------------------------------------------------- */
@font-face {
  font-family: "Neue Haas Grotesk Display";
  src: url("fonts/NeueHaasGroteskDisplay-35Thin.otf") format("opentype");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Neue Haas Grotesk Display";
  src: url("fonts/NeueHaasGroteskDisplay-55Roman.otf") format("opentype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Neue Haas Grotesk Display";
  src: url("fonts/NeueHaasGroteskDisplay-75Bold.otf") format("opentype");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  /* -----------------------------------------------------------
     CORE PALETTE (from Zon Color Palette.pdf)
     --------------------------------------------------------- */
  --zon-spacelight: #010214; /* near-black, the brand's dark anchor */
  --zon-deep-red: #cb2f19; /* burning-red edge */
  --zon-sunlight: #ff6826; /* primary brand orange */
  --zon-amber: #ffc06b; /* warm highlight */
  --zon-cream: #efe6d4; /* soft neutral, paper */
  --zon-white: #ffffff;

  /* Extended shades — derived, not from the palette PDF, for UI */
  --zon-space-900: #010214;
  --zon-space-800: #0a0b1d;
  --zon-space-700: #14162a;
  --zon-space-600: #1f2239;
  --zon-space-500: #2c304a;
  --zon-space-400: #4a4f6b;
  --zon-space-300: #7a7f96;
  --zon-space-200: #b6b9c7;
  --zon-space-100: #e2e3ea;

  --zon-cream-50: #fbf8f1;
  --zon-cream-100: #efe6d4;
  --zon-cream-200: #e2d5b8;
  --zon-cream-300: #cbbd9c;

  --zon-sun-300: #ffd8a8;
  --zon-sun-400: #ffc06b;
  --zon-sun-500: #ff8a3d;
  --zon-sun-600: #ff6826; /* primary */
  --zon-sun-700: #e54b15;
  --zon-sun-800: #cb2f19;
  --zon-sun-900: #8f1d0f;

  /* -----------------------------------------------------------
     SEMANTIC — Light mode (cream paper)
     --------------------------------------------------------- */
  --bg: var(--zon-cream-50);
  --bg-alt: var(--zon-cream-100);
  --surface: #ffffff;
  --surface-alt: var(--zon-cream-100);
  --surface-inverse: var(--zon-spacelight);

  --fg: var(--zon-spacelight);
  --fg-1: var(--zon-spacelight);
  --fg-2: #3a3d53; /* ~space-500 lightened */
  --fg-3: var(--zon-space-400);
  --fg-muted: var(--zon-space-300);
  --fg-on-dark: var(--zon-cream-50);
  --fg-on-dark-2: #b8b9c7;

  --accent: var(--zon-sun-600);
  --accent-hover: var(--zon-sun-700);
  --accent-press: var(--zon-sun-800);
  --accent-soft: #ffe6d6;
  --accent-fg: var(--zon-spacelight); /* on orange */

  --border: rgba(1, 2, 20, 0.12);
  --border-strong: rgba(1, 2, 20, 0.24);
  --border-inverse: rgba(239, 230, 212, 0.16);

  /* Status */
  --success: #2e7d4f;
  --warning: var(--zon-sun-600);
  --danger: var(--zon-deep-red);
  --info: #3a4e7a;

  /* Signature gradients */
  --gradient-sunlight: linear-gradient(
    180deg,
    #fbf8f1 0%,
    #ffc06b 40%,
    #ff6826 78%,
    #cb2f19 100%
  ); /* @kind color */
  --gradient-spacelight: linear-gradient(
    125deg,
    #ff8a3d 0%,
    #ff6826 28%,
    #cb2f19 52%,
    #2a0a1a 80%,
    #010214 100%
  ); /* @kind color */
  --gradient-horizon: linear-gradient(
    180deg,
    #010214 0%,
    #14162a 45%,
    #cb2f19 78%,
    #ff8a3d 92%,
    #ffc06b 100%
  ); /* @kind color */
  --gradient-logo: linear-gradient(
    90deg,
    #ffd8a8 0%,
    #ff8a3d 45%,
    #ff6826 70%,
    #cb2f19 100%
  ); /* @kind color */

  /* -----------------------------------------------------------
     SPACING
     --------------------------------------------------------- */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --space-24: 96px;
  --space-32: 128px;

  /* -----------------------------------------------------------
     RADII — low-key; ZON is mostly sharp-edged
     --------------------------------------------------------- */
  --radius-0: 0px;
  --radius-1: 2px;
  --radius-2: 4px;
  --radius-3: 8px;
  --radius-pill: 999px;

  /* -----------------------------------------------------------
     SHADOWS — restrained, cool-cast toward space-navy
     --------------------------------------------------------- */
  --shadow-xs: 0 1px 2px rgba(1, 2, 20, 0.06);
  --shadow-sm: 0 2px 6px rgba(1, 2, 20, 0.06), 0 1px 2px rgba(1, 2, 20, 0.05);
  --shadow-md: 0 6px 18px rgba(1, 2, 20, 0.08), 0 2px 4px rgba(1, 2, 20, 0.04);
  --shadow-lg: 0 20px 40px rgba(1, 2, 20, 0.14);
  --shadow-glow:
    0 0 0 1px rgba(255, 104, 38, 0.35), 0 0 40px rgba(255, 104, 38, 0.25);

  /* -----------------------------------------------------------
     TYPE — Neue Haas Grotesk Display
     --------------------------------------------------------- */
  --font-sans:
    "Neue Haas Grotesk Display", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-display:
    "Neue Haas Grotesk Display", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-mono:
    "Neue Haas Grotesk Display", "Helvetica Neue", Helvetica, Arial, sans-serif;

  --fw-thin: 300; /* @kind font */
  --fw-regular: 400; /* @kind font */
  --fw-bold: 700; /* @kind font */

  /* Type scale (desktop baseline) */
  --fs-display-xl: clamp(72px, 9vw, 148px); /* @kind font */
  --fs-display: clamp(56px, 6.5vw, 104px); /* @kind font */
  --fs-h1: clamp(40px, 4.5vw, 64px); /* @kind font */
  --fs-h2: clamp(32px, 3.2vw, 44px); /* @kind font */
  --fs-h3: 24px; /* @kind font */
  --fs-h4: 18px; /* @kind font */
  --fs-body: 16px; /* @kind font */
  --fs-body-sm: 14px; /* @kind font */
  --fs-caption: 12px; /* @kind font */
  --fs-eyebrow: 11px; /* @kind font */

  --lh-tight: 0.96; /* @kind font */
  --lh-snug: 1.08; /* @kind font */
  --lh-normal: 1.28; /* @kind font */
  --lh-loose: 1.55; /* @kind font */

  --tracking-tight: -0.02em; /* @kind font */
  --tracking-normal: 0em; /* @kind font */
  --tracking-wide: 0.08em; /* @kind font */
  --tracking-eyebrow: 0.16em; /* @kind font */

  /* -----------------------------------------------------------
     MOTION
     --------------------------------------------------------- */
  --ease-standard: cubic-bezier(0.22, 0.61, 0.36, 1); /* @kind other */
  --ease-emphasis: cubic-bezier(0.16, 1, 0.3, 1); /* @kind other */
  --ease-in: cubic-bezier(0.5, 0, 0.75, 0); /* @kind other */
  --dur-fast: 140ms; /* @kind other */
  --dur-std: 240ms; /* @kind other */
  --dur-slow: 520ms; /* @kind other */
}

/* -----------------------------------------------------------
   SEMANTIC — Dark mode (spacelight)
   Apply with [data-theme="dark"] on <html> or a container.
   --------------------------------------------------------- */
[data-theme="dark"] {
  --bg: var(--zon-spacelight);
  --bg-alt: var(--zon-space-800);
  --surface: var(--zon-space-700);
  --surface-alt: var(--zon-space-600);
  --surface-inverse: var(--zon-cream-50);

  --fg: var(--zon-cream-50);
  --fg-1: var(--zon-cream-50);
  --fg-2: #b8b9c7;
  --fg-3: var(--zon-space-300);
  --fg-muted: var(--zon-space-400);
  --fg-on-dark: var(--zon-cream-50);

  --accent: var(--zon-sun-500);
  --accent-hover: var(--zon-sun-400);
  --accent-press: var(--zon-sun-600);
  --accent-soft: rgba(255, 104, 38, 0.14);

  --border: rgba(239, 230, 212, 0.12);
  --border-strong: rgba(239, 230, 212, 0.28);
}

/* =====================================================================
   BASE ELEMENTS (opt-in — attach `.zon` to root or apply to <body>)
   ===================================================================== */
html,
body {
  font-family: var(--font-sans);
  font-weight: var(--fw-regular);
  color: var(--fg);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: "ss01", "kern";
  text-rendering: optimizeLegibility;
}

/* Type roles — use these classes rather than re-declaring sizes */
.zon-eyebrow {
  font: var(--fw-regular) var(--fs-eyebrow)/1.2 var(--font-sans);
  text-transform: uppercase;
  letter-spacing: var(--tracking-eyebrow);
  color: var(--fg-2);
}
.zon-display-xl {
  font: var(--fw-thin) var(--fs-display-xl)/var(--lh-tight) var(--font-display);
  letter-spacing: var(--tracking-tight);
  color: var(--fg-1);
  text-wrap: balance;
}
.zon-display {
  font: var(--fw-thin) var(--fs-display)/var(--lh-tight) var(--font-display);
  letter-spacing: var(--tracking-tight);
  color: var(--fg-1);
  text-wrap: balance;
}
.zon-h1 {
  font: var(--fw-thin) var(--fs-h1)/var(--lh-snug) var(--font-display);
  letter-spacing: var(--tracking-tight);
  color: var(--fg-1);
  text-wrap: balance;
}
.zon-h2 {
  font: var(--fw-regular) var(--fs-h2)/var(--lh-snug) var(--font-display);
  letter-spacing: -0.01em;
  color: var(--fg-1);
  text-wrap: balance;
}
.zon-h3 {
  font: var(--fw-bold) var(--fs-h3)/1.2 var(--font-sans);
  letter-spacing: -0.005em;
  color: var(--fg-1);
}
.zon-h4 {
  font: var(--fw-bold) var(--fs-h4)/1.3 var(--font-sans);
  color: var(--fg-1);
}
.zon-body {
  font: var(--fw-regular) var(--fs-body)/var(--lh-loose) var(--font-sans);
  color: var(--fg-2);
  text-wrap: pretty;
}
.zon-body-sm {
  font: var(--fw-regular) var(--fs-body-sm)/1.5 var(--font-sans);
  color: var(--fg-2);
}
.zon-caption {
  font: var(--fw-regular) var(--fs-caption)/1.4 var(--font-sans);
  color: var(--fg-3);
}
.zon-mono {
  font: var(--fw-regular) var(--fs-body-sm)/1.45 var(--font-mono);
  color: var(--fg-2);
}

/* Signature logotype treatment: gradient text */
.zon-gradient-text {
  background: var(--gradient-logo);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
/* =====================================================================
   ZON — shell layout, reconciled from the five sites' styles.css
   Radiance 9e1b983, clients/latos/public/styles.css, 2026-08-20.
   ADR 0021 item 3: one template, newer behaviour wins.
   ===================================================================== */

@keyframes zonPulse {
  0%,
  100% {
    transform: scale(0.985);
    opacity: 0.92;
  }
  50% {
    transform: scale(1.04);
    opacity: 1;
  }
}
@keyframes zonRise {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    scroll-behavior: auto !important;
  }
}

* {
  box-sizing: border-box;
}
html {
  scroll-behavior: smooth;
}
body {
  margin: 0;
  background: var(--zon-cream-50);
}
[hidden] {
  display: none !important;
}
a {
  color: var(--accent);
  text-decoration: none;
}
:focus-visible {
  outline: 3px solid var(--zon-amber);
  outline-offset: 3px;
}
::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
::-webkit-scrollbar-thumb {
  background: rgba(1, 2, 20, 0.18);
  border-radius: 6px;
}

#zh-railnav a {
  color: #8b8fa2;
}
#zh-main > section {
  flex: 0 0 auto;
}

/* --------------------------------------------------------------------
   The Deployment Package reader (`#tdp`).

   `tools/build-tdp-fragment.py` emits the markup these rules style, and it
   emits no `style=` attributes at all -- that is the whole reason it is a
   generator rather than a verbatim slice. An inline attribute outranks
   every rule below, so styling the hub's own bytes would have meant an
   `!important` on nearly every declaration; instead the cascade is clean
   and this block is the only thing deciding how the reader looks.

   Both grid tracks are flexible. The contents pane is the index, never the
   wider of the two: a fixed first track starves the document at the widths
   that matter, and a 36-page package rendered into 250-odd pixels wraps
   every heading and cuts body copy to three words a line.
   -------------------------------------------------------------------- */
.tdp-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  margin-bottom: 28px;
}
.tdp-eyebrow {
  color: var(--zon-sun-600);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.tdp-head__h {
  margin: 12px 0 0;
  color: var(--zon-spacelight);
  font-weight: 300;
  font-size: clamp(34px, 4vw, 54px);
  letter-spacing: -0.025em;
  line-height: 0.98;
}
.tdp-head__side {
  display: flex;
  align-items: center;
  gap: 16px;
}
.tdp-head__meta {
  color: var(--zon-space-300);
  font-size: 13px;
}
.tdp-btn {
  border: 1px solid var(--border);
  border-radius: 2px;
  background: var(--zon-white);
  color: var(--zon-spacelight);
  font: inherit;
  font-size: 13px;
  padding: 7px 13px;
  cursor: pointer;
  transition: color var(--dur-std) var(--ease-standard),
    border-color var(--dur-std) var(--ease-standard);
}
.tdp-btn:hover {
  color: var(--zon-sun-700);
  border-color: var(--zon-sun-600);
}

.tdp-reader {
  position: relative;
  display: grid;
  grid-template-columns: minmax(240px, 300px) minmax(0, 1fr);
  height: clamp(560px, 74vh, 900px);
  border: 1px solid var(--border);
  background: var(--zon-white);
}
.tdp-reader.tdp-full {
  position: fixed;
  inset: 0;
  z-index: 900;
  height: 100vh;
  height: 100dvh;
  border: 0;
}
.tdp-exit {
  display: none;
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 2;
}
.tdp-reader.tdp-full .tdp-exit {
  display: block;
}

.tdp-toc {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--zon-cream-50);
  border-right: 1px solid var(--border);
}
.tdp-toc__head {
  padding: 18px 18px 14px;
  border-bottom: 1px solid var(--border);
}
.tdp-count {
  margin-top: 8px;
  color: var(--zon-spacelight);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.tdp-progress {
  margin-top: 10px;
  height: 2px;
  background: rgba(1, 2, 20, 0.12);
}
.tdp-progress__fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--zon-sun-600);
  transition: width var(--dur-std) var(--ease-standard);
}
.tdp-tree {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 12px 10px 24px;
  scrollbar-width: thin;
  scrollbar-color: rgba(1, 2, 20, 0.16) transparent;
}
/* The pane scrolls independently of the page, and the browser default reads
   as a page-level scrollbar -- which of the two is moving stops being
   obvious the moment they look the same. */
.tdp-tree::-webkit-scrollbar {
  width: 10px;
}
.tdp-tree::-webkit-scrollbar-track {
  background: transparent;
}
.tdp-tree::-webkit-scrollbar-thumb {
  background: rgba(1, 2, 20, 0.16);
  border-radius: 0;
}
.tdp-group {
  margin: 18px 0 6px;
  padding: 0 10px;
  color: var(--zon-space-300);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.tdp-tree > .tdp-group:first-child {
  margin-top: 0;
}
/* A subhead is a label, not a destination: `2.1` has no article behind it in
   the package, so making it clickable would be a link to nowhere. */
.tdp-sub {
  margin: 12px 0 4px;
  padding: 0 10px;
  color: var(--zon-spacelight);
  font-size: 13px;
  font-weight: 700;
}
.tdp-sub__n {
  display: inline-block;
  min-width: 30px;
  color: var(--zon-space-300);
  font-variant-numeric: tabular-nums;
  font-weight: 400;
}
.tdp-item {
  display: flex;
  gap: 8px;
  padding: 7px 10px;
  border-left: 2px solid transparent;
  color: var(--fg-2);
  font-size: 13px;
  line-height: 1.35;
  text-decoration: none;
  transition: background var(--dur-std) var(--ease-standard),
    color var(--dur-std) var(--ease-standard);
}
.tdp-item--child {
  padding-left: 30px;
}
.tdp-item__n {
  flex: 0 0 auto;
  color: var(--zon-space-300);
  font-variant-numeric: tabular-nums;
}
.tdp-item__t {
  /* `min-width: 0` is the whole point of this rule: a flex item's default
     minimum is its content width, so without it the longest entry title sets
     the rail's width and the tree scrolls sideways instead of wrapping. */
  min-width: 0;
}
.tdp-item:hover {
  color: var(--zon-sun-700);
}
.tdp-item[aria-current="location"] {
  background: #ffe9dc;
  border-left-color: var(--zon-sun-600);
  color: var(--zon-sun-800);
  font-weight: 700;
}
.tdp-item[aria-current="location"] .tdp-item__n {
  color: var(--zon-sun-800);
}

.tdp-scroll {
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
  background: var(--zon-white);
}
.tdp-crumb {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 32px;
  background: var(--zon-white);
  border-bottom: 1px solid var(--border);
}
.tdp-crumb__text {
  color: var(--fg-2);
  font-size: 12px;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tdp-crumb__nav {
  display: flex;
  gap: 8px;
  flex: 0 0 auto;
}
/* Disabled at the ends but never removed: dropping a button from the DOM
   reflows the pair every time the reader reaches the first or last section. */
.tdp-nav {
  width: 30px;
  height: 30px;
  border: 1px solid var(--border);
  border-radius: 2px;
  background: var(--zon-white);
  color: var(--zon-spacelight);
  font: inherit;
  line-height: 1;
  cursor: pointer;
  transition: color var(--dur-std) var(--ease-standard),
    border-color var(--dur-std) var(--ease-standard);
}
.tdp-nav:hover:not(:disabled) {
  color: var(--zon-sun-700);
  border-color: var(--zon-sun-600);
}
.tdp-nav:disabled {
  color: var(--zon-space-200);
  cursor: default;
}

.tdp-art {
  padding: 36px 32px;
  border-top: 1px solid var(--border);
}
.tdp-art:first-of-type {
  border-top: 0;
}
.tdp-art__kicker {
  color: var(--zon-sun-600);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.tdp-art__h {
  margin: 10px 0 0;
  color: var(--zon-spacelight);
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.1;
}
.tdp-art__body p,
.tdp-art__body li,
.tdp-art__body div {
  color: #1f2133;
  font-size: 16px;
  line-height: 1.62;
  max-width: 74ch;
}
.tdp-art__body p {
  margin: 14px 0 0;
}
.tdp-art__body h4 {
  margin: 24px 0 0;
  color: var(--zon-spacelight);
  font-size: 15px;
  font-weight: 700;
}

/* The end of a part is otherwise a dead stop -- the reader scrolls into the
   next part's first section with nothing saying a part ended. */
.tdp-end {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 32px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
}
.tdp-end__label {
  color: var(--zon-space-300);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.tdp-end__next {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  padding: 9px 14px;
  border: 1px solid var(--zon-sun-600);
  border-radius: 2px;
  color: var(--zon-sun-800);
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
  transition: color var(--dur-std) var(--ease-standard),
    border-color var(--dur-std) var(--ease-standard);
}
.tdp-end__next:hover {
  color: var(--zon-sun-700);
  border-color: var(--zon-sun-700);
}
.tdp-end__target {
  color: var(--fg-2);
  font-weight: 400;
}

/* Six chips in a tray, replacing a bold line of names joined by unicode
   arrows: the brand rules the dingbats out as glyphs, and a chip row keeps
   its meaning when it wraps where a single arrow line does not. */
.tdp-flow {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 16px;
  padding: 12px;
  background: var(--zon-cream-50);
}
.tdp-chip {
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: 2px;
  background: var(--zon-white);
  color: var(--zon-spacelight);
  font-size: 13px;
  font-weight: 700;
}
.tdp-chip--first {
  border-color: var(--zon-sun-600);
  color: var(--zon-sun-800);
}

/* `table-layout: fixed` with percentage columns rather than the intrinsic
   widths a default table picks. The failure it avoids is the one that makes
   the table useless: with content-driven widths the three narrow columns
   hold their intrinsic size at a narrow pane and `What happens` -- the
   entire substance of the table -- absorbs the whole deficit. Every column
   here shrinks proportionally instead, so none can collapse and the row
   never overflows sideways. */
.tdp-tbl {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
  margin-top: 16px;
  font-size: 13px;
}
.tdp-tbl th,
.tdp-tbl td {
  border: 1px solid var(--border);
  padding: 9px 11px;
  text-align: left;
  vertical-align: top;
  color: var(--fg-2);
  line-height: 1.5;
  overflow-wrap: break-word;
}
.tdp-tbl th {
  background: var(--zon-spacelight);
  color: var(--zon-cream-50);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.tdp-tbl tbody tr:nth-child(even) td {
  background: var(--zon-cream-50);
}
.tdp-tbl th:nth-child(1),
.tdp-tbl td:nth-child(1) {
  width: 9%;
}
.tdp-tbl th:nth-child(2),
.tdp-tbl td:nth-child(2) {
  width: 18%;
}
.tdp-tbl th:nth-child(4),
.tdp-tbl td:nth-child(4) {
  width: 14%;
}

@media (prefers-reduced-motion: reduce) {
  .tdp-item,
  .tdp-btn,
  .tdp-nav,
  .tdp-end__next,
  .tdp-progress__fill {
    transition: none;
  }
}

@media (max-width: 1180px) {
  .tdp-reader {
    grid-template-columns: minmax(216px, 264px) minmax(0, 1fr);
  }
}

/* Stacked, and no pane pinned to a fixed height. Pinning them is what the
   hub does, and it puts a 36-page document behind a 520px window with a
   contents pane showing four of 31 entries. Once stacked, the page is the
   scroller and both panes grow to their content. `#tdp-toc` keeps a cap so
   the contents cannot push the document off the bottom of the screen, and
   its divider moves from the right edge to the bottom -- which is only
   possible because the border is a rule here and not a `style=` attribute
   the fragment carries. */
@media (max-width: 980px) {
  .tdp-reader {
    grid-template-columns: 1fr;
    height: auto;
  }
  .tdp-reader.tdp-full {
    height: 100dvh;
  }
  .tdp-toc {
    border-right: 0;
    border-bottom: 1px solid var(--border);
  }
  .tdp-tree {
    max-height: 232px;
  }
  .tdp-scroll {
    overflow-y: visible;
  }
  .tdp-reader.tdp-full .tdp-scroll {
    overflow-y: auto;
  }
  .tdp-art {
    padding: 32px 20px;
  }
  .tdp-crumb {
    padding: 12px 20px;
  }
  /* The header row is dropped rather than kept two screens above its data,
     so each cell prints its own column name from `data-label` instead. */
  .tdp-tbl,
  .tdp-tbl tbody,
  .tdp-tbl tr,
  .tdp-tbl td {
    display: block;
    width: auto;
  }
  .tdp-tbl thead {
    display: none;
  }
  .tdp-tbl tr {
    margin-top: 12px;
    border: 1px solid var(--border);
  }
  .tdp-tbl td {
    border: 0;
    border-top: 1px solid var(--border);
  }
  .tdp-tbl tr td:first-child {
    border-top: 0;
  }
  .tdp-cell::before {
    content: attr(data-label);
    display: block;
    margin-bottom: 2px;
    color: var(--zon-space-300);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
  }
}

/* The roadmap phase tabs' resting colours -- the two labels inside each
   `#zh-phasebar` button. These belong in the sheet rather than in
   `ROADMAP_JS`'s `paint()` precisely because they *can* live here: unlike the
   button's own background, which the extracted fragment pins with a
   `style="background: none"` attribute, neither label carries an inline
   colour, so a plain selector wins and the script only has to override the
   active one. Without these the number and the name inherit the same colour
   and the tab reads as one run of text. */
.zh-ph-num {
  color: var(--fg-3);
}
.zh-ph-name {
  color: var(--fg-1);
}

.presentation-section {
  padding: 88px 56px;
  background: var(--zon-cream-50);
}
.presentation-section h2 {
  margin: 12px 0 32px;
  color: var(--zon-spacelight);
  font-size: clamp(32px, 3.6vw, 46px);
  font-weight: 300;
  letter-spacing: -0.02em;
}
.presentation-eyebrow {
  color: var(--zon-sun-800);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.presentation-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
}
.presentation-card {
  min-height: 44px;
  padding: 0;
  overflow: hidden;
  border: 1px solid rgba(1, 2, 20, 0.1);
  border-radius: 3px;
  background: #fff;
  color: inherit;
  cursor: pointer;
  font: inherit;
  text-align: left;
}
.presentation-art {
  display: grid;
  place-items: center;
  aspect-ratio: 16 / 9;
  color: #fff;
  background:
    radial-gradient(circle at 72% 28%, rgb(255 184 0 / 70%), transparent 30%),
    var(--zon-spacelight);
}
.presentation-cover {
  width: 100%;
  object-fit: cover;
}
.presentation-copy,
.presentation-copy span {
  display: block;
}
.presentation-copy {
  padding: 20px;
}
.presentation-copy strong {
  display: block;
  margin-bottom: 7px;
  font-size: 20px;
}
.presentation-copy span {
  color: var(--fg-2);
}

/* #116: the `resources` section's two card grids -- `document`s in
   `#zh-resgrid`, `deck`s in `#zh-deckgrid`, the exact ids this file's own
   mobile-omission comment above already named. Four columns, row-major
   (native `grid-template-columns: repeat(4, 1fr)` fill, no manual
   placement) -- inferred from the ticket's own spec, not measured: no local
   clone of the Radiance source was available to re-measure the real site's
   grid against. `.zh-rescard` is shared by both grids' cards; the slide
   badge is `deck`-only, per `_resource_card_html()`. */
#zh-resgrid,
#zh-deckgrid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
  margin: 16px 0 32px;
}
.zh-rescard {
  position: relative;
  overflow: hidden;
  border: 1px solid rgba(1, 2, 20, 0.1);
  border-radius: 3px;
  background: #fff;
}
.zh-rescard img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: var(--zon-cream-100);
}
.zh-rescard-thumb {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 4 / 3;
  background: var(--zon-cream-100);
}
.zh-rescard-thumb--empty {
  color: var(--zon-space-400);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.zh-rescard-title {
  display: block;
  padding: 10px 12px;
  font-size: 14px;
  font-weight: 600;
  color: var(--zon-spacelight);
}
.zh-rescard-badge {
  position: absolute;
  top: 8px;
  right: 8px;
  padding: 2px 8px;
  border-radius: 3px;
  background: rgba(1, 2, 20, 0.72);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

/* The `presentations` grid. `auto-fill` with a floor rather than the fixed
   `repeat(4, 1fr)` the two `resources` grids use: those two are stuck needing a
   breakpoint to collapse (see this file's own mobile-omission comment above,
   which explains why they never got one), and a track list that reflows on its
   own does not. Three across at the content column's real width, fewer as it
   narrows, no media query in the way.

   A presentation card is wider than a resource card, so its image is 16:9
   rather than 4:3 -- a slide export and a video frame are both widescreen, and
   4:3 would crop the sides off every one of them. */
#zh-presgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 24px;
  margin: 16px 0 32px;
}
#zh-presgrid .zh-rescard img {
  aspect-ratio: 16 / 9;
}
#zh-presgrid .zh-rescard .zh-rescard-thumb {
  aspect-ratio: 16 / 9;
}
#zh-presgrid .zh-rescard-title {
  padding: 12px 14px 0;
  font-size: 15px;
}
/* The meta line's own bottom padding closes the card, so the title above it
   sets none -- two stacked paddings between the title and the line that
   describes it would read as two separate blocks rather than one caption. */
.zh-rescard-meta {
  display: block;
  padding: 4px 14px 12px;
  font-size: 12.5px;
  color: var(--zon-space-400);
  font-variant-numeric: tabular-nums;
}
/* A `video` card is an `<a>` (`_presentation_card_html()`), so it needs the
   anchor colour and underline taken back off -- the card is the affordance, and
   an underlined title inside a bordered, thumbnailed tile reads as a second,
   competing link. */
.zh-rescard--link {
  display: block;
  text-decoration: none;
  color: inherit;
}
.zh-rescard--link:hover {
  border-color: rgba(1, 2, 20, 0.28);
}

/* The platform footer bar. Measured from the Radiance console's own footer
   (see `_FOOTER_LINKS`): a top rule, the copyright pushed to one end and the
   link group to the other, 12px muted text.

   Two adaptations, both forced by this shell rather than chosen. The source
   insets its row with `px-4` inside a centred `container`; there is no such
   container here, so the inset is instead the `56px` every `_SECTION_STYLE`
   already uses, which is what lines the copyright up with the section copy
   above it. And the source stacks at Tailwind's `sm` (640px) while this sheet's
   only breakpoint is 760px -- the stack rule lives in that existing block
   below rather than opening a second, nearly-identical media query.

   These are `.zh-`-prefixed rather than more `.site-footer` rules on purpose:
   `ADMIN_CSS` owns `.site-footer` for the authoring surface's own footer, and
   `portal.admin` serves that sheet at the same `/static/style.css` path this
   one answers on `portal.serve`. Distinct class, no collision to reason
   about. */
.zh-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 24px 56px;
  border-top: 1px solid var(--border);
  color: var(--fg-2);
  font-size: 12px;
  /* The source's `mt-auto`. `#zh-main` is a `height:100vh` column flex
     container, so this absorbs whatever space the sections leave and holds the
     footer at the bottom of the page instead of letting it ride up under short
     content. On a page that does overflow there is no free space to absorb and
     the margin resolves to zero, so it simply follows the last section. */
  margin-top: auto;
}
.zh-footer__links {
  display: flex;
  gap: 24px;
}
/* `color: inherit` rather than the sheet's `--accent`: these are chrome, and
   three orange links under every page's content would read as a fourth call to
   action. Hover is what marks them as links. */
.zh-footer a {
  color: inherit;
}
.zh-footer a:hover {
  color: var(--fg-1);
}

@media (max-width: 760px) {
  #zh-shell {
    display: block !important;
    height: 100dvh !important;
  }
  #zh-rail {
    position: relative !important;
    height: auto !important;
    padding: 16px !important;
    overflow: visible !important;
  }
  #zh-railnav {
    flex-direction: row !important;
    margin-top: 16px !important;
    overflow-x: auto !important;
    padding-bottom: 4px !important;
  }
  #zh-railnav a {
    flex: 0 0 auto;
    border-left: 0 !important;
    border-bottom: 2px solid transparent;
    white-space: nowrap;
  }
  #zh-rail > div:last-child {
    display: none !important;
  }
  #zh-main {
    height: calc(100dvh - 126px) !important;
  }
  #zh-main > section {
    padding-left: 20px !important;
    padding-right: 20px !important;
  }
  .presentation-grid {
    grid-template-columns: 1fr;
  }
  /* The footer is a `<footer>`, not a `<section>`, so the `#zh-main > section`
     rule above does not reach it -- it needs the same 20px inset spelled for
     itself, alongside the stack the source does at its own breakpoint. */
  .zh-footer {
    flex-direction: column;
    align-items: flex-start;
    padding-left: 20px;
    padding-right: 20px;
  }
}
