/* AG Cluster Live app styles — layered on tokens.css (unmodified copy, see its own header
   comment). Series-neon + ambient-glow additions live HERE, not in tokens.css, so the tokens
   file stays a clean diff against its upstream (ART-DIRECTION-2026-08-03.md rules 1-9, refined by
   rule 10, the DATA-FIRST FORM RULE, which outranks the others — see components.mjs for the
   per-card rule-10 reasoning). */

/* ── series-neon tokens (data/meaning colors, distinct from tokens.css's semantic set) ───────
   tokens.css already owns --ok/--wait/--bad/--ink-faint for HONESTY states (landed/attention/
   failure/absent) — those are reused as-is for the ladder's skip/unavailable/gap rendering.
   These --series-* vars are for METRIC IDENTITY only (which stat a color belongs to), per rule 3
   ("neon = data + meaning only") and rule 4 ("number may carry its series' neon"). */
:root {
  --series-slot: #22e5ff;   /* cyan — current slot */
  --series-rate: #b6ff4d;   /* lime — slots/sec */
  --series-tx: #ff4fd8;     /* magenta — tx throughput */
  /* Ladder lane identity colors — deliberately a DIFFERENT triad from --series-* above, even
     though "Txs" and "Fees" are conceptually close to the tx-throughput/fee summary cards: the
     ladder lanes are a distinct visual context (three stacked wells, not summary tiles), and
     reusing the exact same hues would associate one color with two different meanings. */
  --lane-cu: #ffa94d;   /* amber-orange — compute units */
  --lane-tx: #4dd8ff;   /* sky blue — transactions */
  --lane-fee: #c77dff;  /* violet — fees */
  --pewter: #aab2c0;
  --pewter-dim: #6d7484;
  /* Single inner-padding token every card uses (operator, phone review 2026-08-03: the ladder
     and row-list cards sat flush to their rounded corners while the summary cards didn't — both
     must use the SAME value, applied once here, not re-declared per card type). */
  --card-pad: 1.1rem 1.25rem;
}
:root[data-theme="light"] {
  --series-slot: #0891b2;
  --series-rate: #4d8f16;
  --series-tx: #b3179e;
  --lane-cu: #b5660a;
  --lane-tx: #0284c7;
  --lane-fee: #8b2fd1;
  --pewter: #4b5162;
  --pewter-dim: #6d7484;
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --series-slot: #0891b2;
    --series-rate: #4d8f16;
    --series-tx: #b3179e;
    --lane-cu: #b5660a;
    --lane-tx: #0284c7;
    --lane-fee: #8b2fd1;
    --pewter: #4b5162;
    --pewter-dim: #6d7484;
  }
}

* { box-sizing: border-box; }
body { margin: 0; }

/* Shared quiet-text utility (same semantics as the Drill Deck's own .muted/.faint) — used
 * throughout components.mjs (basis lines, legend, footer, lane-max labels) for "big hero
 * numbers, small quiet labels" (design language §3). Found missing during the 2026-08-03 polish
 * pass: it was used in 12+ places but never actually defined, so every "quiet label" was
 * rendering at full --ink color/size instead of de-emphasized — fixed here, not just for the
 * lane-max labels this pass was checking. */
.muted { color: var(--ink-dim); font-size: 0.85rem; }
.faint { color: var(--ink-faint); font-size: 0.78rem; }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--canvas-2);
  color: var(--ink);
  padding: 0.5rem 1rem;
  z-index: 100;
}
.skip-link:focus { left: 0.5rem; top: 0.5rem; }

.shell { min-height: 100vh; }

/* ── topbar (no sidenav — this is a single-page live app, not a multi-route site) ───────────── */

.topbar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1.25rem;
  border-radius: 0;
  border-bottom: 1px solid var(--glass-border);
  border-left: none;
  border-right: none;
  border-top: none;
  backdrop-filter: blur(18px) saturate(1.45);
}
.brand {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.05rem;
  color: inherit;
  text-decoration: none;
}
.brand-accent { color: var(--series-slot); }
.topbar-sub { margin-right: auto; }
/* SnapStream family group (added 2026-08-03, cross-property nav fix) — this topbar had no nav
   at all before; reuses .faint's ink-dim/ink-faint tokens rather than inventing new color. */
.topbar-family {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  font-size: 0.78rem;
}
.topbar-family a {
  color: var(--ink-dim);
  text-decoration: none;
}
.topbar-family a:hover { color: var(--ink); }
.topbar-family-current { color: var(--ink-faint); }
@media (max-width: 640px) {
  /* Four extra nav items don't fit the single-row topbar on a phone width — wrap rather than
     overflow/clip, same "collapse, don't shrink text" approach the row-list already uses below. */
  .topbar { flex-wrap: wrap; row-gap: 0.4rem; }
  .topbar-family { flex-basis: 100%; }
}
.theme-toggle {
  min-width: 44px;
  min-height: 44px;
  border-radius: 0.6rem;
  border: 1px solid var(--glass-border);
  background: var(--glass-fill);
  color: var(--ink);
  font-size: 1.05rem;
  cursor: pointer;
}

.main { padding: 1.25rem 1.25rem 4rem; max-width: 1280px; margin: 0 auto; }

/* ── ONE ambient glow, anchored behind the summary-card row only (rule 2) ────────────────────
   tokens.css's own .ambient (two drifting blobs) is NOT used by this app — we never attach that
   class to any element here, so its rules simply go unused rather than being edited (keeps the
   copy a clean diff). This is a single static radial, not animated (nothing to honor for
   prefers-reduced-motion because there is no motion here in the first place). */

.hero-glow {
  position: relative;
  padding-top: 0.5rem;
}
.hero-glow::before {
  content: "";
  position: absolute;
  top: -4rem;
  left: 50%;
  width: min(90vw, 1100px);
  height: 420px;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, color-mix(in srgb, var(--series-slot) 16%, transparent), transparent 70%);
  z-index: -1;
  pointer-events: none;
}
:root[data-theme="light"] .hero-glow::before { opacity: 0.5; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) .hero-glow::before { opacity: 0.5; }
}

/* ── summary cards ────────────────────────────────────────────────────────────────────────── */

.conn-banner {
  width: 100%;
  border-radius: 0.9rem;
  padding: 0.65rem 1rem;
  margin-bottom: 1rem;
  font-size: 0.85rem;
  font-weight: 600;
  text-align: center;
  border: 1px solid var(--glass-border);
}
.conn-banner.reconnecting { background: var(--wait-dim); color: var(--wait); }
.conn-banner.gap { background: var(--bad-dim); color: var(--bad); }
.conn-banner[hidden] { display: none; }

/* Every `.glass.card` element (summary cards, ladder section, row-list section) gets the same
   inner padding from this ONE rule — no card type re-declares its own padding value. Content
   that needs to be full-bleed within a card (e.g. the ladder's chart well) still sits inset from
   the card's rounded corners because it's padding on the PARENT, not a per-child concern. */
.card { padding: var(--card-pad); margin-bottom: 1rem; }

.summary-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0.9rem;
}
@media (max-width: 1180px) {
  .summary-row { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
  .summary-row { grid-template-columns: 1fr; }
}

.stat-card {
  min-height: 108px;
  margin-bottom: 0; /* grid `gap` on .summary-row already spaces these; no extra per-card margin */
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.15rem;
}
.stat-value {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 2.6vw, 2.15rem);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
  line-height: 1.05;
}
.series-slot { color: var(--series-slot); }
.series-rate { color: var(--series-rate); }
.series-tx { color: var(--series-tx); }
.stat-label { color: var(--pewter); font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.05em; margin-top: 0.3rem; }
.stat-basis { font-size: 0.72rem; margin-top: 0.1rem; }

/* trend cards: small hand-rolled sparkline between the numeral and the basis line */
.trend-card .sparkline { width: 100%; height: 28px; margin: 0.35rem 0 0.1rem; display: block; }

/* discrete-state cards: badge pill, not a hero numeral (rule 10) */
.state-badge {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  padding: 0.3em 0.75em;
  border-radius: 999px;
  background: var(--glass-fill);
  border: 1px solid var(--glass-border);
  color: var(--ink);
  width: fit-content;
}
.state-badge.primary { color: var(--series-slot); border-color: color-mix(in srgb, var(--series-slot) 45%, var(--glass-border)); }
.state-badge.standby { color: var(--wait); border-color: color-mix(in srgb, var(--wait) 45%, var(--glass-border)); }

.status-line { display: flex; align-items: center; gap: 0.55rem; }
.status-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--ink-faint);
  flex-shrink: 0;
}
.status-dot.open { background: var(--ok); box-shadow: 0 0 8px color-mix(in srgb, var(--ok) 60%, transparent); }
.status-dot.reconnecting { background: var(--wait); box-shadow: 0 0 8px color-mix(in srgb, var(--wait) 60%, transparent); }
.status-dot.closed { background: var(--bad); }
.status-dot.connecting { background: var(--ink-faint); }

/* ── ladder ───────────────────────────────────────────────────────────────────────────────── */

.ladder-section { margin-top: 1.1rem; }
/* Heading and controls stack as two full-width rows rather than sharing one flex line — sharing
   a line let the heading's width squeeze the controls' own available space at mid viewport
   widths, which made the LAST control (freeze) wrap onto a line by itself instead of the whole
   controls row wrapping together (operator, phone review 2026-08-03). Giving controls the full
   card width means its own wrap (if it ever triggers, at very narrow widths) wraps the group,
   not one orphaned button. */
.ladder-head { display: flex; flex-direction: column; align-items: flex-start; gap: 0.6rem; }
.ladder-head h2 { margin: 0; font-size: 1.05rem; }
.ladder-controls { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; width: 100%; }
.ladder-controls button {
  font-family: var(--font-sans);
  font-size: 0.78rem;
  min-height: 36px;
  padding: 0.35rem 0.75rem;
  border-radius: 999px;
  border: 1px solid var(--glass-border);
  background: var(--glass-fill);
  color: var(--ink);
  cursor: pointer;
}
.ladder-controls button[aria-pressed="true"] { background: color-mix(in srgb, var(--series-slot) 18%, var(--glass-fill)); color: var(--series-slot); border-color: var(--series-slot); }
#freeze-btn[aria-pressed="true"] { background: var(--wait-dim); color: var(--wait); border-color: var(--wait); }

/* ── three lanes (CU / Txs / Fees), one shared x-axis ────────────────────────────────────────
   Each lane is a full-width block, so they stack the same way on desktop and on a single-column
   phone — there is no side-by-side arrangement to reflow, which is what keeps the shared x-axis
   aligned across every viewport width without extra media-query bookkeeping. */
.ladder-lanes { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 0.75rem; }
.ladder-lane { width: 100%; }
.lane-label { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 0.3rem; }
.lane-name { font-family: var(--font-display); font-weight: 700; font-size: 0.85rem; }
.lane-cu { color: var(--lane-cu); }
.lane-tx { color: var(--lane-tx); }
.lane-fee { color: var(--lane-fee); }
.lane-max { font-size: 0.72rem; color: var(--pewter); } /* explicitly pewter, per the lane-max spec */
.lane-sub { font-size: 0.72rem; margin-top: 0.3rem; }

.ladder-canvas-wrap {
  width: 100%;
  /* true-black chart well (rule 1: "near-black... except chart wells", which are true black) */
  background: #000;
  border-radius: 0.75rem;
  border: 1px solid var(--line);
  overflow: hidden;
  position: relative;
}
.ladder-lane canvas { width: 100%; height: 120px; display: block; touch-action: pan-y; cursor: crosshair; }
@media (max-width: 640px) {
  /* "shorter wells" on phones (operator directive) — three full-height lanes stacked at desktop
     height would push the row-list card too far down a small screen. */
  .ladder-lane canvas { height: 84px; }
}

.ladder-legend { display: flex; flex-wrap: wrap; gap: 0.9rem; margin-bottom: 0.5rem; }
.ladder-legend .swatch { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 0.35em; vertical-align: middle; }
.swatch.landed { background: var(--ok); }
.swatch.skipped { background: var(--ink-faint); }
.swatch.unavailable { background: var(--wait); }
.swatch.gap { background-image: repeating-linear-gradient(45deg, var(--bad) 0 2px, transparent 2px 5px); }
.swatch.prebuffer { background: transparent; border: 1px dashed var(--ink-faint); }

.tl-pop-host { position: relative; }
.bar-pop {
  position: absolute;
  z-index: 30;
  min-width: 200px;
  padding: 0.6rem 0.75rem;
  border-radius: 0.6rem;
  background: var(--canvas-2);
  border: 1px solid var(--glass-border);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  font-size: 0.8rem;
  color: var(--ink);
}
.bar-pop .k { color: var(--ink-dim); }

/* ── recent-slots row list ───────────────────────────────────────────────────────────────── */

.rows-section { margin-top: 1.1rem; }
.rows-section h2 { margin: 0 0 0.3rem; font-size: 1.05rem; }

.row-list-head, .slot-row {
  display: grid;
  grid-template-columns: 1fr 1.4fr 0.9fr 1.6fr 1.7fr;
  gap: 0.6rem;
  align-items: center;
  padding: 0.4rem 0.2rem;
}
.row-list-head { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; border-bottom: 1px solid var(--line); }
.row-list { max-height: 22rem; overflow-y: auto; }
.slot-row { border-bottom: 1px dashed var(--line); font-size: 0.85rem; font-family: var(--font-mono); }
.slot-row:last-child { border-bottom: none; }
.slot-row .slot-num { color: var(--series-slot); }
.slot-row .unavailable-cell { color: var(--ink-faint); font-style: italic; font-family: var(--font-sans); }
.status-pill { font-family: var(--font-sans); font-size: 0.68rem; padding: 0.15em 0.55em; border-radius: 999px; width: fit-content; }
.status-pill.landed { color: var(--ok); background: var(--ok-dim); }
.status-pill.skipped { color: var(--ink-faint); background: var(--glass-fill); }
.status-pill.unavailable { color: var(--wait); background: var(--wait-dim); }

/* per-row sparkbars (rule 10: "counts compared across slots = bars fit") */
.row-bars { display: flex; gap: 2px; align-items: flex-end; height: 16px; }
.row-bars .bar { width: 5px; border-radius: 1px; background: var(--pewter-dim); }
.row-bars .bar.tx { background: var(--series-tx); }
.row-bars .bar.cu { background: var(--series-rate); }

@media (max-width: 720px) {
  .row-list-head, .slot-row { grid-template-columns: 0.8fr 1fr 2fr; }
  .row-list-head span:nth-child(4), .row-list-head span:nth-child(5),
  .slot-row .cu-cell, .slot-row .fee-cell { display: none; }
}

footer.pagefoot { margin-top: 2rem; font-size: 0.72rem; color: var(--ink-faint); }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
