/* Wheel Screener — design layer on Pico (vendored, no build step). Pinned to light theme. */

:root {
  /* brand / primary action */
  --wheel-accent: #0e9f6e;
  --wheel-accent-strong: #0b8a5f;
  --wheel-accent-soft: rgba(14, 159, 110, 0.10);
  /* data semantics */
  --warn: #b7791f;
  --warn-soft: rgba(183, 121, 31, 0.12);
  --neg: #c0392b;
  --neg-soft: rgba(192, 57, 43, 0.12);
  /* neutral surfaces + structure */
  --ink: #1c2530;
  --border: rgba(16, 24, 40, 0.10);
  --sunken: #f6f8fa;
  /* geometry */
  --radius: 10px;
  --radius-sm: 8px;
  --shadow: 0 1px 3px rgba(16, 24, 40, 0.06), 0 1px 2px rgba(16, 24, 40, 0.04);
  --pico-border-radius: var(--radius-sm);
}

body { background: #f5f7f9; -webkit-font-smoothing: antialiased; }

/* icons: inline SVG sized to text, aligned to the baseline */
.icon { width: 1em; height: 1em; vertical-align: -0.125em; flex-shrink: 0; }

/* --- header (neutral bar, accent rule + accent brand mark) --- */
.app-header {
  background: #fff; color: var(--ink);
  border-bottom: 2px solid var(--wheel-accent);
  padding: 0.85rem 0; margin-bottom: 1.5rem;
}
.app-header__inner { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.brand { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 1.25rem; font-weight: 700; color: var(--wheel-accent); }
.brand-mark { width: 1.15em; height: 1.15em; }
.brand-sub { font-size: 0.875rem; color: var(--pico-muted-color); }

/* --- primary nav: Screener | Search tabs --- */
.app-nav { background: #fff; border-bottom: 1px solid var(--border); }
.app-nav__inner { display: flex; gap: 0.25rem; }
.nav-tab {
  padding: 0.7rem 1rem; font-weight: 600; font-size: 0.95rem; text-decoration: none;
  color: var(--pico-muted-color); border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.nav-tab:hover { color: var(--wheel-accent); }
.nav-tab.active { color: var(--wheel-accent-strong); border-bottom-color: var(--wheel-accent); }

/* --- layout / cards --- */
main.container { max-width: min(1440px, calc(100vw - 2rem)); }   /* wide enough for the full table */
main.container > article, main.container > section { margin-bottom: 1rem; }
article { border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow); }
article > h2, section > h2 { margin-top: 0; font-size: 1.05rem; }
footer { margin-top: 2rem; padding-top: 1rem; border-top: 1px solid var(--border); text-align: center; color: var(--pico-muted-color); }

/* --- badges (replace the yellow highlighter <mark>) --- */
.badge, mark {
  display: inline-flex; align-items: center; gap: 0.25rem;
  padding: 0.1rem 0.5rem; border-radius: 999px;
  font-size: 0.75rem; font-weight: 600; line-height: 1.6;
  background: var(--warn-soft); color: var(--warn);
}
.badge--neg { background: var(--neg-soft); color: var(--neg); }
.badge--ok { background: var(--wheel-accent-soft); color: var(--wheel-accent-strong); }

/* --- form --- */
form { margin-bottom: 0; }
form > .grid { align-items: start; }
form label, .rank-by legend { font-weight: 600; font-size: 0.875rem; }
form label small { font-weight: 400; color: var(--pico-muted-color); }
/* example placeholders read as faded ghost hints, not pre-filled values (e.g. the search "AAPL") */
::placeholder { color: var(--pico-muted-color); opacity: 0.55; font-style: italic; }
.advanced {
  margin: 0.75rem 0 1rem; border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 0 0.85rem;
}
.advanced summary { cursor: pointer; font-weight: 600; font-size: 0.875rem; padding: 0.5rem 0; color: var(--wheel-accent); }
.run-btn {
  width: 100%; margin-top: 1rem; font-weight: 600;
  background: var(--wheel-accent); border-color: var(--wheel-accent);
}
.run-btn:hover { background: var(--wheel-accent-strong); border-color: var(--wheel-accent-strong); }

/* Radio group as a segmented button bar (no JS, no border shimmer) — "Rank by", puts/calls.
   The radios themselves are hidden and the labels ARE the buttons; leaving them visible inside a
   Pico role="group" stretches each input into a full-width pill. */
.rank-by, .seg-field { margin: 0; padding: 0; border: 0; }
.rank-by legend, .seg-field legend { padding: 0; margin-bottom: calc(var(--pico-spacing) * 0.25); }
.segmented { display: flex; }
.segmented input[type="radio"] { position: absolute; opacity: 0; pointer-events: none; }
.segmented label {
  flex: 1; margin: 0 0 0 -1px; display: flex; flex-direction: column; justify-content: center;
  text-align: center; cursor: pointer; line-height: 1.25; min-height: 2.75rem;
  padding: 0.4rem 0.6rem; font-weight: 600; font-size: 0.875rem;
  border: 1px solid var(--pico-form-element-border-color);
}
.segmented label:first-of-type { margin-left: 0; border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.segmented label:last-of-type { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.segmented label small { font-weight: 400; font-size: 0.75rem; color: var(--pico-muted-color); }
.segmented input:checked + label {
  position: relative; z-index: 1; border-color: var(--wheel-accent);
  background: var(--wheel-accent-soft); color: var(--wheel-accent-strong);
}
.segmented input:checked + label small { color: var(--wheel-accent-strong); }
.segmented input:focus-visible + label { outline: 2px solid var(--pico-primary-focus); outline-offset: -2px; }

/* --- results table --- */
figure { margin: 0; overflow-x: auto; }
table { font-size: 0.875rem; margin: 0; width: 100%; }   /* fill the (now wider) card */
th, td { padding: 0.5rem 0.6rem; white-space: nowrap; }
thead th {
  position: sticky; top: 0; z-index: 1; background: var(--sunken);
  border-bottom: 1px solid var(--border);
  font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.02em; font-weight: 600;
}
tbody tr:not(.detail):nth-child(odd) { background: rgba(125, 125, 125, 0.045); }   /* zebra */
tbody tr:not(.detail):hover { background: var(--wheel-accent-soft); }               /* wins over zebra */
thead th:not(:nth-child(1)), tbody td:not(:nth-child(1)) { text-align: right; font-variant-numeric: tabular-nums; }
tbody td:nth-child(1) { text-align: left; }
th a, td a { text-decoration: none; color: inherit; cursor: pointer; }
th a:hover, td a:hover { color: var(--wheel-accent); }
th a:focus-visible, td a:focus-visible { outline: 2px solid var(--pico-primary-focus); outline-offset: 2px; border-radius: 2px; }
td a strong { border-bottom: 1px dotted currentColor; }   /* hint: symbol is clickable */
/* faint sort affordance on all sortable headers; the active one shows a chevron in the markup */
thead th a .icon { opacity: 0.6; }

/* column emphasis: mute reference cols (Bid=7/Mid=8/OI=9/Peers=12); highlight yield, strength + score */
tbody td:nth-child(7), tbody td:nth-child(8),
tbody td:nth-child(9), tbody td:nth-child(12) { color: var(--pico-muted-color); }
.y-hi { color: var(--wheel-accent-strong); font-weight: 700; }
.y-mid { font-weight: 600; }
.y-lo { color: var(--pico-muted-color); }
.strength-cell { font-weight: 700; }   /* the primary rating */
/* score = the output column: a proportional fill bar tinted green→amber→red by tier,
   with matching bold text, so the ranked shortlist reads at a glance */
.score-cell {
  font-weight: 700;
  background: linear-gradient(to right, var(--sc-fill, var(--wheel-accent-soft)) var(--pct, 0%), transparent var(--pct, 0%));
}
.sc-hi  { color: var(--wheel-accent-strong); --sc-fill: var(--wheel-accent-soft); }
.sc-mid { color: var(--warn);                --sc-fill: var(--warn-soft); }
.sc-lo  { color: var(--neg);                 --sc-fill: var(--neg-soft); }

/* results header: count · stats ...... [Export] on one aligned flex row */
.results-head { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.results-head strong { font-size: 1.05rem; }
.result-stats { display: inline-flex; flex-wrap: wrap; gap: 0.15rem 1rem; font-weight: 400; color: var(--pico-muted-color); }
.result-stats span { text-transform: uppercase; font-size: 0.72rem; letter-spacing: 0.02em; }
.result-stats b { font-size: 0.9rem; color: var(--ink); font-variant-numeric: tabular-nums; }
.results-hint { flex-basis: 100%; margin: 0; color: var(--pico-muted-color); }
.export-btn {
  margin: 0 0 0 auto; width: auto; padding: 0.35rem 0.8rem; font-size: 0.875rem;
  display: inline-flex; align-items: center; gap: 0.4rem;
}
.empty-state { text-align: center; color: var(--pico-muted-color); padding: 2rem 1rem; }

/* --- screen funnel: how the universe narrowed to candidates (parsed from the run's stage logs) --- */
.funnel { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.35rem 1.5rem; margin: 0 0 0.85rem; }
.funnel-stage { display: flex; flex-direction: column; gap: 0.15rem; min-width: 4.5rem; }
.funnel-count { font-size: 1.05rem; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.1; }
.funnel-label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--pico-muted-color); }
.funnel-bar { height: 3px; border-radius: 2px; background: var(--wheel-accent-soft); overflow: hidden; }
.funnel-bar > i { display: block; height: 100%; min-width: 2px; background: var(--wheel-accent); border-radius: 2px; }
.funnel-stage:last-child .funnel-count { color: var(--wheel-accent-strong); }   /* the payoff: candidates */
.funnel-stage:last-child .funnel-bar > i { background: var(--wheel-accent-strong); }
.fund-note { font-size: 0.8rem; font-weight: 600; }
.fund-ok { color: var(--wheel-accent-strong); }
.fund-bad { color: var(--neg); }
.ticker-metrics { font-size: 0.8rem; color: var(--pico-muted-color); font-variant-numeric: tabular-nums; }

/* --- candidate detail row --- */
.detail {
  position: relative; margin: 0.25rem 0; padding: 0.75rem 2.25rem 0.75rem 1rem;
  font-size: 0.875rem; background: var(--sunken); white-space: normal;   /* override table nowrap */
  border-left: 3px solid var(--wheel-accent); border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.detail-sym { color: var(--pico-muted-color); font-size: 0.8rem; }
.detail-flags { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem 0.6rem; margin-top: 0.5rem; }
/* quiet chips for non-risk flags (earnings-after-expiry, weeklys, notes) — color is reserved for the
   one real risk, earnings-before-expiry, which uses the amber .badge */
.detail-note { font-size: 0.75rem; color: var(--pico-muted-color); }
/* label|value definition grid — the card body (reuses tier colors + badges from the table) */
.card-grid {
  display: grid; grid-template-columns: max-content 1fr;
  align-items: baseline; gap: 0.25rem 0.85rem; margin: 0.5rem 0 0;
}
.card-grid dt { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.02em; font-weight: 600; color: var(--pico-muted-color); }
.card-grid dd { margin: 0; font-variant-numeric: tabular-nums; }
.detail-close {
  position: absolute; top: 0.5rem; right: 0.5rem;
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.5rem; height: 1.5rem; border-radius: 6px; font-size: 1rem;
  text-decoration: none; color: var(--pico-muted-color);
}
.detail-close:hover { background: var(--neg-soft); color: var(--neg); }

/* --- run states --- */
.run-progress ul { margin: 0.5rem 0 0; padding: 0; list-style: none; font-size: 0.875rem; color: var(--pico-muted-color); font-family: var(--pico-font-family-monospace); }
.run-progress li::before { content: "› "; color: var(--wheel-accent); }
[role="alert"] { border-left: 3px solid var(--neg); }
[role="alert"] .icon { color: var(--neg); margin-right: 0.35rem; }

/* --- responsive / small screens --- */
@media (max-width: 820px) {
  .app-header__inner { flex-direction: column; align-items: flex-start; gap: 0.1rem; }
  table { font-size: 0.8125rem; }
  th, td { padding: 0.45rem 0.5rem; }
  /* drop reference columns (Bid=7, Mid=8, OI=9, Peers=12) — keep the primary Strength (11) */
  thead th:nth-child(7), tbody td:nth-child(7),
  thead th:nth-child(8), tbody td:nth-child(8),
  thead th:nth-child(9), tbody td:nth-child(9),
  thead th:nth-child(12), tbody td:nth-child(12) { display: none; }
  .segmented label { padding: 0.4rem 0.3rem; font-size: 0.8125rem; }
  .segmented label small { font-size: 0.6875rem; }
}

/* --- fundamentals report grid --- */
/* Graded cells reuse the table's green→amber→red language. An UNGRADED cell gets no class at
   all, so it stays plain: blank means "no data", which is not the same claim as "poor". */
.g-hi  { background: var(--wheel-accent-soft); color: var(--wheel-accent-strong); font-weight: 600; }
.g-mid { background: var(--warn-soft); color: var(--warn); }
.g-lo  { background: var(--neg-soft); color: var(--neg); }
/* the results table mutes reference columns by position (nth-child 7/8/9/12); those indices are
   meaningless here, so re-assert the normal ink at higher specificity rather than by luck of order */
.report-table tbody td:not(:first-child) { color: inherit; }
.report-table tbody th { text-align: left; font-weight: 500; }
.report-table tbody tr.group-head th {
  background: var(--sunken); color: var(--pico-muted-color);
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; font-weight: 600;
  padding-top: 0.7rem;
}
/* neutral row hover: the accent tint would read as a grade on ungraded cells */
.report-table tbody tr:not(.group-head):hover { background: rgba(125, 125, 125, 0.09); }
.grade-legend { display: flex; flex-wrap: wrap; gap: 0.25rem 1rem; font-size: 0.75rem;
                color: var(--pico-muted-color); margin: 0.75rem 0 0.5rem; }
.grade-legend span { display: inline-flex; align-items: center; gap: 0.35rem; }
.grade-key { width: 0.8rem; height: 0.8rem; border-radius: 3px; display: inline-block;
             border: 1px solid var(--border); }
.metric-glossary { margin-top: 1rem; font-size: 0.85rem; }
.metric-glossary summary { cursor: pointer; color: var(--pico-muted-color); }
.tab-lede { color: var(--pico-muted-color); font-size: 0.9rem; }

/* --- company identity (shared by the screener card, search and fundamentals) --- */
.company { display: flex; flex-direction: column; gap: 0.15rem; margin: 0 0 0.85rem; }
.company-name { font-weight: 600; font-size: 0.95rem; }
.company-tags {
  font-family: inherit; font-size: 0.72rem; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--pico-muted-color);
}
/* the provider's prose is the one place on these pages that reads as a paragraph, so give it
   a measure rather than letting it run the full width of a wide table card */
.company-desc {
  margin: 0.35rem 0 0; font-size: 0.85rem; line-height: 1.5;
  color: var(--pico-muted-color); max-width: 68ch;
}

/* --- portfolio balances --- */
.account { margin: 1.25rem 0 0.5rem; }
.account h3 { margin: 0 0 0.6rem; font-size: 1rem; display: flex; align-items: baseline; gap: 0.6rem; }
.balance-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 0.75rem; margin: 0;
}
.balance {
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 0.7rem 0.85rem; background: var(--card, transparent);
}
.balance dt {
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em;
  font-weight: 600; color: var(--pico-muted-color);
}
.balance dd { margin: 0.15rem 0 0; font-variant-numeric: tabular-nums; font-size: 1.05rem; }
/* the headline is the account's worth — everything else is a decomposition of it */
.balance.headline { border-color: var(--wheel-accent); background: var(--wheel-accent-soft); }
.balance.headline dd { font-size: 1.4rem; font-weight: 700; color: var(--wheel-accent-strong); }
.balance .detail-note { margin: 0.2rem 0 0; }

/* ── DTE window: a two-thumb range drawn over the real expiry ladder ─────────────────── */
.dte-field { position: relative; }
.dte-note {
  display: block; color: var(--pico-muted-color); font-weight: 400;
  margin: -0.15rem 0 0.6rem;
}
.dte-note strong { color: var(--ink); font-variant-numeric: tabular-nums; }

/* Bar height encodes how broadly an expiry is listed: monthlies exist on every optionable
   name, weeklies only on the liquid subset. Ticks sit at their true position on the scale,
   so the gap between two monthlies is visible as a gap. */
.dte-ladder { position: relative; height: 40px; margin: 0 10px 2px; }
.dte-tick {
  position: absolute; bottom: 0; width: 5px; transform: translateX(-50%);
  background: var(--border); border-radius: 2px 2px 0 0;
  transition: background 0.12s ease;
}
.dte-tick.is-monthly { width: 7px; background: rgba(16, 24, 40, 0.22); }
.dte-tick.in-range { background: var(--wheel-accent); }
.dte-tick.is-monthly.in-range { background: var(--wheel-accent-strong); }

.dte-slider { position: relative; height: 26px; margin: 0 10px; }
.dte-track, .dte-fill {
  position: absolute; top: 50%; height: 4px; margin-top: -2px; border-radius: 2px;
}
.dte-track { left: 0; right: 0; background: var(--border); }
.dte-fill { background: var(--ink); }

.dte-thumb {
  /* A native range insets its thumb by half a thumb-width at each end, so an input sized to
     the track puts value=min ~10px right of 0%. Overhanging by that much on both sides lines
     the thumb centres up with the track ends -- and with the ladder ticks above, which are
     positioned on the same 10px inset. */
  position: absolute; left: -10px; top: 0; width: calc(100% + 20px);
  margin: 0; padding: 0; height: 26px; background: none; border: 0; box-shadow: none;
  -webkit-appearance: none; appearance: none;
  pointer-events: none;  /* the track is inert; only the thumbs take the pointer */
}
.dte-thumb:focus { outline: none; box-shadow: none; }
.dte-thumb::-webkit-slider-runnable-track { background: none; border: 0; height: 26px; }
.dte-thumb::-moz-range-track { background: none; border: 0; height: 26px; }
.dte-thumb::-webkit-slider-thumb {
  -webkit-appearance: none; pointer-events: auto; cursor: grab;
  width: 20px; height: 20px; margin-top: 3px; border-radius: 50%;
  background: var(--ink); border: 0; box-shadow: var(--shadow);
}
.dte-thumb::-moz-range-thumb {
  pointer-events: auto; cursor: grab;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--ink); border: 0; box-shadow: var(--shadow);
}
.dte-thumb::-webkit-slider-thumb:active { cursor: grabbing; }
.dte-thumb:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 3px var(--wheel-accent-soft); }
.dte-thumb:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 3px var(--wheel-accent-soft); }

.dte-boxes { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; margin-top: 0.9rem; }
.dte-boxes label {
  border: 1px solid var(--border); border-radius: var(--radius); padding: 0.5rem 0.75rem;
  font-size: 0.75rem; font-weight: 500; color: var(--pico-muted-color); margin: 0;
}
.dte-boxes label:focus-within { border-color: var(--wheel-accent); }
.dte-boxes input {
  border: 0; padding: 0; margin: 0; height: auto; background: none; box-shadow: none;
  font-size: 1.35rem; font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.dte-boxes input:focus { outline: none; box-shadow: none; }
/* the DTE block is much taller than the segmented control beside it */
.grid-top { align-items: start; }

/* ── exit comparison ─────────────────────────────────────────────────────────────────── */
/* A short put row opens its own comparison, so it has to look pressable. */
tbody tr.row-open { cursor: pointer; }
tbody tr.row-open td:first-child { position: relative; padding-left: 1.1rem; }
tbody tr.row-open td:first-child::before {
  content: "\25B8"; position: absolute; left: 0.3rem; color: var(--wheel-accent);
  transition: transform 0.12s ease; display: inline-block;
}
tbody tr.row-open:has(+ tr.detail) td:first-child::before { transform: rotate(90deg); }
/* A colspan cell contributes its content's min-content width to EVERY column it spans, so a
   nested table inside one silently widens the table above it — clicking a row made the whole
   Open options table jump wider. Pinning the wrapper to width:0 drops that contribution to
   nothing; min-width:100% then fills the cell once the columns are settled, and the <figure>
   around the inner table scrolls if it genuinely does not fit. */
.exits-row > td { padding: 0; background: var(--sunken); }
/* `th, td { white-space: nowrap }` is global and white-space INHERITS, so every sentence inside
   this cell — the warnings, the explanatory note — ran off the side rather than wrapping.
   Reset it for the panel, then let the inner table's numeric columns take nowrap back. */
.exits-row > td { white-space: normal; }
.exits table td:first-child, .exits table th:first-child { white-space: normal; }
/* `table { width: 100% }` is global, and under auto layout the surplus width is handed almost
   entirely to the widest column — here the action names — so a short label like "Roll to 20 Nov"
   sat alone in a cell half the panel wide, with the figure stranded on the far side. Fixed
   layout with declared proportions puts the columns where they are wanted, and the cap stops
   the table sprawling across a wide monitor in the first place. */
/* Scoped to the five-column table these proportions were measured for. Unscoped they also
   matched the roll grid, where `nth-child(1) { width: 32% }` outranks anything .roll-grid says
   and handed a third of an eight-column table to the strike labels. */
.exit-table { table-layout: fixed; max-width: 58rem; }
.exit-table th:nth-child(1), .exit-table td:nth-child(1) { width: 32%; }
.exit-table th:nth-child(2), .exit-table td:nth-child(2) { width: 16%; }
.exit-table th:nth-child(3), .exit-table td:nth-child(3) { width: 14%; }
.exit-table th:nth-child(4), .exit-table td:nth-child(4) { width: 20%; }
.exit-table th:nth-child(5), .exit-table td:nth-child(5) { width: 18%; }
.exits .exit-warnings, .exits > p { max-width: 58rem; }
.exit-controls input { width: 7.5rem; }
.exit-warnings {
  margin: 0 0 0.6rem; padding: 0.5rem 0.75rem 0.5rem 1.9rem; list-style: none;
  background: var(--warn-soft); border-left: 3px solid var(--warn);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0; font-size: 0.8125rem; color: var(--ink);
}
.exit-warnings li { position: relative; }
.exit-warnings li + li { margin-top: 0.2rem; }
.exit-warnings li::before { content: "\26A0"; position: absolute; left: -1.15rem; color: var(--warn); }
.exits-row .exits { width: 0; min-width: 100%; }
.exits-row figure { margin: 0; }
.exits { margin: 0; border: 0; border-radius: 0; background: none; box-shadow: none; }
.exit-controls {
  display: flex; gap: 0.75rem; align-items: end; flex-wrap: wrap; margin-bottom: 0.5rem;
}
.exit-controls label { font-size: 0.75rem; margin: 0; }
.exit-controls input { margin: 0; }
.exit-controls button { width: auto; margin: 0; }
.exit-best td { background: var(--wheel-accent-soft); }
.exit-best td:first-child { box-shadow: inset 3px 0 0 var(--wheel-accent); }
.exit-after {
  margin: 1.25rem 0 0.4rem; font-size: 0.8125rem; font-weight: 600; color: var(--pico-muted-color);
  text-transform: uppercase; letter-spacing: 0.03em;
}
.exit-controls--after { margin: 0.4rem 0 0.6rem; }

/* ── roll surface ────────────────────────────────────────────────────────────────────── */
/* Reaching the money from a deep out-of-the-money strike can take a dozen rows, so the grid
   scrolls rather than growing the panel. The header sticks, because a column of figures whose
   expiry has scrolled off the top is unreadable. */
.roll-grid-wrap { margin: 0 0 0.5rem; max-height: 21rem; overflow-y: auto; }
.roll-grid thead th {
  position: sticky; top: 0; z-index: 1; background: var(--pico-background-color, #fff);
  box-shadow: inset 0 -1px 0 var(--border);
}
/* Fixed layout so eight expiries always fit the panel instead of pushing a scrollbar under
   it. The figures are short and the columns are equal, so nothing needs to wrap. */
.roll-grid { table-layout: fixed; width: 100%; max-width: none; font-size: 0.8125rem; }
.roll-grid th, .roll-grid td { padding: 0.15rem; text-align: center; }
.roll-grid tbody th { text-align: right; white-space: nowrap; font-weight: 600; width: 4.5rem; }
.roll-grid thead th { font-size: 0.6875rem; }
.roll-grid .detail-note { display: block; font-size: 0.6875rem; line-height: 1.2; }
.roll-grid td.rg { padding: 0.15rem; }
.roll-grid td.rg > span {
  display: block; padding: 0.28rem 0.2rem; border-radius: var(--radius-sm);
}
/* Colour carries the SIGN, which is the first thing read here: a roll that pays and one that
   costs are opposite decisions, and tinting every cell the same green said neither. */
.roll-grid td.rg-pos > span { background: var(--wheel-accent-soft); color: var(--wheel-accent-strong); }
.roll-grid td.rg-neg > span { background: var(--neg-soft); color: var(--neg); }
.roll-grid td.rg-pos .detail-note, .roll-grid td.rg-neg .detail-note { color: inherit; opacity: 0.75; }
.roll-grid td.rg-current > span { background: var(--sunken); box-shadow: inset 0 0 0 1px var(--border); }
/* No contract listed at that strike for that expiry — nothing to price, so nothing to tint.
   A shaded blank reads as a result; this one is the absence of one. */
.roll-grid td.rg-empty { color: var(--pico-muted-color); background: none; }
/* A quote nobody trades is not a price, and the cheapest-looking cells are usually these. Hatched
   rather than merely grey: at a glance it has to read as one to skip, not as a neutral middle. It
   deliberately does NOT take the sign colours -- tinting a fictional credit green is the bug. */
.roll-grid td.rg-thin > span {
  color: var(--pico-muted-color); cursor: help;
  background: repeating-linear-gradient(-45deg,
    var(--sunken), var(--sunken) 3px, transparent 3px, transparent 7px);
  box-shadow: inset 0 0 0 1px var(--border);
}
.roll-grid td.rg-thin b { font-weight: 400; }
.roll-grid td.rg-thin .detail-note { color: inherit; opacity: 0.8; }
.roll-context { font-size: 0.8125rem; margin: 0 0 0.6rem; }
.etf-tag {
  margin-left: 0.35rem; padding: 0.05rem 0.3rem; border-radius: 3px; font-size: 0.625rem;
  font-weight: 700; letter-spacing: 0.04em; background: var(--sunken); color: var(--pico-muted-color);
  border: 1px solid var(--border); vertical-align: middle;
}
/* The two segmented knobs stack beside the DTE ladder, which needs the width for its bars. */
.knob-stack { display: flex; flex-direction: column; gap: 0.9rem; }
