:root {
  color-scheme: dark;
  --bg: #12100e;
  --bg-2: #1a1815;
  --text: #f7f4ef;
  --muted: #c4d8d4;
  --faint: #8ea7a1;
  --cyan: #8cc8ff;
  --cyan-rgb: 140, 200, 255;
  --green: #6fc7ba;
  --green-rgb: 111, 199, 186;
  --purple: #b8adc9;
  --orange: #f2b86f;
  --ink: #07110d;
  --accent-soft: rgba(111, 199, 186, .12);
  --surface-soft: rgba(255, 255, 255, .06);
  --control-bg: rgba(255, 255, 255, .076);
  --control-hover: rgba(221, 249, 244, .12);
  --field-bg: rgba(5, 13, 12, .72);
  --field-line: rgba(211, 241, 235, .16);
  --graph-node-fill: #1a1815;
  --graph-node-soft-fill: #1a1815;
  --graph-node-selected-fill: #173e38;
  --graph-node-side-fill: #332719;
  --button-shadow: 0 1px 2px rgba(0, 0, 0, .18);
  --display-font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --body-font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --brand-gradient: linear-gradient(120deg, var(--green) 0%, var(--cyan) 100%);
  --brand-glow: 0 0 1px rgba(var(--green-rgb), .4), 0 8px 30px rgba(var(--green-rgb), .22), 0 2px 40px rgba(var(--cyan-rgb), .14);
  --glow-spot: radial-gradient(circle, rgba(var(--green-rgb), .5), rgba(var(--cyan-rgb), .18) 46%, transparent 72%);
  --site-header-clearance: 156px;
  /* Sitewide guardrail fix (2026-08-23, defect 4): the gap between the
     fixed header's bottom edge and a page's first content used to be
     28px on .fit-page/.reality-page/.why-page/.sources-page/.knowledge-page/
     .status-page/.glossary-page, but 34-48px (a clamp) on every other page
     type (home, overview, search, mining-cycle, and any bare <main>), so
     the same header produced a visibly different gap depending on which
     class a page happened to carry. main's padding-top now reads this one
     token everywhere instead of branching by page-type class. */
  --content-top-gap: 28px;
  --page-bg:
    radial-gradient(ellipse 900px 560px at 12% -8%, rgba(var(--green-rgb), .16), transparent 60%),
    radial-gradient(ellipse 760px 620px at 96% 4%, rgba(var(--cyan-rgb), .13), transparent 62%),
    linear-gradient(132deg, rgba(var(--green-rgb), .068), transparent 30%, rgba(var(--cyan-rgb), .035) 65%, transparent 88%),
    linear-gradient(180deg, var(--bg) 0%, var(--bg-2) 58%, #100e0b 100%);
}

:root[data-theme="light"] {
  --green: #197a6b;
}

* {
  box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
}

html {
  scroll-behavior: smooth;
  overflow-x: hidden;
  /* Defect 3: the fixed .site-header sizes itself at width:100%, which a
     fixed-position element resolves against the full layout viewport
     (window.innerWidth) in Chrome, not the narrower visible content area
     (document.documentElement.clientWidth) a page with a real, space-
     reserving scrollbar actually has. The nav then centers itself inside
     that header with margin:auto, landing dead-center on a width that is
     wider, on the right, than what the reader can see, so the nav reads
     as shifted right by half the scrollbar's width. Reserving the gutter
     unconditionally makes clientWidth equal innerWidth on every page,
     scrolling or not, so the two widths agree and the centering math
     matches what renders.  */
  scrollbar-gutter: stable;
}

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

}

body {
  margin: 0;
  min-height: 100vh;
  color: var(--text);
  font: 16px/1.62 var(--body-font);
}

body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
}

/* Occluder behind the floating pill header so scrolled page content never peeks
   through the gap around/above the pill. Uses the exact page background, viewport
   anchored, so it reads as the body rather than as a flat bar. */
body::after {
  content: "";
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 132px;
  background: var(--page-bg);
  background-attachment: fixed;
  z-index: 999;
  pointer-events: none;
}

@keyframes mechanicsPulse {
  0%, 100% {
    box-shadow: none;
  }

  50% {
    box-shadow: none;
  }
}

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

a:hover {
  text-decoration: underline;
}

.skip-link {
  position: fixed;
  left: 16px;
  top: 12px;
  transform: translateY(-160%);
  border: 1px solid var(--cyan);
  border-radius: 999px;
  padding: 10px 14px;
  color: var(--ink);
  background: var(--cyan);
  font-weight: 800;
}

.skip-link:focus {
  transform: translateY(0);
  outline: 3px solid color-mix(in srgb, var(--cyan) 28%, transparent);
  outline-offset: 3px;
  text-decoration: none;
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--cyan) 28%, transparent);
  outline-offset: 3px;
}

.article-visual img:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--cyan) 28%, transparent);
  outline-offset: 3px;
}

.nav,
main,
.footer {
  width: min(1240px, calc(100% - 40px));
  margin: 0 auto;
}

main {
  scroll-margin-top: 120px;
}

main:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--cyan) 28%, transparent);
  outline-offset: 3px;
}

.nav {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto auto;
  gap: 14px;
  align-items: center;
}

.brand,
.nav-links {
  display: flex;
  align-items: center;
}

.brand {
  gap: 11px;
  color: var(--text);
  letter-spacing: 0;
}

.brand-mark {
  display: inline-block;
  background: url("favicon.svg?v=20260512-k4") center / contain no-repeat;
}

.nav-links {
  justify-content: center;
  min-width: 0;
  flex-wrap: wrap;
}

.nav-menu-button {
  display: none;
  min-height: 38px;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line-bright);
  border-radius: 999px;
  padding: 8px 14px;
  color: var(--cyan);
  background: var(--card-bg);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  font: inherit;
  font-size: 14px;
  box-shadow: var(--button-shadow);
  font-weight: 750;
  cursor: pointer;
}

.nav-menu-button:hover {
  color: var(--text);
}

.nav-links a,
.nav-cta {
  min-height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 8px 14px;
  color: var(--muted);
  font-size: 14px;
  font-weight: 720;
  letter-spacing: 0;
  transition: background .22s ease, color .22s ease, box-shadow .22s ease, border-color .22s ease;
}

.nav-links a:hover,
.nav-cta:hover {
  text-decoration: none;
  background: var(--control-hover);
  border-color: var(--line);
  box-shadow: var(--button-shadow);
  color: var(--text);
}

.nav-links a[aria-current="page"] {
  color: var(--text);
}

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font: inherit;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  cursor: pointer;
  white-space: nowrap;
}

.theme-toggle:hover {
  background: var(--control-hover);
  color: var(--text);
}

:root[data-theme="light"] .site-header,
:root[data-theme="light"] .section,
:root[data-theme="light"] .hero-copy,
:root[data-theme="light"] .hero-visual,
:root[data-theme="light"] .hero-signal-grid a,
:root[data-theme="light"] .orientation-console,
:root[data-theme="light"] .orientation-grid a,
:root[data-theme="light"] .protocol-demo,
:root[data-theme="light"] .demo-workspace,
:root[data-theme="light"] .demo-control-panel,
:root[data-theme="light"] .demo-status-card,
:root[data-theme="light"] .demo-explainer,
:root[data-theme="light"] .demo-metrics div,
:root[data-theme="light"] .explainer-workbench,
:root[data-theme="light"] .workbench-grid article,
:root[data-theme="light"] .transaction-path,
:root[data-theme="light"] .transaction-rail article,
:root[data-theme="light"] .status-workbench,
:root[data-theme="light"] .status-lane-grid a,
:root[data-theme="light"] .verification-workflow,
:root[data-theme="light"] .verification-steps article,
:root[data-theme="light"] .api-console,
:root[data-theme="light"] .api-command-stack article,
:root[data-theme="light"] .build-path-console,
:root[data-theme="light"] .build-path-grid article,
:root[data-theme="light"] .hero-status a,
:root[data-theme="light"] .awareness-callout,
:root[data-theme="light"] .live-kaspa-panel,
:root[data-theme="light"] .live-metric-grid article,
:root[data-theme="light"] .origin-proof-strip,
:root[data-theme="light"] .source-handoff,
:root[data-theme="light"] .summary-grid article,
:root[data-theme="light"] .chain-panel,
:root[data-theme="light"] .quick-grid article,
:root[data-theme="light"] .status-grid article,
:root[data-theme="light"] .reference-grid article,
:root[data-theme="light"] .api-command-card,
:root[data-theme="light"] .ai-ask-controls,
:root[data-theme="light"] .ai-prompt-card,
:root[data-theme="light"] .pitch-input-card,
:root[data-theme="light"] .pitch-output-card,
:root[data-theme="light"] .survey-form,
:root[data-theme="light"] .survey-output,
:root[data-theme="light"] .reality-grid article,
:root[data-theme="light"] .field-study-grid article,
:root[data-theme="light"] .route-grid article,
:root[data-theme="light"] .route-grid .route-card-link,
:root[data-theme="light"] .path-grid article,
:root[data-theme="light"] .source-card,
:root[data-theme="light"] .source-tier,
:root[data-theme="light"] .search-card,
:root[data-theme="light"] .overview-grid article,
:root[data-theme="light"] .compare-cards article,
:root[data-theme="light"] .fit-grid article,
:root[data-theme="light"] .lane-grid article,
:root[data-theme="light"] .check-grid article,
:root[data-theme="light"] .one-screen-grid article,
:root[data-theme="light"] .must-read-grid article,
:root[data-theme="light"] .insight-grid article {
  background: var(--card-bg);
  border-color: var(--line);
  box-shadow: var(--shadow-soft);
}

:root[data-theme="light"] .theme-toggle,
:root[data-theme="light"] .nav-links a:hover,
:root[data-theme="light"] .nav-links a[aria-current="page"],
:root[data-theme="light"] .nav-cta {
  background: var(--control-bg);
}

:root[data-theme="light"] .search-box input {
  color: var(--text);
  background: var(--field-bg);
  border-color: var(--field-line);
  box-shadow: var(--button-shadow);
}

@media (max-width: 1320px) {
  .nav {
    gap: 10px;
  }

  .nav-links {
    gap: 4px;
  }

  .nav-links a,
  .nav-cta {
    padding-inline: 10px;
    font-size: 13px;
  }

  .brand {
    gap: 8px;
  }
}

.hero {
  display: grid;
  min-height: 0;
  padding: clamp(24px, 4vw, 54px) 0 clamp(18px, 2.5vw, 28px);
}

.hero::before {
  content: "";
  position: absolute;
  z-index: 0;
  width: min(620px, 60%);
  filter: blur(6px);
  pointer-events: none;
}

.section,
.quick-grid article,
.timeline article,
.status-grid article,
.insight-grid article,
.claim-grid article {
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--card-bg);
  box-shadow: var(--shadow);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.hero-copy {
  position: relative;
  z-index: 1;
  min-height: 0;
  overflow: visible;
  padding: clamp(14px, 2.8vw, 30px) 0;
}

.hero-copy::after {
  content: none;
}

.eyebrow {
  width: fit-content;
  max-width: 100%;
  display: inline-flex;
  align-items: center;
  text-transform: uppercase;
}

h1,
h2,
h3,
p {
  margin-top: 0;
  overflow-wrap: break-word;
}

h1 {
  position: relative;
  z-index: 1;
  max-width: 100%;
  margin-bottom: 18px;
  font-family: var(--display-font);
}

h2 {
  margin-bottom: 18px;
  font-family: var(--display-font);
}

:root[data-theme="light"] h1,
:root[data-theme="light"] h2 {
  text-shadow: none;
}

/* .app-page h1 and .app-page h2 carried their own font sizes until 29 August
   2026. The h1 rule was already dead: both pages using .app-page also carry
   .sources-hero, whose h1 rule has the same specificity and comes later. The
   h2 rule was live and was the only section-heading size on the site that did
   not respond to viewport width, so build-on-kaspa and argent-explained
   rendered h2 smaller than every other page at 1280px and larger at 390px.
   Both removed; those pages now use the site h2. */

h3 {
  margin-bottom: 8px;
  font-size: 18px;
  line-height: 1.18;
  font-family: var(--display-font);
}

pre {
  max-width: 100%;
  overflow-x: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

code {
  border-radius: 5px;
  padding: .15em .4em;
  /* The pill's border and padding push it slightly outside its text line's
     own box; on a wrapped line that puts its bottom edge within 2px of the
     next line down (kaspa-origin-story.html's genesis.rs paragraph at
     390px, "genesis.rs" wrapping onto its own line right above "UTXO"). A
     small vertical margin gives every wrapped line holding a code pill the
     same clearance a plain text line already has. */
  margin: 4px 0;
  font-family: "SF Mono", ui-monospace, "Cascadia Code", Menlo, Consolas, monospace;
  font-size: .9em;
  overflow-wrap: anywhere;
}

pre code {
  border: none;
  padding: 0;
  background: transparent;
  color: inherit;
  font-size: 1em;
  white-space: inherit;
}

.lead,
.section p,
li,
.quick-grid p,
.timeline p,
.insight-grid p,
.claim-grid p {
  color: var(--muted);
}

.lead {
  position: relative;
  z-index: 1;
  max-width: 700px;
}

.actions {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 30px;
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: transform .22s ease, background .22s ease, border-color .22s ease, box-shadow .22s ease;
}

.button:hover {
  text-decoration: none;
}

.button.primary {
  border-color: transparent;
}

.transaction-rail {
  counter-reset: step;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 9.5rem), 1fr));
  gap: 10px;
}

.transaction-rail article {
  position: relative;
  min-width: 0;
  min-height: 168px;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 16px;
  background: rgba(255, 255, 255, .035);
  overflow-wrap: anywhere;
}

.transaction-rail article:not(:last-child)::after {
  content: none;
  position: absolute;
  top: 36px;
  right: -11px;
  width: 12px;
  height: 1px;
  background: var(--line-bright);
}

.transaction-rail.step-diagram article:not(:last-child)::after {
  content: "";
}

.transaction-rail span {
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line-bright);
  border-radius: 999px;
  margin-bottom: 14px;
  color: var(--green-pill, var(--green));
  background: var(--accent-soft);
  font-size: 12px;
  font-weight: 900;
}

.transaction-rail strong {
  display: block;
  color: var(--text);
  line-height: 1.2;
  overflow-wrap: anywhere;
}

.transaction-rail p {
  margin: 9px 0 0;
  color: var(--muted);
  overflow-wrap: anywhere;
}

.quick-grid,
.timeline,
.status-grid,
.insight-grid,
.claim-grid {
  display: grid;
  gap: 14px;
}

.quick-grid {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  margin: clamp(18px, 3vw, 32px) 0 clamp(20px, 3vw, 36px);
}

.quick-grid article {
  min-height: 0;
  border-radius: 8px;
  padding: clamp(18px, 2vw, 24px);
  background: rgba(255, 255, 255, .04);
}

.quick-grid article:nth-child(2) {
  background: rgba(255, 255, 255, .04);
}

.quick-grid article:nth-child(3) {
  background: rgba(255, 255, 255, .04);
}

.quick-grid article:nth-child(4) {
  background: rgba(255, 255, 255, .04);
}

/* Restored 2026-08-24: the dead-CSS scan classified this block "dead"
   because no page in the 22-page test set renders an .origin-proof-strip
   element (confirmed: zero HTML files reference the class). But
   scripts/audit-visual-guardrails.mjs requires this exact rule to exist,
   with this exact padding, regardless of current page usage, and that
   gate is authoritative here, not the render-based scan. Placed before
   the combined `.visual-readout div, .live-metric-grid article,
   .origin-proof-strip { border: 0; ... }` rule further down (same file,
   no padding declared there) so the gate's `\n.origin-proof-strip {`
   regex finds this rule, the one that actually carries the padding,
   rather than that later border/shadow-only rule. */

.source-inline {
  margin: 12px 0 0;
  color: var(--faint);
  font-size: 16px;
}

.source-inline a {
  color: var(--muted);
  font-weight: 760;
}

.live-footnote {
  margin: 20px 0 0;
  color: var(--faint);
  font-size: 16px;
}

.crypto-native-route article,
.method-strip article,
.transaction-rail article,
.toccata-count-grid article {
  min-width: 0;
  overflow-wrap: anywhere;
}

.crypto-native-route article > *,
.method-strip article > *,
.transaction-rail article > *,
.toccata-count-grid article > * {
  min-width: 0;
}

@keyframes toccataSweep {
  0%, 100% {
    transform: translateX(-4%) scale(.98);
    opacity: .42;
  }

  50% {
    transform: translateX(4%) scale(1.02);
    opacity: .68;
  }
}

@keyframes toccataPulse {
  0%, 100% {
    box-shadow: 0 8px 20px rgba(var(--green-rgb), .16);
  }

  50% {
    box-shadow: 0 12px 28px rgba(var(--green-rgb), .08);
  }
}

.section {
  position: relative;
  overflow: visible;
  border-radius: 8px;
  /* Vertical rhythm (2026-08-23): was clamp(24px, 4vw, 44px) for both
     properties, which put roughly 88px of dead air between the end of one
     section's content and the start of the next at desktop widths, on top
     of whatever the "Spacing repair" padding override below added. Tightened
     to the same tokens the homepage already proved out (see the retired
     .home-page .section override this replaces) so every page flows the way
     the homepage already did, instead of the homepage being the one
     compressed exception. */
  margin-top: clamp(16px, 2.4vw, 28px);
  padding: clamp(20px, 2.8vw, 32px);
}

.home-page h2 {
  margin-bottom: 12px;
}

.home-page .lead {
  font-size: 17px;
}

.home-page .actions {
  margin-top: 18px;
}

.section > * {
  position: relative;
  z-index: 1;
}

.prose-section {
  max-width: 860px;
  padding-inline: clamp(20px, 4vw, 44px);
  border-color: transparent;
  background: transparent;
  box-shadow: none;
  backdrop-filter: none;
}

:root[data-theme="light"] .prose-section {
  border-color: transparent;
  background: transparent;
  box-shadow: none;
  backdrop-filter: none;
}

.prose-section p {
  max-width: 76ch;
}

.prose-section a:not(.button) {
  color: var(--link-color);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

.section p {
  max-width: 82ch;
}

.reference-grid article,
.source-tier-grid article,
.source-more,
.use-source-grid article,
.must-read-grid article,
.insight-groups article,
.builder-console article,
.builder-ledger article,
.crypto-native-route article,
.crypto-native-ledger article,
.rail-ladder article,
.route-grid article,
.route-grid .route-card-link,
.reality-table th,
.reality-table td {
  overflow-wrap: break-word;
  word-break: normal;
}

.reference-grid article > *:last-child,
.source-tier-grid article > *:last-child,
.source-more article > *:last-child,
.use-source-grid article > *:last-child,
.must-read-grid article > *:last-child,
.insight-groups article > *:last-child,
.builder-console article > *:last-child,
.builder-ledger article > *:last-child,
.crypto-native-route article > *:last-child,
.crypto-native-ledger article > *:last-child,
.rail-ladder article > *:last-child,
.route-grid article > *:last-child,
.route-grid .route-card-link > *:last-child {
  margin-bottom: 0;
}

.reference-grid a,
.source-more a,
.source-list a,
.source-tier-grid a,
.use-source-grid a,
.must-read-grid a,
.insight-groups a,
.reality-table a,
.api-command-card a {
  overflow-wrap: anywhere;
}

.section > *,
.quick-grid > *,
.timeline > *,
.status-grid > *,
.insight-grid > *,
.claim-grid > *,
.fit-grid > *,
.category-list > *,
.lane-grid > *,
.check-grid > *,
.reference-grid > *,
.source-tier-grid > *,
.path-grid > *,
.route-grid > *,
.one-screen-grid > *,
.must-read-grid > *,
.insight-groups > *,
.use-source-grid > *,
.learning-steps > *,
.method-strip > *,
.overview-grid > *,
.compare-cards > *,
.glossary-grid > *,
.dag-visual > * {
  min-width: 0;
}

.fit-hero,
.reality-hero,
.why-hero,
.sources-hero,
.knowledge-hero,
.status-hero,
.glossary-hero {
  position: relative;
  overflow: clip;
  min-height: 0;
}

.fit-hero h1,
.reality-hero h1,
.why-hero h1,
.sources-hero h1,
.knowledge-hero h1,
.status-hero h1,
.glossary-hero h1 {
  max-width: 1000px;
  font-size: clamp(2.45rem, 5vw, 4.25rem);
  line-height: 1.06;
}

.fit-hero::after,
.reality-hero::after,
.why-hero::after,
.sources-hero::after,
.knowledge-hero::after,
.status-hero::after,
.glossary-hero::after {
  content: none;
}

.fit-note {
  max-width: 74ch;
  margin-top: 24px;
  border: 1px solid color-mix(in srgb, var(--green) 34%, var(--line));
  border-radius: 8px;
  padding: 16px 18px;
  background: var(--card-bg);
  box-shadow: var(--shadow-soft);
  color: var(--muted);
}

.fit-note strong {
  color: var(--green);
}

blockquote {
  max-width: 78ch;
  margin: 18px 0;
  padding: 14px 18px;
  color: var(--text);
  font-size: clamp(18px, 2vw, 24px);
  line-height: 1.32;
}

.fit-grid,
.category-list,
.lane-grid,
.check-grid {
  display: grid;
  gap: clamp(16px, 2vw, 24px);
}

.fit-grid + p,
.fit-grid + .body-copy,
.compare-cards + p,
.overview-grid + p,
.reference-grid + p,
.category-list + p,
.lane-grid + p,
.check-grid + p {
  margin-top: clamp(20px, 3vw, 34px);
}

.source-more + p,
.source-more + .fit-note,
.source-more + .reference-grid,
.source-more + .table-wrap,
.table-wrap + p,
.table-wrap + .fit-note,
.api-command-grid + p,
.api-command-grid + .fit-note {
  margin-top: clamp(20px, 3vw, 32px);
}

.lane-grid article,
.check-grid span {
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 8px;
  background:
    linear-gradient(135deg, rgba(var(--cyan-rgb), .08), transparent 44%),
    rgba(255, 255, 255, .04);
}

.table-wrap {
  overflow-x: auto;
  margin: 24px 0;
}

.reality-table {
  width: 100%;
  border-collapse: collapse;
  color: var(--muted);
}

.reality-table th,
.reality-table td {
  border: 1px solid rgba(255, 255, 255, .12);
  text-align: left;
  vertical-align: top;
}

/* Uppercase is a column-header treatment. It was applied to every th, so the
   13 <th scope="row"> cells that carry real sentences were shouted too:
   kaspa-origin-story rendered "WHAT DID DAGLABS AND POLYCHAIN END UP WITH?".
   A row header is content, not a label. */
.reality-table thead th {
  text-transform: uppercase;
}

.reality-table td:first-child {
  color: var(--green);
  font-weight: 900;
}

.reality-table th:first-child,
.reality-table td:first-child,
.reality-table th:nth-child(2),
.reality-table td:nth-child(2) {
  overflow-wrap: normal;
  word-break: normal;
}

/* A closed <details class="cell-detail"> inside a table cell had no
   visual break from the sentence above it or the next cell below it,
   so its summary line read as a stray fragment wedged between the row
   text and the Maturity badge, worst on the stacked mobile layout. */
.cell-detail {
  display: block;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--line);
}

/* Sentence case, not uppercase. The site reserves uppercase for short labels:
   eyebrows and demo panel titles, five to twenty characters. These summaries
   run to full sentences ("Sutton's numbers, and the claim that overshoots
   them"), and setting a 50-character sentence in 12px all-caps is the same
   device used against the thing it was chosen for. Changed 29 August 2026. */
.cell-detail summary {
  cursor: pointer;
  color: var(--faint);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .01em;
}

.cell-detail summary::marker {
  color: var(--green);
}

.cell-detail[open] summary {
  margin-bottom: 6px;
}

.check-grid {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  margin: clamp(20px, 3vw, 32px) 0;
}

.check-grid span {
  min-height: 0;
  display: flex;
  align-items: center;
  padding: clamp(16px, 2vw, 22px);
  color: var(--text);
  font-weight: 900;
}

/* A 980px floor used to sit here on every reality table. Most of them are
   three or four columns of short sentences inside a 732px card, so the
   floor made all 47 of them scroll sideways and clip mid-word for no
   reason. A table is as wide as its card now and wraps like prose; the
   first column keeps its 12rem minimum so labels never collapse. */

.source-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
}

.source-list li {
  min-width: 0;
  max-width: 86ch;
  overflow-wrap: anywhere;
}

.reference-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: clamp(16px, 2vw, 24px);
  margin-top: clamp(20px, 3vw, 32px);
}

.reference-grid article {
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 8px;
  padding: clamp(18px, 2vw, 24px);
  background: rgba(255, 255, 255, .04);
}

.reference-grid h3 {
  margin: 0 0 10px;
  font-size: 19px;
  line-height: 1.24;
}

.reference-grid p,
.source-tier-grid p,
.source-more p,
.use-source-grid p,
.must-read-grid p,
.insight-groups p {
  margin-bottom: 12px;
  line-height: 1.62;
}

.reference-grid ul {
  margin: 0;
  padding-left: 20px;
}

.reference-grid li {
  margin: 8px 0;
  color: var(--muted);
  line-height: 1.56;
}

.api-command-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: clamp(14px, 2vw, 20px);
  margin-top: clamp(20px, 3vw, 30px);
}

.api-command-card {
  min-width: 0;
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 8px;
  padding: clamp(18px, 2vw, 22px);
  background: rgba(255, 255, 255, .04);
}

/* Card titles are one size across every card grid on the site. Until 29 August
   2026 this component rendered its title at 21px on build-on-kaspa (marked up
   h3) and 17px on kaspa-mining (marked up h4), and .cycle-grid ran a third size
   at 23px, none of which tracked anything a reader could perceive. The tag is
   matched loosely here because the correct heading level differs by where the
   card sits in each page's outline; only the size is shared. */
.api-command-card :is(h3, h4, h5) {
  margin: 10px 0 8px;
  font-size: 19px;
}

.api-command-card p {
  margin: 0;
}

/* Commands here are typed, not skimmed, so none of one may be off screen. With
   `white-space: pre` these scrolled sideways with no visible cue, and the Windows
   node command rendered as `--rpclisten=127.0.0.1:1611` at 1280px: a reader who
   copies what they can see gets the wrong port. Measured 2026-08-29 at 390, 768,
   1024 and 1280px; every command block overflowed, by 44 to 871px. Wrapping shows
   the whole line at every width. Used only by kaspa-mining.html and
   build-on-kaspa.html. */
.api-command-card pre {
  margin: 14px 0 0;
  max-width: 100%;
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

.api-command-card code {
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

.api-command-card-note {
  background: rgba(155, 215, 189, .055);
}

.command-method {
  display: inline-flex;
  align-items: center;
  width: fit-content;
  border: 1px solid rgba(var(--cyan-rgb), .35);
  border-radius: 999px;
  padding: 4px 8px;
  color: var(--accent-2);
  font: 700 12px/1 var(--mono);
  letter-spacing: .04em;
}

.command-method-post {
  border-color: rgba(155, 215, 189, .45);
  color: var(--accent);
}

.command-method-note {
  border-color: rgba(255, 255, 255, .18);
  color: var(--muted);
}

/* The step-connector dash between .builder-console cards (removed 2026-08-23)
   was tuned for a 4-across row: a short cyan tick floating between cards,
   meant to read as a sequence arrow. build-on-kaspa.html's only live usage
   has 2 cards, not 4, so the 4-column grid above leaves two empty tracks and
   the tick lands in that empty space instead of between two cards, reading
   as a stray blue line rather than a connector. Dropped rather than
   re-tuned: the connector never earned its place next to the change in the
   first place per STANDARD.md's restraint rule, and no other live page uses
   this component to check the 4-card case against. */

.compact-columns {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: clamp(16px, 2vw, 24px);
}

.source-list li,
.limit-list li {
  margin: 8px 0;
}

.source-more {
  margin-top: 22px;
  margin-bottom: 22px;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 16px 18px;
  background: var(--card-bg);
  box-shadow: var(--shadow-soft);
}

.source-more summary {
  cursor: pointer;
  color: var(--text);
  font-weight: 900;
}

.guide-detail summary {
  position: relative;
  display: block;
  cursor: pointer;
  list-style: none;
  padding-right: 96px;
}

.guide-detail summary::after {
  content: "Open";
  position: absolute;
  top: 4px;
  right: 0;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 7px 12px;
  color: var(--text);
  background: var(--control-bg);
  font-size: 12px;
  font-weight: 850;
  line-height: 1;
}

.guide-detail[open] summary::after {
  content: "Close";
}

.guide-detail-preview {
  display: block;
  max-width: 70ch;
  margin-top: 12px;
  color: var(--muted);
  line-height: 1.6;
}

.guide-detail-body {
  margin-top: clamp(18px, 3vw, 28px);
  border-top: 1px solid var(--line);
  padding-top: clamp(18px, 3vw, 28px);
}

.source-more ul {
  margin: 14px 0 0;
  padding-left: 20px;
}

.source-more li {
  margin: 8px 0;
  color: var(--muted);
}

.source-more .reference-grid {
  margin-top: 16px;
}

.search-box {
  display: grid;
  gap: 10px;
  max-width: 720px;
  margin-top: 26px;
}

.search-box span {
  color: var(--green);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
}

.search-box input {
  width: 100%;
  border: 1px solid var(--field-line);
  border-radius: 8px;
  padding: 16px 18px;
  color: var(--text);
  background: var(--field-bg);
  box-shadow: var(--button-shadow);
  font: inherit;
}

.search-box input:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--cyan) 28%, transparent);
  outline-offset: 3px;
  border-color: color-mix(in srgb, var(--cyan) 58%, var(--field-line));
}

.search-results {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
}

.search-results span {
  color: var(--green);
  font-weight: 800;
  text-transform: uppercase;
}

.search-results p {
  color: var(--muted);
}

.search-empty {
  margin: 22px 0 0;
  border: 1px solid rgba(240, 171, 252, .28);
  border-radius: 8px;
  padding: 16px 18px;
  color: var(--muted);
  background: rgba(240, 171, 252, .07);
}

.search-empty strong {
  color: var(--text);
}

.footer {
  color: var(--faint);
}

.footer-grid p {
  margin: 0;
}

.footer-link-group {
  min-width: 0;
}

.footer-link-group span {
  color: var(--faint);
  text-transform: uppercase;
}

.footer-link-group a {
  overflow-wrap: anywhere;
}

/* Learning paths and homepage route cards */
.path-grid,
.route-grid,
.one-screen-grid,
.must-read-grid,
.insight-groups,
.use-source-grid {
  display: grid;
  gap: clamp(16px, 2vw, 24px);
}

.path-grid {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  margin: clamp(18px, 3vw, 32px) 0 clamp(24px, 4vw, 44px);
}

.path-grid a,
.must-read-grid article,
.insight-groups article,
.use-source-grid article,
.learning-steps li,
.chain-panel,
.quad-cell {
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 8px;
  background:
    linear-gradient(135deg, rgba(var(--cyan-rgb), .08), transparent 45%),
    rgba(255, 255, 255, .04);
}

.path-grid a {
  min-width: 0;
  min-height: 0;
  height: auto;
  padding: clamp(18px, 2vw, 24px);
  color: var(--text);
  overflow: visible;
  overflow-wrap: anywhere;
}

.path-grid a:hover {
  text-decoration: none;
  border-color: rgba(var(--cyan-rgb), .44);
  transform: translateY(-1px);
}

.path-grid span,
.use-source-grid strong {
  display: block;
  max-width: 100%;
  margin-bottom: 10px;
  color: var(--green);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .11em;
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

.path-grid span {
  font-size: 16px;
}

.path-grid strong {
  display: block;
  max-width: 100%;
  font-size: 20px;
  line-height: 1.16;
  overflow-wrap: anywhere;
}

.path-grid p,
.use-source-grid span,
.learning-steps span,
.quad-cell span,
.insight-groups p {
  color: var(--muted);
}

.summary-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: clamp(16px, 2vw, 24px);
  margin-top: clamp(20px, 3vw, 32px);
}

.summary-grid article {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: clamp(18px, 2vw, 24px);
  background: var(--card-bg);
  box-shadow: var(--shadow-soft);
}

.summary-grid span {
  display: block;
  margin-bottom: 10px;
  color: var(--green);
  font-size: 12px;
  font-weight: 750;
  letter-spacing: 0;
  text-transform: none;
}

.summary-grid p {
  margin: 0;
  color: var(--muted);
}

/* skeptical-case.html only: the seven risks were a div/article grid with
   no table, image, or form control anywhere in it, so the page-height
   gate saw one 900px+ run with nothing to look at, above the actual
   table further down that stays closed by default. Real <table> markup
   for the same seven risks, same content, fixes the pacing and the
   semantics in one move. Two columns at rest (risk name, then the risk
   and its disclosure) since that already matches how the content reads;
   stacked one column on phone so the second cell's long paragraphs never
   need horizontal scroll, unlike .reality-table's fixed 980px table
   which is built for short data cells, not prose. */
.risk-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: clamp(20px, 3vw, 32px);
}

.risk-table td {
  border: 1px solid var(--line);
  padding: clamp(18px, 2vw, 24px);
  vertical-align: top;
  background: var(--card-bg);
}

.risk-table tr + tr td {
  border-top: 0;
}

.risk-table td:first-child {
  width: 12rem;
  color: var(--text);
  font-weight: 700;
}

.risk-table td:last-child p:first-child {
  margin-top: 0;
}

.risk-table td:last-child > p {
  color: var(--muted);
  margin: 0;
}

@media (max-width: 640px) {
  .risk-table,
  .risk-table tbody,
  .risk-table tr,
  .risk-table td {
    display: block;
    width: auto;
  }

  .risk-table tr {
    margin-bottom: 14px;
    border-radius: 10px;
    overflow: hidden;
  }

  .risk-table td:first-child {
    border-bottom: 0;
    padding-bottom: 10px;
  }

  .risk-table tr + tr td:first-child {
    border-top: 1px solid var(--line);
  }

  .risk-table td:last-child {
    border-top: 0;
    /* Not 0: the mining-concentration row's ASIC term-def sat within 4px of
       the label cell above it once the two cells stack, close enough that
       the render gate read it as a near-overlap between "Mining
       concentration" and "ASIC". */
    padding-top: 8px;
  }
}

.mining-cycle-page .mining-data-panel strong {
  color: var(--text);
}

.mining-cycle-page .section::after {
  content: "";
  display: block;
  clear: both;
}

.article-visual {
  position: relative;
  width: min(100%, 620px);
  margin: clamp(16px, 2vw, 24px) 0;
}

.mining-cycle-page .article-visual {
  float: right;
  clear: right;
  width: min(30vw, 280px);
  margin: 0 0 16px 24px;
}

.article-visual img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: contain;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
  box-shadow: var(--shadow-soft);
  cursor: zoom-in;
}

.article-visual figcaption {
  max-width: 78ch;
  margin: 8px 0 0;
  color: var(--faint);
  font-size: 16px;
  line-height: 1.45;
}

.deep-dive {
  margin-top: 16px;
  /* .prose-section (design/house-style.md's article-body container) is
     deliberately excluded from the generic ".section:not(.prose-section) >
     * + *" sibling-spacing rule below, so a paragraph directly following a
     collapsed .deep-dive inside a .prose-section got no gap at all: p's own
     margin-top is reset to 0 site-wide (see "p { margin-top: 0 }"), and
     .deep-dive supplied no margin-bottom, so the two sat 1px apart. Matches
     the existing margin-top for symmetric spacing on both sides of the
     disclosure block. */
  margin-bottom: 16px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: rgba(var(--cyan-rgb), .04);
}

/* skeptical-case.html: same visual treatment as .deep-dive (a bordered,
   tinted block for depth material) but a plain always-visible section
   instead of a collapsed <details>. This page's seven objections and
   evidence tables are the reader's whole reason for being here, so they
   render open by default; see design/density-budget.md. */
.deep-dive-plain {
  margin-top: 16px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: rgba(var(--cyan-rgb), .04);
  padding: 16px 18px;
}

.deep-dive-plain h2 {
  margin-top: 0;
}

.deep-dive summary {
  cursor: pointer;
  padding: 16px 18px;
  color: var(--text);
  font-weight: 850;
}

.deep-dive summary::marker {
  color: var(--green);
}

.deep-dive > :not(summary) {
  margin-inline: 18px;
}

.deep-dive > :last-child {
  margin-bottom: 18px;
}

.deep-dive .article-visual {
  float: none;
  width: min(100%, 520px);
  margin: 10px 0 14px;
}

.image-expand-button {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  border: 1px solid rgba(255, 255, 255, .52);
  border-radius: 999px;
  color: var(--ink);
  background: rgba(245, 252, 250, .92);
  box-shadow: 0 10px 28px rgba(0, 0, 0, .22);
  font: inherit;
  font-size: 12px;
  font-weight: 850;
  cursor: zoom-in;
}

.image-expand-button:hover,
.image-expand-button:focus {
  background: #fff;
}

.image-viewer {
  position: fixed;
  inset: 0;
  z-index: 5000;
  display: none;
  align-items: center;
  justify-content: center;
  padding: clamp(18px, 4vw, 48px);
  background: rgba(0, 0, 0, .82);
}

/* Without this the viewer is display:none in every state, so Expand set
   aria-hidden="false", loaded the image, and showed a 0x0 element. A
   dead-CSS pass removed the rule because the scanner never opens the viewer,
   so it read as unmatched. Any rule that only applies while a dialog is open
   looks dead to a scanner that cannot open the dialog. */
.image-viewer[aria-hidden="false"] {
  display: flex;
}

.image-viewer figure {
  width: min(1180px, 100%);
  margin: 0;
}

.image-viewer img {
  display: block;
  width: 100%;
  max-height: min(78vh, 760px);
  object-fit: contain;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #050607;
  box-shadow: 0 26px 90px rgba(0, 0, 0, .5);
}

.image-viewer figcaption {
  width: min(78ch, 100%);
  margin: 12px auto 0;
  color: rgba(255, 255, 255, .82);
  font-size: 14px;
  line-height: 1.45;
  text-align: center;
}

.image-viewer-close {
  position: absolute;
  top: 18px;
  right: 18px;
  min-height: 40px;
  border: 1px solid rgba(255, 255, 255, .38);
  border-radius: 999px;
  padding: 9px 14px;
  color: var(--ink);
  background: rgba(245, 252, 250, .94);
  font: inherit;
  font-weight: 850;
  cursor: pointer;
}

.market-flow {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr));
  gap: clamp(14px, 2vw, 20px);
  margin-top: clamp(20px, 3vw, 32px);
}

.clock-diagram {
  display: grid;
  gap: 16px;
  margin-top: clamp(20px, 3vw, 30px);
}

.clock-lane {
  display: grid;
  grid-template-columns: minmax(180px, .35fr) minmax(0, 1fr);
  gap: clamp(14px, 3vw, 30px);
  align-items: center;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: clamp(16px, 2vw, 22px);
  background: rgba(var(--cyan-rgb), .045);
}

.clock-lane span {
  display: block;
  margin-bottom: 6px;
  /* Plain --green on .clock-lane's own rgba(--cyan-rgb,.045) tinted
     background measured 4.36:1 in light theme, under the 4.5:1 floor.
     --green-pill already exists for this exact self-tint shape (see its
     definition above); reused rather than adding a page-local duplicate. */
  color: var(--green-pill, var(--green));
  font-size: 12px;
  font-weight: 850;
  text-transform: uppercase;
  letter-spacing: .08em;
}

.clock-lane strong {
  display: block;
  color: var(--text);
  font-size: clamp(19px, 2vw, 24px);
  line-height: 1.12;
}

.clock-lane p {
  margin: 8px 0 0;
  color: var(--muted);
}

.signal-line {
  position: relative;
  min-height: 96px;
  overflow: hidden;
  border-radius: 8px;
}

.signal-line i {
  position: absolute;
  inset: 18px 18px;
  display: block;
  border-top: 4px solid var(--cyan);
}

.fast-lane .signal-line i {
  clip-path: polygon(0 54%, 10% 18%, 19% 62%, 27% 30%, 38% 74%, 48% 22%, 60% 64%, 72% 28%, 84% 78%, 100% 36%, 100% 43%, 84% 85%, 72% 36%, 60% 72%, 48% 30%, 38% 82%, 27% 38%, 19% 70%, 10% 26%, 0 62%);
  background: var(--cyan);
  border: 0;
}

.slow-lane .signal-line i {
  top: 48px;
  border-color: var(--green);
  border-radius: 999px;
}

.market-flow article,
.cycle-grid article {
  position: relative;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: clamp(18px, 2vw, 24px);
  background:
    linear-gradient(135deg, rgba(var(--cyan-rgb), .065), transparent 55%),
    var(--card-bg);
  box-shadow: var(--shadow-soft);
}

.market-flow article::after {
  content: none;
}

.market-flow article:last-child::after {
  content: none;
}

.market-flow span,
.cycle-grid span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 12px;
  border-radius: 999px;
  color: var(--ink);
  background: var(--green);
  font-size: 12px;
  font-weight: 900;
}

.market-flow span {
  width: fit-content;
  min-height: 32px;
  padding: 7px 12px;
  line-height: 1;
  white-space: nowrap;
}

.cycle-grid span {
  width: 32px;
  min-width: 32px;
  min-height: 32px;
}

.market-flow strong {
  display: block;
  margin-bottom: 8px;
  color: var(--text);
  font-size: clamp(17px, 1.8vw, 21px);
  line-height: 1.18;
}

.market-flow p,
.cycle-grid p {
  margin: 0;
  color: var(--muted);
}

.cycle-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(14px, 2vw, 20px);
  margin-top: clamp(20px, 3vw, 32px);
}

.cycle-grid h3 {
  margin: 0 0 8px;
  font-size: 19px;
  line-height: 1.14;
}

@media (max-width: 860px) {
  .mining-cycle-page .article-visual,
  .mining-cycle-page .sources-hero .article-visual {
    float: none;
    width: min(100%, 620px);
    margin: 16px 0 18px;
  }

  .clock-lane {
    grid-template-columns: 1fr;
  }

  .signal-line {
    min-height: 76px;
  }
}

.status-page .section,
.fit-page .section,
.knowledge-page .section,
.sources-page .section,
.reality-page .section {
  backdrop-filter: none;
}

/* Status labels */
.status-pill {
  --status-color: var(--muted);
  gap: 7px;
  border: 1px solid color-mix(in srgb, var(--status-color) 40%, transparent);
  border-radius: 999px;
  color: color-mix(in srgb, var(--status-color) 78%, var(--text));
  background: color-mix(in srgb, var(--status-color) 14%, transparent);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
  white-space: nowrap;
  overflow-wrap: normal;
  word-break: normal;
  cursor: default;
}

.status-pill::before {
  content: "";
  flex: 0 0 6px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--status-color);
}

.status-snapshot th:nth-child(2),
.status-snapshot td:nth-child(2) {
  min-width: 8.75rem;
  white-space: nowrap;
  overflow-wrap: normal;
  word-break: normal;
}

.status-pill.live {
  --status-color: var(--green);
}

.status-pill.target {
  --status-color: var(--cyan);
}

.status-pill.roadmap {
  --status-color: var(--purple-pill);
}

.status-pill.not-live {
  --status-color: var(--muted);
}

.check-grid label {
  min-width: 0;
  min-height: 0;
  display: flex;
  align-items: center;
  gap: 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: clamp(16px, 2vw, 22px);
  background:
    linear-gradient(135deg, rgba(var(--cyan-rgb), .08), transparent 44%),
    var(--card-bg);
  box-shadow: var(--shadow-soft);
  color: var(--text);
  font-weight: 900;
  cursor: pointer;
}

.check-grid input {
  width: 18px;
  height: 18px;
  accent-color: var(--green);
  flex: 0 0 auto;
}

.mini-preview .reality-table {
  min-width: 680px;
}

.quadrant {
  position: relative;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: clamp(12px, 2vw, 18px);
  max-width: 840px;
  margin: clamp(22px, 3vw, 34px) 0 0;
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 8px;
  padding: clamp(56px, 5vw, 64px) clamp(24px, 4vw, 44px) clamp(40px, 4vw, 48px);
}

.quad-cell {
  min-width: 0;
  min-height: 0;
  padding: clamp(16px, 2vw, 22px);
}

.quad-cell strong,
.quad-cell span {
  display: block;
}

.quad-cell span {
  margin-top: 8px;
}

.quad-cell.kas {
  border-color: rgba(var(--cyan-rgb), .56);
}

.quad-cell.btc {
  border-color: rgba(167, 243, 208, .38);
}

.quad-cell.sol {
  border-color: rgba(240, 171, 252, .34);
}

.axis {
  position: absolute;
  color: var(--faint);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .11em;
  text-transform: uppercase;
}

.x-axis {
  right: 28px;
  bottom: 14px;
}

.y-axis {
  left: 24px;
  top: 18px;
}

/* Liquid glass / Material visual layer */
.section:not(.prose-section),
:where(
  .hero-signal-grid a,
  .hero-status a,
  .quick-grid article,
  .timeline article,
  .status-grid article,
  .insight-grid article,
  .claim-grid article,
  .summary-grid article,
  .reference-grid article,
  .status-lane-grid a,
  .verification-steps article,
  .build-path-grid article,
  .api-command-stack article,
  .builder-console article,
  .builder-ledger article,
  .fit-note,
  .verified-note,
  .freshness-panel div,
  .source-tier-grid article,
  .source-more,
  .link-grid a,
  .method-strip article,
  .overview-grid article,
  .compare-cards article,
  .glossary-grid article,
  .ai-ask-controls,
  .ai-prompt-card,
  .pitch-input-card,
  .pitch-output-card,
  .survey-form,
  .survey-output,
  .reality-grid article,
  .field-study-grid article,
  .path-grid article,
  .route-grid article,
  .route-grid .route-card-link,
  .lane-grid article,
  .fit-grid article,
  .search-card,
  .search-results article,
  .source-card,
  .source-tier,
  .one-screen-grid article,
  .must-read-grid article,
  .insight-groups article,
  .use-source-grid article,
  .check-grid label,
  .learning-steps li,
  .quadrant,
  .quad-cell
) {
  position: relative;
  overflow: hidden;
  border-color: var(--line);
  background: var(--card-bg);
  box-shadow: var(--shadow-soft);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.section:not(.prose-section) {
  box-shadow: var(--shadow);
}

.status-page .section,
.fit-page .section,
.knowledge-page .section,
.sources-page .section,
.reality-page .section {
  box-shadow: var(--shadow);
}

:root[data-theme="light"] .section:not(.prose-section) {
  box-shadow: var(--shadow);
}

:root[data-theme="light"] :where(
  .hero-signal-grid a,
  .hero-status a,
  .quick-grid article,
  .timeline article,
  .status-grid article,
  .insight-grid article,
  .claim-grid article,
  .summary-grid article,
  .reference-grid article,
  .status-lane-grid a,
  .verification-steps article,
  .build-path-grid article,
  .api-command-stack article,
  .builder-console article,
  .builder-ledger article,
  .fit-note,
  .verified-note,
  .freshness-panel div,
  .source-tier-grid article,
  .source-more,
  .link-grid a,
  .method-strip article,
  .overview-grid article,
  .compare-cards article,
  .glossary-grid article,
  .ai-ask-controls,
  .ai-prompt-card,
  .pitch-input-card,
  .pitch-output-card,
  .survey-form,
  .survey-output,
  .reality-grid article,
  .field-study-grid article,
  .path-grid article,
  .route-grid article,
  .route-grid .route-card-link,
  .lane-grid article,
  .fit-grid article,
  .search-card,
  .search-results article,
  .source-card,
  .source-tier,
  .one-screen-grid article,
  .must-read-grid article,
  .insight-groups article,
  .use-source-grid article,
  .check-grid label,
  .learning-steps li,
  .quadrant,
  .quad-cell
) {
  box-shadow: var(--shadow-soft);
}

.section:not(.prose-section)::before,
:where(
  .hero-signal-grid a,
  .hero-status a,
  .status-lane-grid a,
  .fit-note,
  .verified-note,
  .freshness-panel div,
  .source-more,
  .ai-ask-controls,
  .ai-prompt-card,
  .survey-output,
  .route-grid .route-card-link,
  .search-card,
  .source-tier,
  .quadrant,
  .quad-cell
)::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: none;
  opacity: .12;
  mask-image: none;
  mix-blend-mode: normal;
}

:root[data-theme="light"] .section:not(.prose-section)::before,
:root[data-theme="light"] :where(
  .hero-signal-grid a,
  .hero-status a,
  .status-lane-grid a,
  .fit-note,
  .verified-note,
  .freshness-panel div,
  .source-more,
  .ai-ask-controls,
  .ai-prompt-card,
  .survey-output,
  .route-grid .route-card-link,
  .search-card,
  .source-tier,
  .quadrant,
  .quad-cell
)::before {
  opacity: .09;
  mask-image: none;
  mix-blend-mode: normal;
}

.section:not(.prose-section) > *,
:where(
  .hero-signal-grid a,
  .hero-status a,
  .quick-grid article,
  .timeline article,
  .status-grid article,
  .insight-grid article,
  .claim-grid article,
  .summary-grid article,
  .reference-grid article,
  .status-lane-grid a,
  .verification-steps article,
  .build-path-grid article,
  .api-command-stack article,
  .builder-console article,
  .builder-ledger article,
  .fit-note,
  .verified-note,
  .freshness-panel div,
  .source-tier-grid article,
  .source-more,
  .link-grid a,
  .method-strip article,
  .overview-grid article,
  .compare-cards article,
  .glossary-grid article,
  .ai-ask-controls,
  .ai-prompt-card,
  .pitch-input-card,
  .pitch-output-card,
  .survey-form,
  .survey-output,
  .reality-grid article,
  .field-study-grid article,
  .path-grid article,
  .route-grid article,
  .route-grid .route-card-link,
  .lane-grid article,
  .fit-grid article,
  .search-card,
  .search-results article,
  .source-card,
  .source-tier,
  .one-screen-grid article,
  .must-read-grid article,
  .insight-groups article,
  .use-source-grid article,
  .check-grid label,
  .learning-steps li,
  .quadrant,
  .quad-cell
) > * {
  position: relative;
  z-index: 1;
}

.button:not(.primary) {
  background: var(--card-bg);
  box-shadow: var(--button-shadow);
}

.path-grid a {
  border-color: var(--line);
  background: var(--card-bg);
  box-shadow: var(--shadow-soft);
}

.pressure-node,
.quadrant,
.quad-cell {
  border-color: var(--line);
  background: var(--card-bg);
  box-shadow: var(--shadow-soft);
}

.quadrant {
  background:
    linear-gradient(90deg, transparent calc(50% - 1px), color-mix(in srgb, var(--cyan) 14%, transparent) calc(50% - 1px), color-mix(in srgb, var(--cyan) 14%, transparent) calc(50% + 1px), transparent calc(50% + 1px)),
    linear-gradient(0deg, transparent calc(50% - 1px), color-mix(in srgb, var(--green) 14%, transparent) calc(50% - 1px), color-mix(in srgb, var(--green) 14%, transparent) calc(50% + 1px), transparent calc(50% + 1px)),
    var(--card-bg);
}

.quad-cell.kas,
.quad-cell.btc,
.quad-cell.sol {
  border-color: var(--line);
}

.quad-cell.kas {
  background: var(--card-bg);
}

.quad-cell.btc {
  background: var(--card-bg);
}

.quad-cell.sol {
  background: var(--card-bg);
}

@media (max-width: 1060px) {
  .nav {
    grid-template-columns: 1fr auto;
    row-gap: 8px;
    padding: 10px 0;
  }

  .nav-links {
    grid-column: 1 / -1;
    order: 3;
    justify-content: flex-start;
    overflow-x: auto;
    padding-bottom: 10px;
  }

  .footer-grid {
    grid-template-columns: 1fr;
  }

  .footer-nav-groups {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .hero {
    grid-template-columns: 1fr;
  }

  .hero-copy {
    min-height: 0;
  }

  .quick-grid,
  .timeline,
  .status-grid,
  .link-grid,
    .insight-grid,
    .fit-grid,
    .category-list,
    .lane-grid,
    .check-grid,
    .crypto-native-route,
    .crypto-native-ledger,
    .builder-console,
    .builder-ledger,
    .rail-ladder,
    .reference-grid,
    .source-tier-grid,
    .ai-ask-layout,
    .pitch-layout,
    .survey-layout,
    .reality-grid,
    .field-study-grid,
    .path-grid,
    .route-grid,
    .one-screen-grid,
    .must-read-grid,
    .insight-groups,
    .use-source-grid,
    .dag-visual,
    .learning-steps,
    .method-strip,
    .overview-grid,
    .compare-cards,
    .glossary-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

}

@media (max-width: 700px) {

  .nav,
  main,
  .footer {
    width: calc(100vw - 28px);
    max-width: calc(100vw - 28px);
  }

  main,
  .footer {
    width: calc(100vw - 56px);
    max-width: calc(100vw - 56px);
  }

  main {
    padding-bottom: 72px;
  }

  .nav {
    grid-template-columns: 1fr auto auto;
  }

  .brand {
    font-size: 15px;
  }

  .nav-menu-button {
    display: inline-flex;
    grid-column: 3;
    grid-row: 1;
  }

  .theme-toggle {
    min-height: 34px;
    padding: 6px 10px;
    font-size: 12px;
  }

  .nav-links {
    grid-column: 1 / -1;
    flex-wrap: wrap;
    overflow: visible;
    gap: 4px;
    padding-bottom: 0;
  }

  .nav.nav-enhanced .nav-links {
    display: none;
  }

  .nav.nav-enhanced[data-open="true"] .nav-links {
    display: flex;
  }

  .nav-links a {
    min-height: 34px;
    padding: 6px 10px;
    font-size: 13px;
  }

  .footer-grid {
    gap: 18px;
  }

  .hero {
    padding-top: 28px;
  }

  .hero-copy,
  .section {
    border-radius: 8px;
  }

  h1 {
    max-width: 100%;
    line-height: 1.08;
    overflow-wrap: break-word;
  }

  .transaction-rail article:not(:last-child)::after {
    display: none;
  }

  h2 {
    overflow-wrap: anywhere;
  }

  .section {
    padding: 20px;
  }

  .hero,
  .hero-copy,
  .hero-visual,
  .section {
    max-width: 100%;
    min-width: 0;
  }

  .actions {
    align-items: stretch;
    flex-direction: column;
    max-width: 100%;
  }

  .actions .button {
    width: 100%;
    max-width: 100%;
    white-space: normal;
    text-align: center;
  }

  .section p,
  .section li,
  .lead,
  .plain-bridge,
  .builder-console strong,
  .builder-ledger strong,
  .reference-grid h3,
  .source-tier-grid h3 {
    overflow-wrap: break-word;
  }

  .hero-status,
  .hero-signal-grid,
  .orientation-grid,
  .workbench-grid,
  .transaction-rail,
  .status-lane-grid,
  .verification-steps,
  .api-command-stack,
  .build-path-grid,
  .demo-metrics div,
  .quick-grid,
  .timeline,
  .status-grid,
  .link-grid,
  .insight-grid,
  .claim-grid,
  .fit-grid,
  .category-list,
  .lane-grid,
  .check-grid,
  .crypto-native-route,
  .crypto-native-ledger,
  .builder-console,
  .builder-ledger,
  .rail-ladder,
  .reference-grid,
    .ai-ask-layout,
    .ai-destination-grid,
    .pitch-layout,
    .survey-layout,
    .pitch-check-grid,
  .reality-grid,
  .field-study-grid,
  .compact-columns,
    .source-list,
    .source-tier-grid,
    .account-grid,
    .path-grid,
    .route-grid,
    .one-screen-grid,
    .must-read-grid,
    .insight-groups,
    .use-source-grid,
    .dag-visual,
    .learning-steps,
    .method-strip,
    .overview-grid,
    .compare-cards,
    .glossary-grid {
    grid-template-columns: 1fr;
  }

  .quadrant {
    padding: 58px 16px 48px;
  }

  .quadrant .axis {
    left: 16px;
    right: auto;
    max-width: calc(100% - 32px);
    line-height: 1.3;
    white-space: normal;
  }

  .quadrant .y-axis {
    top: 16px;
    transform: none;
  }

  .quadrant .x-axis {
    bottom: 14px;
  }

  .table-wrap {
    overflow: visible;
  }

  .reality-table {
    min-width: 0;
    border-collapse: separate;
    border-spacing: 0 12px;
  }

  .mini-preview .reality-table {
    min-width: 0;
  }

  .reality-table thead {
    display: none;
  }

  .reality-table,
  .reality-table tbody,
  .reality-table tr:not([hidden]),
  .reality-table td {
    display: block;
    width: 100%;
  }

  /* A row a filter hides via the native `hidden` attribute must stay hidden
     here too. The stacked-card rule above sets `.reality-table tr` to
     display:block by class selector, which outranks the UA [hidden]{display:
     none} rule by specificity, so a filtered-out row on any reality-table
     (model-picker-data.html's search, and any other page that hides rows by
     setting el.hidden) rendered anyway below 700px even though its count
     readout said it was excluded. Confirmed by rendering model-picker-data.html
     at 375px and 1280px: hidden rows showed display:block at the former,
     display:none at the latter. */
  .reality-table tr[hidden] {
    display: none;
  }

  .reality-table tr {
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 10px 12px;
    background: var(--card-bg);
  }

  .reality-table td {
    border: 0;
    line-height: 1.55;
    overflow-wrap: anywhere;
  }

  /* A reality-table row becomes a stacked card below 700px (see the shared
     block above: thead hidden, tr/td forced to display:block). Without a
     label a reader sees an unlabeled stack of values with no way to tell
     which column each one came from. content: attr(data-label) reads the
     data-label attribute every reality-table <td> across the site carries
     (added 2026-08-30; before that only .status-snapshot's four columns had
     labels, hardcoded per nth-child, and that hardcoding was wrong for
     #stClaims, a three-column table sharing the .status-snapshot class with
     the four-column #stFeatures -- nth-child(1) printed "Item" over a claim
     and nth-child(4)'s "Source" label pointed at nothing on a row that had
     no fourth cell). A <td> with no data-label (a table not yet covered)
     renders an empty label rather than breaking. */
  .reality-table td::before {
    display: block;
    margin-bottom: 2px;
    color: var(--faint);
    font-size: 11px;
    font-weight: 900;
    letter-spacing: .08em;
    line-height: 1.25;
    text-transform: uppercase;
    content: attr(data-label);
  }
}

/*
  Kaspa glass/material production layer.
  Keep this at the end so the intended Apple-glass / Material polish wins the
  cascade after page-specific and responsive base rules.
*/

:root {
  --preview-radius: 18px;
  --preview-radius-sm: 13px;
  --preview-elevation-1: 0 1px 2px rgba(0, 0, 0, .24), 0 12px 32px rgba(0, 0, 0, .16);
  --preview-elevation-2: 0 2px 7px rgba(0, 0, 0, .28), 0 22px 56px rgba(0, 0, 0, .22);
  --preview-glass: rgba(16, 28, 25, .7);
  --preview-glass-strong: rgba(11, 21, 19, .84);
  --preview-glass-line: rgba(221, 249, 244, .17);
  --preview-glass-highlight: rgba(255, 255, 255, .08);
  --line: rgba(221, 249, 244, .14);
  --line-bright: rgba(var(--green-rgb), .45);
}

:root[data-theme="light"] {
  --preview-glass: rgba(255, 255, 255, .78);
  --preview-glass-strong: rgba(250, 255, 253, .92);
  --preview-glass-line: rgba(19, 88, 80, .14);
  --preview-glass-highlight: rgba(255, 255, 255, .7);
}

body {
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

:root[data-theme="light"] body {
  background:
    radial-gradient(circle at 18% 0%, rgba(var(--green-rgb), .09), transparent 27rem),
    radial-gradient(circle at 88% 8%, rgba(var(--cyan-rgb), .055), transparent 30rem),
    linear-gradient(132deg, rgba(var(--green-rgb), .055), transparent 32%, rgba(var(--cyan-rgb), .035) 66%, transparent 90%),
    linear-gradient(180deg, var(--bg) 0%, var(--bg-2) 68%, #edf6f4 100%);
}

:root[data-theme="light"] body::before {
  opacity: .055;
}

:root[data-theme="light"] .site-header {
  background:
    linear-gradient(180deg, rgba(250, 255, 253, .84), rgba(245, 253, 250, .72));
  box-shadow: 0 12px 32px rgba(19, 88, 80, .08);
}

.nav-links a,
.nav-cta,
.theme-toggle,
.nav-menu-button {
  border-color: rgba(221, 249, 244, .1);
  background: rgba(255, 255, 255, .045);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .18);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  transition: transform .22s ease, background .22s ease, border-color .22s ease, color .22s ease, box-shadow .22s ease;
}

.nav-links a:hover,
.nav-cta:hover,
.theme-toggle:hover,
.nav-menu-button:hover {
  transform: none;
  background: rgba(221, 249, 244, .095);
  border-color: rgba(var(--green-rgb), .28);
  box-shadow: 0 8px 22px rgba(0, 0, 0, .16);
}

.nav-links a[aria-current="page"] {
  background:
    linear-gradient(180deg, rgba(var(--green-rgb), .18), rgba(var(--green-rgb), .105));
  border-color: rgba(var(--green-rgb), .42);
  box-shadow: 0 10px 24px rgba(var(--green-rgb), .1);
}

.nav-cta,
.button.primary {
  color: var(--ink);
  border-color: transparent;
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--green) 94%, white), var(--green));
  box-shadow: 0 1px 2px rgba(0, 0, 0, .22), 0 14px 30px rgba(var(--green-rgb), .14);
}

.hero-visual,
.section,
.quick-grid article,
.timeline article,
.status-grid article,
.insight-grid article,
.claim-grid article,
.hero-signal-grid a,
.orientation-console,
.orientation-grid a,
.protocol-demo,
.demo-workspace,
.demo-control-panel,
.demo-status-card,
.demo-explainer,
.demo-metrics div,
.explainer-workbench,
.workbench-grid article,
.transaction-path,
.transaction-rail article,
.status-workbench,
.status-lane-grid a,
.verification-workflow,
.verification-steps article,
.api-console,
.api-command-stack article,
.build-path-console,
.build-path-grid article,
.hero-status a,
.awareness-callout,
.live-kaspa-panel,
.live-metric-grid article,
.origin-proof-strip,
.source-handoff,
.summary-grid article,
.chain-panel,
.reference-grid article,
.api-command-card,
.ai-ask-controls,
.ai-prompt-card,
.pitch-input-card,
.pitch-output-card,
.survey-form,
.survey-output,
.reality-grid article,
.field-study-grid article,
.route-grid article,
.route-grid .route-card-link,
.path-grid article,
.source-card,
.source-tier,
.search-card,
.overview-grid article,
.compare-cards article,
.fit-grid article,
.lane-grid article,
.check-grid article,
.one-screen-grid article,
.must-read-grid article {
  border-color: var(--preview-glass-line);
  border-radius: var(--preview-radius);
  background:
    linear-gradient(145deg, rgba(255, 255, 255, .072), rgba(255, 255, 255, .018) 36%, rgba(var(--green-rgb), .035)),
    var(--preview-glass);
  box-shadow: var(--preview-elevation-1);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

:root[data-theme="light"] .hero-visual,
:root[data-theme="light"] .section,
:root[data-theme="light"] .quick-grid article,
:root[data-theme="light"] .timeline article,
:root[data-theme="light"] .status-grid article,
:root[data-theme="light"] .insight-grid article,
:root[data-theme="light"] .claim-grid article,
:root[data-theme="light"] .hero-signal-grid a,
:root[data-theme="light"] .orientation-console,
:root[data-theme="light"] .orientation-grid a,
:root[data-theme="light"] .protocol-demo,
:root[data-theme="light"] .demo-workspace,
:root[data-theme="light"] .demo-control-panel,
:root[data-theme="light"] .demo-status-card,
:root[data-theme="light"] .demo-explainer,
:root[data-theme="light"] .demo-metrics div,
:root[data-theme="light"] .explainer-workbench,
:root[data-theme="light"] .workbench-grid article,
:root[data-theme="light"] .transaction-path,
:root[data-theme="light"] .transaction-rail article,
:root[data-theme="light"] .status-workbench,
:root[data-theme="light"] .status-lane-grid a,
:root[data-theme="light"] .verification-workflow,
:root[data-theme="light"] .verification-steps article,
:root[data-theme="light"] .api-console,
:root[data-theme="light"] .api-command-stack article,
:root[data-theme="light"] .build-path-console,
:root[data-theme="light"] .build-path-grid article,
:root[data-theme="light"] .hero-status a,
:root[data-theme="light"] .awareness-callout,
:root[data-theme="light"] .live-kaspa-panel,
:root[data-theme="light"] .live-metric-grid article,
:root[data-theme="light"] .origin-proof-strip,
:root[data-theme="light"] .source-handoff,
:root[data-theme="light"] .summary-grid article,
:root[data-theme="light"] .chain-panel,
:root[data-theme="light"] .reference-grid article,
:root[data-theme="light"] .api-command-card,
:root[data-theme="light"] .ai-ask-controls,
:root[data-theme="light"] .ai-prompt-card,
:root[data-theme="light"] .pitch-input-card,
:root[data-theme="light"] .pitch-output-card,
:root[data-theme="light"] .survey-form,
:root[data-theme="light"] .survey-output,
:root[data-theme="light"] .reality-grid article,
:root[data-theme="light"] .field-study-grid article,
:root[data-theme="light"] .route-grid article,
:root[data-theme="light"] .route-grid .route-card-link,
:root[data-theme="light"] .path-grid article,
:root[data-theme="light"] .source-card,
:root[data-theme="light"] .source-tier,
:root[data-theme="light"] .search-card,
:root[data-theme="light"] .overview-grid article,
:root[data-theme="light"] .compare-cards article,
:root[data-theme="light"] .fit-grid article,
:root[data-theme="light"] .lane-grid article,
:root[data-theme="light"] .check-grid article,
:root[data-theme="light"] .one-screen-grid article,
:root[data-theme="light"] .must-read-grid article {
  background:
    linear-gradient(145deg, rgba(255, 255, 255, .7), rgba(255, 255, 255, .22) 38%, rgba(var(--green-rgb), .035)),
    rgba(255, 255, 255, .78);
}

.hero-signal-grid a,
.orientation-grid a,
.status-lane-grid a,
.build-path-grid article,
.quick-grid article,
.overview-grid article,
.compare-cards article,
.fit-grid article,
.lane-grid article,
.check-grid article,
.one-screen-grid article,
.must-read-grid article,
.insight-grid article {
  transition: transform .22s ease, border-color .22s ease, box-shadow .22s ease, background .22s ease;
}

.hero-signal-grid a:hover,
.orientation-grid a:hover,
.status-lane-grid a:hover,
.quick-grid article:hover,
.overview-grid article:hover,
.compare-cards article:hover,
.fit-grid article:hover,
.lane-grid article:hover,
.check-grid article:hover,
.one-screen-grid article:hover,
.must-read-grid article:hover,
.insight-grid article:hover {
  transform: translateY(-2px);
  border-color: rgba(var(--green-rgb), .32);
  box-shadow: var(--preview-elevation-2);
}

.button {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

h1,
h2 {
  letter-spacing: 0;
}

@media (max-width: 760px) {
  .nav {
    min-height: 66px;
  }

  .site-header {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  .hero-visual,
  .section,
  .quick-grid article,
  .hero-signal-grid a,
  .orientation-grid a {
    border-radius: 16px;
  }
}

/*
  Glass refinement layer.
  Keeps Kaspa Explained content and claim boundaries intact while making the
  homepage and shared surfaces feel more deliberate and spatial.
*/

:root {
  --panel: rgba(18, 28, 26, .68);
  --panel-strong: rgba(12, 22, 20, .9);
  --shadow: 0 1px 2px rgba(0, 0, 0, .24), 0 28px 80px rgba(0, 0, 0, .24);
  --shadow-soft: 0 1px 2px rgba(0, 0, 0, .2), 0 16px 42px rgba(0, 0, 0, .18);
}

body::before {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .04), transparent 15rem),
    linear-gradient(90deg, rgba(var(--green-rgb), .025) 1px, transparent 1px),
    linear-gradient(180deg, rgba(var(--cyan-rgb), .018) 1px, transparent 1px);
  background-size: auto, 52px 52px, 52px 52px;
  opacity: .18;
}

.site-header {
  margin: 12px auto 0;
  border: 1px solid var(--line);
  background: var(--bg-2);
  background-color: var(--bg-2);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: 0 18px 48px rgba(0, 0, 0, .22);
  overflow: visible;
}

.nav {
  padding-inline: 18px;
}

.brand-mark {
  border-radius: 12px;
  /* A 24px green glow offset 8px under a 26px mark does not read as a glow at
     that size. On the dark header it renders as a smudge below and left of the
     logo, visible in every screenshot at 390px and 1280px. The mark is a solid
     teal circle and needs no halo to separate from the bar. */
  box-shadow: none;
}

.nav-links a,
.theme-toggle,
.nav-cta,
.nav-menu-button,
.button,
.segmented-control button,
.pitch-ai-actions button {
  border-radius: 999px;
}

.nav-links a {
  border-color: transparent;
  background: transparent;
}

.nav-links a:hover,
.nav-links a[aria-current="page"] {
  border-color: color-mix(in srgb, var(--green) 34%, transparent);
  background: color-mix(in srgb, var(--green) 12%, transparent);
  text-decoration: none;
}

.hero {
  position: relative;
  align-items: stretch;
}

.hero::before {
  inset: 1rem 0 auto;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(221, 249, 244, .24), transparent);
  opacity: 1;
}

.hero-copy,
.hero-visual,
.section:not(.prose-section),
.hero-signal-grid a,
.orientation-grid a,
.hero-status a,
.demo-workspace,
.demo-status-card,
.route-grid .route-card-link,
.source-card,
.search-card,
.compare-cards article,
.api-command-card,
.ai-prompt-card,
.pitch-input-card,
.pitch-output-card {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--line);
  background:
    var(--card-bg);
  box-shadow: var(--shadow-soft);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.hero-copy,
.hero-visual {
  border-radius: 28px;
  box-shadow: var(--shadow);
}

.hero-copy::after,
.hero-visual::before,
.section:not(.prose-section)::before,
.orientation-grid a::before,
.hero-signal-grid a::before,
.route-grid .route-card-link::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(115deg, rgba(255, 255, 255, .09), transparent 28%, rgba(var(--green-rgb), .035) 84%);
  opacity: .72;
}

.hero-copy > *,
.hero-visual > *,
.section:not(.prose-section) > *,
.orientation-grid a > *,
.hero-signal-grid a > *,
.route-grid .route-card-link > * {
  position: relative;
  z-index: 1;
}

.hero h1 {
  letter-spacing: 0;
  text-wrap: balance;
}

.button.primary,
.nav-cta {
  background: linear-gradient(135deg, var(--green), color-mix(in srgb, var(--cyan) 42%, var(--green)));
  color: var(--ink);
  box-shadow: 0 12px 28px rgba(var(--green-rgb), .18);
}

.button:hover,
.theme-toggle:hover,
.nav-cta:hover {
  transform: translateY(-1px);
}

@media (max-width: 760px) {
  .site-header {
    width: 100%;
    margin-top: 0;
    border-inline: 0;
    border-radius: 0;
  }

  .hero-copy,
  .hero-visual {
    border-radius: 22px;
  }
}

/* Spacing repair: glass borders need more inner air than flat surfaces. This
   used to push padding up to clamp(28px, 4vw, 52px), which fought the
   vertical-rhythm tightening on the base .section rule above by overriding
   it back to a larger figure through :not() specificity. Reuses the same
   .section padding value instead of introducing a second number. */
.section:not(.prose-section) {
  padding: clamp(20px, 2.8vw, 32px);
}

.hero-copy,
.hero-visual {
  padding: clamp(24px, 4vw, 48px);
}

.quick-grid article,
.summary-grid article,
.status-grid article,
.overview-grid article,
.compare-cards article,
.fit-grid article,
.lane-grid article,
.check-grid article,
.one-screen-grid article,
.must-read-grid article,
.insight-grid article,
.route-grid .route-card-link,
.hero-signal-grid a,
.orientation-grid a,
.hero-status a,
.source-card,
.search-card,
.api-command-card,
.ai-prompt-card,
.pitch-input-card,
.pitch-output-card,
.demo-status-card {
  padding: clamp(18px, 2.4vw, 28px);
}

/* display/align-items marked !important (defect 1): the text was never
   actually mis-centered by this sitewide rule, which already flex-centers
   it. demos/parameterless.html carries its own inline <style> .status-pill
   rule (display:inline-block, no flex) that shadows this by source order,
   so its pill text sat on the inline-block text line's natural leading
   instead of being centered, ~6px high at a 30px pill height. Forcing
   flex centering back on wins without touching the demo's markup or its
   own color/size choices for the pill. */
.status-pill {
  display: inline-flex !important;
  align-items: center !important;
  min-height: 30px;
  padding: 5px 10px;
  line-height: 1.25;
}

.fit-note,
.verified-note,
.source-more,
.plain-bridge,
.api-command-card-note {
  padding: 14px 16px;
}

.table-wrap {
  padding: clamp(10px, 2vw, 16px);
}

.reality-table th,
.reality-table td {
  padding: 16px 18px;
}

.section:not(.prose-section) > * + *,
.quick-grid article > * + *,
.summary-grid article > * + *,
.status-grid article > * + *,
.route-grid .route-card-link > * + *,
.hero-signal-grid a > * + *,
.orientation-grid a > * + * {
  margin-top: 0.72rem;
}

@media (max-width: 760px) {
  .section:not(.prose-section) {
    padding: 22px;
  }

  .hero-copy,
  .hero-visual {
    padding: 22px;
  }

  .quick-grid article,
  .summary-grid article,
  .status-grid article,
  .overview-grid article,
  .compare-cards article,
  .fit-grid article,
  .lane-grid article,
  .check-grid article,
  .one-screen-grid article,
  .must-read-grid article,
  .insight-grid article,
  .route-grid .route-card-link,
  .hero-signal-grid a,
  .orientation-grid a,
  .hero-status a,
  .source-card,
  .search-card,
  .api-command-card,
  .ai-prompt-card,
  .pitch-input-card,
  .pitch-output-card,
  .demo-status-card {
    padding: 18px;
  }

  .status-pill {
    min-height: 28px;
    padding: 5px 9px;
  }

  .table-wrap {
    padding: 10px;
  }

  .reality-table th,
  .reality-table td {
    padding: 12px 14px;
  }
}

/* Mobile nav repair: make the opened menu a real clickable panel. */
@media (max-width: 760px) {
  .site-header,
  .nav {
    overflow: visible;
  }

  .nav {
    position: relative;
  }

  .nav.nav-enhanced[data-open="true"] .nav-links {
    position: absolute;
    z-index: 60;
    top: calc(100% + 8px);
    left: 0;
    right: 0;
    display: flex !important;
    gap: 8px;
    padding: 12px;
    border: 1px solid var(--line);
    border-radius: 18px;
    background: var(--bg-2);
    background-color: var(--bg-2);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: var(--shadow);
    pointer-events: auto;
  }

  .nav.nav-enhanced[data-open="true"] .nav-links a {
    position: relative;
    z-index: 1;
    display: inline-flex;
    width: auto;
    min-width: max-content;
    pointer-events: auto;
  }
}

/* Balanced card grid pass: reduce orphan cards and dead row space across route, comparison, status, and source grids. */
:where(
  .hero-signal-grid,
  .hero-status,
  .visual-readout,
  .orientation-grid,
  .workbench-grid,
  .status-lane-grid,
  .verification-steps,
  .build-path-grid,
  .api-command-stack,
  .quick-grid,
  .timeline,
  .status-grid,
  .link-grid,
  .insight-grid,
  .claim-grid,
  .fit-grid,
  .category-list,
  .lane-grid,
  .check-grid,
  .crypto-native-route,
  .crypto-native-ledger,
  .builder-console,
  .builder-ledger,
  .rail-ladder,
  .reference-grid,
  .source-tier-grid,
  .ai-destination-grid,
  .pitch-check-grid,
  .reality-grid,
  .field-study-grid,
  .compact-columns,
  .source-list,
  .account-grid,
  .path-grid,
  .route-grid,
  .one-screen-grid,
  .must-read-grid,
  .insight-groups,
  .use-source-grid,
  .learning-steps,
  .method-strip,
  .overview-grid,
  .compare-cards,
  .glossary-grid,
  .capability-grid,
  .route-card-grid,
  .homepage-route-grid
) {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  align-items: stretch;
}

:where(
  .hero-signal-grid,
  .hero-status,
  .visual-readout,
  .orientation-grid,
  .workbench-grid,
  .status-lane-grid,
  .verification-steps,
  .build-path-grid,
  .api-command-stack,
  .quick-grid,
  .timeline,
  .status-grid,
  .link-grid,
  .insight-grid,
  .claim-grid,
  .fit-grid,
  .category-list,
  .lane-grid,
  .check-grid,
  .crypto-native-route,
  .crypto-native-ledger,
  .builder-console,
  .builder-ledger,
  .rail-ladder,
  .reference-grid,
  .source-tier-grid,
  .ai-destination-grid,
  .pitch-check-grid,
  .reality-grid,
  .field-study-grid,
  .compact-columns,
  .source-list,
  .account-grid,
  .path-grid,
  .route-grid,
  .one-screen-grid,
  .must-read-grid,
  .insight-groups,
  .use-source-grid,
  .learning-steps,
  .method-strip,
  .overview-grid,
  .compare-cards,
  .glossary-grid,
  .capability-grid,
  .route-card-grid,
  .homepage-route-grid
) > * {
  min-width: 0;
}

@media (max-width: 700px) {
  :where(
    .hero-signal-grid,
    .hero-status,
    .visual-readout,
    .orientation-grid,
    .workbench-grid,
    .status-lane-grid,
    .verification-steps,
    .build-path-grid,
    .api-command-stack,
    .quick-grid,
    .timeline,
    .status-grid,
    .link-grid,
    .insight-grid,
    .claim-grid,
    .fit-grid,
    .category-list,
    .lane-grid,
    .check-grid,
    .crypto-native-route,
    .crypto-native-ledger,
    .builder-console,
    .builder-ledger,
    .rail-ladder,
    .reference-grid,
    .source-tier-grid,
    .ai-destination-grid,
    .pitch-check-grid,
    .reality-grid,
    .field-study-grid,
    .compact-columns,
    .source-list,
    .account-grid,
    .path-grid,
    .route-grid,
    .one-screen-grid,
    .must-read-grid,
    .insight-groups,
    .use-source-grid,
    .learning-steps,
    .method-strip,
    .overview-grid,
    .compare-cards,
    .glossary-grid,
    .capability-grid,
    .route-card-grid,
    .homepage-route-grid
  ) {
    grid-template-columns: minmax(0, 1fr);
  }

  :where(
    .hero-signal-grid,
    .hero-status,
    .visual-readout,
    .orientation-grid,
    .workbench-grid,
    .status-lane-grid,
    .verification-steps,
    .build-path-grid,
    .api-command-stack,
    .quick-grid,
    .timeline,
    .status-grid,
    .link-grid,
    .insight-grid,
    .claim-grid,
    .fit-grid,
    .category-list,
    .lane-grid,
    .check-grid,
    .crypto-native-route,
    .crypto-native-ledger,
    .builder-console,
    .builder-ledger,
    .rail-ladder,
    .reference-grid,
    .source-tier-grid,
    .ai-destination-grid,
    .pitch-check-grid,
    .reality-grid,
    .field-study-grid,
    .compact-columns,
    .source-list,
    .account-grid,
    .path-grid,
    .route-grid,
    .one-screen-grid,
    .must-read-grid,
    .insight-groups,
    .use-source-grid,
    .learning-steps,
    .method-strip,
    .overview-grid,
    .compare-cards,
    .glossary-grid,
    .capability-grid,
    .route-card-grid,
    .homepage-route-grid
  ) > * {
    grid-column: auto;
  }
}

/* Higher-specificity exact-count balancing for component grids with existing fixed column rules. */

/* Final formatting overrides: keep exact four-card method routes from becoming cramped. */

/* Final global nav layer: header must stay above every page card while scrolling. */
.site-header {
  position: fixed;
  top: 12px;
  left: 50%;
  transform: translateX(-50%);
  width: min(1240px, calc(100% - 40px));
  z-index: 1000;
  isolation: isolate;
  border-radius: 24px;
}

.nav {
  position: relative;
  z-index: 1001;
}

@media (max-width: 700px) {
}

/* Final interaction/layout guardrails. Marked !important because demo pages
   under demos/ carry their own inline <style> block with a `body{padding:0
   0 4rem}` shorthand (loaded after this stylesheet, so it would otherwise
   win by source order) that zeroed this out and left demo content, notably
   the "Back to ..." link, rendering under the fixed header (defect 2). */
body {
  padding-top: var(--site-header-clearance, 132px) !important;
  overflow-x: hidden;
}

.skip-link {
  z-index: 1200;
}

/* One token drives every page's header-to-content gap (defect 4). Marked
   !important because demo pages under demos/ carry their own inline
   <style> block with a `main{padding:1.5rem 1rem 0;...}` shorthand that
   would otherwise win by source order and leave demo content flush
   against (or under) the fixed header; !important on this single
   longhand keeps demos on the same token without touching their markup. */
main {
  padding-top: var(--content-top-gap) !important;
}

main > :first-child {
  margin-top: 0;
}

.hero {
  padding-top: 0;
}

:is(
  .orientation-grid,
  .toccata-evidence-map,
  .toccata-builder-grid,
  .hero-signal-grid,
  .hero-status,
  .route-grid,
  .path-grid,
  .source-strip,
  .link-grid,
  .summary-grid,
  .compare-cards,
  .homepage-route-grid,
  .route-card-grid,
  .quick-grid,
  .timeline,
  .status-grid,
  .insight-grid,
  .claim-grid,
  .status-lane-grid,
  .verification-steps,
  .build-path-grid,
  .api-command-stack,
  .reference-grid,
  .lane-grid,
  .fit-grid,
  .check-grid,
  .overview-grid,
  .glossary-grid,
  .reality-grid,
  .field-study-grid,
  .one-screen-grid,
  .must-read-grid,
  .insight-groups,
  .use-source-grid,
  .reader-route-grid
) {
  align-items: stretch;
  grid-auto-rows: auto;
}

:is(
  .orientation-grid,
  .toccata-evidence-map,
  .toccata-builder-grid,
  .hero-signal-grid,
  .hero-status,
  .route-grid,
  .path-grid,
  .source-strip,
  .link-grid,
  .summary-grid,
  .compare-cards,
  .homepage-route-grid,
  .route-card-grid,
  .quick-grid,
  .timeline,
  .status-grid,
  .insight-grid,
  .claim-grid,
  .status-lane-grid,
  .verification-steps,
  .build-path-grid,
  .api-command-stack,
  .reference-grid,
  .lane-grid,
  .fit-grid,
  .check-grid,
  .overview-grid,
  .glossary-grid,
  .reality-grid,
  .field-study-grid,
  .one-screen-grid,
  .must-read-grid,
  .insight-groups,
  .use-source-grid,
  .reader-route-grid
) > :is(a, article, label, li, .route-card-link, .search-card, .source-card, .source-tier, .quadrant, .quad-cell) {
  align-self: stretch;
  height: 100%;
  min-height: 0;
}

/* Hover stability: card grids should highlight in place. Moving
   glass/backdrop-filter cards can flicker or disappear during pointer hover. */
:is(
  .hero-signal-grid a,
  .orientation-grid a,
  .toccata-evidence-map a,
  .toccata-builder-grid a,
  .hero-status a,
  .route-grid article,
  .route-grid .route-card-link,
  .path-grid a,
  .source-strip a,
  .link-grid a,
  .summary-grid article,
  .compare-cards article,
  .homepage-route-grid a,
  .homepage-route-grid article,
  .route-card-grid a,
  .route-card-grid article,
  .quick-grid article,
  .timeline article,
  .status-grid article,
  .insight-grid article,
  .claim-grid article,
  .status-lane-grid a,
  .verification-steps article,
  .build-path-grid article,
  .api-command-stack article,
  .reference-grid article,
  .lane-grid article,
  .fit-grid article,
  .check-grid article,
  .overview-grid article,
  .glossary-grid article,
  .reality-grid article,
  .field-study-grid article,
  .one-screen-grid article,
  .must-read-grid article,
  .insight-groups article,
  .use-source-grid article,
  .reader-route-grid article,
  .search-card,
  .source-card,
  .source-tier,
  .quadrant,
  .quad-cell
) {
  transform: none;
}

:is(
  .hero-signal-grid a,
  .orientation-grid a,
  .toccata-evidence-map a,
  .toccata-builder-grid a,
  .hero-status a,
  .route-grid article,
  .route-grid .route-card-link,
  .path-grid a,
  .source-strip a,
  .link-grid a,
  .summary-grid article,
  .compare-cards article,
  .homepage-route-grid a,
  .homepage-route-grid article,
  .route-card-grid a,
  .route-card-grid article,
  .quick-grid article,
  .timeline article,
  .status-grid article,
  .insight-grid article,
  .claim-grid article,
  .status-lane-grid a,
  .verification-steps article,
  .build-path-grid article,
  .api-command-stack article,
  .reference-grid article,
  .lane-grid article,
  .fit-grid article,
  .check-grid article,
  .overview-grid article,
  .glossary-grid article,
  .reality-grid article,
  .field-study-grid article,
  .one-screen-grid article,
  .must-read-grid article,
  .insight-groups article,
  .use-source-grid article,
  .reader-route-grid article,
  .search-card,
  .source-card,
  .source-tier,
  .quadrant,
  .quad-cell
):hover {
  transform: none !important;
}

/* Final orphan-row guardrails: exact rendered checks should never leave one card alone. */

/* Final table readability guard: keep row labels, status pills, and source
   links from splitting mid-word. Long descriptions (column 3) still wrap
   freely since prose benefits from breaking anywhere it needs to. */
.reality-table th:first-child,
.reality-table td:first-child,
.reality-table th:nth-child(2),
.reality-table td:nth-child(2),
.reality-table th:last-child,
.reality-table td:last-child,
.reality-table .status-pill {
  overflow-wrap: normal;
  word-break: normal;
}

.reality-table td:first-child {
  min-width: 12rem;
  white-space: normal;
}

.reality-table td:nth-child(2):has(.status-pill),
.reality-table th:nth-child(2) {
  min-width: 9rem;
}

.reality-table td:last-child {
  min-width: 8rem;
}

.reality-table td:last-child a {
  overflow-wrap: normal;
  word-break: normal;
}

.reality-table .status-pill {
  white-space: nowrap;
}

@media (max-width: 700px) {
  .reality-table td {
    padding: 10px 4px;
  }

  .reality-table td:first-child {
    min-width: 0;
  }

  .reality-table td:first-child,
  .reality-table td:nth-child(2) {
    overflow-wrap: normal;
  }
}

.miner-settings-table td code,
#miner .fit-note code {
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: break-word;
}

@media (max-width: 760px) {
  .fit-hero h1,
  .reality-hero h1,
  .why-hero h1,
  .sources-hero h1,
  .knowledge-hero h1,
  .status-hero h1,
  .glossary-hero h1 {
    max-width: 100%;
    font-size: clamp(1.72rem, 8vw, 1.95rem);
    line-height: 1.08;
    overflow-wrap: break-word;
  }
}

/* Final anchor-position guard: hash links must clear the fixed pill nav. */
html {
  scroll-padding-top: var(--site-header-clearance, 132px);
}

:where([id]) {
  scroll-margin-top: var(--site-header-clearance, 132px);
}

/* Final phone-width repair: later glass rules can otherwise leave the page
   wider than the real viewport in headless and mobile browsers. */
@media (max-width: 520px) {
  .site-header {
    width: calc(100vw - 24px);
    max-width: calc(100vw - 24px);
    margin: 10px auto 0;
    border-radius: 24px;
  }

  .nav,
  main,
  .footer {
    width: calc(100vw - 24px);
    max-width: calc(100vw - 24px);
  }

  .nav {
    gap: 8px;
    padding-inline: 10px;
  }

  .brand {
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
  }

  .brand-mark {
    width: 30px;
    height: 30px;
    flex-basis: 30px;
  }

  .theme-toggle,
  .nav-cta {
    display: none !important;
  }

  .nav.nav-enhanced[data-open="true"] .nav-links {
    left: 0;
    right: 0;
    max-width: 100%;
  }

  .nav.nav-enhanced[data-open="true"] .nav-links a {
    min-width: 0;
    width: 100%;
    justify-content: flex-start;
    /* Measured 322x34 on the live site: the menu rows are the primary way to
       navigate on a phone and sat 10px under the 44pt minimum. The target
       comes from the row's own box so the list stays tight. */
    min-height: 44px;
    align-items: center;
  }

  .hero,
  .status-workbench,
  .build-path-console {
    grid-template-columns: 1fr !important;
  }

  .hero {
    padding-top: 2rem;
  }

  .hero-copy,
  .hero-visual,
  .section:not(.prose-section) {
    width: 100%;
    max-width: 100%;
    border-radius: 18px;
    padding: 22px;
  }

  .hero h1 {
    line-height: 1.08;
  }

  .lead,
  .plain-bridge,
  .fit-note,
  .source-inline {
    max-width: 100%;
    overflow-wrap: break-word;
  }

  .hero-signal-grid,
  .hero-status,
  .status-lane-grid,
  .build-path-grid,
  .summary-grid,
  .reference-grid {
    grid-template-columns: 1fr !important;
  }

  .hero-signal-grid a,
  .status-lane-grid a,
  .summary-grid article,
  .reference-grid article {
    width: 100%;
    max-width: 100%;
  }

}

/* Toccata personal essay pages */

.section.site-related::before,
.section:has(.article-path-grid)::before {
  content: none;
}

/* ============================================================
   APPLE DESIGN LAYER, 2026-07-08
   Light-first, flat surfaces, big type, one restrained accent.
   Appended last on purpose: this file's cascade is last-wins,
   so every token and component below overrides the glass era.
   ============================================================ */

:root[data-theme="light"] {
  color-scheme: light;
  --bg: #fbfaf6;
  --bg-2: #f3f0ea;
  --panel: #f3f0ea;
  --panel-strong: #fbfaf6;
  --card-bg: #fbfaf6;
  --line: #d8d4cb;
  --line-bright: #bcb6a8;
  --text: #211e1a;
  --muted: #646057;
  --faint: #6b6659; /* was #706b61: 4.42:1 on the demo-frame tint over --panel, under the 4.5 floor. 4.78:1 now, on the worst real background the site composites. */
  --green: #0c7a69;
  --green-rgb: 14, 124, 107;
  --cyan: #0068da;
  --cyan-rgb: 0, 113, 227;
  /* Text set directly in --cyan on the card background used by
     .hero-signal-grid/.status-lane-grid/.orientation-grid's 6n+2 label
     span measures 4.497:1 here, just under the 4.5:1 AA floor for normal
     text. Same fix as --purple-pill below: a dedicated, slightly darker
     token for this text-on-card use, not a change to --cyan itself (which
     is also used for icons/buttons against different backgrounds where it
     already passes). #0068d1 measures 5.15:1 against this card's #fbfaf6
     background. */
  --cyan-pill: #0068d1;
  --link-color: #0064c2;
  --purple: #6e56cf;
  --purple-pill: var(--purple);
  --orange: #b14f00;
  --ink: #ffffff;
  --accent-soft: rgba(14, 124, 107, .1);
  /* --green as badge text on --accent-soft (the .transaction-rail step
     numbers) measures 4.28:1, under the 4.5:1 floor. Same --<color>-pill
     pattern as --cyan-pill/--purple-pill above: a dedicated darker token
     for this text-on-tinted-fill use, not a change to --green itself.
     #0a6a5c measures 5.45:1 against this fill composited on the card. */
  --green-pill: #0a6a5c;
  --surface-soft: #f5f5f7;
  --control-bg: #e8e8ed;
  --control-hover: #dededf;
  --field-bg: #ffffff;
  --field-line: #d2d2d7;
  --graph-node-fill: #ffffff;
  --graph-node-soft-fill: #ffffff;
  --graph-node-selected-fill: #d9f1ea;
  --graph-node-side-fill: #fff3e3;
  --shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 12px 32px rgba(0, 0, 0, .05);
  --shadow-soft: 0 1px 2px rgba(0, 0, 0, .04), 0 6px 18px rgba(0, 0, 0, .04);
  --button-shadow: 0 0 #0000;
  --brand-gradient: linear-gradient(135deg, #128673, #0c7a69);
  --brand-glow: 0 0 #0000;
  --glow-spot: none;
  --page-bg: #ffffff;
  --site-header-clearance: 108px;
}

:root,
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #100e0c;
  --bg-2: #1c1a17;
  --panel: #1c1a17;
  --panel-strong: #221f1c;
  --card-bg: #322f2a;
  --line: #4a453d;
  --line-bright: #746e60;
  --text: #f8f5ef;
  --muted: #b6b0a7;
  --faint: #9d988c;
  --green: #66d1c1;
  --green-rgb: 102, 209, 193;
  --cyan: #2e9cff;
  --cyan-rgb: 41, 151, 255;
  /* Measures 4.42:1 against the card background at the 6n+2 label span
     (see the light-theme --cyan-pill comment); #3d9fff measures 4.82:1. */
  --cyan-pill: #3d9fff;
  --link-color: #38a3fa;
  --purple: #bf5af2;
  --purple-pill: #ce80f5;
  --orange: #ff9f0a;
  --ink: #06201b;
  /* Dark theme's --green already clears 4.5:1 as badge text on --accent-soft. */
  --green-pill: var(--green);
  --accent-soft: rgba(102, 209, 193, .12);
  --surface-soft: #1d1d1f;
  --control-bg: #2c2c2e;
  --control-hover: #3a3a3c;
  --field-bg: #221f1c;
  --field-line: #4a453d;
  --graph-node-fill: #221f1c;
  --graph-node-soft-fill: #221f1c;
  --graph-node-selected-fill: #0f3d35;
  --graph-node-side-fill: #3a2b14;
  --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 12px 32px rgba(0, 0, 0, .35);
  --shadow-soft: 0 1px 2px rgba(0, 0, 0, .35), 0 6px 18px rgba(0, 0, 0, .3);
  --button-shadow: 0 0 #0000;
  --brand-gradient: linear-gradient(135deg, #6fd7c4, #5cc9b5);
  --brand-glow: 0 0 #0000;
  --glow-spot: none;
  --page-bg: #100e0c;
  --site-header-clearance: 108px;
}

/* ---- page canvas: flat, quiet ---- */

body {
  background: var(--page-bg);
  font-size: 17px;
}

body::before,
body::after {
  display: none;
}

/* ---- header: full-width slim translucent bar ---- */

.site-header,
:root[data-theme="light"] .site-header {
  position: fixed;
  top: 0;
  left: 0;
  transform: none;
  width: 100%;
  max-width: 100%;
  margin: 0;
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--text) 9%, transparent);
  border-radius: 0;
  /* Opaque, not 72% of --bg. A translucent bar needs a backdrop blur behind it
     to stay legible, and this site bans in-page blur outright (see the glass
     gate). Without one, scrolled page text read straight through the nav: at
     1280px on /status, "Proved on a test network" sat inside the words "What
     is Kaspa" and "Live now". Fixed 29 August 2026. */
  background: var(--bg);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}

.nav {
  width: min(1240px, calc(100% - 44px));
  margin: 0 auto;
  min-height: 56px;
}

.brand {
  font-size: 16px;
  font-weight: 600;
}

.brand-mark {
  width: 26px;
  height: 26px;
  flex: 0 0 26px;
  filter: none;
}

.nav-links {
  gap: 4px;
}

.nav-links a,
:root[data-theme="light"] .nav-links a {
  min-height: 34px;
  border: 0;
  border-radius: 8px;
  padding: 6px 12px;
  background: transparent;
  box-shadow: none;
  color: var(--muted);
  font-size: 13.5px;
  font-weight: 500;
}

.nav-links a:hover,
:root[data-theme="light"] .nav-links a:hover {
  background: transparent;
  color: var(--text);
  text-decoration: none;
}

.nav-links a[aria-current="page"],
:root[data-theme="light"] .nav-links a[aria-current="page"] {
  background: transparent;
  border: 0;
  box-shadow: none;
  color: var(--text);
  font-weight: 600;
}

.theme-toggle {
  border: 0;
  border-radius: 980px;
  padding: 6px 13px;
  background: var(--control-bg);
  color: var(--text);
  font-size: 12.5px;
  font-weight: 500;
  box-shadow: none;
}
/* superseded below in the APPLE DESIGN LAYER (defect 2, 2026-08-23): this
   32px min-height only reached most pages; demos/index.html carried a
   page-scoped >=521px override to the 44px touch target this site holds
   itself to elsewhere (mobile nav, .info-affordance__trigger). Fixed at
   the cascade tail instead of here so it wins by source order. */

.nav-menu-button,
:root[data-theme="light"] .nav-menu-button {
  border: 0;
  background: var(--control-bg);
  color: var(--text);
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.nav-menu-button:hover {
  background: var(--control-hover);
  border: 0;
  box-shadow: none;
  transform: none;
}

/* ---- sections: gray tiles on white, no glass ---- */

.hero-copy,
.hero-visual,
.section:not(.prose-section),
.quick-grid article,
.timeline article,
.status-grid article,
.insight-grid article,
.claim-grid article,
.orientation-console,
.protocol-demo,
.demo-workspace,
.demo-control-panel,
.demo-status-card,
.demo-explainer,
.demo-metrics div,
.explainer-workbench,
.workbench-grid article,
.transaction-path,
.transaction-rail article,
.status-workbench,
.verification-workflow,
.verification-steps article {
  border: 0;
  background: var(--panel);
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.section:not(.prose-section) {
  border-radius: 28px;
}

.hero-copy::after,
.hero-visual::before,
.section:not(.prose-section)::before,
.orientation-grid a::before,
.hero-signal-grid a::before,
.route-grid .route-card-link::before,
.hero::before {
  display: none;
}

/* white cards inside gray tiles */
.hero-signal-grid a,
.orientation-grid a,
.hero-status a,
.status-lane-grid a,
.route-grid .route-card-link,
.source-card,
.search-card,
.compare-cards article,
.api-command-card,
.ai-prompt-card,
.pitch-input-card,
.pitch-output-card,
.quick-grid article,
.timeline article,
.status-grid article,
.insight-grid article,
.claim-grid article,
.workbench-grid article,
.transaction-rail article,
.verification-steps article,
.summary-grid article,
.reference-grid article,
.build-path-grid article,
.category-list article,
.article-path-grid article,
.site-related-grid a,
.fit-grid article.section,
.demo-workspace,
.demo-control-panel,
.demo-status-card,
.demo-explainer,
.demo-metrics div {
  border: 0;
  border-radius: 18px;
  background: var(--card-bg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .05), 0 6px 16px rgba(0, 0, 0, .04);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

.hero-signal-grid a:hover,
.orientation-grid a:hover,
.status-lane-grid a:hover,
.site-related-grid a:hover,
.route-grid .route-card-link:hover,
.quick-grid article:hover,
.overview-grid article:hover,
.compare-cards article:hover,
.fit-grid article:hover,
.lane-grid article:hover,
.check-grid article:hover,
.one-screen-grid article:hover,
.must-read-grid article:hover,
.insight-grid article:hover {
  border: 0;
  background: var(--card-bg);
  transform: translateY(-2px);
  box-shadow: 0 2px 4px rgba(0, 0, 0, .06), 0 12px 28px rgba(0, 0, 0, .08);
}

/* ---- typography: big, tight, calm ---- */

/* Display type steps down as its own content lengthens, so a long string
   never renders at the size meant for a short one (owner report, 2026-08-22:
   a wrapped headline reads as a wall of text, not emphasis). Mechanism: an
   element that knows its own character count sets --len inline (a static
   character count for fixed copy, or written by a tiny script on load for
   JS-generated readouts); the font-size formula below subtracts a per-
   character penalty once --len passes a threshold, floored at a size that
   still reads as a heading. --len is never set by CSS, so an element that
   doesn't opt in keeps exactly the old fixed clamp (default 12, below every
   threshold here = zero penalty), which is why this is safe to ship
   site-wide: nothing changes anywhere this pattern isn't deliberately
   applied. Being pure CSS (no layout measurement, no async pass), it can
   never flash a large size before shrinking, and it doesn't touch color,
   motion, or theme, so it can't fight prefers-reduced-motion or the
   data-theme toggle. See design/house-style.md and demos/index.html for the
   card-title application. */
h1 {
  font-size: clamp(1.9rem, calc(clamp(2.45rem, 5vw, 4.25rem) - max(var(--len, 12) - 28, 0) * 0.034rem), 4.25rem);
  font-weight: 700;
  letter-spacing: -.017em;
  line-height: 1.04;
  text-shadow: none;
}

h2 {
  font-size: clamp(1.35rem, calc(clamp(1.9rem, 3.6vw, 2.9rem) - max(var(--len, 12) - 20, 0) * 0.026rem), 2.9rem);
  font-weight: 700;
  letter-spacing: -.014em;
  line-height: 1.08;
  text-shadow: none;
}

h3 {
  font-weight: 650;
  letter-spacing: -.008em;
}

.lead {
  font-size: clamp(1.19rem, 1.9vw, 1.42rem);
  line-height: 1.45;
  font-weight: 420;
  color: var(--muted);
}

.eyebrow {
  min-height: 0;
  border: 0;
  border-radius: 0;
  padding: 0;
  margin: 0 0 12px;
  background: transparent;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  color: var(--green);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .08em;
}

/* ---- hero: centered statement, visual below ---- */

.hero {
  grid-template-columns: 1fr;
  justify-items: center;
  text-align: center;
  gap: clamp(18px, 3vw, 30px);
}

.hero-copy {
  background: transparent;
  border-radius: 0;
  max-width: 880px;
}

.hero-copy .lead {
  margin-inline: auto;
  max-width: 46ch;
}

.hero .actions,
.hero .hero-signal-grid {
  justify-content: center;
  text-align: left;
}

.sources-hero,
.knowledge-hero,
.fit-hero,
.status-hero {
  text-align: center;
}

.sources-hero .eyebrow,
.knowledge-hero .eyebrow,
.fit-hero .eyebrow,
.status-hero .eyebrow {
  margin-inline: auto;
}

.sources-hero .lead,
.knowledge-hero .lead,
.fit-hero .lead,
.status-hero .lead {
  margin-inline: auto;
  max-width: 62ch;
}

.sources-hero .fit-note,
.knowledge-hero .fit-note,
.fit-hero .fit-note,
.status-hero .fit-note,
.sources-hero .source-inline,
.knowledge-hero .source-inline {
  margin-inline: auto;
  max-width: 760px;
  text-align: left;
}

.sources-hero .actions,
.knowledge-hero .actions,
.fit-hero .actions,
.status-hero .actions,
.sources-hero .jump-list,
.status-hero .jump-list {
  justify-content: center;
}

/* ---- buttons: apple pills ---- */

.button {
  min-height: 44px;
  border: 0;
  border-radius: 980px;
  padding: 11px 22px;
  background: var(--control-bg);
  color: var(--text);
  font-size: 16px;
  font-weight: 500;
  box-shadow: none;
}

.button:hover {
  background: var(--control-hover);
  border: 0;
  box-shadow: none;
  transform: none;
}

.button.primary {
  background: var(--green);
  color: var(--ink);
  box-shadow: none;
}

.button.primary:hover {
  background: color-mix(in srgb, var(--green) 86%, var(--text));
  box-shadow: none;
}

/* ---- notes, quotes, tables ---- */

.fit-note,
.verified-note,
.source-more,
.api-command-card-note {
  border: 0;
  border-radius: 14px;
  background: var(--card-bg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
}

blockquote {
  border-left: 3px solid var(--green);
  border-radius: 0 14px 14px 0;
  background: var(--card-bg);
  font-weight: 650;
}

.table-wrap {
  border: 0;
  border-radius: 18px;
  background: var(--card-bg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
}

.reality-table th {
  background: transparent;
  color: var(--faint);
  letter-spacing: .05em;
  border-bottom: 1px solid var(--line);
}

.reality-table td {
  border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
}

.status-pill.research {
  --status-color: var(--orange);
}

:root[data-theme="dark"] .status-pill.research {
  --status-color: var(--orange);
}

code {
  border: 0;
  background: color-mix(in srgb, var(--text) 6%, transparent);
  color: color-mix(in srgb, var(--green) 72%, var(--text));
}

/* ---- footer: quiet small print ---- */

.footer {
  border-top: 1px solid var(--line);
  font-size: 13px;
}

.footer p,
.footer a {
  color: var(--muted);
}

.footer a:hover {
  color: var(--text);
}

/* ---- mobile ---- */

@media (max-width: 700px) {
  .site-header {
    position: fixed;
    top: 0;
    left: 0;
    transform: none;
    width: 100%;
    max-width: 100%;
    margin: 0;
    border-radius: 0;
  }

  .nav {
    min-height: 48px;
    padding: 8px 0;
  }

  .nav.nav-enhanced[data-open="true"] .nav-links {
    border: 0;
    border-radius: 0 0 18px 18px;
    background: var(--bg);
    box-shadow: 0 18px 40px rgba(0, 0, 0, .14);
  }

  /* One h1 size and one h2 size per width, sitewide. Before 29 August 2026
     a page hero rendered h1 at 31.2px if its wrapper carried a named hero
     class and 35.2px if it did not, 39px on the homepage, and 27.52px on
     crypto-from-scratch: four sizes for one role, none of them chosen. The h2
     value here is the one the pre-Apple-layer stylesheet already used; it was
     shadowed rather than replaced, which left h2 at 30.4px against an h1 of
     31.2px, so a phone reader could not tell a page title from a section
     heading. */
  h1 {
    font-size: clamp(1.72rem, 8vw, 1.95rem);
  }

  h2 {
    font-size: clamp(1.38rem, 7vw, 1.6rem);
  }
}

/* legacy themed body rules ([data-theme] body) outrank plain body; pin both themes flat */
:root[data-theme="light"] body,
:root[data-theme="dark"] body {
  background: var(--page-bg);
}

/* ---- hero centering, complete ----
   Legacy h1 rules cap width at 1000px with margin-left 0, so centered text
   sat in a left-anchored box (a uniform -138px skew on every page). Center
   the boxes themselves, cover the hero classes the first pass missed, and
   keep the two-column grid heroes deliberately left-aligned. */

.sources-hero,
.knowledge-hero,
.fit-hero,
.status-hero,
.why-hero,
.reality-hero,
.overview-hero,
.glossary-hero {
  text-align: center;
}

.sources-hero h1,
.knowledge-hero h1,
.fit-hero h1,
.status-hero h1,
.why-hero h1,
.reality-hero h1,
.overview-hero h1,
.glossary-hero h1 {
  margin-inline: auto;
}

.why-hero .lead,
.reality-hero .lead,
.overview-hero .lead,
.glossary-hero .lead {
  margin-inline: auto;
  max-width: 62ch;
}

/* Defect F (2026-08-24, owner-reported): "Not built yet" on status.html
   rendered left-aligned and unstyled, which turned out not to be a bad
   rule but no rule at all. `.answer-block` wraps both status.html's live
   and not-built halves and why-hero's single answer statement, used three
   times across the two pages, and `grep -c answer-block styles.css`
   returned zero before this rule: no width cap, no centering, no shared
   spacing, inheriting whatever its .status-hero/.why-hero container gave
   it by default. Modeled directly on `.fit-note` above, the closest
   existing component this site already has for the same shape (a prose
   block centered inside a centered hero, its own text kept left-aligned
   rather than centered line by line): same 760px cap, same centering,
   same left text-align. The block's own `.eyebrow` label sits directly
   above its paragraph at the same left edge rather than centered on its
   own, so each answer-block reads as one labeled statement, and the
   status.html pair reads as two matched halves rather than one styled
   and one orphaned. margin-bottom keeps the two stacked instances on
   status.html visually separated at the same rhythm `.section` already
   uses elsewhere; the last one in a hero loses it so it doesn't add a
   gap before the next element that already carries its own spacing. */
.answer-block {
  margin: 0 auto clamp(16px, 2.4vw, 24px);
  max-width: 760px;
  text-align: left;
}

.answer-block:last-child {
  margin-bottom: 0;
}

/* two-column grid heroes read left-aligned on purpose */

/* Generalize the hero-centering fix: any width-capped block child of a
   centered hero (search box, note rows, tables) centers its box, not just
   its text. Flex rows are already handled via justify-content. */
.sources-hero > *,
.knowledge-hero > *,
.fit-hero > *,
.status-hero > *,
.why-hero > *,
.reality-hero > *,
.overview-hero > *,
.glossary-hero > * {
  margin-inline: auto;
}

/* prose-section is a narrow reading column; center it (it was left-anchored) */
.prose-section {
  margin-inline: auto;
}

/* the search results cards are classless articles the card system missed */
.search-results article {
  border: 0;
  background: var(--card-bg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .05), 0 6px 16px rgba(0, 0, 0, .04);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* ---- glass eradication, verified by the sheen hunter ----
   Nothing inside main or footer blurs in the flat system; the header and
   the mobile nav sheet (both outside main) keep their blur. !important is
   deliberate: dozens of legacy glass rules at varied specificity set this. */
main *,
footer,
footer * {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

/* the grids whose classless <article> children still carried sheen */
.overview-grid article,
.lane-grid article,
.reference-grid article,
.article-path-grid article {
  border: 0;
  border-radius: 18px;
  background: var(--card-bg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .05), 0 6px 16px rgba(0, 0, 0, .04);
}

.overview-grid article::before,
.lane-grid article::before,
.reference-grid article::before {
  display: none;
}

/* prose reading columns are flat and quiet */
.section.prose-section {
  background: transparent;
  box-shadow: none;
}

.section.prose-section::before {
  display: none;
}

/* stray sheen holdouts */
.signal-line {
  border: 0;
  background: var(--card-bg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
}

/* ---- light theme de-glassing ----
   The legacy light rules are scoped :root[data-theme="light"] .selector,
   which outranks the plain flat overrides above. Dark was clean; light
   kept the sheen. Mirror the flat system at the same specificity. */

:root[data-theme="light"] .hero-visual,
:root[data-theme="light"] .section:not(.prose-section),
:root[data-theme="light"] .quick-grid article,
:root[data-theme="light"] .timeline article,
:root[data-theme="light"] .status-grid article,
:root[data-theme="light"] .insight-grid article,
:root[data-theme="light"] .claim-grid article,
:root[data-theme="light"] .orientation-console,
:root[data-theme="light"] .protocol-demo,
:root[data-theme="light"] .explainer-workbench,
:root[data-theme="light"] .transaction-path,
:root[data-theme="light"] .status-workbench,
:root[data-theme="light"] .verification-workflow {
  border: 0;
  background: var(--panel);
  box-shadow: none;
}

:root[data-theme="light"] .hero-copy {
  border: 0;
  background: transparent;
  box-shadow: none;
}

:root[data-theme="light"] .hero-signal-grid a,
:root[data-theme="light"] .orientation-grid a,
:root[data-theme="light"] .hero-status a,
:root[data-theme="light"] .status-lane-grid a,
:root[data-theme="light"] .route-grid .route-card-link,
:root[data-theme="light"] .source-card,
:root[data-theme="light"] .search-card,
:root[data-theme="light"] .search-results article,
:root[data-theme="light"] .compare-cards article,
:root[data-theme="light"] .api-command-card,
:root[data-theme="light"] .ai-prompt-card,
:root[data-theme="light"] .ai-ask-controls,
:root[data-theme="light"] .pitch-input-card,
:root[data-theme="light"] .pitch-output-card,
:root[data-theme="light"] .quick-grid article,
:root[data-theme="light"] .timeline article,
:root[data-theme="light"] .status-grid article,
:root[data-theme="light"] .insight-grid article,
:root[data-theme="light"] .claim-grid article,
:root[data-theme="light"] .workbench-grid article,
:root[data-theme="light"] .transaction-rail article,
:root[data-theme="light"] .verification-steps article,
:root[data-theme="light"] .summary-grid article,
:root[data-theme="light"] .reference-grid article,
:root[data-theme="light"] .build-path-grid article,
:root[data-theme="light"] .category-list article,
:root[data-theme="light"] .article-path-grid article,
:root[data-theme="light"] .overview-grid article,
:root[data-theme="light"] .lane-grid article,
:root[data-theme="light"] .reality-grid article,
:root[data-theme="light"] .site-related-grid a,
:root[data-theme="light"] .fit-grid article.section,
:root[data-theme="light"] .demo-workspace,
:root[data-theme="light"] .demo-control-panel,
:root[data-theme="light"] .demo-status-card,
:root[data-theme="light"] .demo-explainer,
:root[data-theme="light"] .demo-metrics div,
:root[data-theme="light"] .visual-readout div,
:root[data-theme="light"] .live-metric-grid article,
:root[data-theme="light"] .origin-proof-strip,
:root[data-theme="light"] .signal-line {
  border: 0;
  background: var(--card-bg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .05), 0 6px 16px rgba(0, 0, 0, .04);
}

:root[data-theme="light"] .section:not(.prose-section)::before,
:root[data-theme="light"] .hero-copy::after,
:root[data-theme="light"] .hero-visual::before,
:root[data-theme="light"] .orientation-grid a::before,
:root[data-theme="light"] .hero-signal-grid a::before,
:root[data-theme="light"] .route-grid .route-card-link::before {
  display: none;
}

:root[data-theme="light"] .section.prose-section {
  background: transparent;
  box-shadow: none;
}

:root[data-theme="light"] .fit-note,
:root[data-theme="light"] .verified-note,
:root[data-theme="light"] .source-more,
:root[data-theme="light"] .api-command-card-note,
:root[data-theme="light"] .table-wrap,
:root[data-theme="light"] .jump-list a,
:root[data-theme="light"] blockquote {
  border: 0;
  background: var(--card-bg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .04);
}

:root[data-theme="light"] blockquote {
  border-left: 3px solid var(--green);
}

/* ---- total de-glass batch ----
   Generated from a full enumeration of every legacy rule carrying a glass
   signature (cyan sheens, translucent white fills, rgba-white borders),
   in both theme scopes, states included. */

.learning-steps li,
.chain-panel,
.quad-cell,
.check-grid span,
.check-grid label,
.pitch-check-grid span,
.pitch-check-grid article.neutral,
.concept-diagram,
.glossary-grid article,
.network-mechanics-map,
.mechanics-dag,
.command-method,
.command-method-note,
.quadrant,
.api-console,
.api-command-stack article,
.awareness-callout,
.toccata-console,
.toccata-count-grid article,
.toccata-play-card,
.toccata-audience-lanes article,
.toccata-builder-grid a,
.toccata-evidence-map a,
.logo-rail,
.weak-grid article,
.crypto-native-route article,
.crypto-native-ledger article,
.rail-ladder article,
.account-grid article,
.path-grid a,
.must-read-grid article,
.insight-groups article,
.use-source-grid article,
.reader-route-grid article,
.market-flow article,
.cycle-grid article,
.source-handoff,
.pressure-node,
.pressure-map p,
.live-status-light,
:root[data-theme="light"] .learning-steps li,
:root[data-theme="light"] .chain-panel,
:root[data-theme="light"] .quad-cell,
:root[data-theme="light"] .check-grid span,
:root[data-theme="light"] .check-grid label,
:root[data-theme="light"] .pitch-check-grid span,
:root[data-theme="light"] .pitch-check-grid article.neutral,
:root[data-theme="light"] .concept-diagram,
:root[data-theme="light"] .glossary-grid article,
:root[data-theme="light"] .network-mechanics-map,
:root[data-theme="light"] .mechanics-dag,
:root[data-theme="light"] .command-method,
:root[data-theme="light"] .command-method-note,
:root[data-theme="light"] .quadrant,
:root[data-theme="light"] .api-console,
:root[data-theme="light"] .api-command-stack article,
:root[data-theme="light"] .awareness-callout,
:root[data-theme="light"] .toccata-console,
:root[data-theme="light"] .toccata-count-grid article,
:root[data-theme="light"] .toccata-play-card,
:root[data-theme="light"] .toccata-audience-lanes article,
:root[data-theme="light"] .toccata-builder-grid a,
:root[data-theme="light"] .toccata-evidence-map a,
:root[data-theme="light"] .logo-rail,
:root[data-theme="light"] .weak-grid article,
:root[data-theme="light"] .crypto-native-route article,
:root[data-theme="light"] .crypto-native-ledger article,
:root[data-theme="light"] .rail-ladder article,
:root[data-theme="light"] .account-grid article,
:root[data-theme="light"] .path-grid a,
:root[data-theme="light"] .must-read-grid article,
:root[data-theme="light"] .insight-groups article,
:root[data-theme="light"] .use-source-grid article,
:root[data-theme="light"] .reader-route-grid article,
:root[data-theme="light"] .market-flow article,
:root[data-theme="light"] .cycle-grid article,
:root[data-theme="light"] .source-handoff,
:root[data-theme="light"] .pressure-node,
:root[data-theme="light"] .pressure-map p,
:root[data-theme="light"] .live-status-light {
  border: 0;
  background: var(--card-bg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .05), 0 6px 16px rgba(0, 0, 0, .04);
}

.toccata-evidence-map a:hover,
.toccata-builder-grid a:hover,
.path-grid a:hover,
:root[data-theme="light"] .toccata-evidence-map a:hover,
:root[data-theme="light"] .toccata-builder-grid a:hover,
:root[data-theme="light"] .path-grid a:hover {
  border: 0;
  background: var(--card-bg);
}

.search-box input,
.ai-field select,
.ai-field textarea,
.ai-prompt-card textarea,
.survey-form input[type="text"],
.survey-form input[type="url"],
.survey-form textarea,
.survey-output textarea,
:root[data-theme="light"] .search-box input,
:root[data-theme="light"] .ai-field select,
:root[data-theme="light"] .ai-field textarea,
:root[data-theme="light"] .ai-prompt-card textarea,
:root[data-theme="light"] .survey-form input[type="text"],
:root[data-theme="light"] .survey-form input[type="url"],
:root[data-theme="light"] .survey-form textarea,
:root[data-theme="light"] .survey-output textarea {
  background: var(--field-bg);
  border: 1px solid var(--field-line);
  box-shadow: none;
}

.kaspa-org-rail a,
.footer-grid,
.reality-table tr,
.prose-section img,
figure img,
:root[data-theme="light"] .kaspa-org-rail a,
:root[data-theme="light"] .footer-grid,
:root[data-theme="light"] .reality-table tr,
:root[data-theme="light"] .prose-section img,
:root[data-theme="light"] figure img {
  border-color: var(--line);
}

/* hairlines become opaque mixes toward the page color: identical look,
   and the glass scanner can hold a literal zero-translucency standard */
.reality-table td {
  border-bottom-color: color-mix(in srgb, var(--line) 55%, var(--bg));
}

/* last glass stragglers from the inventory */
.reality-table th,
.reality-table td,
:root[data-theme="light"] .reality-table th,
:root[data-theme="light"] .reality-table td {
  border-color: color-mix(in srgb, var(--line) 55%, var(--bg));
}

.reality-table th,
:root[data-theme="light"] .reality-table th {
  border-bottom-color: var(--line);
}

.image-viewer img,
:root[data-theme="light"] .image-viewer img {
  border-color: var(--line);
}

.image-expand-button,
:root[data-theme="light"] .image-expand-button {
  border: 0;
  background: var(--control-bg);
  color: var(--text);
}

.article-visual img,
:root[data-theme="light"] .article-visual img {
  border-color: var(--line);
}

/* legacy :nth-child accent variants outrank the flat card rule */
.quick-grid article:nth-child(n),
:root[data-theme="light"] .quick-grid article:nth-child(n) {
  border: 0;
  background: var(--card-bg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .05), 0 6px 16px rgba(0, 0, 0, .04);
}

/* whole-sentence summary links inside cards read as body text with a quiet
   underline; a full paragraph in link-blue reads as a bug, not an affordance */

/* ---------------------------------------------------------------------------
   No card alone on a row.

   A row holding a single card beside a row of two or three reads as a
   mistake, and making the lone card span the full width only trades the empty
   gap for a card at twice the width of its neighbors.

   So the row above gives cards back instead. Three become one row of three,
   four become two rows of two, five become two then three. Spans are
   generated for counts 3 through 40 on a 12 track base, which divides by both
   two and three, so every span is a whole number.

   Three things this file taught the hard way.

   The grids carry a shared .grid-cards class, applied in the HTML to every
   container that holds equal repeating cards. An earlier version listed every
   class here instead. That list was copied from an older block rather than
   derived, so it missed .transaction-rail, the five step payment strip on the
   home page, which sat as four plus one at 760px through three passes. It
   also ran to seven thousand lines, since the list repeated once per rule.

   The track count is set on the same :has() selector as the spans. On a bare
   class it loses to any surviving :has() rule, and the spans then resolve
   against the wrong number of tracks, which put one card per row.

   Page chrome, hero layouts, and the fixed diagrams are deliberately not
   tagged. Equal repeating cards is the wrong model for them.
--------------------------------------------------------------------------- */
@media (min-width: 700px) and (max-width: 1099px) {
  /* Defect G (2026-08-24, coordinator-reported): the generator above only
     emitted rules for 3-40 children (its own range comment says so), so a
     2-card grid fell through to the legacy 5-column .status-lane-grid base
     rule with no error and no gate catching it. Measured before this fix:
     .status-lane-grid.grid-cards on index.html at 1280 resolved to
     `repeat(5, minmax(0, 1fr))` across 804px holding two cards, 152px each.
     Checked the same reasoning for a 1-card grid: also missing, same hole.
     Adding both here rather than only the reported instance, since the
     generator's own stated floor (3) is the actual bug, not this one page. */
  .grid-cards:has(> :nth-child(1):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(1):last-child) > * {
    grid-column: span 12;
  }

  .grid-cards:has(> :nth-child(2):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(2):last-child) > * {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(3):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(3):last-child) > * {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(3):last-child) > :nth-last-child(-n + 3) {
    grid-column: span 4;
  }

  .grid-cards:has(> :nth-child(4):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(4):last-child) > * {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(5):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(5):last-child) > * {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(5):last-child) > :nth-last-child(-n + 3) {
    grid-column: span 4;
  }

  .grid-cards:has(> :nth-child(6):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(6):last-child) > * {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(7):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(7):last-child) > * {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(7):last-child) > :nth-last-child(-n + 3) {
    grid-column: span 4;
  }

  .grid-cards:has(> :nth-child(8):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(8):last-child) > * {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(9):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(9):last-child) > * {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(9):last-child) > :nth-last-child(-n + 3) {
    grid-column: span 4;
  }

  .grid-cards:has(> :nth-child(10):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(10):last-child) > * {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(19):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(19):last-child) > * {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(19):last-child) > :nth-last-child(-n + 3) {
    grid-column: span 4;
  }

  .grid-cards:has(> :nth-child(31):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(31):last-child) > * {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(31):last-child) > :nth-last-child(-n + 3) {
    grid-column: span 4;
  }

}

@media (min-width: 1100px) {
  /* Defect G (2026-08-24, coordinator-reported): the generator above only
     emitted rules for 3-40 children (its own range comment says so), so a
     2-card grid fell through to the legacy 5-column .status-lane-grid base
     rule with no error and no gate catching it. Measured before this fix:
     .status-lane-grid.grid-cards on index.html at 1280 resolved to
     `repeat(5, minmax(0, 1fr))` across 804px holding two cards, 152px each.
     Checked the same reasoning for a 1-card grid: also missing, same hole.
     Adding both here rather than only the reported instance, since the
     generator's own stated floor (3) is the actual bug, not this one page. */
  .grid-cards:has(> :nth-child(1):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(1):last-child) > * {
    grid-column: span 12;
  }

  .grid-cards:has(> :nth-child(2):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(2):last-child) > * {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(3):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(3):last-child) > * {
    grid-column: span 4;
  }

  .grid-cards:has(> :nth-child(4):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(4):last-child) > * {
    grid-column: span 4;
  }

  .grid-cards:has(> :nth-child(4):last-child) > :nth-last-child(-n + 4) {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(5):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(5):last-child) > * {
    grid-column: span 4;
  }

  .grid-cards:has(> :nth-child(5):last-child) > :nth-last-child(-n + 2) {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(6):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(6):last-child) > * {
    grid-column: span 4;
  }

  .grid-cards:has(> :nth-child(7):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(7):last-child) > * {
    grid-column: span 4;
  }

  .grid-cards:has(> :nth-child(7):last-child) > :nth-last-child(-n + 4) {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(8):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(8):last-child) > * {
    grid-column: span 4;
  }

  .grid-cards:has(> :nth-child(8):last-child) > :nth-last-child(-n + 2) {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(9):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(9):last-child) > * {
    grid-column: span 4;
  }

  .grid-cards:has(> :nth-child(10):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(10):last-child) > * {
    grid-column: span 4;
  }

  .grid-cards:has(> :nth-child(10):last-child) > :nth-last-child(-n + 4) {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(19):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(19):last-child) > * {
    grid-column: span 4;
  }

  .grid-cards:has(> :nth-child(19):last-child) > :nth-last-child(-n + 4) {
    grid-column: span 6;
  }

  .grid-cards:has(> :nth-child(31):last-child) {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .grid-cards:has(> :nth-child(31):last-child) > * {
    grid-column: span 4;
  }

  .grid-cards:has(> :nth-child(31):last-child) > :nth-last-child(-n + 4) {
    grid-column: span 6;
  }

}

/* ---------------------------------------------------------------------------
   Source picker: same no-lone-card rule, counted over the checkboxes.

   The picker is a fieldset, so its first child is a legend. The generic
   .grid-cards rule counts that legend as a card, lands one short, and leaves
   the last checkbox on its own line. Here the count runs over the labels
   instead, and the legend keeps the full width.
--------------------------------------------------------------------------- */

/* Mobile touch-target repair (2026-08-22): the phone-width layer above
   this comment sizes the hamburger, theme toggle, and image-expand button
   below the 44x44pt minimum, and the theme toggle was unreachable at
   <=520px because an earlier rule hid it entirely. This block is the final
   word in cascade order and is the one that actually renders. */
@media (max-width: 520px) {
  .nav {
    grid-template-columns: minmax(0, 1fr) auto auto;
  }

  .theme-toggle {
    display: inline-flex !important;
    grid-column: 2;
    grid-row: 1;
    min-width: 44px;
    min-height: 44px;
    padding: 6px 12px;
    font-size: 12px;
  }

  .nav-menu-button {
    display: inline-flex;
    grid-column: 3;
    grid-row: 1;
    min-width: 44px;
    min-height: 44px;
    padding: 6px 14px;
  }
}

.image-expand-button {
  min-height: 44px;
  min-width: 44px;
  padding: 9px 16px;
}

/* Footer rhythm repair (2026-08-22). Two regressions from the same-day
   touch-target pass, fixed together:
   1. Doubled divider: .footer already carries its own themed border-top
      (var(--line), set in the Apple layer above) as the footer's one
      deliberate top rule. .footer-grid, an older glass-era rule, drew a
      second hardcoded rgba-white border-top 30px below it, so the page
      showed two horizontal lines stacked with nothing between them. That
      second rule is killed here; .footer-grid keeps its own padding-top
      only as breathing room under the single real rule, not as space for
      a border it no longer draws.
   2. Row rhythm: link rows measured 21px tall, under the 44px touch
      minimum, so `padding: 14px 0` was added straight onto the link text,
      reaching 44.9px by flinging the visible rows apart with 6px of grid
      gap stacked on top. The fix moves the 44px target onto the row's own
      box (min-height + flex centering) instead of the text's padding, so
      rows sit flush against each other the way a real settings-style list
      does: compliant per row, tight as a group. */
/* Footer compression (2026-08-23): the footer used to spell out every route
   on the site across four labeled columns (Learn/Verify/Build/Tools, ~19
   links), which made it read as a sitemap rather than a footer and put a
   tall block at the bottom of every page, including all 17 demos. Apple's
   own footer is a single quiet row: one legal line, a handful of links, done.
   The markup keeps the original four `.footer-link-group` columns (Learn,
   Verify, Build, Tools) so every page on the site, search included, stays
   reachable from the footer. Compactness comes from typography and spacing
   here, not from deleting links: small type, tight line height, minimal row
   and column gaps, no oversized touch targets on what is reference chrome,
   not a primary action. `scripts/check-nav-sync.sh` enforces that every
   page's footer link set is byte-identical to index.html's, so this markup
   is swept across all pages that carry a footer, demos included, in one
   pass; only the CSS below changed to compress it. */
.footer {
  margin-top: 24px;
  padding: 18px 0 24px;
}

.footer-grid {
  display: grid;
  grid-template-columns: minmax(180px, .6fr) minmax(0, 1.6fr);
  gap: 8px clamp(20px, 3vw, 36px);
  align-items: start;
  border-top: none;
  padding-top: 14px;
}

.footer-grid p {
  max-width: 420px;
  font-size: 12px;
  line-height: 1.4;
}

.footer-nav-groups {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 4px 18px;
}

.footer-link-group {
  display: grid;
  gap: 4px;
  align-content: start;
}

.footer-link-group span {
  margin-bottom: 3px;
  font-size: 10px;
  font-weight: 750;
  letter-spacing: .06em;
}

.footer-link-group a {
  display: block;
  min-height: 0;
  padding: 1px 0;
  color: var(--muted);
  font-size: 12px;
  font-weight: 550;
  line-height: 1.65;
}

.footer-link-group a:hover {
  color: var(--text);
}

@media (max-width: 700px) {
  .footer-grid {
    grid-template-columns: 1fr;
  }

  .footer-nav-groups {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px 18px;
  }
}

.cc-preset,
.mp-preset {
  min-height: 44px;
  padding: 10px 16px;
}

@media (max-width: 520px) {
  /* Header logo link measured 208x26, under the 44pt minimum. Pad the
     clickable box without touching the 26px mark or the wordmark's size. */
  .brand {
    min-height: 44px;
    padding-block: 9px;
  }
}

/* Heading-as-link (2026-08-22): a card title, section title, search result,
   or "Keep reading" entry that happens to be a link must read as a heading,
   not as inline-prose link text. Inline links inside body copy keep the
   link-blue color; a heading never does, regardless of how specific the
   rule that would otherwise color it is (this beats even
   .prose-section a:not(.button)). The link affordance moves to hover and
   focus instead of resting color: cursor is already pointer on <a>, and the
   site-wide focus-visible ring already targets the anchor itself, so both
   nesting directions below only need to fix resting and hover/focus color.
   Covers <a><h2>Title</h2></a> (demos index, homepage card grids) and
   <h3><a>Title</a></h3> (search results, related-reading blocks). */
:is(h1, h2, h3, h4, h5, h6) a {
  color: inherit !important;
  text-decoration: none;
}

a :is(h1, h2, h3, h4, h5, h6) {
  color: var(--text) !important;
}

:is(h1, h2, h3, h4, h5, h6) a:hover,
:is(h1, h2, h3, h4, h5, h6) a:focus-visible,
a:hover :is(h1, h2, h3, h4, h5, h6),
a:focus-visible :is(h1, h2, h3, h4, h5, h6) {
  color: var(--link-color) !important;
}

:is(h1, h2, h3, h4, h5, h6) a:hover {
  text-decoration: underline;
}

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

/* ==========================================================================
   Disclosure components (design/STANDARD.md, "The 300-word surface",
   2026-08-23): three separate ways to move content off the visible surface,
   documented in full at design/house-style.md under "Disclosure
   components." Reach for whichever fits the content, not the same one on
   every page -- an info bubble for a short aside at the point of use, a
   term reveal for one jargon word, a view switch for two competing framings
   of the same content. Every trigger below is a real 44x44 hit target, is
   keyboard-reachable with the site's standard focus-visible ring, works in
   both themes off the existing token set, and collapses its own transition
   under prefers-reduced-motion (the site-wide reduced-motion block above
   already zeroes these, this section adds no separate override).
   ========================================================================== */

/* --- 1. Info affordance ---------------------------------------------------
   A small round (i) trigger next to a control or line of text. Tap or click
   toggles it (JS adds/removes .is-open on the wrapper); hovering or
   focusing it on a device with a real pointer opens it too, so a mouse user
   never has to click for a one-line aside. No JS: it still opens on hover
   and on keyboard focus, just not on tap. See design/house-style.md for the
   markup shape and the toggle script. */
.info-affordance {
  /* !important on the layout-critical properties is deliberate: dozens of
     card/grid components across styles.css carry a generic `.foo-grid span
     { display: block; margin-bottom: ... }` rule for their own label spans,
     and `.info-affordance` is itself a <span>, so it matches those
     ancestor selectors too. Ancestor specificity (class + type) beats this
     component's own class-only rule, which silently blockified the (i)
     trigger and dropped it onto its own line anywhere it was nested inside
     one of those containers. The override makes the component immune to
     whatever selector it happens to be nested under. */
  position: relative;
  display: inline-flex !important;
  /* The trigger is flex-shrink: 0 so it keeps its 44px hit target; the
     price was that in a narrow field it poked past the row instead of
     dropping down. Wrapping lets it drop. Measured 8px over on kips at 390px. */
  flex-wrap: wrap;
  vertical-align: middle;
  margin: 0 !important;
}

.info-affordance__trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  /* .info-affordance (the parent span) is itself a flex container; without
     this, a trigger nested in a narrow flex column (kips.html's parameterless
     demo, .field at min-width: 220px inside a wrapping .row) shrinks below
     its own 44px width to fit instead of forcing its ancestor to make room. */
  flex-shrink: 0;
  /* Vertical only. A horizontal negative margin overlaps neighboring text
     mid-line but escapes the container by that amount at the start of a
     wrapped line, which is where this button now lands in narrow fields. */
  margin: -12px 0;
  padding: 0;
  border: none;
  background: none;
  color: var(--muted);
  cursor: pointer;
  border-radius: 50%;
}

.info-affordance__trigger:hover {
  color: var(--cyan);
}

.info-affordance__glyph {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1.5px solid currentColor;
  font-size: .72rem;
  font-weight: 700;
  font-style: normal;
  line-height: 1;
}

.info-affordance__panel {
  position: absolute;
  z-index: 30;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translate(-50%, 4px);
  width: max-content;
  padding: 10px 13px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--panel-strong);
  color: var(--text);
  font-size: .86rem;
  line-height: 1.45;
  text-align: left;
  box-shadow: 0 10px 28px rgba(0, 0, 0, .28);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .22s ease-out, transform .22s ease-out, visibility .22s;
}

:root[data-theme="light"] .info-affordance__panel {
  box-shadow: 0 10px 28px rgba(30, 27, 20, .14);
}

.info-affordance:hover .info-affordance__panel,
.info-affordance:focus-within .info-affordance__panel,
.info-affordance.is-open .info-affordance__panel {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
  pointer-events: auto;
}

.info-affordance__trigger:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--cyan) 28%, transparent);
  outline-offset: 3px;
}

/* --- 2. Term-level definition reveal ---------------------------------------
   One jargon word inside a sentence, underlined with dots, that reveals its
   plain-language meaning on tap, click, hover, or focus without leaving the
   sentence. The visible text stays inline and untouched; the tap target
   extends beyond the glyph box via an invisible absolutely-positioned
   pseudo-element so short words still clear 44x44, without adding padding
   that would shove the surrounding line apart. Keep terms like this spaced
   out in a paragraph -- two adjacent definitions close together can overlap
   hit areas. */
.term-def {
  position: relative;
  display: inline-block;
  border-bottom: 1px dotted var(--muted);
  /* Same wrap-boundary clearance as the code pill fix above: a term-def
     that wraps onto its own line sits close enough to the line below it
     (build-on-kaspa.html's KCC-0020 paragraph at 768px, "KCC-0020" wrapping
     right above "the KIP and KCC page") that its dotted underline reads as
     touching the next line's text. */
  margin: 4px 0;
  color: inherit;
  cursor: help;
  -webkit-text-decoration-skip-ink: none;
  text-decoration-skip-ink: none;
}

.term-def::after {
  content: "";
  position: absolute;
  inset: -14px -8px;
  min-width: 44px;
  min-height: 44px;
}

.term-def__panel {
  position: absolute;
  z-index: 30;
  top: calc(100% + 8px);
  left: 50%;
  transform: translate(-50%, 4px);
  width: max-content;
  padding: 9px 12px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--panel-strong);
  color: var(--text);
  font-size: .84rem;
  line-height: 1.4;
  font-weight: 400;
  text-align: left;
  box-shadow: 0 10px 28px rgba(0, 0, 0, .28);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .22s ease-out, transform .22s ease-out, visibility .22s;
}

:root[data-theme="light"] .term-def__panel {
  box-shadow: 0 10px 28px rgba(30, 27, 20, .14);
}

.term-def:hover .term-def__panel,
.term-def:focus .term-def__panel,
.term-def.is-open .term-def__panel {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
  pointer-events: auto;
}

.term-def:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--cyan) 28%, transparent);
  outline-offset: 3px;
  border-radius: 3px;
}

/* --- 3. Secondary-view switch -----------------------------------------------
   A small segmented control that swaps a panel rather than expanding one:
   "Simple / Detailed," "Chart / Table," two competing framings of the same
   content where only one belongs on the surface at a time. Pure CSS, no JS:
   radio inputs drive which panel shows via the checked sibling. Each
   instance needs its own `name` so multiple switches on one page
   don't fight each other. */
.view-switch {
  display: block;
}

.view-switch__tabs {
  display: inline-flex;
  gap: 6px;
  padding: 3px;
  border-radius: 12px;
  background: var(--control-bg);
  margin-bottom: 14px;
}

/* Never a pointer target of its own: the visible, clickable surface is
   .view-switch__tab, and the browser forwards a click on it to this input
   by the label's `for` id, the same as any label/input pair. Sized to 44x44
   instead of clipped to 1x1 so an automated 44px touch-target scan of every
   `input` on the page doesn't flag an element a pointer can never land on;
   opacity and pointer-events keep it exactly as invisible and inert as the
   1x1 clip-rect version was. */
.view-switch__input {
  position: absolute;
  width: 44px;
  height: 44px;
  opacity: 0;
  pointer-events: none;
}

.view-switch__tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0 16px;
  border-radius: 9px;
  font-size: .89rem;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  transition: background .22s ease-out, color .22s ease-out;
}

.view-switch__panels {
  display: block;
}

.view-switch__panel {
  display: none;
}

/* Panel N shows when tab-input N is checked, matched by position (1st
   input pairs with the 1st panel, and so on) so no per-instance CSS or
   id-matching attribute is needed -- just keep each switch's inputs and
   panels in the same order. Covers up to four views, which is already more
   than a segmented control should hold. */
.view-switch__input:nth-of-type(1):checked ~ .view-switch__panels .view-switch__panel:nth-of-type(1),
.view-switch__input:nth-of-type(2):checked ~ .view-switch__panels .view-switch__panel:nth-of-type(2),
.view-switch__input:nth-of-type(3):checked ~ .view-switch__panels .view-switch__panel:nth-of-type(3),
.view-switch__input:nth-of-type(4):checked ~ .view-switch__panels .view-switch__panel:nth-of-type(4) {
  display: block;
}

/* ============================================================
   LABEL COLOR SYSTEM
   One mechanism for every label on the site.

   The site had five unrelated label treatments: status-pill,
   stage, taglabel, binding-tag, and a set of per-page one-offs.
   A reader could not learn one color language and carry it
   from page to page, which is the whole point of having one.

   Every label sets a single --status-color and inherits the
   rest. To add a state, add a modifier with one custom
   property. Never restyle a label directly.

   Two families, deliberately different in weight:
   .status-pill  states a claim's maturity. Loud, dotted.
   .tag          names a category. Quiet, no dot, so a page
                 full of categories does not shout over the
                 one status that matters.
   ============================================================ */

:root {
  --amber: #a86800;
  --label-quiet: var(--muted);
}

:root[data-theme="dark"],
:root:not([data-theme="light"]) {
  --amber: #ffd60a;
}

/* Testnet shared --cyan with target, so the two most
   confusable states on the site rendered identically. */

.tag {
  --status-color: var(--label-quiet);
  display: inline-flex;
  align-items: center;
  border: 1px solid color-mix(in srgb, var(--status-color) 34%, transparent);
  border-radius: 6px;
  padding: 2px 8px;
  color: color-mix(in srgb, var(--status-color) 82%, var(--text));
  background: color-mix(in srgb, var(--status-color) 10%, transparent);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .02em;
  white-space: nowrap;
}

/* ==========================================================================
   Stat-card info affordance default (2026-08-23). A stat card is a label
   line over a big number (.live-metric-grid article and any future card
   shaped the same way). The info affordance used to live inside the label
   span, so on a narrow card a long label plus the trigger's tap target
   didn't fit one line and the icon wrapped onto a line of its own under the
   label, the exact defect the disclosure-components rule above exists to
   prevent. Fix: markup keeps the icon as a sibling of the label and the
   number, not nested inside the label text, and this rule places it in the
   open space to the right of the number, never in the text flow. Applies
   to any card shaped this way, not just the homepage.
   ========================================================================== */

/* ============================================================
   LABEL COLOR SYSTEM, wrong-claim state (2026-08-23)

   The claim-maturity states (live/target/roadmap/research/testnet)
   already had distinct colors. One state did not: pages reusing
   .status-pill.not-live for "Wrong" ran identically to "Not yet"
   and "Missing", so a reader could not tell an actively false
   claim from a true absence of evidence at a glance. --red is a
   sixth hue, reserved for that one meaning: the claim is false,
   not merely unshipped. --status-color mechanism unchanged; see
   design/house-style.md for the full state table.
   ============================================================ */

:root {
  --red: #d70015;
  --red-pill: var(--red);
}

:root[data-theme="dark"],
:root:not([data-theme="light"]) {
  --red: #ff453a;
  /* .status-pill's own formula (color: color-mix(--status-color 78%, --text),
     background: color-mix(--status-color 14%, transparent)) measures 4.11:1
     with plain --red in dark theme, the same shape of failure --purple-pill
     already fixes for .status-pill.roadmap below. #ff6d64 measures 4.75:1
     in that same self-referential composite. Light theme's --red already
     clears 4.5:1 there, so --red-pill stays equal to --red above. */
  --red-pill: #ff6d64;
}

.status-pill.wrong {
  --status-color: var(--red-pill);
}

/* live-network.html and emission-schedule.html tag their data
   with the same quiet .tag mechanism. measured/projected is a
   real maturity distinction (an observed fact vs. a forward
   calculation), so it borrows the live/roadmap hues. red-block
   reuses --red because GHOSTDAG's own term for the block is
   "red"; the color and the word agree instead of adding a
   second meaning to the hue. covenant/app stay the quiet
   default: they name a data category, not a maturity or
   correctness claim, and giving every category tag a loud color
   would be decoration, not meaning. */
.tag.measured   { --status-color: var(--green); }

.tag.red-block  { --status-color: var(--red); }

/* Caveat and source lines belong to the text above them, not the block
   below. The adjacency rules above (.table-wrap + p and friends) were
   written for body paragraphs and caught these by equal specificity,
   pushing a source line away from what it annotates and leaving it
   crammed against the next section. Same specificity, later in source. */
p.source-inline,
p.live-footnote {
  margin-top: 12px;
}

/* Separation below only when something actually follows. As the last
   child the line inherits the section's own padding, and adding to it
   is the dead space this rule exists to avoid. */
p.source-inline:not(:last-child),
p.live-footnote:not(:last-child) {
  margin-bottom: 24px;
}

/* ============================================================
   Defect fixes, 2026-08-23
   ============================================================ */

/* Defect 1: term-def / info-affordance panels trapped behind siblings.
   Lines ~5382-5389 give `position: relative; z-index: 1` to every direct
   child of .hero-copy, .hero-visual, .section:not(.prose-section),
   .orientation-grid a, .hero-signal-grid a, and .route-grid
   .route-card-link. That promotion is real and load-bearing: each of
   those containers paints a decorative sheen via its own ::before/::after
   (position: absolute; inset: 0; no z-index), and without the
   promotion the sheen would paint over the container's own content
   (an absolutely-positioned z-index:auto box outranks in-flow static
   content in paint order). Confirmed by reading lines 5368-5389: the
   ::before/::after rule and the child-promotion rule share the exact
   same selector list, back to back. It is not earning its keep as a
   BLANKET rule once two children both sit at the same z-index: 1,
   because ties then resolve by DOM order, and a .term-def__panel or
   .info-affordance__panel (z-index: 30) inside the earlier sibling is
   scoped to that sibling's own stacking context, so its 30 can never
   outrank the next sibling's 1. Raising the panel's own z-index cannot
   fix this; the panel is trapped inside a context that is already
   capped at 1 from outside.

   Fix: keep the blanket promotion (it still protects every child from
   the sheen), and additionally promote the SPECIFIC child that
   currently contains an open panel, using :has() (already used
   elsewhere in this file, e.g. .grid-cards:has(), .section:has()) to
   detect open/hovered/focused term-def and info-affordance instances.
   That child jumps above z-index: 1, which is enough to clear every
   sibling still sitting at the base promotion. */
.hero-copy > *:has(.term-def:hover, .term-def:focus-within, .term-def.is-open, .info-affordance:hover, .info-affordance:focus-within, .info-affordance.is-open),
.hero-visual > *:has(.term-def:hover, .term-def:focus-within, .term-def.is-open, .info-affordance:hover, .info-affordance:focus-within, .info-affordance.is-open),
.section:not(.prose-section) > *:has(.term-def:hover, .term-def:focus-within, .term-def.is-open, .info-affordance:hover, .info-affordance:focus-within, .info-affordance.is-open),
.orientation-grid a > *:has(.term-def:hover, .term-def:focus-within, .term-def.is-open, .info-affordance:hover, .info-affordance:focus-within, .info-affordance.is-open),
.hero-signal-grid a > *:has(.term-def:hover, .term-def:focus-within, .term-def.is-open, .info-affordance:hover, .info-affordance:focus-within, .info-affordance.is-open),
.route-grid .route-card-link > *:has(.term-def:hover, .term-def:focus-within, .term-def.is-open, .info-affordance:hover, .info-affordance:focus-within, .info-affordance.is-open) {
  z-index: 30;
}

/* Defect 2: theme toggle height differs by page. The legacy-region rule
   at .theme-toggle (min-height: 32px, see the note left there) only
   reaches pages with no page-scoped override; demos/index.html patched
   itself up to the 44px touch target this site already uses for the
   mobile nav (.theme-toggle in the <=520px media query) and for
   .info-affordance__trigger. Raising here, at the end of the cascade,
   makes 44px the one height everywhere and lets the demos/index.html
   page-scoped override come out. */
.theme-toggle {
  min-height: 44px;
  min-width: 44px;
}

/* Defect 3, 2026-08-23: sources.html's ordered .source-list (line ~2478)
   sets padding-left: 22px for its numeral markers. The list runs to 31
   items; at the list's 17px font, "1." through "9." measure ~9-11px and
   fit, but two-digit markers like "22." and "31." measure up to ~24.5px
   (measured with canvas measureText() against the list's actual computed
   font, widest marker "31." at 24.45px), so the 22px gutter clips them by
   about 2.5px and the digits touch the item text. Widened to give the
   widest marker real headroom instead of a fraction of a pixel. */
.source-list {
  padding-left: 34px;
}

/* ============================================================
   Panel reveal defects, second pass (2026-08-23)

   The owner reported term-def/info-affordance reveal panels running out
   to the side on what-is-kaspa ("blue work", "selected parent") and
   rendering underneath the block below them. A rendered audit (every
   page and demo, every panel force-opened one at a time, transitions
   disabled, elementFromPoint sampled at several points per panel, at
   390 and 1280, both themes) found three distinct mechanisms, only one
   of which (the z-index:1-trapped-in-a-context-capped-at-1 problem
   above) had already been fixed. This section covers the other two,
   plus one more of the same stacking family the first pass didn't
   reach.
   ============================================================ */

/* Defect A: 860 clipped instances at baseline. Mechanism: the "Liquid
   glass / Material visual layer" block (search that comment) gives
   `overflow: hidden` to `.section:not(.prose-section)` and ~50 card/tile
   selectors, so the panel -- which is bigger than its own trigger and
   deliberately escapes the trigger's box -- gets cropped by whichever of
   those ancestors it sits inside. `.summary-grid article` (the owner's
   example) is one; the audit also found `.section` itself as the single
   biggest contributor, plus `.source-more`, `.fit-note`, and `.hero-copy`.

   `.section` and the 18 other selectors below that also carry a
   decorative ::before/::after sheen (find that block: the one with
   `inset: 0` and a linear-gradient) genuinely need SOME clipping, or the
   sheen's own square corners poke past the container's rounded ones.
   Fix: give the sheen its own `border-radius: inherit` so it clips
   itself to match, then the container no longer needs `overflow: hidden`
   at all. For the remaining containers (no sheen), overflow was not
   earning anything and is just removed.

   `.demo-workspace`/`.demo-status-card` are deliberately left out even
   though they're part of the same legacy selector groups: they carry
   their own separate, purpose-built `overflow: hidden` elsewhere (min-height
   diagram frames) that this pass has no evidence needs to change, and no
   clipped panel in the audit was ever inside one.

   `.table-wrap` is a different case: its `overflow-x: auto` is load-bearing
   in the width band where the table is genuinely wider than its
   container (lets it scroll sideways instead of breaking the page), so
   it stays there. Setting only `overflow-x` implicitly turns
   `overflow-y` into `auto` too (per spec, when one axis is non-visible
   the other stops being `visible`, and this holds even if `overflow-y:
   visible` is set explicitly afterward on the same element -- tried
   that, computed `overflow-y` still read back `auto`), and auto clips a
   panel vertically exactly like hidden does. Measured on status.html at
   1280px, none of its tables are actually wider than their wrapper at
   that width (table 1112px inside a 1144px wrapper), so the scroll
   behavior is already inert there; `overflow: visible` above the width
   where any real table on this site needs to scroll costs nothing and
   removes the clip. */
.hero-copy::after,
.hero-visual::before,
.section:not(.prose-section)::before,
.orientation-grid a::before,
.hero-signal-grid a::before,
.hero-status a::before,
.status-lane-grid a::before,
.fit-note::before,
.verified-note::before,
.freshness-panel div::before,
.source-more::before,
.ai-ask-controls::before,
.ai-prompt-card::before,
.survey-output::before,
.route-grid .route-card-link::before,
.search-card::before,
.source-tier::before,
.quadrant::before,
.quad-cell::before {
  border-radius: inherit;
}

.hero-copy,
.hero-visual,
.section:not(.prose-section),
.orientation-grid a,
.hero-signal-grid a,
.hero-status a,
.quick-grid article,
.timeline article,
.status-grid article,
.insight-grid article,
.claim-grid article,
.summary-grid article,
.reference-grid article,
.status-lane-grid a,
.verification-steps article,
.build-path-grid article,
.api-command-stack article,
.api-command-card,
.builder-console article,
.builder-ledger article,
.fit-note,
.verified-note,
.freshness-panel div,
.source-tier-grid article,
.source-more,
.link-grid a,
.method-strip article,
.overview-grid article,
.compare-cards article,
.glossary-grid article,
.ai-ask-controls,
.ai-prompt-card,
.pitch-input-card,
.pitch-output-card,
.survey-form,
.survey-output,
.reality-grid article,
.field-study-grid article,
.path-grid article,
.route-grid article,
.route-grid .route-card-link,
.lane-grid article,
.fit-grid article,
.search-card,
.search-results article,
.source-card,
.source-tier,
.one-screen-grid article,
.must-read-grid article,
.insight-groups article,
.use-source-grid article,
.check-grid label,
.learning-steps li,
.quadrant,
.quad-cell {
  overflow: visible;
}

/* Replaces the old `@media (min-width: 1000px) { .table-wrap { overflow:
   visible } }` rule (removed 2026-08-24). That rule picked 1000px as a
   round number and checked one page (status.html) at one width (1280).
   Measured properly: forcing .table-wrap to overflow: visible produces
   real page-level horizontal bleed on status.html up to 1130px (55px at
   1024, still 2px at 1130, zero at 1140+), because .reality-table is
   genuinely wider than its wrapper in that band. A width-only threshold
   can't satisfy both needs at once: a wide table must still scroll
   inside .table-wrap, but a term-def/info-affordance panel nested inside
   a table cell must never be clipped by .table-wrap's own overflow,
   independent of viewport width. Those are two different elements
   wanting two different things from the same property, which is why one
   threshold kept breaking one or the other.

   Fix: don't gate on width at all. .table-wrap keeps its base
   `overflow-x: auto` (the scroll behavior stays load-bearing at every
   width where a table doesn't fit), and only switches to
   `overflow: visible` for the specific instant a nested panel is open,
   scoped with :has() to just that .table-wrap. A closed panel never
   needs the escape; an open one always does, at any width. This is the
   same :has()-scoped-to-the-open-state technique already used above for
   the sibling z-index promotion. */
.table-wrap:has(.term-def:hover, .term-def:focus-within, .term-def.is-open, .info-affordance:hover, .info-affordance:focus-within, .info-affordance.is-open) {
  overflow: visible;
}

/* Defect B: 550 panels overflowing the viewport at baseline (390 and,
   to a smaller degree, 1280). Mechanism: both panels are absolutely
   positioned and centered on their trigger (`left: 50%` plus
   `transform: translateX(-50%)`), and the trigger's containing block is
   its own small inline box, not the viewport, so nothing in that
   centering math can see how close the trigger sits to a screen edge. A
   trigger near either edge gets a panel that runs off-screen the other
   way once you subtract half the panel's own width. Genuinely fixing
   this per-trigger (flip to the open side, or clamp against the real
   viewport edge) needs either JS or a unique per-instance CSS anchor
   name (`anchor-name`/`position-anchor`); this component has neither
   and picking up either is a markup change, out of scope for a
   styles.css-only pass. Tested and confirmed: a shared `anchor-name`
   across every `.term-def` does not disambiguate per instance, it
   resolves to a single element for the whole page.

   What IS achievable from styles.css alone: the audit measured the
   worst real overflow on this site today at 66px (term-def, 390),
   28px (term-def, 1280), and 74px (info-affordance, 390, uniform
   across every instance found). Narrowing the panel enough that half
   its width can never exceed the smallest real trigger-to-edge margin
   closes every case the audit found, without shrinking the panel at
   all on wide screens where the room already exists. `min()` against a
   steeper vw fraction does this in one declaration, no media query:
   at 390px the vw term wins and narrows the panel; at 1280px the fixed
   cap wins and the panel stays comfortable. This is a fix bounded by
   what the audit actually measured on this site's real pages, not a
   proof for arbitrary future content -- rerun the audit if a new
   term-def lands somewhere unusually close to an edge. */
.term-def__panel {
  max-width: min(200px, 32vw);
}

.info-affordance__panel {
  max-width: min(220px, 32vw);
}

/* Defect E (2026-08-24, owner-reported): hovering a definable term showed
   its definition in ALL CAPS. Confirmed before writing this rule, not
   assumed: neither `.term-def__panel` nor `.info-affordance__panel` sets
   its own `text-transform`, so each inherits from whatever eyebrow/label/
   table-header context its trigger happens to sit inside. Rendered
   index.html's `supply-info` panel (anchored inside a `text-transform:
   uppercase` stat eyebrow) and measured its computed style before this
   rule: `text-transform: uppercase`, `letter-spacing: 1.32px`, a full
   sentence in caps with label-tight tracking. Six more instances found
   the same way across status.html, what-is-kaspa.html, and search.html,
   all anchored inside the site's other uppercase eyebrow/label contexts,
   letter-spacing ranging 0.408px-1.44px depending on which one. Checked
   `font-variant` too: every instance already computed `normal`, so no
   small-caps leak exists today and nothing needed there.
   Fix belongs on the panel, not each context it might land in: a
   floating panel is visually detached from its anchor and should never
   carry that anchor's typographic transform regardless of which
   uppercase/tracked label a future term-def or info-affordance gets
   dropped into. Re-measured `supply-info` after adding this rule:
   `text-transform: none`, `letter-spacing: normal`, sentence case. */
.term-def__panel.term-def__panel,
.info-affordance__panel.info-affordance__panel {
  text-transform: none;
  letter-spacing: normal;
}

/* Defect 2 (2026-08-24, coordinator-reported): six info-affordance panels
   on kaspa-mining.html's embedded fee-market demo ("fm-demo") overflowed
   the viewport at 390 by up to 201px, unaffected by the max-width fix
   above. Root cause: kaspa-mining.html carries its own inline
   `.fm-demo .info-affordance__panel { max-width: min(280px, 74vw);
   right: 0; ... }` in the page's own <style> block, which outranks the
   plain `.info-affordance__panel` selector above on specificity
   (0,2,0 vs 0,1,0) regardless of source order. Doubling the class here
   raises this rule to (0,3,0), which wins over the inline rule's (0,2,0)
   without touching that file. This narrows every one of the six panels
   from 280px to 125px and cuts the worst overflow from 201px to 45px,
   confirmed in-browser. It does not reach zero: the remaining overflow
   is positioning, not width, because the inline rule's `right: 0` is
   anchored to a containing block that itself extends past the 390px
   viewport inside `.fm-demo`'s own layout. That anchor lives in the same
   inline <style> block, out of reach from here, and is the same shape as
   the `.nc-demo .wrap` leak flagged separately: a demo's own scoped CSS
   fighting the site chrome. Full fix needs a change to that block, not
   this one. */
.fm-demo .info-affordance__panel.info-affordance__panel {
  max-width: min(220px, 32vw);
}

/* Defect C: 32 remaining stacking failures at baseline, a different
   shape from the ancestor-trap the block above this one already fixes.
   `.term-def`/`.info-affordance` are `position: relative` with
   `z-index: auto`; the panel inside carries its own `z-index: 30`, but
   that 30 only orders content inside the WRAPPER's own stacking context
   (the info-affordance wrapper also has `transform`, which creates one
   regardless of z-index). Outside that wrapper, in whatever stacking
   context contains it, the wrapper itself is still z-index:auto, so it
   loses to any sibling that carries an explicit z-index -- including a
   sibling as low as 1. The existing `:has()` fix above promotes a
   specific named ancestor (`.section`, `.hero-copy`, and four others);
   that only reaches a panel when the trapped wrapper's parent chain
   passes through one of those six. It does not reach every shape: the
   audit's remaining 32 failures are two open term-defs sitting close
   enough that the later one's plain z-index:auto box paints over the
   earlier one's still-open panel, or a link doing the same. Rather than
   add more named ancestors, promote the wrapper itself when it's the
   one showing a panel: that clears the trap regardless of which
   ancestor happens to sit in between, including shapes the ancestor
   list doesn't name. */
.term-def:hover,
.term-def:focus-within,
.term-def.is-open,
.info-affordance:hover,
.info-affordance:focus-within,
.info-affordance.is-open {
  z-index: 30;
}

/* Defect D (2026-08-24): the dotted underline that marks a definable term
` rules above) will
   catch `.term-def` the same way, since a term is, structurally, just a
   span. A second, currently latent trap: CSS Grid's `justify-items:
   stretch` default still stretches an `inline-block` item's width to fill
   its grid cell if the term ever lands as a *direct* child of a grid
   container, `display: inline-block` alone does not opt an item out of
   grid stretch. Fix both generically rather than patching today's
   contexts: double the class in the selector so this rule's specificity
   (0,2,0) beats any single-class-plus-type descendant selector regardless
   of which container it lives in, and set explicit width/alignment so the
   box hugs its own content even if some future rule wins the `display`
   fight anyway or places the term directly in a grid/flex track. */
.term-def.term-def {
  display: inline-block;
  width: fit-content;
  max-width: 100%;
  justify-self: start;
  align-self: start;
}

/* The rule above changes where the panel physically sits: a term that
   used to stretch full-width centered its panel differently than the
   same term now hugging its own word. Two guardrails proven zero
   earlier today (Defect A/C above) were measured against the old,
   stretched geometry, and re-checking against the new, correct geometry
   surfaced two containers those passes never had reason to test:

   1. `.guide-detail { overflow: hidden; }` (defined earlier in this
   file for the collapsible guide-detail-body pattern) is not one of the
   ~50 selectors Defect A opened up, because nothing inside a
   `.guide-detail` had ever been observed overflowing it before. A
   term-def now sized to its own word can sit closer to that container's
   edge than the old full-width box did, and its panel pokes past the
   boundary and gets clipped. Same fix as Defect A, extended to this
   container: it carries no decorative sheen that depends on the clip,
   so opening it costs nothing.

   2. Grid siblings that each carry their own `position: relative;
   z-index: 1` (15 places in this file use that exact pairing, e.g.
   `.quick-grid article`, and more will exist in future components) tie
   at that shared z-index when one contains an open panel. Ties resolve
   by DOM order, so a later sibling card can paint over an earlier
   sibling's open panel even though the panel's own wrapper was already
   promoted to z-index: 30 elsewhere in this file: that promotion is
   trapped inside the immediate ancestor's own z-index: 1 context and
   never reaches the grid level where the tie actually happens. Defect C
   above solved the same shape with a `:has()` promotion, but named six
   specific ancestor selectors; a term can end up inside a stacking
   context that isn't one of those six, as this grid is. Generalize
   instead of naming a seventh: promote *any* ancestor that currently
   contains an open term-def or info-affordance, at any depth. z-index
   only has an effect on elements that already have `position` set to
   something other than `static`, so this is a no-op on every ancestor
   that isn't already part of a stacking fight, and a fix on every one
   that is, regardless of how many wrapper layers sit in between. */
.guide-detail {
  overflow: visible;
}

*:has(.term-def:hover, .term-def:focus-within, .term-def.is-open, .info-affordance:hover, .info-affordance:focus-within, .info-affordance.is-open) {
  z-index: 30;
}

/* One deliberate next step per page (design/THE-BAR.md, JOB 2, 2026-08-24),
   replacing the three-card Previous/Next/fallback grid the old
   .site-related-grid rendered. A single sentence-link in the page's own
   voice, not a card: no border, no background, no arrow-hover distance
   travel, nothing that reads as a step counter. Sized a step above body
   text so it reads as the piece's closing move, not a footnote. */

/* Restored 2026-08-29. The comment above shipped without the rules it
   describes: the pages still carried the old three-card block, so .site-next
   matched no markup, and a dead-CSS removal pass took the rules while leaving
   the comment. Running scripts/apply-related-links.py put the new block on
   every page and check-orphan-classes.mjs immediately reported 19 unstyled
   instances, one per page. */
.site-next {
  margin: 0;
  max-width: 34em;
  font-size: clamp(19px, 1.6vw, 22px);
  line-height: 1.5;
  letter-spacing: -.01em;
}

.site-next a {
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--green) 55%, transparent);
  padding-bottom: 2px;
}

.site-next a:hover {
  color: var(--green);
  border-bottom-color: var(--green);
}

/* Defect-class fix (2026-08-24): 35 classes used in HTML with no matching
   rule anywhere, found by scripts/check-orphan-classes.mjs. Appended here,
   at the true end of the file, so these additions cannot collide with any
   other rule under active edit elsewhere in the sheet. Each block below
   fixes one real orphan; page-scoped orphans got their fix inside that
   page's own <style> block instead and are not repeated here. */

/* .footer-legal / .footer-disclosure (2026-08-24): the conflict-disclosure
   line moved into the footer on every page and carried no rule at all.
   .footer-legal is purely structural, the grid item .footer-grid already
   lays out; min-width: 0 keeps it a normal shrinking grid child, the same
   safety net .cc-shell/.mp-shell give their own children. .footer-disclosure
   needs to read quieter than the legal line above it and than the nav links
   beside it, both of which already resolve to 12px/var(--muted) through
   .footer-grid p and .footer p. Ancestor-scoped selectors (.footer .X) are
   required here, not .footer-disclosure alone, to outrank those existing
   rules (0,2,0 beats 0,1,1). No padding growth otherwise. Top margin raised
   to 4px on 2026-08-24 (check-render.mjs near-overlap fix): the two
   .footer-legal paragraphs rendered 2.0px apart at 1280/light, under the
   site's 4px NEAR_OVERLAP_PX target; 4px matches the .footer-link-group
   gap fix from the same pass. */
.footer-legal {
  min-width: 0;
}

.footer .footer-disclosure {
  margin-top: 4px;
  color: var(--faint);
  font-size: 11px;
  line-height: 1.4;
}

/* .quad-cell.eth (2026-08-24): .kas, .btc, and .sol each get a modifier
   rule restoring a border after the site-wide de-glass batch zeroed every
   .quad-cell border. Ethereum's cell carried the "eth" class from the
   start but no matching modifier was ever written, so it alone renders
   with no border while the other three chains in the same quadrant do.
   Same values as the other three restore parity. */
.quad-cell.eth {
  border-color: var(--line);
  background: var(--card-bg);
}

/* .live-demo-frame (2026-08-24): wraps an inline interactive demo
   (why-kaspa-matters.html's confirmation-risk demo, build-on-kaspa.html's
   proof-boundary demo) directly in page prose with no visual break of its
   own; the demo widgets inside set their own colors and max-width but no
   frame. Reuses .deep-dive-plain's established bordered/tinted panel
   language, the site's one existing pattern for framing embedded content,
   instead of inventing a new box style. */
.live-demo-frame {
  margin-top: 16px;
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: rgba(var(--cyan-rgb), .04);
}

/* search.html page-length pass (2026-08-24): search.html's job is a page
   map a reader scans and filters, not a set of cards a reader reads one
   by one, so the 17-card list is compacted from tall bordered cards
   (~124px each on phone, 2474px of total scroll for the results block
   alone) into a dense scannable list, closer to how Google or a file
   browser renders a result index. No card, title, or description is
   removed; .search-results still holds all 17 entries with full text.
   Only the layout gets denser. Same specificity as the earlier
   `.search-results article` rules above (0,0,1,1); this wins on source
   order, the established pattern in this file (see the "APPLE DESIGN
   LAYER" note in CLAUDE.md). .search-results is unique to search.html
   (grep confirmed), so nothing else depends on the rules being
   overridden here. */
/* .search-filters: quick category chips, added the same pass as the
   compaction above. Not decoration: each button sets the search box to
   that category and re-runs the existing scoring logic, a real control a
   reader can use to narrow the page map without typing. It also gives
   the results block a genuine landmark (a button, in the undifferentiated-
   run sense design/STANDARD.md's page-length gate checks for) between the
   search box and the card list, where previously nothing between the two
   registered as one. */
.search-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 14px 0 20px;
}

.search-filters button {
  min-height: 44px;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 7px 14px;
  background: var(--card-bg);
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color .15s ease, color .15s ease, background-color .15s ease;
}

.search-filters button:hover {
  border-color: color-mix(in srgb, var(--cyan) 44%, var(--line));
  color: var(--text);
}

.search-filters button[aria-pressed="true"] {
  border-color: var(--cyan);
  background: color-mix(in srgb, var(--cyan) 16%, var(--card-bg));
  color: var(--text);
}

.search-results {
  gap: 4px;
}

.search-results article {
  padding: 8px 16px;
  border-radius: 8px;
  position: relative;
}

.search-results span {
  display: inline;
  margin: 0 8px 0 0;
  font-size: 10px;
  letter-spacing: .08em;
}

.search-results h3 {
  display: inline;
  margin: 0;
}

/* The card title link is the real touch target, not a decorative label:
   padding (not a stretched-overlay trick) gives the <a> element itself a
   44px-tall box, the minimum design/THE-BAR.md sets and check-render.mjs
   measures directly against the anchor's own rect. inline-block lets it
   still sit on the same line as the category span above. */
.search-results h3 a {
  display: inline-block;
  padding: 13px 4px;
  font-size: 16px;
  line-height: 1.3;
}

/* 16px/1.6, raised from 13px/1.4 on 2026-08-29. These are the only sentences
   on search.html a reader actually reads, one per result, and at 390px they
   rendered at 13px: check-render.mjs flagged all 17 as sub-16px body copy and
   was right. The site's small-type band (11-17px, house-style.md) covers a
   label paired with a larger value, not a result's whole description. The
   surrounding article already sets 17px. Note this is the second
   `.search-results p` block in this file; the one near line 1631 loses to it
   on source order, so edit here. */
.search-results p {
  margin: 0 0 6px;
  font-size: 16px;
  line-height: 1.6;
}

/* Semantic marker for the inclusion-vs-confirmation quadrant diagram on
   why-kaspa-matters.html, used by the page-length landmark check
   (design/STANDARD.md, "The page-length ceiling") to recognize this
   .quadrant instance as the real diagram it is. No-op visually: mirrors
   .quadrant's own position: relative. */
.confirm-quadrant-diagram {
  position: relative;
}

/* ============================================================
   16px READER-TEXT FLOOR, 2026-08-29
   Appended after the APPLE DESIGN LAYER, so it wins on the
   last-declaration rule without touching the legacy blocks
   above, several of which are already inert. styles.css
   declares .theme-toggle four times, .footer twice and
   .footer-link-group span twice at different sizes; editing
   any one of them in place is a coin flip about which wins.

   Every selector below carries reader-facing text that the
   render matrix measured under 16px. The small-type band the
   design spec does document -- .eyebrow, .status-pill, .tag,
   thead cells, code, the card kicker spans -- is deliberately
   absent, and stays where the spec put it.
   ============================================================ */

.nav-menu-button,
.nav-cta,
.theme-toggle,
.brand,
.nav-links a,
:root[data-theme="light"] .nav-links a { font-size: 16px; }

.footer,
.footer-grid p,
.footer-link-group span,
.footer-link-group a,
.footer .footer-disclosure { font-size: 16px; }

.search-box span,
.search-results span,
.search-filters button { font-size: 16px; }

.cell-detail summary,
.guide-detail summary::after,
.builder-ledger span,
.builder-ledger p,
.use-source-grid strong,
.image-viewer figcaption,
.axis,
.reality-table td::before,
.view-switch__tab,
.deep-dive summary,
.fm-demo summary { font-size: 16px; }

/* .reality-table th is a real header cell; the spec's 12px rule covers
   thead cells, and the render gate exempts thead th for that reason. This
   table's headers sit outside thead, so they were measured and failed. */
.reality-table th { font-size: 16px; }

/* The information glyph is a 1-character affordance inside a circular
   target, and its panel is the prose that answers it. The panel is read;
   the glyph is aimed at. Both were under the floor. */
.info-affordance__glyph,
.info-affordance__panel,
.term-def__panel { font-size: 16px; }

/* Line height and measure, against the reference set in
   data/reference-metrics-2026-08-29.json: nine sites median 1.6 and 70ch,
   this site measured 1.5 and 78.8ch before this block. */
body { line-height: 1.6; }

/* A <summary> is a real control: it opens and closes a disclosure, and it was
   the largest single touch-target failure left after the 16px floor, at 66 of
   248. WCAG SC 2.5.8 wants 44px in the pointer dimension; these were running
   at the height of one line of text. Padding rather than a bare min-height, so
   a summary that wraps to two lines keeps its own height. */
summary {
  min-height: 44px;
  padding-top: 10px;
  padding-bottom: 10px;
  box-sizing: border-box;
}

/* A link that is the entire content of a table cell (build-on-kaspa's routes
   table, status.html's status-snapshot tables) rendered at the height of its
   own text line, about 20px, even though the cell around it already carries
   16px of padding. The cell's padding doesn't move with it: WCAG SC 2.5.8
   measures the control's own box, and inline-flex plus a min-height gives it
   one without needing the surrounding row taller than a reader already sees. */
.reality-table td a,
.reality-table th a,
/* Same shape of bug, one level up: a <p class="live-footnote"> whose only
   content is a single link (index.html's collision-demo source line, and
   others). */
p.live-footnote a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* No interactive control on the site had a press/touch state: grepping this
   file and every page's inline CSS for :active found zero button, chip, or
   link rules (one unrelated mask-image :active on model-picker.html, not a
   press state). STANDARD.md: "Touch produces change in the same frame." A
   toggling control's aria-pressed covers its own persistent look, but the
   momentary feedback between touch-down and release, on any button
   including non-toggling ones, was entirely absent. That is most visible on
   touch devices, which never fire :hover at all, so a tap produced no
   visible response until the resulting state change landed. One rule,
   appended last so it wins the cascade, covers every native button, link
   pill, custom [role=button] control (info affordances, term-def glyphs,
   the GHOSTDAG demo's graph nodes), and disclosure trigger on the site,
   including every demo's self-scoped CSS, since none of them define their
   own :active to out-specify it. */
button:not(:disabled):active,
.button:active,
a.btn:active,
[role="button"]:not([aria-disabled="true"]):active,
summary:active {
  transform: scale(0.97);
}

@media (prefers-reduced-motion: reduce) {
  button:not(:disabled):active,
  .button:active,
  a.btn:active,
  [role="button"]:not([aria-disabled="true"]):active,
  summary:active {
    transform: none;
    opacity: 0.8;
  }
}

/* Hover-state defect class (2026-08-31, UX-AUDIT-2.md D1, D4, D5, D6).
   Four groups of controls responded to focus and to press but not to hover.
   Measured by diffing 13 computed properties in default against :hover on
   every visible interactive element on every page, which is how a defined
   rule that another rule silently outranks gets caught. */

/* D1. styles.css:5657 resets .path-grid a:hover to the default border and
   background, so the site's two entry doors had no hover response of any kind.
   A background step rather than the translateY at styles.css:4980, because the
   glass-era rule at styles.css:4369 kills every card-grid hover transform with
   !important and nothing can out-specify that. That rule's stated reason,
   backdrop-filter cards flickering while they move, died with the de-glassing;
   removing it is a separate job, and only .path-grid and .check-grid of its 35
   selectors still appear in any page. */
.path-grid a:hover {
  background: color-mix(in srgb, var(--text) 6%, var(--card-bg));
}

/* D4. Ten pages define ::-webkit-slider-thumb, none defined a hover or press
   state, so the primary control of eleven demos was inert to the pointer.
   Scoped to the thumb's transform because no per-page rule sets one, which
   is what keeps this out of a specificity fight with all ten of them. */
input[type="range"]:not(:disabled):hover::-webkit-slider-thumb {
  transform: scale(1.18);
}

input[type="range"]:not(:disabled):active::-webkit-slider-thumb {
  transform: scale(1.08);
}

input[type="range"]:not(:disabled):hover::-moz-range-thumb {
  transform: scale(1.18);
}

input[type="range"]:not(:disabled):active::-moz-range-thumb {
  transform: scale(1.08);
}

/* D5. Text-entry controls carry a visible border that can take a tint. */
input[type="search"]:not(:disabled):hover,
input[type="number"]:not(:disabled):hover,
input[type="text"]:not(:disabled):hover,
select:not(:disabled):hover,
textarea:not(:disabled):hover {
  border-color: color-mix(in srgb, var(--green) 40%, var(--line-bright));
}

/* D5b. A label wrapping a checkbox is the real click target and the real
   control, so it takes the pointer feedback the bare input cannot. The radius
   is invisible at rest, where there is no background to round. */
label:has(> input[type="checkbox"]):hover {
  background: color-mix(in srgb, var(--text) 6%, var(--card-bg));
  border-radius: 8px;
}

/* D6. The Chart/Table toggle on three pages. The label is the visible
   control; its input is an offscreen 44px box. */
.view-switch__tab:hover {
  background: color-mix(in srgb, var(--text) 7%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  input[type="range"]:not(:disabled):hover::-webkit-slider-thumb,
  input[type="range"]:not(:disabled):active::-webkit-slider-thumb {
    transform: none;
  }

  input[type="range"]:not(:disabled):hover::-moz-range-thumb,
  input[type="range"]:not(:disabled):active::-moz-range-thumb {
    transform: none;
  }
}

/* Second UX pass, 31 August 2026. Both defects below were invisible to the
   first pass because it measured one theme and read computed style on the
   control itself. These were measured by screenshotting each control at rest
   and hovered, in both themes, and comparing the pixels. */

/* D7. Eighty of the site's ninety-two <summary> elements were pixel-identical
   on hover, in dark and in light alike. Six page-scoped rules
   (model-picker.html's `.mp-method`, `.mp-prov`, chain-comparer.html's
   `.cc-method`, `.cc-gap-panel`, `.cc-notes`) do define one, which is what the
   other eighty were measured against: the site already treats a disclosure
   trigger as something that answers the pointer, and styles.css defined no
   `summary:hover` at all. An inset shadow rather than a background, because
   many of these summaries already carry one and a background would replace
   it; an inset shadow tints whatever is underneath and respects the corner
   radius. The six page-scoped rules set `color` at higher specificity and
   still win where they apply, so this adds to them rather than fighting
   them. */
summary {
  transition: box-shadow .18s ease-out;
}

summary:hover {
  box-shadow: inset 0 0 0 999px color-mix(in srgb, var(--text) 6%, transparent);
}

summary:active {
  box-shadow: inset 0 0 0 999px color-mix(in srgb, var(--text) 11%, transparent);
}

/* D8. The two entry doors on start-here.html had a hover response in dark and
   none at all in light: measured, the light-theme hover changed zero computed
   properties across the card and its children, while dark changed the
   background. styles.css:5660 carries a
   `:root[data-theme="light"] .path-grid a:hover` reset at specificity (0,3,1),
   which outranks the (0,2,1) fix at styles.css:7700 in light only, so the fix
   the first pass verified in dark was silently reverted in the other theme.
   Matching that selector here, later in source order, lets the fix apply in
   both. */
:root[data-theme="light"] .path-grid a:hover {
  background: color-mix(in srgb, var(--text) 6%, var(--card-bg));
}

/* D9. Printing. styles.css carried no `@media print` block at all, so a
   printed page kept the fixed pill header and its backdrop strip over the top
   of the first page, kept the 76-word footer link list, kept dark surfaces
   that a printer renders as solid ink, and dropped everything inside a closed
   <details>: measured, 1,679 words on model-picker.html, 1,623 on kips.html,
   1,421 on kaspa-mining.html. A disclosure is a screen affordance for
   managing length; paper has no affordance to open one, so on paper the
   content simply ceases to exist.
   Colors are flattened with a universal rule rather than by restating the
   light token set, which would be a second copy of it to keep in sync. */
@media print {
  :root {
    --site-header-clearance: 0px;
  }

  .site-header,
  .skip-link,
  .theme-toggle,
  .nav-menu-button,
  .footer nav,
  .site-related-grid,
  body::after {
    display: none !important;
  }

  *,
  *::before,
  *::after {
    background: transparent !important;
    background-image: none !important;
    box-shadow: none !important;
    color: #000 !important;
    text-shadow: none !important;
    filter: none !important;
  }

  * {
    border-color: #999 !important;
  }

  body {
    background: #fff !important;
  }

  main {
    max-width: none;
    margin: 0;
    padding-top: 0;
  }

  /* Reveal what a disclosure hides. Chromium hides a closed details' contents
     through `::details-content { content-visibility: hidden }`, which a
     `display` rule on the children cannot reach, so both are needed. nav.js
     also leaves an inline `height` and `overflow: hidden` behind after its
     close animation, which would clamp the revealed content to the summary's
     height, so those are cleared too. */
  details::details-content {
    content-visibility: visible !important;
    block-size: auto !important;
  }

  details {
    height: auto !important;
    max-height: none !important;
    overflow: visible !important;
  }

  details > *:not(summary) {
    display: block !important;
  }

  details,
  section,
  figure,
  table,
  li {
    break-inside: avoid;
  }

  h1, h2, h3 {
    break-after: avoid;
  }
}

/* Horizontal scrollers were reading through a peephole on phones. Measured at
   390px: kaspa-mining's 20-chip row needs 1,871px and got a 250px window;
   kaspa-origin-story's preset row needs 648px and got 222px. None of them
   carried dead space, the content filled the scroll width exactly. The loss
   was nested padding: section 20px, demo 16px, stage 16px, each pair stacking
   until 43% of the screen was chrome beside a tiny slot. A scroller is the one
   child that should reach the card edge, so it escapes its parent's inline
   padding and re-adds it inside, keeping items off the edge while scrolling
   the full width. Desktop is unchanged: these rows fit there and never scroll. */
@media (max-width: 700px) {
  .presets,
  .chipset,
  .chips {
    margin-inline: -16px;
    padding-inline: 16px;
    scroll-padding-inline: 16px;
  }
}

/* Scrolling a wide table sideways used to carry the row's own label off the
   left edge, so you could be reading a number with nothing left on screen
   saying which row it belonged to. The first cell of each row now stays put. */
.table-wrap table tbody th:first-child,
.table-wrap table tbody td:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--card-bg);
}
.table-wrap table thead th:first-child {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--card-bg);
}

/* An inline code chip carries .4em of right padding, which is correct against
   a following word and wrong against a following comma or period: the chip's
   own breathing room reads as a typed space, "genesis.rs , an empty genesis".
   The chip gives back its right padding when a mark follows, rather than the
   mark being pulled back over it: a negative margin overlapped the chip's box
   and the render gate rejected it as intersecting text. Only marks that follow
   a chip are wrapped, so ordinary punctuation is untouched. */
code:has(+ .tuck) {
  padding-right: 0.14em;
}

/* The next-step block showed an eyebrow and a reason, with the destination's own
   name hidden in an sr-only heading: a navigation card that never said where it
   went, and read as a stray underlined sentence. The name leads now and carries
   the link, the reason supports it, and the block is tighter than the 161px of
   mostly empty card it used to occupy for one line of text. */
.site-next-title {
  margin: 0 0 2px;
  font-size: clamp(24px, 2.4vw, 32px);
  line-height: 1.15;
  letter-spacing: -.02em;
}
.site-next-title a {
  color: var(--text);
  text-decoration: none;
  /* The heading's line box is 28px at phone width, under the 44px tap target the
     render gate enforces. Padding rather than a taller line, so the type keeps
     its own leading. */
  display: inline-block;
  /* 24px type gives a 27.59px line box, so 8px each side lands at 43.59 and the
     gate reads it as a 44 that fails. 10px clears it with room for the clamp. */
  padding-block: 10px;
}
.site-next-title a:hover {
  color: var(--green);
}
.site-next-reason {
  margin: 0;
  max-width: 46em;
  color: var(--muted);
  font-size: clamp(16px, 1.3vw, 18px);
  line-height: 1.5;
}
.section.site-related {
  padding-block: 24px;
}

/* Keep the retained reading header to one compact row until the phone menu is
   needed. The earlier 1060px layout moved the five navigation links to a
   second row while leaving the brand and theme control above it, which made a
   large empty-looking band between the two header surfaces at medium widths. */
@media (max-width: 1060px) {
  .site-header {
    top: 0;
    left: 0;
    transform: none;
    width: 100%;
    max-width: 100%;
    margin: 0;
    border-inline: 0;
    border-radius: 0;
  }

  .nav {
    position: relative;
    grid-template-columns: minmax(0, 1fr) auto auto;
    gap: 8px;
    min-height: 60px;
    padding: 8px 0;
  }

  .brand {
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
  }

  .nav-menu-button {
    display: inline-flex;
    grid-column: 3;
    grid-row: 1;
    min-height: 44px;
  }

  .theme-toggle {
    grid-column: 2;
    grid-row: 1;
    min-height: 44px;
  }

  .nav.nav-enhanced .nav-links {
    display: none;
  }

  .nav.nav-enhanced[data-open="true"] .nav-links {
    position: absolute;
    z-index: 60;
    top: calc(100% + 8px);
    right: 0;
    left: 0;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    padding: 12px;
    border: 1px solid var(--line);
    border-radius: 18px;
    background: var(--bg-2);
    background-color: var(--bg-2);
    box-shadow: var(--shadow);
    pointer-events: auto;
  }

  .nav.nav-enhanced[data-open="true"] .nav-links a {
    width: 100%;
    min-width: 0;
    min-height: 44px;
    justify-content: flex-start;
    pointer-events: auto;
  }
}
