/* zyrs.css, shared tokens and section primitives for the Zyrs Nasdaq
   Buyback Protocol site. Direction-specific files (dir-a/b/c.css) layer on
   top of this. Fonts: Petrona (display), Public Sans (body/UI), Courier
   Prime (numbers/labels). Caveat and the handwritten-note treatment it
   supported were removed 2026-09-05: nothing on this page is handwritten.
   Loaded from a single Google Fonts link tag in index.html, not from here.
   Ground is pale tinted paper, never pure white; the market panel is the
   one dark surface on the page. */

:root{
  --paper: #F1F5EC;
  --paper-warm: #F1F5EC;
  --ink: #1A2419;
  --ink-soft: #57634F;
  --accent: #297249;
  --accent-soft: #9CAC91;
  --accent-deep: #297249;
  --accent-ink: #297249;
  --line: #D6DECB;
  --card: #F1F5EC;
  --dark: #16241A;
  --dark-ink: #F1F5EC;
  --pale-green: #DDE7D0;
  --radius: 4px;
  --font-display: 'Petrona', Georgia, serif;
  --font-body: 'Public Sans', system-ui, sans-serif;
  --font-mono: 'Courier Prime', 'Courier New', monospace;
  color-scheme: light;

  /* Spacing scale. Every padding, margin and gap in this file and
     dir-a.css resolves to one of these -- no off-scale values. */
  --space-2xs: 4px;
  --space-xs: 8px;
  --space-sm: 12px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 32px;
  --space-2xl: 48px;
  --space-3xl: 64px;
  --space-4xl: 96px;

  /* Type scale. Five steps, each at least 1.25x the one below it.
     Marketing headings (h1/h2) are fluid with clamp(); table and UI
     chrome (labels, legal lines, mono figures, buttons, nav) are fixed
     rem so they don't reflow mid-word at odd viewport widths. */
  --text-2xs: 0.875rem;                       /* 14px -- smallest allowed; nothing on this page goes under 14px */
  --text-base: 1rem;                         /* 16px -- body copy, buttons, nav */
  --text-lg: 1.25rem;                        /* 20px -- stat numbers, hand notes */
  --text-h2: clamp(1.75rem, 3vw, 2.25rem);   /* 28-36px */
  --text-h1: clamp(2.25rem, 5vw, 3.5rem);    /* 36-56px */
}

*{ box-sizing: border-box; }
button, input, select, textarea{ margin: 0; font: inherit; }
html{ -webkit-text-size-adjust: 100%; overflow-x: hidden; }
body{
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.5;
  overflow-x: clip;
  max-width: 100vw;
}
img{ max-width: 100%; display: block; }
a{ color: inherit; }
p{ max-width: 70ch; text-wrap: pretty; }
.container{ max-width: 1180px; margin: 0 auto; padding: 0 var(--space-lg); }
@media (max-width: 480px){ .container{ padding: 0 var(--space-md); } }


h1,h2,h3{ font-weight: 600; margin: 0; line-height: 1.08; text-wrap: balance; }
h1{ font-family: var(--font-display); font-size: var(--text-h1); }
h2,h3{ font-family: var(--font-body); letter-spacing: -0.01em; }
h2{ font-size: var(--text-h2); }
h3{ font-size: var(--text-lg); }
.eyebrow, .data-label, .num-label{
  font-family: var(--font-mono); font-size: var(--text-2xs); letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-soft);
}

/* Single global keyboard-focus rule. Every link, button, input, select
   and focusable element gets this unless a component defines a more
   specific outline-offset for its own geometry (table rows, sortable
   headers) -- nothing in this file sets outline:none without one. */
:focus-visible{ outline: 2px solid var(--accent); outline-offset: 2px; }

/* Utility classes: replace one-off inline styles in index.html so all
   spacing traces back to the token scale above. */
.mt-2xs{ margin-top: var(--space-2xs); }
.mt-xs{ margin-top: var(--space-xs); }
.mt-sm{ margin-top: var(--space-sm); }
.mt-md{ margin-top: var(--space-md); }
.mt-lg{ margin-top: var(--space-lg); }
.mt-xl{ margin-top: var(--space-xl); }
.mb-xs{ margin-bottom: var(--space-xs); }
.gc-full{ grid-column: 1/-1; }
.text-center{ text-align: center; }
.actions-row{ display: flex; flex-wrap: wrap; gap: var(--space-sm); }
.mono-list{ font-family: var(--font-mono); font-size: var(--text-2xs); padding-left: var(--space-md); }
.wordmark{ font-family: var(--font-body); font-weight: 600; font-size: var(--text-lg); letter-spacing: -0.01em; }
.wordmark-sm{ font-size: var(--text-base); }
.cta-row{ display: flex; flex-wrap: wrap; gap: var(--space-sm); margin-top: var(--space-lg); }
.cta-row.is-centered{ justify-content: center; }

.btn{
  display: inline-flex; align-items: center; gap: var(--space-xs);
  font-family: var(--font-body); font-weight: 600; font-size: var(--text-base);
  padding: var(--space-sm) var(--space-lg); border-radius: 4px; border: 1px solid var(--ink);
  cursor: pointer; text-decoration: none; background: transparent; color: var(--ink);
  transition: transform .15s ease, background-color .15s ease;
}
.btn:hover{ transform: translateY(-1px); }
.btn:active{ transform: translateY(0); }
.btn-filled{ background: var(--accent); border-color: var(--accent); color: #F1F5EC; }
.btn-filled:hover{ background: var(--accent-deep); }
/* A pre-launch CTA is WAITING, not broken. At 45% opacity the filled button
   read as a rendering fault: washed out white text on a washed out green.
   It now becomes an outlined button in full-strength ink, which is a
   deliberate state a reader can parse, and it says what it is waiting for
   via the ::after label rather than looking disabled for no reason. */
.btn[disabled], .btn.is-disabled{
  opacity: 1;
  background: transparent;
  border-color: var(--line);
  color: var(--ink-soft);
  cursor: default;
  pointer-events: none;
}
.btn-filled.is-disabled::after{ content: none; }

/* Observer activation is opt-in; absent JS leaves every element visible. */
.reveal{ transition: opacity 480ms cubic-bezier(.2,.7,.2,1), transform 480ms cubic-bezier(.2,.7,.2,1); transition-delay: var(--reveal-delay, 0ms); }
.reveal.reveal-pending{ opacity: 0; transform: translateY(12px); }
.reveal.in{ opacity: 1; }
.reveal:focus-within{ opacity: 1; transform: none; transition: none; }

/* Contract-address pill, Ramen convention: data-ca on the chip, set by set-ca.mjs */
.ca-pill{
  display: inline-flex; align-items: center; gap: var(--space-xs);
  font-family: var(--font-mono); font-size: var(--text-2xs);
  padding: var(--space-xs) var(--space-md); border-radius: 4px; border: 1px dashed var(--line);
  background: var(--card); color: var(--ink-soft);
}
.ca-pill[data-ca=""] .ca-pill-label::after{ content: "pending"; }
.ca-pill[data-ca]:not([data-ca=""]) .ca-pill-label::after{ content: attr(data-ca); }
.ca-pill button{
  font-family: var(--font-mono); font-size: var(--text-2xs); border: 1px solid var(--line);
  background: transparent; border-radius: 4px; padding: var(--space-2xs) var(--space-xs); cursor: pointer;
  transition: background-color .15s ease, transform .1s ease;
}
.ca-pill button:hover{ background: var(--pale-green); }
.ca-pill button:active{ transform: scale(.96); }
.ca-pill[data-ca=""] button{ display: none; }
.ca-pill[data-ca]:not([data-ca=""]) button:empty::after{ content: "copy"; }

/* Stat row */
.stat-row{ display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-lg); font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.stat-row b{ color: var(--ink); font-weight: 600; }
.stat-row .ca-pill{ margin: 0; }

/* Tape under the nav. 21st.dev id 19171 Ticker: symbol, price, signed
   change with a triangle. Scrolls by translateX on a duplicated list. */
.marquee{ overflow: hidden; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); background: var(--card); }
.marquee-track{ display: flex; white-space: nowrap; width: max-content; animation: marquee 32s linear infinite; padding: var(--space-sm) 0; }
.marquee:hover .marquee-track{ animation-play-state: paused; }
.ticker{
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  padding: 0 var(--space-md); border: 0; border-right: 1px solid var(--line);
  background: transparent; color: inherit; font: inherit; cursor: pointer;
  font-family: var(--font-mono); font-size: var(--text-2xs); font-variant-numeric: tabular-nums;
}
.ticker-sym{ color: var(--accent); font-weight: 700; }
.ticker-price{ color: var(--ink-soft); }
.ticker-chg{ display: inline-flex; align-items: center; gap: 2px; font-weight: 700; }
.ticker-chg.is-up{ color: var(--accent); }
.ticker-chg.is-down{ color: var(--ink-soft); }
.ticker-chg svg{ width: 12px; height: 12px; flex: none; }
.ticker-chg .rot-180{ transform: rotate(180deg); }
@keyframes marquee{ from{ transform: translateX(0); } to{ transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce){
  .marquee-track{ animation-play-state: paused; }
}

/* Thin scroll-position line, fixed to the very top of the viewport. Reads
   the actual scroll fraction (see initScrollLoop) via a scaleX transform,
   never width, so it stays transform-only. */
.scroll-progress{
  position: fixed; top: 0; left: 0; width: 100%; height: 2px;
  background: var(--accent); transform: scaleX(0); transform-origin: left center;
  z-index: 40; pointer-events: none;
}

/* Chain facts. The dark treatment moved to the market panel (#market is
   now the one dark surface on the page), so this card turns light like
   every other card on the page. */
.chain-facts{
  background: var(--card); color: var(--ink); border-radius: var(--radius);
  padding: var(--space-xl); display: grid; gap: var(--space-lg);
  font-family: var(--font-mono); font-size: var(--text-2xs); font-variant-numeric: tabular-nums;
}
.chain-facts-dl{
  display: grid; gap: var(--space-md); grid-template-columns: repeat(auto-fit,minmax(160px,1fr));
  margin: 0;
}
.chain-facts dt{ color: var(--ink-soft); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: .08em; }
.chain-facts dd{ margin: var(--space-2xs) 0 0; font-size: var(--text-lg); }
.chain-scale{ border-top: 1px solid var(--line); padding-top: var(--space-lg); }
.chain-scale .eyebrow{ margin-bottom: var(--space-md); }
.chain-scale-dl{
  display: grid; gap: var(--space-md); grid-template-columns: repeat(auto-fit,minmax(180px,1fr));
  margin: 0;
}
.chain-scale-dl dd{ font-size: var(--text-lg); font-family: var(--font-mono); max-width: none; }

/* Queue table. Font size held at the smallest step for the same Courier
   Prime width reason as the marquee above. */
table.queue{ width: 100%; border-collapse: collapse; font-family: var(--font-mono); font-size: var(--text-2xs); font-variant-numeric: tabular-nums; }
table.queue th, table.queue td{ padding: 0 var(--space-xs); text-align: left; border-bottom: 1px solid var(--line); height: 44px; vertical-align: middle; }
table.queue th{
  font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: .08em; color: var(--ink-soft);
  position: sticky; top: 0; background: var(--paper); z-index: 1;
}
.table-scroll{ overflow: auto; max-height: 70vh; }
table.queue tbody tr{ height: 44px; }
.col-chg{ font-weight: 700; font-family: var(--font-mono); }
.col-num{ text-align: right; font-variant-numeric: tabular-nums; }

/* First-render entrance is owned by ZyrsMotion; refreshes preserve final rows. */
table.queue tbody tr{ transition: background-color .15s ease; }
table.queue tbody tr[data-symbol]{ cursor: pointer; }
table.queue tbody tr[data-symbol]:hover{ background: var(--card); }
table.queue tbody tr[data-symbol]:active{ background: var(--pale-green); }
table.queue tbody tr[data-symbol]:focus-visible{ outline: 2px solid var(--accent); outline-offset: 2px; }
/* Selected row: background tint only. No side rail. */
table.queue tbody tr.is-selected{ background: rgba(41,114,73,.06); }
.col-trend{ width: 80px; vertical-align: middle; }
.spark{ display: block; width: 80px; height: 30px; }
.spark-empty{ color: var(--ink-soft); font-size: var(--text-2xs); }
table.queue .queue-empty-row td{ font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--ink-soft); padding: var(--space-lg) var(--space-xs); }
@media (max-width: 480px){
  /* Touch targets: rows need to clear 44px at 390 -- padding alone
     (12px font + 16px top/bottom) gets there without changing the
     visual density on desktop. The matching .sort-btn override lives
     after its own base rule further down, so source order doesn't let
     the base rule win it back. */
  table.queue td, table.queue th{ padding: var(--space-md) var(--space-xs); }
}

/* FAQ. Native <details>/<summary> throughout so keyboard behaviour (Enter,
   Space, focus) is entirely the browser's -- JS only layers a height
   transition and cancels nothing about the native toggle if JS never runs. */
details.faq-item{ border-bottom: 1px solid var(--line); padding: var(--space-md) 0; }
details.faq-item summary{
  cursor: pointer; font-family: var(--font-body); font-weight: 600; list-style: none;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-md);
}
details.faq-item summary::-webkit-details-marker{ display:none; }
details.faq-item summary:hover .faq-q{ color: var(--accent-ink); }
details.faq-item .faq-icon{ position: relative; width: 14px; height: 14px; flex: none; }
details.faq-item .faq-icon::before,
details.faq-item .faq-icon::after{
  content: ''; position: absolute; top: 50%; left: 50%; background: var(--ink);
  width: 14px; height: 2px; transform: translate(-50%,-50%);
}
details.faq-item .faq-icon::after{
  width: 2px; height: 14px; transform: translate(-50%,-50%) rotate(0deg);
  transition: transform .25s ease;
}
details.faq-item[open] .faq-icon::after{ transform: translate(-50%,-50%) rotate(90deg); }
@media (prefers-reduced-motion: reduce){
  details.faq-item .faq-icon::after{ transition: none; }
}
details.faq-item .faq-body{ overflow: hidden; }
details.faq-item .faq-body p{ margin: var(--space-md) 0 0; color: var(--ink-soft); }

/* Section rhythm: generous between major sections, per the hierarchy
   principle that grouping inside a card stays tight and separation
   between sections stays wide. */
section{ padding: var(--space-3xl) 0; }
@media (max-width: 768px){ section{ padding: var(--space-2xl) 0; } }

.legal-line{ font-family: var(--font-body); font-size: var(--text-2xs); color: var(--ink-soft); }
.market-section .legal-line{ color: rgba(241,245,236,.85); }

footer.site-footer{ padding: var(--space-xl) 0; border-top: 1px solid var(--line); font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--ink-soft); }
footer.site-footer .foot-row{ display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-sm); }

/* Mobile drawer + burger, shared across all three directions. Off-canvas
   and hidden above 768px no matter what; only the burger under 768px
   opens it. */
.drawer-toggle{
  display: none; background: none; border: 1px solid var(--line); border-radius: 4px;
  padding: var(--space-xs) var(--space-sm); font-family: var(--font-mono); font-size: var(--text-2xs);
  cursor: pointer; min-height: 44px; align-items: center;
}
[data-drawer]{ display: none; }
/* Budget toggle + Buy CTA live in the nav bar on desktop only; under
   768px they move into the drawer instead, so the bar never has to fit
   three chips + a filled button + the burger in ~340px. */
.nav-desktop-only{ display: contents; }
@media (max-width: 900px){ .nav-desktop-only{ display: none; } }
.drawer-budget{ display: none; }
@media (max-width: 768px){
  .drawer-toggle{ display: inline-flex; }
  /* Docked flush against the viewport's right edge at all times (never
     translated further right to hide it) so its box, and everything
     inside it, always sits within the 0-390 viewport bounds -- closed
     state is a fade+pointer-lock, not an off-canvas slide, which avoids
     the horizontal-overflow bug some engines produce for translateX(100%)
     off-canvas panels. */
  [data-drawer]{
    display: block; position: fixed; inset: 0 0 0 auto; width: 78%; max-width: 320px;
    background: var(--paper); opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity .2s ease, visibility 0s .2s;
    z-index: 30; padding: var(--space-lg); border-left: 1px solid var(--line); overflow-y: auto;
  }
  [data-drawer].is-open{ opacity: 1; visibility: visible; pointer-events: auto; transition: opacity .2s ease, visibility 0s; }
  [data-drawer] a{ display: block; padding: var(--space-sm) 0; font-family: var(--font-mono); }
  .nav-desktop-only{ display: none; }
  .drawer-budget{ display: flex; gap: var(--space-xs); margin: var(--space-sm) 0; }
  .drawer-budget-slider{ display: flex; margin: var(--space-2xs) 0 var(--space-sm); }
}

/* Budget slider: sage track, deep green thumb, mono readout. Filled portion
   is a hard two-stop background (no smoothing/blend) driven by --pct (set
   in JS), so it reads as two flat colour segments, not a gradient fill. */
.budget-slider-wrap{ display: flex; align-items: center; gap: var(--space-xs); }
.budget-slider-wrap input[type="range"]{
  -webkit-appearance: none; appearance: none; width: 120px; height: 24px;
  background: transparent; cursor: pointer; margin: 0;
}
.budget-slider-wrap input[type="range"]::-webkit-slider-runnable-track{
  height: 4px; border-radius: 4px;
  background: linear-gradient(to right, var(--accent) 0%, var(--accent) var(--pct,20%), var(--accent-soft) var(--pct,20%), var(--accent-soft) 100%);
}
.budget-slider-wrap input[type="range"]::-moz-range-track{ height: 4px; border-radius: 4px; background: var(--accent-soft); }
.budget-slider-wrap input[type="range"]::-moz-range-progress{ height: 4px; border-radius: 4px; background: var(--accent); }
.budget-slider-wrap input[type="range"]::-webkit-slider-thumb{
  -webkit-appearance: none; appearance: none; width: 16px; height: 16px; border-radius: 4px;
  background: var(--accent-deep); border: 2px solid var(--paper); box-shadow: 0 0 0 1px var(--accent-deep);
  margin-top: -6px; cursor: pointer; transition: transform .15s ease;
}
.budget-slider-wrap input[type="range"]::-moz-range-thumb{
  width: 16px; height: 16px; border-radius: 4px; background: var(--accent-deep);
  border: 2px solid var(--paper); box-shadow: 0 0 0 1px var(--accent-deep); cursor: pointer;
}
.budget-slider-wrap input[type="range"]:hover::-webkit-slider-thumb,
.budget-slider-wrap input[type="range"]:focus-visible::-webkit-slider-thumb,
.budget-slider-wrap input[type="range"]:active::-webkit-slider-thumb{ transform: scale(1.15); }
.budget-slider-wrap input[type="range"]:focus-visible{ outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce){
  .budget-slider-wrap input[type="range"]::-webkit-slider-thumb{ transition: none; }
}
.budget-readout{ font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--ink); min-width: 64px; }
.drawer-budget-slider{ display: none; }
@media (max-width: 480px){
  .budget-slider-wrap input[type="range"]{ width: 140px; height: 44px; }
  .budget-slider-wrap input[type="range"]::-webkit-slider-thumb{ width: 22px; height: 22px; margin-top: -9px; }
  .budget-slider-wrap input[type="range"]::-moz-range-thumb{ width: 22px; height: 22px; }
}

/* Queue filters */
.queue-filters{
  display: flex; flex-wrap: wrap; align-items: end; gap: var(--space-sm) var(--space-lg);
  margin-top: var(--space-md); padding: var(--space-md); background: var(--card); border-radius: var(--radius);
}
.qf-field{ display: flex; flex-direction: column; gap: var(--space-2xs); flex: 1 1 160px; min-width: 140px; }
.qf-label{ font-family: var(--font-mono); font-size: var(--text-2xs); text-transform: uppercase; letter-spacing: .08em; color: var(--ink-soft); }
.qf-field input[type="text"], .qf-field select{
  font-family: var(--font-mono); font-size: var(--text-2xs); min-height: 44px; padding: 0 var(--space-sm);
  border: 1px solid var(--line); border-radius: 4px; background: var(--paper); color: var(--ink);
  transition: border-color .15s ease;
}
.qf-field input[type="text"]:hover, .qf-field select:hover{ border-color: var(--ink-soft); }
.qf-field input[type="text"]:focus-visible, .qf-field select:focus-visible{ outline: 2px solid var(--accent); outline-offset: 2px; }
.qf-toggle{ display: inline-flex; align-items: center; gap: var(--space-xs); min-height: 44px; font-family: var(--font-mono); font-size: var(--text-2xs); cursor: pointer; }
.qf-toggle:hover{ color: var(--accent-ink); }
.qf-toggle input{ width: 20px; height: 20px; accent-color: var(--accent); cursor: pointer; }
.qf-count{ margin-left: auto; align-self: center; }

/* Sortable queue headers */
table.queue th[data-sort-key]{ padding: 0; }
.sort-btn{
  display: inline-flex; align-items: center; gap: var(--space-2xs); width: 100%;
  font: inherit; text-transform: inherit; letter-spacing: inherit; color: inherit;
  background: none; border: none; cursor: pointer; padding: var(--space-sm) var(--space-xs); text-align: left;
  transition: color .15s ease;
}
.sort-btn:hover{ color: var(--accent); }
.sort-btn:active{ color: var(--accent-deep); }
.sort-btn:focus-visible{ outline: 2px solid var(--accent); outline-offset: 2px; }
.sort-arrow{ font-family: var(--font-mono); }
@media (max-width: 480px){
  .sort-btn{ padding: var(--space-md) var(--space-xs); }
}

/* Now buying action row */
.now-buying-actions .btn{ font-size: var(--text-2xs); padding: var(--space-sm) var(--space-md); min-height: 44px; }

/* Extra mobile touch-target pass: the smallest chip-style controls (budget
   toggle, drawer burger, CA copy button) sit under 44px on their own
   padding alone at this width. */
@media (max-width: 480px){
  .budget-toggle button,
  .ca-pill button{
    min-height: 44px; display: inline-flex; align-items: center; justify-content: center;
  }
}


/* ---- Candlestick chart (js/zyrs-chart.js) ----------------------------
   The market picture the page was missing. Every candle is a real trading
   day fetched from /api/candles; when the series is unavailable nothing is
   drawn and the mount says why, because an invented candle would break the
   only promise this site makes. Lives inside the dark market panel, so it
   sits directly on --dark with no card of its own -- a card here would be
   a card inside a card. */
.chart-block{ margin-top: var(--space-lg); }
.snapshot-line{ color: var(--paper); font: .875rem var(--font-mono); overflow-wrap: anywhere; }
.chart-note{ color: rgba(241,245,236,.85); font-size: var(--text-2xs); margin-top: var(--space-2xs); max-width: 62ch; }
.candle-mount{ margin-top: var(--space-md); min-height: 180px; }
.candles{ display: block; width: 100%; height: auto; }
.chart-facts{
  display: flex; flex-wrap: wrap; gap: var(--space-md); align-items: baseline;
  margin-top: var(--space-sm); font-family: var(--font-mono); font-size: var(--text-2xs); color: rgba(241,245,236,.85);
  font-variant-numeric: tabular-nums;
}
.chart-facts b{ color: var(--dark-ink); }
.chart-facts .is-up{ color: var(--accent-soft); }
.chart-facts .is-down{ color: rgba(241,245,236,.8); }
.chart-facts a{ color: var(--accent-soft); }
.chart-tf{ display: flex; flex-wrap: wrap; gap: 2px; margin-bottom: var(--space-sm); }
.chart-tf button{
  font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: 700;
  padding: var(--space-xs) var(--space-sm); min-height: 44px;
  border: 1px solid rgba(241,245,236,.18); background: transparent; color: rgba(241,245,236,.85);
  border-radius: 4px; cursor: pointer;
}
.chart-tf button[aria-pressed="true"]{ color: var(--dark-ink); border-color: var(--accent-soft); }
.chart-wrap{ position: relative; }
.chart-tip{
  position: absolute; top: 4px; z-index: 2; min-width: 148px; pointer-events: none;
  background: var(--dark); color: var(--dark-ink); border: 1px solid rgba(241,245,236,.18);
  border-radius: 4px; padding: var(--space-sm) var(--space-md); font-family: var(--font-mono);
  font-size: var(--text-2xs); font-variant-numeric: tabular-nums;
}
.chart-tip-stamp{ color: rgba(241,245,236,.85); margin-bottom: var(--space-xs); }
.chart-tip-row{ display: flex; justify-content: space-between; gap: var(--space-md); }
.chart-tip .is-up{ color: var(--accent-soft); }
.chart-tip .is-down{ color: rgba(241,245,236,.8); }
.chart-dates{
  display: flex; justify-content: space-between; gap: var(--space-xs);
  padding-right: 120px; margin-top: var(--space-xs);
  font-family: var(--font-mono); font-size: var(--text-2xs); color: rgba(241,245,236,.85);
  font-variant-numeric: tabular-nums;
}
.candles{ touch-action: none; }
@media (max-width: 640px){
  .chart-block{ padding: 0; }
  .candle-mount{ overflow-x: auto; }
  .candles{ min-width: 520px; }
}


/* ---- Drawer, rebuilt --------------------------------------------------
   Scrim, header with a real close control, and a footer group. The old
   drawer had no way out of it at all on a phone. */
.drawer-scrim{
  position: fixed; inset: 0; z-index: 25;
  background: rgba(26, 36, 25, .38);
  animation: scrimIn .2s ease both;
}
@keyframes scrimIn{ from{ opacity: 0 } to{ opacity: 1 } }
.drawer-head{
  display: flex; align-items: center; justify-content: space-between;
  padding-bottom: var(--space-md); margin-bottom: var(--space-xs);
  border-bottom: 1px solid var(--line);
}
.drawer-close{
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 44px; min-height: 44px; padding: 0 var(--space-sm);
  font-family: var(--font-mono); font-size: var(--text-2xs);
  background: transparent; border: 1px solid var(--line); border-radius: 4px;
  color: var(--ink); cursor: pointer;
}
.drawer-close:hover{ background: var(--pale-green); }
.drawer-foot{
  margin-top: var(--space-md); padding-top: var(--space-md);
  border-top: 1px solid var(--line);
  display: flex; flex-direction: column; gap: var(--space-sm);
}
/* The drawer CTA was inheriting a zero horizontal padding rule meant for
   plain drawer links, so a 999px pill rendered with no side padding. */
[data-drawer] .btn{
  justify-content: center; padding: var(--space-sm) var(--space-lg); width: 100%;
}
@media (prefers-reduced-motion: reduce){ .drawer-scrim{ animation: none } }

/* ---- Queue on a phone -------------------------------------------------
   The grid child's automatic min-width let the table's min-content width
   (413px) blow the 1fr track past the 358px container, so the whole section
   including the SEC provenance line was clipped with no way to scroll to it. */
.queue-layout > *{ min-width: 0; }
@media (max-width: 640px){
  table.queue{ min-width: 600px; }
  .table-scroll{ overflow-x: auto; -webkit-overflow-scrolling: touch; }
}


/* ---- Market panel, the one dark surface on the page ---------------------
   Quote header (exchange badge, ticker, name, last, signed change, range,
   volume, session) then the chart. Every value comes from /api/candles.
   Every colour below is chosen and checked against --dark (#16241A):
   --dark-ink solid ~13.4:1, --dark-ink at .7 opacity ~7.2:1, --accent-soft
   solid ~6.7:1, --paper at .8 opacity ~9.8:1. All clear 4.5:1. */
.market-section{ position: relative; background: var(--dark); color: var(--dark-ink); padding: var(--space-2xl) 0; overflow: hidden; }
.market-section > canvas[data-shader]{
  position: absolute; inset: 0; width: 100%; height: 100%; display: block; pointer-events: none; z-index: 0;
}
.market-section > .container{ position: relative; z-index: 1; }
.market-section .eyebrow, .market-section .data-label{ color: rgba(241,245,236,.85); }
.market-section .sec-title{ color: var(--dark-ink); }
.quote-head{
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: var(--space-md) var(--space-lg); padding-bottom: var(--space-md); border-bottom: 1px solid rgba(241,245,236,.18);
}
.quote-ident{ display: flex; align-items: baseline; gap: var(--space-sm); flex-wrap: wrap; }
.exchange-badge{
  font-family: var(--font-mono); font-size: var(--text-2xs); letter-spacing: .08em;
  padding: 2px var(--space-xs); border: 1px solid var(--dark-ink); border-radius: 3px; color: var(--dark-ink);
}
.quote-symbol{ font-family: var(--font-mono); font-size: var(--text-h2); font-weight: 700; line-height: 1; color: var(--dark-ink); }
.quote-name{ color: rgba(241,245,236,.85); font-size: var(--text-base); }
.quote-figures{ display: flex; align-items: baseline; gap: var(--space-md); flex-wrap: wrap; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.quote-last b{ font-size: var(--text-h2); font-weight: 700; color: var(--dark-ink); font-family: var(--font-mono); }
.quote-change{ font-size: var(--text-h2); font-weight: 700; padding: 2px var(--space-xs); border-radius: 4px; display: inline-flex; align-items: center; gap: 4px; }
.quote-change.is-up{ color: var(--accent-soft); background: rgba(241,245,236,.06); }
.quote-change.is-down{ color: rgba(241,245,236,.8); background: rgba(241,245,236,.08); }
.quote-change svg{ width: 12px; height: 12px; flex: none; }
.quote-change .rot-180{ transform: rotate(180deg); }
.quote-ohlc .data-label{ color: rgba(241,245,236,.7); }
.quote-meta{ font-size: var(--text-2xs); color: rgba(241,245,236,.85); }
.quote-ohlc{
  flex: 1 0 100%; width: 100%; display: flex; flex-wrap: wrap; gap: var(--space-sm) var(--space-lg);
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
}
.quote-ohlc b{ color: var(--dark-ink); font-weight: 700; font-size: var(--text-base); }
@media (max-width: 640px){ .quote-symbol{ font-size: var(--text-lg); } .quote-last b, .quote-change{ font-size: var(--text-lg); } }

/* A separate inset wash also works over inline heatmap backgrounds. */
.flash{ animation: quoteFlash 600ms ease-out; }
@keyframes quoteFlash{
  from{ box-shadow: inset 0 0 0 100vmax rgba(156,172,145,.25); }
  to{ box-shadow: inset 0 0 0 100vmax rgba(156,172,145,0); }
}

/* Sticky 40px market summary bar above the nav. */
.mkt-bar{
  position: sticky; top: 0; z-index: 22; height: 40px;
  background: var(--paper); color: var(--ink); border-bottom: 1px solid transparent;
  box-shadow: 0 0 0 rgba(156,172,145,.12); transition: box-shadow 120ms ease, border-color 120ms ease;
  font-family: var(--font-mono); font-size: var(--text-2xs); font-variant-numeric: tabular-nums;
}
.mkt-bar-inner{
  max-width: 1180px; margin: 0 auto; padding: 0 var(--space-lg); height: 40px;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: var(--space-sm);
}
.mkt-bar-status{ display: inline-flex; align-items: center; gap: var(--space-xs); }
.mkt-pulse{
  width: 8px; height: 8px; border-radius: 4px; background: var(--ink-soft); flex: none;
}
.mkt-pulse.is-on{ background: var(--accent); animation: mktpulse 3s ease-in-out infinite; }
@keyframes mktpulse{ 0%, 100%{ transform: scale(1); } 50%{ transform: scale(1.3); } }
@media (prefers-reduced-motion: reduce){
  .mkt-pulse.is-on{ animation: none; }
}
.mkt-bar-quote{ justify-self: center; display: inline-flex; align-items: center; }
.mkt-bar-quote .ticker{ border-right: 0; padding: 0; }
.mkt-bar-quote .ticker-chg{ font-size: var(--text-base); }
.mkt-bar-ago{ justify-self: end; color: var(--ink); }
.market-section [data-updated-ago]{ color: var(--paper); }
@media (max-width: 390px){
  .mkt-bar-ago{ display: none; }
  .mkt-bar-inner{ grid-template-columns: auto 1fr; }
}

/* Heatmap tiles inside the dark panel. */
.heatmap-block{ margin-top: var(--space-lg); }
.heatmap{
  position: relative; width: 100%; aspect-ratio: 16 / 7;
  background: var(--dark);
}
.heatmap-tile{
  position: absolute; overflow: hidden; margin: 0; border: 0; cursor: pointer;
  padding: 4px 6px; text-align: left; display: flex; flex-direction: column; justify-content: space-between;
  font-family: var(--font-mono); color: inherit; min-width: 0;
}
.heatmap-tile .hm-sym{ font-weight: 700; font-size: var(--text-2xs); line-height: 1.2; }
.heatmap-tile .hm-chg{ font-weight: 400; font-size: var(--text-2xs); line-height: 1.2; }
.heatmap-tile:hover{ outline: 1px solid rgba(241,245,236,0.7); outline-offset: -1px; }
.heatmap-tile[aria-pressed="true"]{ outline: 1px solid rgba(241,245,236,0.9); outline-offset: -1px; }
.heatmap-tile-more{ justify-content: center; }
.hm-empty{ color: rgba(241,245,236,.85); font-family: var(--font-mono); font-size: var(--text-2xs); padding: var(--space-md); }
@media (prefers-reduced-motion: reduce){
  .heatmap-tile{ transition: none; }
}

.sec-title{
  display: flex; align-items: baseline; gap: var(--space-sm); flex-wrap: wrap;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  margin-bottom: var(--space-sm);
}
.sec-title .num, .sec-title [data-field]{ font-weight: 700; font-size: var(--text-lg); }
.hair{
  display: grid; grid-template-columns: repeat(12, 1fr); gap: 1px; background: var(--paper);
}
.hair > *{ background: var(--pale-green); padding: var(--space-sm); min-width: 0; }
section{ border-top: 1px solid var(--line); }

/* Pass 4: one mark, one numeric rhythm, one interaction timing. */
::selection{ background: var(--pale-green); color: var(--ink); }
.brand-symbols{ position: absolute; width: 0; height: 0; overflow: hidden; }
.section-mark{ color: var(--ink-soft); flex: 0 0 12px; align-self: center; }
.empty-ring{ color: currentColor; opacity: .25; display: inline-block; vertical-align: middle; margin-right: 8px; flex: none; }
.spark-empty{ display: inline-flex; align-items: center; }
.spark-empty .empty-ring{ width: 16px; height: 16px; margin-right: 4px; }
.chart-empty{ display: flex; align-items: center; justify-content: center; min-height: 180px; }
.quote-loading{ color: var(--accent-soft); align-self: center; animation: quoteLoading 1.2s linear infinite; }
.quote-loading[hidden]{ display: none; }
@keyframes quoteLoading{ to{ transform: rotate(360deg); } }
.candle-series{ transform-box: fill-box; }
.mkt-bar.is-scrolled{ border-bottom-color: var(--line); box-shadow: 0 0 6px rgba(156,172,145,.12); }
.table-scroll{ scrollbar-color: var(--accent-soft) var(--paper); padding: 4px; }
table.queue .col-num, table.queue .col-rank{ text-align: right; }
table.queue th{ font-weight: 700; }
.num, output, [data-roll], [data-field], [data-q], [data-universe], [data-filter-count],
[data-budget-reach], .sec-title, .hm-sym, .hm-chg, .how-strip-n, .mono-list, .side-panel dd,
.chain-facts dd, .candles text{ font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.data-label, .num-label, .qf-label, .qf-toggle, .exchange-badge, .chart-tip-row > span:first-child,
.chart-tip-stamp, .chart-dates, .chart-tf button, .mkt-bar, .hm-sym, .hm-chg{
  text-transform: uppercase; letter-spacing: .08em;
}
.num, .num-label, .data-label, .quote-meta, .chain-facts dd, .side-panel .kv{ line-height: 24px; }
.stat-row b, .quote-meta b{ font-weight: 700; }
.faq-q{ letter-spacing: -0.01em; }
.quote-symbol, .ticker-sym{ letter-spacing: .08em; }
.chart-tip-row, .chart-tip-stamp, .chart-dates{ line-height: 24px; }
button, .btn, .heatmap-tile, table.queue tbody tr, .nav-links a, .nav-ghost{
  transition: color 120ms ease, background-color 120ms ease, border-color 120ms ease, outline-color 120ms ease;
}
.heatmap-tile:focus-visible, table.queue tbody tr[data-symbol]:focus-visible,
.sort-btn:focus-visible, .qf-field input:focus-visible, .qf-field select:focus-visible{
  outline: 2px solid var(--accent); outline-offset: 2px; position: relative; z-index: 3;
}
.heatmap-tile:focus-visible{ position: absolute; }
.btn:hover, .btn:active, .ca-pill button:active{ transform: none; }
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{ animation: none !important; transition: none !important; scroll-behavior: auto !important; }
  .reveal.reveal-pending{ opacity: 1; transform: none; }
  .flash{ animation: none; }
}

/* Proof link in the facts row (dev lock record). Inherits ink by default, so give it accent plus an underline to read as clickable evidence. */
.fact-proof{ color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }

/* Launch proof, directly under the hero buttons. The contract address and the
   dev lock are the two things a visitor checks first, so they carry ink on
   pale green inside a solid accent frame with a slow glow, at full address
   length. The muted dashed chip treatment was unreadable at a glance. */
.hero-proof{ display: flex; flex-direction: column; gap: var(--space-sm); margin-top: var(--space-md); max-width: 620px; }
.hero-proof .ca-pill{
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-md);
  font-family: var(--font-mono); font-size: var(--text-base); font-weight: 700;
  color: var(--ink); background: var(--pale-green);
  border: 2px solid var(--accent); border-radius: 4px;
  padding: var(--space-sm) var(--space-md);
  animation: proof-glow 3.2s ease-in-out infinite;
}
.hero-proof .ca-pill-label{ min-width: 0; word-break: break-all; overflow-wrap: anywhere; letter-spacing: .01em; }
.hero-proof .ca-pill button{
  flex: none; display: inline-block; font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: 700;
  color: var(--card); background: var(--accent); border: 1px solid var(--accent);
  border-radius: 4px; padding: var(--space-2xs) var(--space-sm); cursor: pointer;
  transition: background-color .12s ease;
}
.hero-proof .ca-pill button:hover{ background: var(--ink); border-color: var(--ink); }
.hero-proof .lock-chip{
  display: inline-flex; align-items: center; gap: var(--space-xs); align-self: flex-start;
  font-family: var(--font-mono); font-size: var(--text-base); color: var(--ink);
  background: var(--pale-green); border: 2px solid var(--accent); border-radius: 4px;
  padding: var(--space-xs) var(--space-md);
  box-shadow: 0 0 0 1px rgba(41, 114, 73, .20), 0 0 18px rgba(41, 114, 73, .26);
}
.hero-proof .lock-chip .data-label{ color: var(--ink-soft); }
.hero-proof .lock-chip b{ font-weight: 700; }
.hero-proof .fact-proof{ color: var(--accent); text-decoration: underline; text-underline-offset: 2px; font-weight: 700; }
@keyframes proof-glow{
  0%, 100%{ box-shadow: 0 0 0 1px rgba(41, 114, 73, .18), 0 0 16px rgba(41, 114, 73, .20); }
  50%{ box-shadow: 0 0 0 1px rgba(41, 114, 73, .32), 0 0 30px rgba(41, 114, 73, .38); }
}
@media (prefers-reduced-motion: reduce){ .hero-proof .ca-pill{ animation: none; box-shadow: 0 0 0 1px rgba(41, 114, 73, .28); } }
@media (max-width: 767px){
  .hero-proof .ca-pill{ flex-direction: column; align-items: stretch; gap: var(--space-xs); }
  .hero-proof .ca-pill button{ align-self: flex-start; }
}
