/* ==========================================================================
   components.css: component layer for CSR design system
   Consumes: tokens.css, base.css
   Produces: .nav-island, .nav-brand, .nav-wordmark, .nav-links, .nav-actions,
             .theme-toggle, .nav-burger, .btn, .btn-primary, .btn-go,
             .btn-secondary, .btn-ghost, .chip, .chip-dot (.is-live/.is-watch/
             .is-attention/.is-off), .telemetry, .card, .instrument-card,
             .panel, .panel-bar, .kpis, .kpi, .chart, .panel-foot,
             .frost, .diagram-card, .code (.c-key/.c-str/.c-num/.c-comment),
             .field, .skip-link, .icon
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. Icons
   Drawn glyphs, from lib/icons.mjs. Every arrow, check, caret and status mark
   on the site used to be a Unicode character, which meant the reader's emoji
   or fallback font chose the weight, the baseline and sometimes the colour.
   These size to the text they sit beside and take its colour, so an icon in a
   button, a chip or a paragraph needs no per-site override.
   -------------------------------------------------------------------------- */
.icon {
  width: 1em;
  height: 1em;
  flex: none;
  display: inline-block;
  vertical-align: -0.125em;
}

/* --------------------------------------------------------------------------
   1. Skip link: accessibility
   -------------------------------------------------------------------------- */
.skip-link {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 9999;
  padding: var(--space-8) var(--space-16);
  background: var(--orange);
  color: var(--on-signal);
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  border-radius: var(--radius-sm);
  /* visually hidden until focused */
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  overflow: hidden;
  text-decoration: none;
}

.skip-link:focus {
  clip: auto;
  clip-path: none;
  overflow: visible;
  white-space: normal;
}

/* --------------------------------------------------------------------------
   2. Nav island
   -------------------------------------------------------------------------- */
.nav-island {
  position: sticky;
  top: var(--space-16);
  margin: var(--space-16) auto 0;
  max-width: var(--page-max);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-16);
  padding: var(--space-8) var(--space-12) var(--space-8) var(--space-16);
  background: var(--nav-bg);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid var(--hair);
  border-radius: var(--radius-pill);
  z-index: 100;
  transition: background 0.2s ease;
}

[data-nav].scrolled {
  background: var(--nav-bg-scrolled);
}

/* --------------------------------------------------------------------------
   3. Nav brand + wordmark
   -------------------------------------------------------------------------- */
.nav-brand {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  text-decoration: none;
  flex-shrink: 0;
}

.nav-brand:hover {
  text-decoration: none;
}

.nav-wordmark {
  font-family: var(--font-mono);
  text-transform: uppercase;
  font-size: var(--text-micro);
  letter-spacing: 0.14em;
  color: var(--fg);
  line-height: 1;
}

.nav-wordmark em {
  font-style: normal;
  color: var(--muted);
}

/* Visually hidden, read by assistive tech. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   4. Nav links
   -------------------------------------------------------------------------- */
.nav-links {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: var(--space-16);
  list-style: none;
}

.nav-links a {
  font-family: var(--font-mono);
  text-transform: uppercase;
  font-size: var(--text-caption);
  color: var(--fg-2);
  text-decoration: none;
  letter-spacing: 0.1em;
  white-space: nowrap;
  padding-bottom: 2px;
  border-bottom: 1px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}

.nav-links a:hover {
  color: var(--fg);
  text-decoration: none;
}

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

/* --------------------------------------------------------------------------
   5. Nav actions + controls
   -------------------------------------------------------------------------- */
.nav-actions {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  flex-shrink: 0;
}

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: transparent;
  border: 1px solid var(--hair);
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--fg-2);
  font-family: var(--font-mono);
  font-size: 14px;
  transition: border-color 0.15s ease, color 0.15s ease;
  padding: 0;
}

/* One button, two drawings: the icon shows the theme the click gives you, so
   the moon is up while the light theme is active and the sun while the dark
   one is. The pre-paint script in partials/head.html has already stamped
   data-theme on <html> by the time this resolves, so neither icon flashes. */
.theme-toggle .icon {
  width: 16px;
  height: 16px;
}

.theme-toggle .icon-sun,
html[data-theme="dark"] .theme-toggle .icon-moon {
  display: none;
}

html[data-theme="dark"] .theme-toggle .icon-sun {
  display: inline-block;
}

/* 44px hit area on the two 32px icon buttons without changing what is drawn. */
.theme-toggle,
.nav-burger {
  position: relative;
}

.theme-toggle::after,
.nav-burger::after {
  content: "";
  position: absolute;
  inset: -6px;
}

@media (pointer: coarse) {
  .btn {
    min-height: 44px;
  }
}

.theme-toggle:hover {
  border-color: var(--hair-active);
  color: var(--fg);
}

.nav-burger {
  display: none;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: transparent;
  border: 1px solid var(--hair);
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--fg-2);
  padding: 0;
  font-size: 16px;
  line-height: 1;
}

.nav-burger .icon {
  width: 18px;
  height: 18px;
}

/* Both states ship in the button; aria-expanded decides which one is drawn. */
.nav-burger .icon-close,
.nav-burger[aria-expanded="true"] .icon-menu {
  display: none;
}

.nav-burger[aria-expanded="true"] .icon-close {
  display: inline-block;
}

/* --------------------------------------------------------------------------
   6. Mobile nav: collapse to burger below 1200px (full 7-link nav needs the room)
   -------------------------------------------------------------------------- */
@media (max-width: 1200px) {
  .nav-island {
    flex-wrap: wrap;
    border-radius: var(--radius-lg);
    gap: var(--space-12);
  }

  .nav-burger {
    display: inline-flex;
  }

  .nav-links {
    display: none;
    flex-direction: column;
    align-items: flex-start;
    width: 100%;
    gap: var(--space-4);
    padding: var(--space-12) 0 var(--space-8);
    border-top: 1px solid var(--hair);
  }

  .nav-island.menu-open .nav-links {
    display: flex;
  }

  .nav-links a {
    font-size: var(--text-caption);
    padding: var(--space-8) 0;
  }
}

/* The menu CTA only exists on a phone; on wider screens the bar carries it. */
.nav-links .nav-links-cta {
  display: none;
}

/* --------------------------------------------------------------------------
   6b. Phone: one-row bar, tighter menu
   Brand (240px) plus toggle, CTA and burger (232px) never fit inside 390px, so
   the actions wrapped under the wordmark and the sticky bar stood 93px tall.
   Below 560px the CTA leaves the bar and reappears at the foot of the open
   menu, the actions share the brand's row, and the links drop to 28px rows.
   -------------------------------------------------------------------------- */
@media (max-width: 560px) {
  .nav-island {
    top: var(--space-8);
    margin-top: var(--space-8);
    padding: var(--space-8) var(--space-12);
    gap: var(--space-8);
  }

  .nav-brand { order: 1; }
  .nav-actions { order: 2; }
  .nav-links { order: 3; }

  .nav-actions .btn {
    display: none;
  }

  .nav-links {
    gap: 0;
    padding: var(--space-8) 0 var(--space-4);
  }

  .nav-links a {
    padding: var(--space-4) 0;
  }

  .nav-links .nav-links-cta {
    display: inline-flex;
    align-self: stretch;
    justify-content: center;
    margin-top: var(--space-8);
    padding: var(--space-12) var(--space-16);
    color: var(--on-signal);
    border: 1px solid var(--orange);
  }
}

/* --------------------------------------------------------------------------
   7. Buttons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-8);
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-size: var(--text-caption);
  font-weight: var(--fw-medium);
  padding: var(--space-8) var(--space-16);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-decoration: none;
  line-height: 1;
  transition: opacity 0.15s ease, box-shadow 0.15s ease;
  white-space: nowrap;
  max-width: 100%;
}

/* Most buttons are two or three words and want nowrap. A few carry a whole
   sentence ("Border manufacturing and maquiladora applied intelligence"),
   which measured 578px inside a 390px phone and pushed the page sideways.
   Below the phone breakpoint a long label wraps rather than escaping. */
@media (max-width: 560px) {
  .btn { white-space: normal; line-height: 1.3; text-align: left; }
}

.btn:hover {
  text-decoration: none;
  opacity: 0.85;
}

.btn:active {
  opacity: 0.7;
}

/* Signal fill. Text colour follows the theme: black on the bright dark-theme
   signals, white on the darker light-theme ones. */
.btn-primary {
  background: var(--orange);
  color: var(--on-signal);
  border-color: var(--orange);
}

.btn-go {
  background: var(--green);
  color: var(--on-signal);
  border-color: var(--green);
}

.btn-secondary {
  background: transparent;
  color: var(--fg);
  border-color: var(--fg);
}

.btn-ghost {
  background: transparent;
  color: var(--muted);
  border-color: var(--hair);
}

/* --------------------------------------------------------------------------
   8. Status chips
   -------------------------------------------------------------------------- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-8);
  border: 1px solid var(--hair);
  padding: var(--space-8) 14px;
  font-family: var(--font-mono);
  text-transform: uppercase;
  font-size: var(--text-caption);
  letter-spacing: 0.1em;
  border-radius: var(--radius-pill);
  color: var(--fg-2);
  line-height: 1;
  white-space: nowrap;
}

.chip-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

.chip-dot.is-live {
  background: var(--green);
  box-shadow: 0 0 6px var(--green);
}

.chip-dot.is-warn { background: var(--yellow); box-shadow: 0 0 6px var(--yellow); }

.chip-dot.is-watch {
  background: var(--yellow);
}

.chip-dot.is-attention {
  background: var(--orange);
}

.chip-dot.is-off {
  background: var(--muted);
}

/* --------------------------------------------------------------------------
   9. Telemetry bar
   -------------------------------------------------------------------------- */
.telemetry {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-24);
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  color: var(--muted);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--hair);
  padding: var(--space-8) 0;
}

@media (max-width: 800px) {
  .telemetry {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   10. Card: base and instrument variant
   -------------------------------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--hair);
  border-radius: var(--radius-sm);
  padding: var(--space-24);
}

.instrument-card {
  position: relative;
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--hair);
  border-radius: var(--radius-sm);
  padding: var(--space-24);
  border-top: 2px solid var(--orange);
}

/* Cursor spotlight: driven by --mx/--my set in motion.js on pointermove.
   Gated on fine-pointer so it only fires for mouse users.                */
@media (hover: hover) and (pointer: fine) {
  .instrument-card::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: radial-gradient(
      circle at var(--mx, 50%) var(--my, 50%),
      rgba(255, 255, 255, 0.05),
      transparent 40%
    );
    opacity: 0;
    transition: opacity 0.3s ease;
    border-radius: inherit;
  }

  .instrument-card:hover::before {
    opacity: 1;
  }
}

.instrument-card.signal-green {
  border-top-color: var(--green);
}

.instrument-card.signal-yellow {
  border-top-color: var(--yellow);
}

/* --------------------------------------------------------------------------
   11. Instrument panel
   -------------------------------------------------------------------------- */
.panel {
  background: var(--surface);
  border: 1px solid var(--hair);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

/* panel-bar: header row with id badge + timestamp */
.panel-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-8) var(--space-16);
  border-bottom: 1px solid var(--hair);
  background: var(--surface-strong);
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--muted);
  gap: var(--space-16);
}

.panel-bar .panel-id {
  color: var(--orange);
  font-weight: var(--fw-bold);
}

/* kpis grid: one row of equal columns, however many entries there are.
   A fixed repeat(3, 1fr) silently wrapped the fourth entry onto a second
   row with no row gap, so on /method and /press the fourth number sat on
   top of the first entry's label. grid-auto-flow: column sizes the row to
   the item count instead of assuming three. */
.kpis {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  padding: var(--space-20) var(--space-16);
  column-gap: 0;
  row-gap: var(--space-20);
}

.kpi {
  padding: 0 var(--space-16);
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.kpi + .kpi {
  border-left: 1px solid var(--hair-faint);
}

.kpi:first-child {
  padding-left: 0;
}

.kpi:last-child {
  padding-right: 0;
}

.kpi .kl {
  overflow-wrap: anywhere;
}

/* Below the point where four labels stop fitting, wrap to two columns and
   then to one, dropping the divider wherever an item starts a row. */
@media (max-width: 760px) {
  .kpis {
    grid-auto-flow: row;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .kpi:nth-child(odd) { border-left: 0; padding-left: 0; }
  .kpi:nth-child(even) { padding-right: 0; }
}

@media (max-width: 460px) {
  .kpis { grid-template-columns: minmax(0, 1fr); row-gap: var(--space-16); }
  .kpi { border-left: 0; padding-left: 0; padding-right: 0; }
}

/* kv = the big number (uses Syne via .display or direct font-family) */
.kpi .kv {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--text-heading);
  line-height: var(--leading-tight);
  color: var(--fg);
  letter-spacing: var(--tracking-heading);
}

.kpi .kl {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--muted);
}

/* mini bar chart */
.chart {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 40px;
  padding: 0 var(--space-16) var(--space-12);
}

.chart-bar {
  flex: 1;
  min-height: 2px;
  border-radius: 1px 1px 0 0;
  /* height and background set via inline style (signal color) */
  background: var(--orange);
  transition: opacity 0.15s ease;
}

.chart-bar:hover {
  opacity: 0.7;
}

/* panel footer */
.panel-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-8) var(--space-16);
  border-top: 1px solid var(--hair-faint);
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--muted);
  gap: var(--space-16);
}

/* --------------------------------------------------------------------------
   12. Frosted hero card
   -------------------------------------------------------------------------- */
.frost {
  background: var(--frost-bg);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid var(--hair);
  border-radius: var(--radius-lg);
  padding: var(--space-32);
  box-shadow: var(--shadow-frost);
}

/* --------------------------------------------------------------------------
   13. Diagram cards
   -------------------------------------------------------------------------- */
.diagram-card {
  background: var(--surface);
  border: 1px solid var(--hair);
  border-radius: var(--radius-sm);
  padding: var(--space-24);
  display: flex;
  flex-direction: column;
  gap: var(--space-16);
}

.diagram-card .diagram-label {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--muted);
}

/* --------------------------------------------------------------------------
   14. Code blocks + syntax tokens
   -------------------------------------------------------------------------- */
.code {
  background: var(--lift);
  border: 1px solid var(--hair-faint);
  padding: var(--space-20);
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.75;
  white-space: pre-wrap;
  overflow-x: auto;
  color: var(--fg-2);
  border-radius: var(--radius-sm);
}

/* Syntax highlight tokens */
.c-key     { color: var(--orange); }
.c-str     { color: var(--green); }
.c-num     { color: var(--yellow); }
.c-comment { color: var(--muted); }

/* --------------------------------------------------------------------------
   15. Field rows
   -------------------------------------------------------------------------- */
.field {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-16);
  border: 1px solid var(--hair);
  padding: 12px 16px;
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  color: var(--fg-2);
}

.field + .field {
  border-top: none;
}

.field:first-child {
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}

.field:last-child {
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
}

.field:only-child {
  border-radius: var(--radius-sm);
}

.field-key {
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-size: var(--text-micro);
  flex-shrink: 0;
}

.field-value {
  color: var(--fg);
  text-align: right;
}

/* ---- long-form document hero + prose (phase 2) ---- */
.doc-hero {
  padding: var(--space-64) 0 var(--space-40);
  border-bottom: 1px solid var(--hair);
  margin-bottom: var(--space-40);
}
.doc-hero .lede { margin-top: var(--space-16); }
.link-row { display: flex; flex-wrap: wrap; gap: var(--space-12); }
.doc-hero .link-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-12);
  margin-top: var(--space-24);
}
.prose { max-width: 65ch; color: var(--fg-2); }
.prose > * + * { margin-top: var(--space-16); }
.prose h2 {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--text-heading-xs);
  line-height: 1.2;
  letter-spacing: var(--tracking-heading);
  color: var(--fg);
  margin-top: var(--space-48);
}
.prose h3 {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--text-subheading);
  color: var(--fg);
  margin-top: var(--space-32);
}
.prose p { font-size: var(--text-body); line-height: var(--leading-body); }
.prose ul, .prose ol { padding-left: var(--space-24); }
.prose li { margin-top: var(--space-8); line-height: var(--leading-body); }
.prose a { color: var(--orange); text-decoration: underline; text-underline-offset: 2px; }
.prose code {
  font-family: var(--font-mono);
  font-size: 0.92em;
  background: var(--lift);
  border: 1px solid var(--hair);
  border-radius: var(--radius-sm);
  padding: 0.1em 0.4em;
}
.prose pre {
  background: var(--lift);
  border: 1px solid var(--hair);
  border-radius: var(--radius-md);
  padding: var(--space-16);
  overflow-x: auto;
}
.prose pre code {
  background: none;
  border: 0;
  padding: 0;
  font-size: var(--text-caption);
  line-height: 1.6;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--fg-2);
}
.citation {
  margin-top: var(--space-48);
  border: 1px solid var(--hair);
  padding: var(--space-20);
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  line-height: 1.6;
  color: var(--fg-3);
  word-break: break-word;
}
.citation .cite-label {
  display: block;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--muted);
  margin-bottom: var(--space-8);
}

/* --------------------------------------------------------------------------
   16. Site footer
   -------------------------------------------------------------------------- */
.site-footer {
  margin-top: var(--space-80);
  border-top: 1px solid var(--hair);
  padding: var(--space-48) 0 var(--space-32);
}
.footer-inner {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-48);
  align-items: start;
}
.footer-name { color: var(--fg); font-size: var(--text-body); }
.footer-name strong { font-weight: var(--fw-semibold); }
.footer-addr {
  margin-top: var(--space-8);
  font-family: var(--font-mono);
  font-size: var(--text-caption);
  letter-spacing: 0.04em;
  color: var(--muted);
}
.footer-addr a { color: var(--fg-2); }
.footer-desc {
  margin-top: var(--space-16);
  max-width: 58ch;
  font-size: var(--text-caption);
  line-height: var(--leading-body);
  color: var(--fg-3);
}
.footer-links {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-8);
}
.footer-links a {
  font-family: var(--font-mono);
  text-transform: uppercase;
  font-size: var(--text-caption);
  letter-spacing: 0.1em;
  color: var(--fg-2);
  text-decoration: none;
}
.footer-links a:hover { color: var(--fg); }
.footer-base {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-16);
  margin-top: var(--space-40);
  padding-top: var(--space-20);
  border-top: 1px solid var(--hair-faint);
}
.footer-license { font-size: var(--text-caption); line-height: var(--leading-body); color: var(--muted); }
.footer-license a { color: var(--fg-2); text-decoration: underline; text-underline-offset: 2px; }
@media (max-width: 800px) {
  .footer-inner { grid-template-columns: 1fr; gap: var(--space-24); }
  .footer-links { flex-direction: row; flex-wrap: wrap; align-items: flex-start; gap: var(--space-16); }
  .footer-base { flex-direction: column; align-items: flex-start; gap: var(--space-12); }
}

/* ── Heartbeat: live operator telemetry (assets/js/heartbeat.js) ──────────
   .hb            compact pill (hero, footer)
   .hb-monitor    wide ECG panel body (homepage vitals, method page)
   [data-hb-live] set by JS while the strap is streaming                    */
.hb {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  padding: 8px 14px 8px 12px;
  border: 1px solid var(--hair);
  border-radius: var(--radius-pill);
  background: var(--surface);
}
.hb-dot {
  --hb-glow: var(--orange);
  flex: none;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--hb-glow);
  animation: hb-pulse 0.83s ease-out infinite;
}
.hb-read {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  font-family: var(--font-mono);
  color: var(--fg);
}
.hb-bpm {
  font-size: 16px;
  font-weight: var(--fw-semibold);
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
  min-width: 2.4ch;
  text-align: right;
}
.hb-unit {
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.hb-ecg { width: 116px; height: 26px; color: var(--orange); }
.hb-track { animation: hb-scroll 2.49s linear infinite; }
.hb-wave {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.hb-state {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}
[data-hb-live] .hb-state { color: var(--green); }
[data-hb-live] .hb-dot { --hb-glow: var(--green); }
[data-hb-live] .hb-ecg { color: var(--green); }

.hb-monitor-body {
  display: flex;
  align-items: center;
  gap: var(--space-32);
  padding: var(--space-24);
}
.hb-monitor-read {
  display: flex;
  align-items: baseline;
  gap: var(--space-12);
  font-family: var(--font-mono);
}
.hb-monitor-read .hb-dot { align-self: center; width: 12px; height: 12px; }
.hb-monitor-bpm {
  font-size: clamp(56px, 9vw, 96px);
  font-weight: var(--fw-semibold);
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--fg);
}
.hb-monitor-unit {
  font-size: var(--text-caption);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.hb-ecg-wide {
  flex: 1;
  min-width: 0;
  width: 100%;
  height: 96px;
  display: block;
  color: var(--orange);
}
.hb-ecg-wide .hb-track { animation-name: hb-scroll-wide; animation-duration: 4.98s; }
@media (max-width: 700px) {
  .hb-monitor-body { flex-direction: column; align-items: flex-start; gap: var(--space-16); }
  .hb-ecg-wide { height: 64px; }
}

@keyframes hb-pulse {
  0% { transform: scale(0.85); box-shadow: 0 0 0 0 color-mix(in srgb, var(--hb-glow) 50%, transparent); }
  12% { transform: scale(1.35); }
  40% { transform: scale(1); box-shadow: 0 0 0 7px color-mix(in srgb, var(--hb-glow) 0%, transparent); }
  100% { transform: scale(0.85); }
}
@keyframes hb-scroll { from { transform: translateX(0); } to { transform: translateX(-120px); } }
@keyframes hb-scroll-wide { from { transform: translateX(0); } to { transform: translateX(-240px); } }
@media (prefers-reduced-motion: reduce) {
  .hb-dot, .hb-track { animation: none; }
}

/* ── Copy buttons + citation blocks (behavior in assets/polish.js) ────── */
.copy-btn {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-2);
  background: transparent;
  border: 1px solid var(--hair);
  border-radius: var(--radius-pill);
  padding: 4px 12px;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.copy-btn:hover { border-color: var(--hair-active); color: var(--fg); }
.copy-btn[data-copied] { color: var(--green); border-color: var(--green); }

.cite-panel .code,
pre.cite-code {
  margin: 0;
  padding: var(--space-16) var(--space-20);
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.55;
  color: var(--fg-2);
  background: transparent;
  overflow-x: auto;
  white-space: pre-wrap;
  word-break: break-word;
}

.quote-rows { list-style: none; margin: 0; padding: 0; }
/* The stat column sizes to its content rather than sitting at a flat 96px.
   "1,065,357" measures 117px at 22px mono, so the fixed track let the number
   run under the claim text beside it. minmax(0, 1fr) keeps the claim column
   able to shrink instead of pushing the row wider. */
.quote-row {
  display: grid;
  grid-template-columns: minmax(96px, max-content) minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-16);
  padding: var(--space-16) var(--space-20);
}
.quote-row + .quote-row { border-top: 1px solid var(--hair-faint); }
.quote-stat {
  font-family: var(--font-mono);
  font-size: 22px;
  font-weight: var(--fw-semibold);
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}
.quote-claim {
  font-size: var(--text-body);
  line-height: var(--leading-body);
  color: var(--fg-2);
}
@media (max-width: 700px) {
  /* On a phone the stat gets its own line rather than a track it overflows. */
  .quote-row { grid-template-columns: minmax(0, 1fr); gap: var(--space-8); }
  .quote-row .copy-btn { grid-column: 1; justify-self: start; }
}
