/* app.css — terminal shell for the three-feature single page (Phase 4.2).
 *
 * The page is a terminal, not a blog column: a sticky command bar (brand ·
 * view nav · feed-status chip · theme toggle), a wider/denser content wrap,
 * mono-uppercase section eyebrows, and a persistent status strip. Everything
 * references tokens — never raw hex. Data-dense component work lands in 4.3–4.4.
 */

* { box-sizing: border-box; }

body {
  margin: 0;
  padding: 0;
  background: transparent;   /* let the fixed grid/grain atmosphere show through */
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-2);
  line-height: 1.5;
}

/* Content wrap — every full-bleed strip re-centres its inner content here. */
.cmdbar__inner,
main,
.statusbar__inner {
  max-width: var(--wrap);
  margin-inline: auto;
  width: 100%;
}
main { padding: var(--sp-6) var(--sp-5); }

h1, h2 { margin: 0; font-weight: 650; }
h1 { font-size: var(--fs-4); letter-spacing: -0.01em; }
h2 { font-size: var(--fs-3); margin-bottom: var(--sp-2); }
p { margin: var(--sp-2) 0; }
.muted { color: var(--ink-muted); font-size: var(--fs-1); }

/* ---- command bar (sticky terminal chrome) ---- */

.cmdbar {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--canvas) 82%, transparent);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--line);
}
.cmdbar__inner {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  min-height: 60px;
  padding: var(--sp-2) var(--sp-5);
}

.brand-lockup {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  text-decoration: none;
  color: inherit;
  flex: none;
}
.logo-tile {
  display: grid;
  place-items: center;
  height: 34px;
  width: 34px;
  border-radius: var(--r-sm);
  background: var(--accent);
  color: var(--canvas);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 17px;
  line-height: 1;
  transition: transform var(--dur-mid) var(--ease-out-expo);
}
.brand-lockup:hover .logo-tile { transform: rotate(-10deg); }
.brand-lockup:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--r-sm); }
.brand-text { display: flex; flex-direction: column; line-height: 1.15; }
.brand-name { font-family: var(--font-display); font-weight: 700; font-size: 15px; letter-spacing: -0.01em; color: var(--ink); }
.brand-sub { font-size: 11px; color: var(--ink-faint); margin-top: 1px; }

/* view nav — mono-uppercase, active = accent (no dashboard underline) */
.cmdnav {
  display: flex;
  gap: var(--sp-1);
  margin-left: auto;
  overflow-x: auto;
  scrollbar-width: none;
}
.cmdnav::-webkit-scrollbar { display: none; }

/* ---- feed-status chip (freshness / connection indicator) ---- */

.datamark {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-1) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface);
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-muted);
  white-space: nowrap;
}
.datamark__dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--ink-faint);
  box-shadow: 0 0 0 0 transparent;
}
.datamark__dot[data-state="loading"] { background: var(--ink-muted); animation: dot-pulse 1.4s ease-in-out infinite; }
.datamark__dot[data-state="seed"]  { background: var(--warn); box-shadow: 0 0 8px -1px var(--warn); }
.datamark__dot[data-state="fresh"] { background: var(--pos); box-shadow: 0 0 8px -1px var(--pos); }
.datamark__dot[data-state="error"] { background: var(--neg); box-shadow: 0 0 8px -1px var(--neg); }
@keyframes dot-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) { .datamark__dot[data-state="loading"] { animation: none; } }

/* ---- banner (themed drift/error state) ---- */

.banner {
  margin: var(--sp-3) 0;
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  border-left: 3px solid var(--line-strong);
  font-size: var(--fs-1);
  color: var(--ink);
}
.banner--error {
  background: color-mix(in srgb, var(--neg) 12%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--neg) 45%, var(--line));
  border-left: 3px solid var(--neg);
}

/* First-visit educational/research notice (js/ui/about.js) — accent-tinted,
   non-blocking, with inline "Read more" + "Got it" actions. */
.banner--notice {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--line));
  border-left: 3px solid var(--accent);
}
/* The `display: flex` above beats the UA `[hidden] { display: none }` (equal
   specificity, author wins), so `notice.hidden = true` wouldn't hide it without
   this higher-specificity override. */
.banner--notice[hidden] { display: none; }
.banner__icon { color: var(--accent); font-size: var(--fs-2); line-height: 1; }
.banner__text { flex: 1 1 16rem; }
.banner__actions {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-left: auto;
}

/* Compact button modifier (reused by the notice's "Got it"). */
.btn--sm { padding: 4px 10px; font-size: var(--fs-0); }

/* ---- view nav tabs (in the command bar) ---- */

.tab {
  appearance: none;
  background: none;
  border: none;
  border-radius: var(--r-sm);
  padding: var(--sp-2) var(--sp-3);
  color: var(--ink-muted);
  font-family: var(--font-mono);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  cursor: pointer;
  white-space: nowrap;
  transition: color var(--dur-fast);
}
.tab:hover { color: var(--ink); }
.tab.is-active { color: var(--accent); }
.tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---- section eyebrow (01 — EXPLORER) ---- */

.eyebrow {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin: 0 0 var(--sp-4);
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--ink-faint);
}
.eyebrow .idx { color: var(--accent); }
.eyebrow .rule { height: 1px; width: 40px; background: var(--line-strong); }

/* ---- cards (DL panel recipe) ---- */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  padding: var(--sp-5);
}

/* ---- data-dense terminal tables (Phase 4.3) ----
 * Mono tabular numerics, tight rows, hairline + zebra bodies, right-aligned
 * numbers, hover/focus row highlight. Sticky headers are scoped to the ladder's
 * own scroll container below so long chains scroll under a pinned header. */

.datatable {
  width: 100%;
  border-collapse: collapse;
  margin-top: var(--sp-3);
  font-family: var(--font-mono);
  font-size: var(--fs-1);
  font-variant-numeric: tabular-nums;
}
.datatable th, .datatable td {
  text-align: left;
  padding: var(--sp-1) var(--sp-3);   /* tight terminal row height */
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.datatable thead th {
  background: var(--surface);
  color: var(--ink-faint);
  font-weight: 400;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  border-bottom: 1px solid var(--line-strong);
}
.datatable tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--ink) 3%, transparent); }
.datatable tbody tr:hover td { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.datatable tbody tr:focus-within td { background: var(--accent-tint); }
.datatable tr:last-child td { border-bottom: none; }
.datatable .num { text-align: right; font-variant-numeric: tabular-nums; }

/* ---- explorer: underlying chips (DL tag-style selectors) ---- */

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: var(--sp-3) 0;
}
.chip {
  appearance: none;
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: var(--sp-2) var(--sp-3);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
  transition: border-color var(--dur-fast), background var(--dur-fast);
}
.chip:hover { border-color: var(--line-strong); }
.chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.chip.is-active { background: var(--accent-tint); border-color: var(--accent); }
.chip.is-active:hover { border-color: var(--accent); }
.chip__label { font-weight: 600; font-size: var(--fs-1); }
.chip__sub {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-faint);
}
.chip.is-active .chip__sub { color: var(--accent); }
/* Stock chips read a touch quieter than the pinned indices. */
.chip--stock .chip__label { font-weight: 500; }

/* ---- explorer: underlying type-ahead picker (PLAN §5.5) ---- */

.picker { margin: var(--sp-3) 0; }
/* Search and the browse dropdown sit on one row and wrap on narrow screens. */
.picker-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  align-items: center;
  margin-bottom: var(--sp-2);
}
/* Browse-all-stocks dropdown — the alphabetical alternative to typing.
 * Styled to match the search box and the .control selects below the picker. */
.picker-browse {
  flex: 0 1 auto;
  font-family: var(--font-sans);
  font-size: var(--fs-1);
  color: var(--ink);
  background: var(--canvas);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--sp-2) var(--sp-3);
  min-width: 12rem;
  transition: border-color var(--dur-fast);
}
.picker-browse:focus { border-color: var(--accent); }
.picker-browse:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.picker-browse:disabled { opacity: 0.5; cursor: not-allowed; }
.picker-search {
  flex: 1 1 16rem;
  width: 100%;
  max-width: 22rem;
  font-family: var(--font-sans);
  font-size: var(--fs-1);
  color: var(--ink);
  background: var(--canvas);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--sp-2) var(--sp-3);
  transition: border-color var(--dur-fast);
}
.picker-search::placeholder { color: var(--ink-faint); }
.picker-search:focus { border-color: var(--accent); }
.picker-search:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* The chip row scrolls inside itself when a search returns many matches, so
 * the page body never grows or scrolls sideways. */
.picker #underlying-chips { max-height: 14rem; overflow-y: auto; }
.picker-count {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-faint);
  min-height: 1.4em;
  margin: var(--sp-1) 0 0;
}
.picker-empty { margin: var(--sp-2) 0; }

kbd {
  font-family: var(--font-mono);
  font-size: var(--fs-0);
  padding: 0 var(--sp-1);
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: 4px;
  background: var(--canvas);
}

/* ---- explorer: controls (DL field inputs + field-labels) ---- */

.controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin: var(--sp-3) 0 var(--sp-2);
}
.control {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--ink-faint);
}
.control select, .control input {
  font-family: var(--font-sans);
  font-size: var(--fs-1);
  text-transform: none;
  letter-spacing: normal;
  color: var(--ink);
  background: var(--canvas);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: var(--sp-2) var(--sp-3);
  min-width: 9rem;
  transition: border-color var(--dur-fast);
}
/* Wide enough for "2026-07-07 · Tue · 4d" so filling it doesn't reflow. */
#expiry-select { min-width: 12.5rem; }
/* Text lines that fill in after the slice loads — reserve their height. */
#explorer-meta, #ladder-note, #bs-contract { min-height: 1.5em; }
.control input { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.control select:focus, .control input:focus { border-color: var(--accent); }
.control select:focus-visible, .control input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* ---- explorer: strike ladder ---- */

/* Self-contained scroll region: long chains scroll here (both axes) under a
 * pinned header, so the page body never grows unbounded or scrolls sideways. */
.ladder-wrap {
  max-height: min(65vh, 40rem);
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.ladder-wrap .datatable { margin-top: 0; }
.ladder-wrap thead th { position: sticky; top: 0; z-index: 1; }
/* Option-chain convention: calls lean pos, puts lean neg (header cue only). */
.ladder thead th.ce { color: var(--pos); }
.ladder thead th.pe { color: var(--neg); }
.ladder td.strike { text-align: center; font-weight: 650; color: var(--ink); }

/* Model-priced Greek columns (Δ / θ) — muted tabular numerics that recede
 * behind the premium so the eye lands on price first. Uncomputable cells
 * (missing contract, or no spot yet) drop to the faintest ink. */
.ladder td.greek { color: var(--ink-faint); }
.ladder td.greek--empty { color: var(--ink-faint); opacity: 0.55; }
.ladder td.contract.contract--missing { text-align: right; }
.ladder tbody tr.is-atm td {
  background: var(--accent-tint);
  border-top: 1px solid var(--accent);
  border-bottom: 1px solid var(--accent);
}

/* Expected-move boundaries (PLAN §5.3): the ladder rows nearest the 1σ / 2σ
 * band edges carry a dashed warn-toned rule so the realistic travel range by
 * expiry reads at a glance — distinct from the accent ATM row. The inner (1σ)
 * band is the stronger cue. */
.ladder tbody tr.is-sigma1 td { border-top: 1px dashed var(--warn); border-bottom: 1px dashed var(--warn); }
.ladder tbody tr.is-sigma2 td { border-top: 1px dashed var(--line-strong); border-bottom: 1px dashed var(--line-strong); }
.ladder td.strike .sigma-tag {
  display: inline-block;
  margin-left: var(--sp-1);
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.08em;
  color: var(--warn);
  vertical-align: middle;
}
.ladder tbody tr.is-sigma2 td.strike .sigma-tag { color: var(--ink-muted); }

/* P(ITM) leg column — a probability, kept in slightly receded ink so the money
 * columns stay primary. */
.legs td.leg-pitm { color: var(--ink-muted); }
.contract__sym { white-space: nowrap; }
.contract__id {
  font-size: var(--fs-0);
  color: var(--ink-faint);
}
.contract--missing { color: var(--ink-faint); }

.contract-btn {
  appearance: none;
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  display: block;
  cursor: pointer;
  border-radius: var(--r-sm);
}
.contract-btn:hover .contract__sym { color: var(--accent); text-decoration: underline; }
.contract-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Model-premium cell: the whole (right-aligned, tabular) number is the button
 * that loads the contract into the toolkit. Hover/focus lift it to the accent
 * so it reads as the interactive column amid the muted Greeks. */
.ladder td.contract .contract-btn {
  width: 100%;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.ladder td.contract .contract-btn:hover,
.ladder td.contract .contract-btn:focus-visible { color: var(--accent); }

/* "Model-priced" banner above the chain — a warn-toned tag so nobody mistakes
 * the synthetic premiums/Greeks for market data. */
.model-note {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: var(--sp-3) 0 var(--sp-2);
  font-size: var(--fs-0);
  color: var(--ink-faint);
}
.tag-model {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  padding: 2px var(--sp-2);
  border: 1px solid var(--warn);
  border-radius: var(--r-pill);
  color: var(--warn);
  white-space: nowrap;
}

/* ---- expiry calendar (dense hairline rows, sticky week headers) ---- */

.cal-week { margin-top: var(--sp-5); }
.cal-week:first-child { margin-top: var(--sp-2); }
.cal-week__title {
  position: sticky;
  top: var(--cmdbar-h);   /* pin under the command bar while its week is in view */
  z-index: 1;
  margin: 0;
  padding: var(--sp-2) 0;
  background: var(--surface);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--ink-faint);
  border-bottom: 1px solid var(--line-strong);
}
.cal-day {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2) var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--line);
  transition: background var(--dur-fast);
}
.cal-day:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.cal-day.is-next { background: var(--accent-tint); border-bottom-color: var(--accent); }
.cal-day__when { display: flex; align-items: baseline; gap: var(--sp-3); }
.cal-day__date {
  font-family: var(--font-mono);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  white-space: nowrap;
}
.dte {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-faint);
  white-space: nowrap;
}
.dte--imminent { color: var(--warn); font-weight: 600; }
.cal-day__who { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.cal-tag {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  padding: 2px var(--sp-2);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--ink-faint);
  white-space: nowrap;
}
/* The "+N more" overflow chip when a day lists more names than MAX_TAGS. */
.cal-tag--more { color: var(--accent); border-color: var(--accent); }
/* Trading-day countdown beside the calendar-DTE badge (PLAN §6.5). */
.cal-day__sessions {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--ink-muted);
  white-space: nowrap;
}
/* Market-holiday rows interleaved among the expiries — dimmed, no hover lift,
   so the tradable expiries stay the focus. */
.cal-day--holiday {
  background: repeating-linear-gradient(
    -45deg, transparent, transparent 6px,
    color-mix(in srgb, var(--ink-faint) 6%, transparent) 6px,
    color-mix(in srgb, var(--ink-faint) 6%, transparent) 12px);
}
.cal-day--holiday:hover { background: repeating-linear-gradient(
    -45deg, transparent, transparent 6px,
    color-mix(in srgb, var(--ink-faint) 6%, transparent) 6px,
    color-mix(in srgb, var(--ink-faint) 6%, transparent) 12px); }
.cal-day--holiday .cal-day__date { color: var(--ink-muted); font-weight: 500; }
.cal-tag--closed { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 45%, var(--line)); }
.cal-holiday-name {
  font-family: var(--font-mono);
  font-size: var(--fs-0);
  color: var(--ink-muted);
  font-style: italic;
}
/* "Show stock expiries" toggle — a compact inline checkbox control. */
.cal-stocks {
  flex-direction: row;
  align-items: center;
  gap: var(--sp-2);
  margin: var(--sp-2) 0 var(--sp-3);
  cursor: pointer;
}
.cal-stocks input { accent-color: var(--accent); min-width: 0; cursor: pointer; }

.linklike {
  appearance: none;
  background: none;
  border: none;
  padding: 0;
  margin-top: var(--sp-2);
  color: var(--accent);
  font: inherit;
  font-size: var(--fs-1);
  cursor: pointer;
}
.linklike:hover { text-decoration: underline; }

/* ---- toolkit & payoff: instrument panels (Phase 4.4) ----
 * The BS calculator and payoff read as terminal instruments: the Greeks as a
 * hairline-gridded mono stat readout, DL field inputs, terminal buttons, a
 * multi-leg table on the 4.3 datatable style, and a payoff <canvas> framed and
 * themed entirely off tokens (see drawChart() in js/ui/toolkit.js). Everything
 * here references primary tokens — the legacy aliases are gone. */

.panel .card + .card { margin-top: var(--sp-4); }

.control--sm { min-width: 0; }
.control--sm select, .control--sm input { min-width: 6.5rem; }

/* Greeks / price readout: an instrument grid — opaque mono cells on the
 * recessed canvas, separated by hairline seams (1px gaps over the --line
 * backing), mono-uppercase micro-labels above tabular-numeric values. */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  gap: 1px;
  margin: var(--sp-3) 0;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
}
.stat {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  padding: var(--sp-3);
  background: var(--canvas);
}
.stat__label {
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-faint);
  white-space: nowrap;
}
.stat__value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-2);
  font-weight: 600;
  color: var(--ink);
}

/* IV solver row: a standalone stat sits beside its market-price field, so it
 * carries its own hairline frame (it isn't inside the .stats grid). */
.iv-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  align-items: stretch;
  margin: var(--sp-3) 0;
}
.iv-row .stat {
  min-width: 9rem;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}

.bs-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-3);
  align-items: center;
  margin-top: var(--sp-3);
}

/* ---- strategy template picker (DL tag-style chips) ---- */
.tpl-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: var(--sp-3) 0 var(--sp-2);
}
.tpl-chip {
  appearance: none;
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: var(--sp-1) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--ink-muted);
  cursor: pointer;
  transition: border-color var(--dur-fast), color var(--dur-fast), background var(--dur-fast);
}
.tpl-chip:hover { border-color: var(--accent); color: var(--accent); }
.tpl-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.tpl-chip.is-active {
  background: var(--accent-tint);
  border-color: var(--accent);
  color: var(--accent);
}
#tpl-note.warn { color: var(--warn); }

/* ---- position-size / risk calculator (PLAN §5.6) ---- */
.risk-sizer {
  margin-top: var(--sp-4);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--line);
}
.risk-sizer__title {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--ink-muted);
  margin: 0 0 var(--sp-2);
}
#risk-out.warn { color: var(--warn); }

/* ---- shareable strategy link (PLAN §6.1) ---- */
.payoff-actions { margin-top: var(--sp-3); }
.btn {
  appearance: none;
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--canvas);
  color: var(--ink);
  cursor: pointer;
  transition: border-color var(--dur-fast), color var(--dur-fast);
}
.btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Per-leg editable cells — DL field inputs, mono tabular, right-aligned to
 * line up under the 4.3 datatable's numeric columns. */
.legs input {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-1);
  color: var(--ink);
  background: var(--canvas);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 2px var(--sp-2);
  text-align: right;
  transition: border-color var(--dur-fast);
}
.legs input:focus { border-color: var(--accent); }
.legs input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.leg-premium { width: 6.5rem; }
.leg-iv { width: 4.5rem; }
.leg-lots { width: 4rem; }
.leg-dir { font-weight: 650; }
.leg-dir--buy { color: var(--pos); }
.leg-dir--sell { color: var(--neg); }

/* ---- saved strategies & journal-lite (PLAN §6.2) ---- */
.journal {
  margin-top: var(--sp-4);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--line);
}
.journal__title {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--ink-muted);
  margin: 0 0 var(--sp-2);
}
.journal__save { align-items: end; }
.journal__save .btn { align-self: end; }
.journal__list {
  list-style: none;
  margin: var(--sp-3) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.saved {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--sp-1) var(--sp-3);
  align-items: baseline;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.saved__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--sp-2) var(--sp-3); }
.saved__name { font-weight: 650; }
.saved__meta { font-size: var(--fs-1); color: var(--ink-muted); }
.saved__pnl {
  grid-column: 1 / -1;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-1);
}
.saved__pnl.pos { color: var(--pos); }
.saved__pnl.neg { color: var(--neg); }
.saved__pnl.flat { color: var(--ink-muted); }
.saved__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); justify-self: end; }
.saved__act--danger { color: var(--neg); }
.saved__close-form {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-1);
}
.saved__close-price {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-1);
  color: var(--ink);
  background: var(--canvas);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  padding: 2px var(--sp-2);
  width: 8rem;
  text-align: right;
}
.saved__close-price:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.saved__close-preview { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.saved__close-preview.pos { color: var(--pos); }
.saved__close-preview.neg { color: var(--neg); }
.journal__io { display: flex; flex-wrap: wrap; gap: var(--sp-4); margin-top: var(--sp-3); }

/* ---- payoff header, T+n curve legend & IV-shift slider (PLAN §5.4) ---- */
.payoff-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2) var(--sp-4);
}
.payoff-head h2 { margin: 0; }
.payoff-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
.pl-curve {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-muted);
}
/* A short line-swatch keyed to the canvas stroke of each curve. */
.pl-curve::before {
  content: "";
  width: 14px;
  height: 0;
  border-top: 2px solid currentColor;
}
.pl-curve--expiry { color: var(--accent); }
.pl-curve--mid { color: var(--ink-muted); }
.pl-curve--mid::before { border-top-style: dashed; }
.pl-curve--now { color: var(--ink-faint); }
.pl-curve--now::before { border-top-style: dotted; }
.pl-curve.is-off { opacity: 0.35; } /* no time on the clock — only expiry drawn */

.ivshift-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  margin: var(--sp-2) 0 var(--sp-3);
}
.ivshift { flex-direction: row; align-items: center; gap: var(--sp-2); }
.ivshift input[type="range"] {
  width: 12rem;
  min-width: 8rem;
  accent-color: var(--accent);
  cursor: pointer;
}
.ivshift-val {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-1);
  color: var(--accent);
  min-width: 4.5rem;
}

/* Payoff instrument: a framed well on the recessed canvas; the plot itself
 * (grid, axis, accent P/L curve, pos/neg fills, markers) is painted from
 * tokens by drawChart(). */
#payoff-canvas {
  display: block;
  width: 100%;
  height: 260px;
  margin-top: var(--sp-3);
  background: var(--canvas);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}

/* ---- status strip (persistent terminal footer) ---- */

.statusbar {
  margin-top: var(--sp-6);
  border-top: 1px solid var(--line);
  background: color-mix(in srgb, var(--surface) 40%, transparent);
}
.statusbar__inner {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--sp-2) var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-faint);
}
.statusbar__mark { color: var(--ink-muted); }
/* Inline footer link that opens the About dialog — reads as part of the strip. */
.statusbar__link {
  appearance: none;
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: var(--ink-faint);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.statusbar__link:hover { color: var(--accent); }
.statusbar__link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---- About / disclaimer dialog (js/ui/about.js) ---- */

.about {
  width: min(38rem, calc(100vw - 2 * var(--sp-4)));
  max-height: min(85vh, 44rem);
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xl);
  background: var(--surface);
  color: var(--ink);
  overflow: hidden;
}
/* Flex column so the head/foot stay put and only the body scrolls when the
   disclaimer copy is taller than the dialog (only applies while open — a closed
   <dialog> keeps the UA `display: none`). */
.about[open] { display: flex; flex-direction: column; }
.about::backdrop { background: color-mix(in srgb, var(--canvas) 72%, transparent); backdrop-filter: blur(2px); }
.about__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--line);
  flex: 0 0 auto;
}
.about__title { margin: 0; font-size: var(--fs-3); }
.about__close {
  appearance: none;
  display: grid;
  place-items: center;
  height: 32px;
  width: 32px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--ink-muted);
  cursor: pointer;
  line-height: 1;
}
.about__close:hover { border-color: var(--line-strong); color: var(--ink); }
.about__close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.about__body {
  padding: var(--sp-4) var(--sp-5);
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
  overscroll-behavior: contain;
  font-size: var(--fs-1);
  line-height: 1.55;
}
.about__body p { margin: 0 0 var(--sp-3); }
.about__list { margin: 0 0 var(--sp-3); padding-left: var(--sp-4); display: grid; gap: var(--sp-2); }
.about__list li { color: var(--ink-muted); }
.about__list strong, .about__body > p strong { color: var(--ink); }
.about__foot { margin: 0; color: var(--ink-faint); font-size: var(--fs-0); }
.about__foot a { color: var(--accent); }
.about__actions {
  display: flex;
  justify-content: flex-end;
  padding: var(--sp-3) var(--sp-5);
  border-top: 1px solid var(--line);
  flex: 0 0 auto;
}

/* ---- toasts ---- */

.toasts {
  position: fixed;
  bottom: var(--sp-4);
  right: var(--sp-4);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  z-index: 10;
}
.toast {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--r-md);
  box-shadow: 0 12px 32px rgb(0 0 0 / 0.45);
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-1);
  color: var(--ink);
  max-width: 22rem;
  animation: toast-in var(--dur-mid) var(--ease-out-expo) both;
}
.toast--error { border-left-color: var(--neg); }
.toast:has(.toast__action) {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}
.toast__action {
  flex: none;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: var(--r-sm);
  padding: var(--sp-1) var(--sp-3);
  font: inherit;
  font-size: var(--fs-0);
  cursor: pointer;
}
.toast__action:hover { background: var(--accent-soft); }
.toast__action:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

@keyframes toast-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .toast { animation: none; }
}

/* ---- states & motion (Phase 4.5) ----
 * Themed empty / loading states, skeleton placeholders for the first data
 * paint, fade-rise scroll reveals, and a responsive scroll wrapper so wide
 * tables scroll inside their own box (the page body never scrolls sideways).
 * All motion routes through the one house easing and is disabled under
 * prefers-reduced-motion. */

/* Empty state: a hairline dashed well with centred mono-muted copy — clearly a
 * state, not content. Renderers add .empty-state to the note/host they own. */
.empty-state {
  display: block;
  margin: var(--sp-3) 0;
  padding: var(--sp-5) var(--sp-4);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--ink) 2%, transparent);
  color: var(--ink-muted);
  font-family: var(--font-mono);
  font-size: var(--fs-1);
  text-align: center;
}

/* Skeleton placeholders for the pre-paint / CSV load. Bars animate via the
 * base.css .skeleton pulse (reduced-motion aware there). */
.skeleton-bar {
  display: block;
  height: 0.85em;
  border-radius: var(--r-sm);
}
.ladder .skeleton-cell { padding: var(--sp-2) var(--sp-3); }
.cal-skeleton { display: flex; flex-direction: column; gap: var(--sp-2); margin-top: var(--sp-3); }
.cal-skeleton .skeleton-bar { height: 2.25em; }

/* Fade-rise scroll reveals. Progressive enhancement: elements only start
 * hidden once js/ui/reveal.js has confirmed it can reveal them (.reveal-ready
 * on <html>), so content is never trapped invisible if the script never runs
 * or motion is reduced (reveal.js leaves everything visible in that case). */
.reveal-ready [data-reveal] { opacity: 0; }
.reveal-ready [data-reveal].is-revealed {
  animation: fade-rise var(--dur-reveal) var(--ease-out-expo) both;
}

/* Wide tables scroll inside their own box on narrow viewports. */
.table-scroll { overflow-x: auto; }

/* Feed chip collapses to a bare status dot before the command bar crowds. */
@media (max-width: 56rem) {
  #datamark-text { display: none; }
  .datamark { padding: var(--sp-1); }
}

@media (max-width: 40rem) {
  .cmdbar__inner { gap: var(--sp-3); padding: var(--sp-2) var(--sp-4); }
  .brand-sub { display: none; }
  main { padding: var(--sp-5) var(--sp-4); }
  .statusbar__inner { padding: var(--sp-4); }
  .card { padding: var(--sp-3) var(--sp-4); }
  .datatable { font-size: var(--fs-0); }
  .datatable th, .datatable td { padding: var(--sp-1) var(--sp-2); }
  .control { flex: 1 1 8rem; }
  .control select, .control input { min-width: 0; width: 100%; }
}
