:root {
  /* "cyber" theme — the original dark/neon palette. This is the CSS
     default (and the no-JS fallback), even though the site now starts
     new visitors in "light" mode via theme-init.js. */
  --bg-void: #0b0c1e;
  --bg-panel: #141631;
  --bg-panel-alt: #1c1f45;
  --border-glow: rgba(47, 111, 238, 0.25);
  --fg-primary: #e9eaf6;
  --fg-muted: #8b8fc0;
  --fg-muted-rgb: 139, 143, 192;
  --accent-blue: #2f6fee;
  --accent-blue-rgb: 47, 111, 238;
  --accent-cyan: #00e5ff;
  --accent-cyan-rgb: 0, 229, 255;
  --accent-magenta: #ff2ec4;
  --accent-magenta-rgb: 255, 46, 196;
  --accent-orange: #ff8a3d;
  --accent-orange-rgb: 255, 138, 61;
  --accent-red: #ff3860;
  --accent-red-rgb: 255, 56, 96;
  --on-accent: #0b0c1e;

  --font-mono: ui-monospace, "Cascadia Code", "SFMono-Regular", Consolas,
    "Liberation Mono", Menlo, "Courier New", monospace;
  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
}

[data-theme="light"] {
  --bg-void: #f3f8f8;
  --bg-panel: #e7f2f2;
  --bg-panel-alt: #daebeb;
  --border-glow: rgba(131, 204, 210, 0.45);
  --fg-primary: #22303a;
  --fg-muted: #5c6b76;
  --fg-muted-rgb: 92, 107, 118;
  --accent-blue: #83ccd2;
  --accent-blue-rgb: 131, 204, 210;
  --accent-cyan: #5fb8be;
  --accent-cyan-rgb: 95, 184, 190;
  --accent-magenta: #c98fd1;
  --accent-magenta-rgb: 201, 143, 209;
  --accent-orange: #f2a65a;
  --accent-orange-rgb: 242, 166, 90;
  --accent-red: #f688a2;
  --accent-red-rgb: 246, 136, 162;
  --on-accent: #22303a;
}

/* Light theme drops the neon-glow aesthetic entirely rather than re-tinting
   it — shadows/filters read as noise on a light background, not style.
   Exception: the CV kill-chain's scroll-reveal highlight keeps its glow in
   light mode too, same as in cyber mode. */
[data-theme="light"] *:not(.kc-node-index):not(.kc-node-body),
[data-theme="light"] *:not(.kc-node-index):not(.kc-node-body)::before,
[data-theme="light"] *:not(.kc-node-index):not(.kc-node-body)::after {
  box-shadow: none !important;
  text-shadow: none !important;
  filter: none !important;
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
  /* Belt-and-braces: nothing on the page is meant to require horizontal
     scrolling, so clip anything that would (e.g. a few px of rounding
     error on absolutely-positioned/aspect-ratio content) instead of
     letting the whole page grow a horizontal scrollbar.

     `clip`, not `hidden`, and the difference matters: `overflow-x: hidden`
     forces the other axis to compute as `overflow-y: auto`, which turns
     html and body into scroll containers. A position:sticky descendant then
     sticks to *that* container rather than the viewport -- which is why the
     mobile nav scrolled away instead of staying at the top. `clip` clips
     without creating a scroll container, so overflow-y stays `visible` and
     sticky works. The `hidden` line below it is the fallback for browsers
     without `clip` support: they keep the guard and lose only the sticky. */
  overflow-x: hidden;
  overflow-x: clip;
  max-width: 100%;
}

html {
  /* Fluid base size so rem-based sizing across the site scales gently with
     viewport width instead of staying pinned to 16px everywhere — small on
     narrow phones, a bit larger on tablets/desktops and up. */
  font-size: clamp(15px, 0.4vw + 13.5px, 18px);
}

body {
  background: var(--bg-void);
  color: var(--fg-primary);
  font-family: var(--font-sans);
  line-height: 1.6;
  min-height: 100vh;
}

a {
  color: var(--accent-blue);
  text-decoration: none;
}

a:hover, a:focus {
  color: var(--accent-cyan);
  text-decoration: underline;
  text-shadow: 0 0 8px rgba(var(--accent-cyan-rgb), 0.4);
}

h1, h2, h3 {
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--accent-blue);
}

.site-main {
  /* Explicit, not left to `auto`. .site-content is a column flex container,
     so without a definite width this box sizes to its own min-content --
     and the live map's table is a nowrap 8-column grid with a ~630px
     min-content. That propagated all the way up and stretched the whole
     page to 658px inside a 375px viewport, instead of the table scrolling
     inside its own overflow-x container. The table wrapper's `overflow-x:
     auto` does not stop this on its own: overflow zeroes the automatic
     minimum size of a flex item, not the min-content contribution of a
     plain block. */
  width: 100%;
  max-width: 1040px;
  margin: 0 auto;
  padding: 2rem 1.25rem 4rem;
}

.page {
  padding-top: 1rem;
}

@media (min-width: 1100px) {
  /* Clearance for the floating nav is already reserved once, by
     .site-content's padding-left -- adding a margin here would just gutter
     it twice. What was left was `margin: 0 auto`, which split the remaining
     width evenly and so pushed the column back towards the middle, leaving
     a wide empty band down the right-hand side.

     Start the column at the gutter the nav already established and let it
     grow rightwards instead. Capped so text lines don't become unreadably
     long on a wide display, and short of the full width so the content
     doesn't run flush into the right edge.

     Note the margins are 0, not `0 auto` and not `margin-right: auto`:
     .site-content is a column flex container, and an auto margin on the
     cross axis switches the item off stretching, so the column silently
     resizes to fit its own content instead of the viewport. Plain zero
     margins keep it stretched up to max-width and aligned to the start. */
  .site-main {
    margin-left: 0;
    margin-right: 0;
    max-width: min(1500px, calc(100% - 2rem));
  }
}

@media (max-width: 700px) {
  .site-main {
    padding: 1.25rem 1rem 3rem;
  }
}
