/* ============================================================================
   design-system.css — SHARED across every niche. Scale, type roles, element
   classes. The per-niche look lives entirely in theme-<niche>.css (loaded
   BEFORE this file), which supplies the CSS variables consumed here.

   RULE for new code: no literal colors, no literal font names in this file —
   only var(--...). The legacy rules below predate the system and migrate
   onto tokens phase by phase (fonts Phase 1, colors Phase 2, elements
   Phase 3); scripts/css_census.py reports the remaining literal count.
   ========================================================================== */

/* ---- SCALE — shared across every niche. Niches change voice via the
   theme's fonts and colors, never via sizes: a niche that needs a
   different scale is a design-system change, not a theme. ---- */
:root {
    --size-title:   24px;  --lh-title:   1.15;
    --size-heading: 18px;  --lh-heading: 1.25;
    --size-body:    15px;  --lh-body:    1.6;
    --size-muted:   13px;  --lh-muted:   1.5;
    --size-label:   11px;  /* uppercase micro-labels (table headers, chips) */
}

/* ---- SPACING SCALE — the one source of truth for gaps/padding ---- */
:root {
    --space-1: 4px;
    --space-2: 8px;
    --space-3: 12px;
    --space-4: 16px;
    --space-6: 24px;
    --space-8: 32px;

    --panel-pad: var(--space-6);   /* inside a panel: 24px */
    --cell-pad:  var(--space-3);   /* table cells: 12px */
    --cell-pad-dense: var(--space-2) var(--space-3);  /* admin grids: 8/12 */
    --stack:     var(--space-4);   /* vertical gap between elements in a panel */
}

/* ---- THE 5 TYPE ROLES (+2 variants). Element defaults below map the
   common tags onto these so most markup needs no class; the .t-* classes
   are for text that plays a role its tag doesn't imply. ---- */
.t-title   { font-family: var(--font-display); font-weight: 500; font-size: var(--size-title);   line-height: var(--lh-title); letter-spacing: .005em; color: var(--ink-hi); }
.t-heading { font-family: var(--font-display); font-weight: 500; font-size: var(--size-heading); line-height: var(--lh-heading); color: var(--ink-accent); }
.t-body    { font-family: var(--font-body);    font-weight: 400; font-size: var(--size-body);    line-height: var(--lh-body);  color: var(--ink); }
.t-muted   { font-family: var(--font-body);    font-weight: 400; font-size: var(--size-muted);   line-height: var(--lh-muted); color: var(--ink-mute); }
.t-num     { font-family: var(--font-display); font-weight: 500; font-variant-numeric: tabular-nums; color: var(--ink-hi); } /* size from context */
.t-link    { font-family: var(--font-body); font-size: var(--size-body); color: var(--link); text-decoration: underline; }
.t-label   { font-family: var(--font-body); font-weight: 500; font-size: var(--size-label); letter-spacing: .06em; text-transform: uppercase; color: var(--ink-mute); }

/* ---- Element defaults: the tags carry the roles. ---- */
h3 { font-family: var(--font-display); }
button, input, select, textarea { font-family: var(--font-body); }
/* Data-entry fields: the recessed well, applied to the elements so all
   existing forms adopt it without markup changes (.input is the alias
   for non-form elements that want the look). Checkboxes/radios are
   excluded — they keep native rendering, themed via accent-color. */
.input,
input:not([type="radio"]), select, textarea {
    background: var(--field-bg);
    color: var(--ink);
    border: 1px solid var(--field-border);
    border-radius: 4px;
    padding: 8px 11px;
    font-family: var(--font-body);
    font-size: 14px;
}
.input::placeholder,
input::placeholder, textarea::placeholder { color: var(--ink-mute); }
.input:focus,
input:not([type="radio"]):focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--focus);
    box-shadow: 0 0 0 2px var(--focus-ring);
}
/* ==== NOTIFICATION BADGE (round chip) ==== */
.notif-badge {
    position: absolute; top: -6px; right: -6px;
    min-width: 16px; height: 16px; padding: 0 4px; box-sizing: border-box;
    display: inline-flex; align-items: center; justify-content: center;
    font-family: var(--font-body); font-size: 10px; font-weight: 600;
    color: var(--on-accent); background: var(--accent);   /* red is reserved for loss */
    border-radius: 999px;
}

/* ==== CHECKBOX ==== */
.checkbox, input[type="checkbox"] {
    appearance: none; -webkit-appearance: none;
    width: 18px; height: 18px; flex: none;
    background: var(--field-bg);
    border: 1px solid var(--field-border);
    border-radius: 4px;
    padding: 0;
    cursor: pointer;
    display: inline-grid; place-content: center;
    vertical-align: middle;
}
.checkbox:checked, input[type="checkbox"]:checked { border-color: var(--accent); }
.checkbox:checked::after, input[type="checkbox"]:checked::after {
    content: ""; width: 10px; height: 10px;
    border-radius: 2px; background: var(--accent);   /* the inset fill block */
}
.checkbox:focus-visible, input[type="checkbox"]:focus-visible {
    outline: none; box-shadow: 0 0 0 2px var(--focus-ring);
}
input[type="radio"] { accent-color: var(--accent); }
/* File pickers: the Browse pseudo-button wears the primary variant */
input[type="file"] { background: none; border: none; padding: 0; }
input[type="file"]::file-selector-button {
    font-family: var(--font-display); font-weight: 500; font-size: 12px;
    text-transform: capitalize; letter-spacing: .01em;
    background: var(--btn-primary-bg); color: var(--btn-primary-ink);
    border: 2px solid;
    border-color: var(--btn-primary-hi) var(--btn-primary-lo) var(--btn-primary-lo) var(--btn-primary-hi);
    border-radius: 4px; padding: 4px 12px; margin-right: 10px; cursor: pointer;
}

/* ==== SELECT (opt-in wrapper: box themed + CSS chevron; the native
   option list is UA-rendered and follows color-scheme only) ==== */
.select-wrap { position: relative; display: inline-block; }
.select {
    appearance: none; -webkit-appearance: none;
    background: var(--field-bg);
    color: var(--ink);
    border: 1px solid var(--field-border);
    border-radius: 4px;
    font-family: var(--font-body); font-size: 14px;
    padding: 8px 32px 8px 11px; cursor: pointer;
}
.select:focus { outline: none; border-color: var(--focus); box-shadow: 0 0 0 2px var(--focus-ring); }
.select-wrap::after {   /* CSS chevron — no image literal */
    content: ""; position: absolute; right: 12px; top: 50%;
    width: 0; height: 0; transform: translateY(-50%); pointer-events: none;
    border-left: 4px solid transparent; border-right: 4px solid transparent;
    border-top: 5px solid var(--ink-mute);
}

/* money/price/count fields line up like the tables */
.input-num, input[type="number"] {
    font-family: var(--font-display);
    font-variant-numeric: tabular-nums;
    text-align: right;
}
/* Native number spinners are unstyleable in Firefox (no pseudo-element at
   all) and flush-against-the-text in Chromium - so they're hidden and
   replaced by the .spin-wrap custom steppers (wired up in JS, themed,
   with an actual gap). */
input[type="number"] { appearance: textfield; -moz-appearance: textfield; }
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.spin-wrap { display: inline-flex; align-items: center; gap: 6px; vertical-align: middle; }
.spin-wrap > input[type="number"] { min-width: 0; }
.spin-col { display: inline-flex; flex-direction: column; gap: 2px; }
.spin-btn {
    width: 16px; height: 11px; padding: 0; margin: 0;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--surface-inset); color: var(--ink-mute);
    border: 1px solid var(--field-border); border-radius: 2px;
    font-size: 8px; line-height: 1; cursor: pointer;
}
.spin-btn:hover { color: var(--accent); border-color: var(--accent); filter: none; }
/* compact numerics (admin knobs) */
input.input-sm { padding: 4px 6px; }
/* Numeric contexts get tabular figures so columns of prices/stakes align.
   (The one deliberate visual change of Phase 1 beyond the scale itself.) */
.positions-table, .users-table, .eval-table, .ob-row,
.account-stat .value, .market-card .card-price { font-variant-numeric: tabular-nums; }

/* ---- Element classes (Phase 3): the kit for new markup and for the
   JS-template migration. Existing inline styles were swept onto var()
   values and convert to these classes as panels are touched. ---- */
.btn-danger  { background: var(--danger-action); color: var(--on-accent); border-color: transparent; }
/* .btn-info retired 2026-08-06 (never used); informational BOXES keep the
   blue family (--hl/-bg/-border), buttons don't need a blue. */
.panel-intro { font-size: var(--size-muted); color: var(--ink-mute); margin: 0 0 10px 0; }
/* .doc-intro: no reserved height - Andrew prefers a tight intro-to-box gap
   over equal-height LLM doc panels (2026-08-02). */
.hint        { font-size: 12px; color: var(--ink-mute); }
.note-box       { padding: 10px 12px; border-radius: 4px; font-size: var(--size-muted); }
.note-box.warn  { background: var(--warn-bg); border: 1px solid var(--warn-accent); color: var(--warn); }
.note-box.info  { background: var(--hl-bg); border: 1px solid var(--hl-border); color: var(--hl); }
.note-box.error { background: var(--danger-bg); color: var(--danger); }

/* Always reserve the vertical-scrollbar gutter: without this, tabs
   taller than the viewport (Markets) show a scrollbar and shorter
   ones (My Account) don't, so the whole page shifts sideways a few
   pixels on every tab switch. */
html { overflow-y: scroll; }
body {
    font-family: var(--font-body);
    font-size: var(--size-body);
    line-height: var(--lh-body);
    color: var(--ink);
    max-width: var(--page-max);
    margin: 0 auto;
    box-sizing: border-box;   /* min-height:100vh must include the padding
                                 or the pinned footer overshoots by it */
    padding: 0 20px 20px;     /* top padding lives on .site-header (sticky) */
    background-color: var(--surface-page);
}
h1 { font-family: var(--font-display); font-weight: 500; font-size: var(--size-title); line-height: var(--lh-title); letter-spacing: .005em; color: var(--ink-hi); text-align: center; margin-bottom: 12px; }
h2 { font-family: var(--font-display); font-weight: 500; font-size: var(--size-heading); line-height: var(--lh-heading); color: var(--ink-accent); border-bottom: 1px solid var(--border-strong); padding-bottom: 10px; }

/* ---- Toasts (the alert() replacement): banner-styled, top-right ---- */
#toastHost {
    position: fixed; top: 16px; right: 16px; z-index: 3000;
    display: flex; flex-direction: column; gap: 8px;
    max-width: 380px;
}
#toastHost .toast {
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
    opacity: 1; transition: opacity 0.4s;
}
#toastHost .toast.gone { opacity: 0; }

/* ---- App-owned confirm modal ---- */
#modalOverlay {
    position: fixed; inset: 0;
    background: rgba(0, 0, 0, 0.55);
    display: none; align-items: center; justify-content: center;
    z-index: 2000;
}
#modalOverlay.open { display: flex; }

/* ---- Auth overlay ---- */
#authOverlay {
    position: fixed; top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(0,0,0,0.55);
    display: none; align-items: center; justify-content: center;
    z-index: 1000;
}
#authBox {
    position: relative;
    background: var(--surface-panel); padding: 28px;
    border: 2px solid;
    border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
    border-radius: var(--radius);
    box-shadow: 0 4px 16px rgba(0,0,0,0.3);
    width: 360px; max-width: 90vw;
}
#authBox h2 { margin-top: 0; border-bottom: none; }
#authBox input[type="password"] { width: 100%; box-sizing: border-box; margin: 6px 0 12px; }
#authError { color: var(--danger-action); font-size: var(--size-muted); margin-bottom: 8px; min-height: 18px; }

/* Admin's two nav rows pin under the site header (2026-08-19): the
   panes are long, and scrolling one loses both which group you are in
   and the leaf switcher. One sticky wrapper, so the pair travels as a
   block and only one offset has to be measured. --header-h is set from
   JS (core.js) because the header's height moves with wrap + zoom. */
.admin-nav {
    position: sticky; top: 0; z-index: 350;
    background: var(--surface-page);
}
@media (min-width: 1101px) {
    /* Below 1101px the site header is in normal flow, so top:0 is right. */
    .admin-nav { top: var(--header-h, 0px); }
}

/* Page column width. Shared, not per-niche - the notification dropdown
   measures the gutter against it. */
:root { --page-max: 1400px; }

/* ---- Site footer (same voice as the tab row) ---- */
/* Above the auth overlay (2026-08-19): About / T&C / Privacy have to be
   reachable BEFORE you have an account, and the links live down here. */
.site-footer {
    position: relative; z-index: 1001;
    background: var(--surface-panel);
    border-radius: var(--radius);
    border-top: 1px solid var(--border-strong);
    padding: 10px var(--panel-pad);
    margin-top: var(--space-6);
    display: flex; align-items: center; flex-wrap: wrap; gap: 6px 18px;
    font-size: 12px; color: var(--ink-mute);
}
.site-footer .spacer { flex: 1; }

/* ---- Site header: title + banners + tab bar. Pinned on desktop
   (Andrew, 2026-08-17); normal flow below 1101px where vertical space
   is the scarcer resource. ---- */
.site-header { padding-top: 20px; background: var(--surface-page);
               position: relative; }

/* Notification dropdown (2026-08-19). Fixed to the window's right edge and
   sized to the GUTTER beside the centred page column, so on a wide window
   it opens beside what you were reading instead of on top of it. Narrower
   windows have no gutter to sit in, so it overlaps - there is nowhere else
   for it to go, and clamp()'s floor keeps it readable when that happens. */
/* .panel.notif-panel, not .notif-panel: .panel sets position:relative and
   is declared later in this file, so a single-class selector loses on
   source order (it silently did - the dropdown landed on the left). */
.panel.notif-panel {
    position: fixed;
    top: calc(var(--header-h, 64px) + 4px);
    right: 8px;
    z-index: 1000;
    margin: 0;
    /* border-box so the width below is the WHOLE box - .panel adds 24px of
       padding a side, which silently made a 308px panel render 360px wide. */
    box-sizing: border-box;
    width: 380px;
    max-width: calc(100vw - 16px);
    box-shadow: 0 4px 16px rgba(0,0,0,0.35);
}
@media (min-width: 1900px) {
    /* Wide enough that the centred column leaves a usable gutter: shrink
       into it so the dropdown opens BESIDE what you were reading. Below
       this it stays 380px and overlaps - there is nowhere else to put it,
       and a squeezed panel would be worse than an honest overlap. */
    .panel.notif-panel {
        width: min(380px, calc((100vw - var(--page-max)) / 2 - 16px));
    }
}
@media (min-width: 1101px) {
    .site-header { position: sticky; top: 0; z-index: 400; }
}

/* ---- Identity cluster (right side of the main tab row) ---- */
.tab-bar-right {
    margin-left: auto;
    display: flex; align-items: center; gap: 14px;
    padding: 0;   /* align-items:center on the bar does the levelling */
    font-size: var(--size-muted);
}
.tab-bar-right #userBalance {
    font-family: var(--font-display); font-weight: 500;
    font-variant-numeric: tabular-nums; color: var(--ink-hi);
}
.tab-bar-right #identityBadge { color: var(--ink-mute); }
.tab-bar-right select { width: auto; padding: 4px 8px; font-size: 12px; }
.tab-bar-right button.signout {
    background: var(--btn-secondary-bg); color: var(--btn-secondary-ink);
    border-color: var(--btn-secondary-hi) var(--btn-secondary-lo) var(--btn-secondary-lo) var(--btn-secondary-hi);
    padding: 5px 12px; font-size: 12px;
    width: auto; margin: 0;
}

/* ---- Tab bar ---- */
/* ==== TABS (underline style, one accent, every level) ==== */
.tab-row, .tab-bar {
    display: flex; flex-wrap: wrap; gap: 4px;
    padding: 8px 8px 0;
    border-bottom: 1px solid var(--border-strong);
    margin-bottom: 0;
}
/* The main bar carries the identity cluster now — a touch more presence */
.tab-strip { display: contents; }
.tab-bar {
    background: var(--surface-panel);
    border-radius: var(--radius);
    padding: 8px var(--panel-pad) 0;   /* edges align with panel content */
    align-items: center;
    margin-bottom: var(--stack);
}
/* Nav anchors need :visited variants: the global `a:visited` rule ties
   their specificity and sits later in the file, and every internal hash
   is "visited" immediately - without these, the whole nav turned violet
   (the 2026-08-14 anchor conversion's one visible side effect). */
.tab, .tab-bar > button, .subtab-bar button,
.tab-strip a, .subtab-bar a,
.tab-strip a:visited, .subtab-bar a:visited {
    font-family: var(--font-display); font-weight: 500; font-size: 14px;
    color: var(--ink-mute); background: none; cursor: pointer;
    padding: 9px 16px; border: none;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    width: auto; margin: 0 0 -1px 0;
    text-decoration: none; display: inline-block;
}
.tab:hover, .tab-bar > button:hover, .subtab-bar button:hover,
.tab-strip a:hover, .subtab-bar a:hover {
    color: var(--ink); background: none; filter: none;
}
.tab.active, .tab-bar > button.active, .subtab-bar button.active,
.tab-strip a.active, .subtab-bar a.active,
.tab-strip a.active:visited, .subtab-bar a.active:visited {
    color: var(--tab-active); border-bottom-color: var(--tab-active);
    background: none;
}
/* Market list rows + featured cards are real anchors (2026-08-14):
   block layout, inherit ink, no underline - the row IS the link. */
a.market, a.market-card,
a.market:visited, a.market-card:visited {
    display: block; color: inherit; text-decoration: none;
}

/* ---- Tab content ---- */
.tab-pane { display: none; }
.tab-pane.active { display: block; }

/* ---- Sub-tabs (Admin) ---- */
.subtab-bar {
    display: flex; flex-wrap: wrap; gap: 4px;
    padding: 12px var(--panel-pad) 0;
    border-bottom: 1px solid var(--border-strong);
    margin-bottom: 16px;
}
.subtab-pane { display: none; }
.subtab-pane.active { display: block; }

/* ---- Panels ---- */
.panel {
    position: relative;
    background: var(--surface-panel);
    border: 2px solid;
    border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
    border-radius: var(--radius);
    padding: var(--panel-pad);
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    margin-bottom: 16px;
}
.panel::before,
.market-card::before,
#authBox::before {           /* the signature inset line (theme-colored;
                                    transparent in themes without it) */
    content: "";
    position: absolute;
    inset: 5px;
    border: 1px solid var(--panel-line);
    border-radius: calc(var(--radius) - 3px);
    pointer-events: none;
}
/* Identity-framed panels (admin orange) keep their own border — no inset line. */
.panel.admin-panel::before { content: none; }
/* Panel h2s are flex rows (2026-08-16): the action buttons (Refresh,
   Clear, pager...) sit vertically CENTRED with the title text instead of
   top-aligned against the line box, and the first button pushes the whole
   button group to the right edge. DOM order is preserved left-to-right
   (the old float:right stacked multiple buttons in reverse). */
.panel h2 { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; }
.panel h2 button { width: auto; font-size: 12px; padding: 4px 10px; }
.panel h2 button:first-of-type { margin-left: auto; }
/* Even vertical rhythm inside panels: one gap rule instead of per-element
   margins (inline margins on panel children are being stripped as touched).
   .stack is the same rule for panels that wrap their body in an inner div. */
.panel > * + *, .stack > * + * { margin-top: var(--stack); }
.panel > :first-child { margin-top: 0; }   /* the panel's padding IS the gap */
.panel > h2:first-child { margin-top: -4px; }   /* optical: h2 cap-height sits low */
/* Clickable panels share the market-card hover affordance. */
.panel.clickable { cursor: pointer; transition: transform 0.15s, box-shadow 0.15s; }
.panel.clickable:hover { transform: translateY(-2px); box-shadow: 0 4px 10px rgba(0,0,0,0.12); }
.placeholder { color: var(--ink-mute); font-style: italic; }

/* ---- Featured market cards ---- */
.cards-grid {
    display: grid;
    /* minmax(0,...): a bare 1fr track lets the chart canvas's rendered
       width become the track's min-content and feed back wider under
       zoom - the horizontal cousin of the family-card grow loop. */
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 14px;
    margin-bottom: 16px;
}
.market-card canvas { max-width: 100%; }
@media (max-width: 768px) {
    .cards-grid { grid-template-columns: minmax(0, 1fr); }
}
/* Tall screens (1440p-class) get 8 featured slots from the JS - still
   two across, four down: the extra HEIGHT shows more markets; the
   column count never changes. */
.market-card {
    position: relative;
    background: var(--surface-panel);
    border: 2px solid;
    border-color: var(--bevel-hi) var(--bevel-lo) var(--bevel-lo) var(--bevel-hi);
    border-radius: var(--radius);
    padding: var(--panel-pad);
    box-shadow: 0 2px 4px rgba(0,0,0,0.08);
    cursor: pointer;
    transition: transform 0.15s, box-shadow 0.15s;
    display: flex; flex-direction: column;
}
.market-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 10px rgba(0,0,0,0.12);
}
.market-card .card-question {
    font-weight: 600; color: var(--ink-hi);
    margin-bottom: var(--space-2);
    line-height: 1.3;
}
.market-card .card-price {
    font-size: 26px; font-weight: 700; color: var(--accent);
    margin: 2px 0 4px;
}
.market-card .card-volume { font-size: 12px; color: var(--ink-mute); margin-bottom: 8px; }
.market-card .card-chart-wrap { position: relative; height: 110px; }
.market-card .card-empty { color: var(--ink-faint); font-size: 12px; text-align: center; padding-top: 38px; }
/* Family cards (group markets): narrower chart + a right-hand legend
   with option name + current odds (2026-08-15). The card is a flex
   column so the chart row FILLS the card's height (single-market
   neighbours set the grid row height; without this the family chart sat
   jammed at the top). The legend sizes to its content - the chart takes
   whatever width the names leave over; names cap at 16ch and wrap. */
a.market-card.family { display: flex; flex-direction: column; }
.market-card.family .card-chart-row { flex: 1 1 auto; }
.market-card.family .card-chart-wrap { height: auto; min-height: 110px; }
/* The canvas must sit OUTSIDE layout flow: with an auto-height wrap,
   the canvas's rendered height set the wrap's height, the responsive
   chart then resized to fill it, and the card grew forever (the
   classic Chart.js flexbox feedback loop). Absolute = the wrap's size
   comes from the flex row, never from the canvas. */
.market-card.family .card-chart-wrap canvas {
    position: absolute; inset: 0; width: 100% !important; height: 100% !important;
}
.card-chart-row { display: flex; gap: 10px; align-items: stretch; }
.card-chart-row .card-chart-wrap { flex: 1 1 auto; min-width: 0; }
.card-fam-legend {
    flex: 0 0 auto; align-content: center;
    display: grid; grid-template-columns: auto auto auto; gap: 3px 7px;
    font-size: 11px; color: var(--ink);
}
.card-fam-legend .cfl-row { display: contents; }
.card-fam-legend .cfl-name { max-width: 16ch; overflow-wrap: break-word; }
.card-fam-legend .cfl-swatch { width: 10px; height: 10px; border-radius: 2px; align-self: center; }
.card-fam-legend .cfl-odds { justify-self: end; align-self: center; font-variant-numeric: tabular-nums; color: var(--ink-hi); }

/* ---- Market list rows ---- */
.market {
    background: var(--surface-raised);
    padding: 12px;
    margin: 8px 0;
    border-radius: 4px;
    cursor: pointer;
    transition: background 0.2s;
}
.market:hover { background: var(--surface-hover); }
.market.selected { background: var(--accent-soft); border: 2px solid var(--accent); }
.market.resolved { background: var(--surface-inset); opacity: 0.85; }

/* ---- Bids / Matches ---- */
.bid {
    padding: 10px; margin: 5px 0;
    background: var(--surface-inset); border-radius: 4px;
}
.match {
    padding: 10px; margin: 5px 0;
    background: var(--ok-bg); border-radius: 4px;
    border-left: 4px solid var(--yes);
}

/* ---- Detail panel layout (3 columns on desktop, 1 on mobile) ---- */
.detail-grid {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 16px;
}
@media (max-width: 1100px) {
    .detail-grid { grid-template-columns: 1fr; }
}

/* ---- Forms ---- */
input {
    padding: 9px; margin: 4px 0;
    width: 100%; box-sizing: border-box;
}
button { margin: 4px 0; box-sizing: border-box; }   /* default size = auto width */
button {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: 14px;
    letter-spacing: .01em;
    text-transform: capitalize;
    padding: 10px 22px;
    border-radius: 4px;
    border: 2px solid;
    background: var(--btn-primary-bg);
    color: var(--btn-primary-ink);
    border-color: var(--btn-primary-hi) var(--btn-primary-lo) var(--btn-primary-lo) var(--btn-primary-hi);
    cursor: pointer;
}
/* One hover for every variant and theme: brighten whatever the fill is. */
button:hover { filter: brightness(1.15); }
.bid-form { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.btn-primary {
    background: var(--btn-primary-bg); color: var(--btn-primary-ink);
    border-color: var(--btn-primary-hi) var(--btn-primary-lo) var(--btn-primary-lo) var(--btn-primary-hi);
}
.btn-secondary, .invalid-btn {
    background: var(--btn-secondary-bg); color: var(--btn-secondary-ink);
    border-color: var(--btn-secondary-hi) var(--btn-secondary-lo) var(--btn-secondary-lo) var(--btn-secondary-hi);
}
.btn-yes, .yes-btn,
.btn-green {                       /* alias: confirm/execute actions */
    background: var(--btn-yes-bg); color: var(--btn-yes-ink);
    border-color: var(--btn-yes-hi) var(--btn-yes-lo) var(--btn-yes-lo) var(--btn-yes-hi);
}
.btn-no, .no-btn,
.btn-red {                         /* alias: destructive actions */
    background: var(--btn-no-bg); color: var(--btn-no-ink);
    border-color: var(--btn-no-hi) var(--btn-no-lo) var(--btn-no-lo) var(--btn-no-hi);
}
.cancel-btn {
    background: var(--btn-secondary-bg); color: var(--btn-secondary-ink);
    border-color: var(--btn-secondary-hi) var(--btn-secondary-lo) var(--btn-secondary-lo) var(--btn-secondary-hi);
    border: none; border-radius: 4px;
    padding: 3px 8px; font-size: var(--size-label); cursor: pointer;
    float: right; margin-left: 5px; width: auto;
}
.cancel-btn:hover { background: var(--neutral-action-hover); }

/* ==== STATUS BANNER (chip scaled to full width) ==== */
.banner, .status {
    font-family: var(--font-body); font-size: var(--size-muted);
    padding: 10px 14px; border-radius: 4px;
    border-left: 3px solid;              /* severity stripe, like the table */
}
.banner-ok, .status.success { background: var(--ok-bg);     color: var(--ok);     border-left-color: var(--ok); }
.banner-warn                { background: var(--warn-bg);   color: var(--warn);   border-left-color: var(--warn); }
.banner-danger, .status.error { background: var(--danger-bg); color: var(--danger); border-left-color: var(--danger); }
.banner-info                { background: var(--surface-raised); color: var(--ink); border-left-color: var(--accent); }
/* legacy show/hide contract */
.status { display: none; margin: 10px 0; }
.status.success, .status.error { display: block; }

.admin-panel { border: 2px solid var(--admin-accent); }

/* ---- QA harness (a regular panel since the Big List; the QA banner +
   wipe confirm carry the danger signal) ---- */
#qaPanel .qa-row { margin-bottom: 12px; }
#qaPanel input[type="number"], #qaPanel input[type="text"] {
    width: 110px; padding: 4px 6px;
}
#qaPanel button {
    padding: 6px 14px; margin: 3px; width: auto; font-size: var(--size-muted);
}
#qaPanel button.danger {
    background: var(--btn-no-bg); color: var(--btn-no-ink);
    border-color: var(--btn-no-hi) var(--btn-no-lo) var(--btn-no-lo) var(--btn-no-hi);
}
#qaOutput {
    background: var(--terminal-bg); color: var(--terminal-ink);
    font-family: var(--font-mono);
    font-size: 12px; padding: 12px; border-radius: 4px;
    min-height: 80px; max-height: 400px;
    overflow-y: auto; white-space: pre-wrap;
    margin-top: 10px;
}

/* ---- Recent Events ---- */
#eventLogList .event-row {
    display: flex; align-items: baseline; gap: 10px;
    padding: 6px 0; border-bottom: 1px solid var(--border);
    font-size: var(--size-muted);
}
#eventLogList .event-row:last-child { border-bottom: none; }
#eventLogList .event-time {
    color: var(--ink-mute); font-family: var(--font-mono);
    font-size: 12px; white-space: nowrap;
}
/* Log chips are plain .chip-*; the severity mapping happens at render
   time in eventChipClass(). white-space guard for long event types. */
#eventLogList .chip { white-space: nowrap; }

/* ---- My Account ---- */
.account-header-card {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr;
    gap: 12px;
    margin-top: 6px;
}
.account-stat {
    background: var(--surface-raised);
    border: 1px solid var(--border-mid);
    border-radius: 4px;
    padding: 10px 12px;
}
.account-stat .label { font-size: var(--size-label); color: var(--ink-mute); text-transform: uppercase; letter-spacing: 0.5px; }
.account-stat .value { font-size: 20px; font-weight: 700; color: var(--ink-hi); margin-top: 4px; }
.account-stat .sub   { font-size: var(--size-label); color: var(--ink-mute); margin-top: 2px; }
.account-stat.pos .value { color: var(--ok); }
.account-stat.neg .value { color: var(--danger); }
/* ---- DATA TABLE (shared: transactions, positions, accounts — the
   legacy table classes ride the same base) ---- */
a { color: var(--link); }
a:visited { color: var(--link); }

.data-table, .positions-table, .users-table {
    width: 100%; border-collapse: collapse; font-family: var(--font-body);
}
.data-table th, .positions-table th, .users-table th {
    font-size: var(--size-label); font-weight: 500; letter-spacing: .07em; text-transform: uppercase;
    color: var(--ink-mute); text-align: left; padding: var(--cell-pad);
    border-bottom: 1px solid var(--border-strong);
}
.data-table td, .positions-table td, .users-table td {
    font-size: var(--size-muted); color: var(--ink); padding: var(--cell-pad);
    border-bottom: 1px solid var(--border);
}
.data-table.dense th, .data-table.dense td,
.positions-table.dense th, .positions-table.dense td,
.users-table.dense th, .users-table.dense td { padding: var(--cell-pad-dense); }
.data-table tbody tr:last-child td,
.positions-table tbody tr:last-child td,
.users-table tbody tr:last-child td { border-bottom: none; }

/* numeric columns — put .num on both th and td */
.data-table .num, .positions-table .num, .users-table .num {
    text-align: right; font-family: var(--font-display);
    font-variant-numeric: tabular-nums; color: var(--ink-hi);
}
/* headers keep the header voice, aligned over their numbers */
.data-table th.num, .positions-table th.num, .users-table th.num {
    font-family: var(--font-body); color: var(--ink-mute);
}
.num.pos { color: var(--ok); }      /* directional deltas, on top of .num */
.num.neg { color: var(--danger); }

/* code-like identifiers (type, reference) */
.cell-mono { font-family: var(--font-mono); color: var(--ink-mute); }

/* interactive rows only */
tr.row-link { cursor: pointer; }
tr.row-link:hover { background: var(--surface-raised); }

/* left side-stripe on the first cell */
.data-table td.side-yes, .positions-table td.side-yes { border-left: 3px solid var(--ok); }
.data-table td.side-no,  .positions-table td.side-no  { border-left: 3px solid var(--danger); }

/* ---- STATUS CHIP (reused by status messages later) ---- */
.chip { display: inline-block; font-family: var(--font-body); font-size: var(--size-label); font-weight: 500; padding: 2px 9px; border-radius: 3px; }
.chip-ok     { background: var(--ok-bg);          color: var(--ok); }
.chip-warn   { background: var(--warn-bg);        color: var(--warn); }
.chip-danger { background: var(--danger-bg);      color: var(--danger); }
.chip-info   { background: var(--info-bg);        color: var(--info); }
.chip-muted  { background: var(--surface-raised); color: var(--ink-mute); }
.positions-table tr.side-yes td:first-child { border-left: 3px solid var(--yes); }
.positions-table tr.side-no  td:first-child { border-left: 3px solid var(--no); }
.question-link {
    color: var(--link); cursor: pointer; text-decoration: none;
}
.question-link:hover { text-decoration: underline; }
.positions-table .outcome-yes { color: var(--ok); font-weight: 600; }
.positions-table .outcome-no  { color: var(--danger); font-weight: 600; }
.positions-table .outcome-invalid { color: var(--warn); font-weight: 600; }
.positions-table .pnl-pos { color: var(--ok); font-weight: 600; }
.positions-table .pnl-neg { color: var(--danger); font-weight: 600; }
@media (max-width: 720px) {
    .account-header-card { grid-template-columns: 1fr 1fr; }
}
#eventLogList .event-row.verbose .event-msg,
#eventLogList .event-row.verbose .event-time { color: var(--ink-mute); }
#eventLogList .event-msg { flex: 1; color: var(--ink-hi); }

/* ---- Back Office users table ---- */
.users-table tr:hover { background: var(--surface-raised); }
.users-table .qa-row { background: var(--accent-soft); }

/* Disabled buttons read as disabled (e.g. Submit Evals while a run
   is in flight — makes "did I actually click?" answerable at a glance) */
button:disabled { opacity: 0.45; cursor: not-allowed; }

/* ---- BUTTON SIZES — compose with the color variants ---- */
.btn-mini {            /* in-table actions: CSV / Open / Del, Edit, Promote */
    font-size: 12px;
    padding: 4px 10px;
    border-width: 1px;   /* thinner bevel reads right at small size */
    width: auto;
}
.btn-block {           /* full-width form submits: Submit Question, Bid Yes/No, Resolve */
    display: block;
    width: 100%;
    padding: 10px 0;
}
/* .btn-export retired 2026-08-06: two barely-distinguishable greens is a
   distinction nobody can read. Export/retrieve actions wear .btn-green. */
/* Equal-width button groups (pagers, paired actions): same min-width,
   text still grows the odd long one. */
.btn-eq    { min-width: 96px; }
.btn-eq-sm { min-width: 56px; }

/* ---- Submit Question ---- */
.last-submission {
    margin-top: 16px;
    padding: 12px;
    background: var(--surface-page);
    border-radius: 4px;
    font-size: 14px;
}
.last-submission .ls-label { color: var(--ink-mute); font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px; }
.last-submission .ls-status { color: var(--accent); font-weight: 600; }
.last-submission .ls-status.queued { color: var(--warn); }

/* ---- Project Status ---- */
.ps-section-label {
    font-size: var(--size-muted); text-transform: uppercase; letter-spacing: 0.5px;
    color: var(--ink-mute); margin: 22px 0 10px; font-weight: 600;
}
.ps-section-label:first-child { margin-top: 0; }
.ps-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 900px) { .ps-grid { grid-template-columns: 1fr; } }
.ps-module {
    border-radius: 6px; padding: 12px 14px;
    border-left: 3px solid var(--border-strong);
    background: var(--surface-raised);
}
.ps-module.be { border-left-color: var(--yes); }        /* green = BE */
.ps-module.fe { border-left-color: var(--no); }         /* red/peach = FE */
.ps-module.platform { border-left-color: var(--accent); } /* violet = platform */
.ps-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; gap: 8px; }
.ps-label { font-weight: 700; color: var(--ink-hi); font-size: 14px; }
.ps-meta { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.ps-tests { font-size: var(--size-label); color: var(--ink-mute); }
.ps-tests.has { color: var(--ok); font-weight: 600; }
.ps-badge {   /* a .chip carrying build state */
    display: inline-block; font-family: var(--font-body);
    font-size: var(--size-label); font-weight: 500;
    padding: 2px 9px; border-radius: 3px; white-space: nowrap;
}
.ps-badge.complete { background: var(--ok-bg); color: var(--ok); }
.ps-badge.basic    { background: var(--warn-bg); color: var(--warn); }
.ps-badge.missing  { background: var(--danger-bg); color: var(--danger); }
.ps-done, .ps-todo { font-size: var(--size-muted); line-height: 1.4; margin: 3px 0; color: var(--ink); }
.ps-done strong { color: var(--ok); }
.ps-todo strong { color: var(--warn); }
.ps-note { font-size: 12px; color: var(--ink-mute); font-style: italic; margin-bottom: 14px; }
/* Per-card notes */
.ps-notes {
    margin-top: 10px;
    padding-top: 8px;
    border-top: 1px dashed rgba(0,0,0,0.12);
    font-size: 12px;
}
.ps-notes-view {
    color: var(--ink);
    cursor: pointer;
    padding: 4px 0;
    white-space: pre-wrap;
    word-break: break-word;
}
.ps-notes-view:hover { color: var(--ink-hi); }
.ps-notes-view.empty {
    color: var(--ink-faint);
    font-style: italic;
}
.ps-notes-view .ps-notes-prefix {
    display: inline-block;
    margin-right: 6px;
    color: var(--ink-mute);
    font-style: normal;
}
.ps-notes-edit { display: none; margin-top: 4px; }
.ps-notes-edit.active { display: block; }
.ps-notes-edit textarea {
    width: 100%;
    min-height: 70px;
    box-sizing: border-box;
    font-family: inherit;
    font-size: 12px;
    padding: 6px 8px;
    border: 1px solid var(--field-border);
    border-radius: 3px;
    resize: vertical;
}
.ps-notes-actions {
    display: flex;
    gap: 6px;
    margin-top: 4px;
}
.ps-notes-actions button {
    width: auto;
    padding: 3px 12px;
    font-size: var(--size-label);
    margin: 0;
}
.ps-notes-actions .cancel { background: var(--neutral-action); }
.ps-notes-actions .cancel:hover { background: var(--neutral-action-hover); }

/* ---- Admin > Glossary + System Prompt (long-form notes) ---- */
.admin-notes-textarea {
    width: 100%;
    height: 440px;        /* uniform across Glossary/Policy/Prompt/Sources/
                             Dimensions/Models; still drag-resizable */
    min-height: 360px;
    box-sizing: border-box;
    font-family: var(--font-mono);
    font-size: var(--size-muted);
    line-height: 1.5;
    padding: 10px 12px;
    border: 1px solid var(--border-strong);
    border-radius: 3px;
    resize: vertical;
}
.admin-notes-actions {
    margin-top: 10px;
    display: flex;
    align-items: center;
}
.admin-notes-actions button {
    width: auto;
    padding: 6px 18px;
    font-size: var(--size-muted);
    margin: 0;
}

/* Evals table — looser than positions-table for inline editing */
.eval-table th, .eval-table td { vertical-align: top; padding: 8px 6px; }
.eval-table textarea, .eval-table input, .eval-table select {
    font-family: inherit;
    font-size: var(--size-muted);
    padding: 4px 6px;
    border: 1px solid var(--field-border);
    border-radius: 3px;
    box-sizing: border-box;
}
/* Textareas: drag-to-resize vertical (corner handle), no scrollbar
   (autogrow keeps the height fitted; if the user drags shorter, they
   can drag it back rather than scrolling). */
.eval-table textarea {
    resize: vertical;
    overflow: hidden;
}
/* # column: narrow input, no spinner arrows, no drag handle */
.eval-table .eval-qn {
    width: 48px;
    -moz-appearance: textfield;
    resize: none;
}
.eval-table .eval-qn::-webkit-outer-spin-button,
.eval-table .eval-qn::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
/* Verdict column: just wide enough for "FAIL → redirect" */
.eval-table .eval-verdict { width: 130px; }
/* Per-row Del button — vertical-only; one column-wide. */
.eval-table .eval-delete-btn {
    display: block;
    width: 56px;
    padding: 4px 6px;
    font-size: 12px;
    margin: 0;
}

/* ---- Specific market detail view ---- */
.back-link {
    display: inline-block;
    color: var(--accent);
    text-decoration: none;
    font-size: var(--size-muted);
    margin-bottom: 8px;
}
.back-link:hover { text-decoration: underline; }

.order-book-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 18px;
    margin-top: 8px;
}
@media (max-width: 700px) {
    .order-book-grid { grid-template-columns: 1fr; }
    /* Stacked = no mirror symmetry: NO bars grow from the left too. */
    .ob-no .ob-depth { right: auto; left: 0; }
}
.order-book-side h3 {
    margin: 0 0 6px;
    font-size: var(--size-muted);
    padding-bottom: 4px;
    border-bottom: 1px solid var(--border);
}
.ob-yes-head { color: var(--yes); }
.ob-no-head  { color: var(--no); }
.ob-subtle { font-size: 12px; color: var(--ink-mute); font-weight: normal; }
/* ---- ORDER BOOK (row + depth bar) ---- */
.ob-row {
    position: relative; display: grid; grid-template-columns: auto 1fr auto auto; gap: 12px;
    align-items: center; padding: 7px 12px; font-family: var(--font-body);
    font-size: var(--size-muted); border-bottom: 1px solid var(--border);
}
.ob-actions { display: flex; gap: 4px; }
.ob-row:last-child { border-bottom: none; }
.ob-row > * { position: relative; z-index: 1; }              /* text above the bar */
.ob-depth   { position: absolute; top: 0; bottom: 0; width: var(--depth, 0%); z-index: 0; pointer-events: none; }
.ob-yes .ob-depth { left: 0;  background: color-mix(in srgb, var(--ok) 16%, transparent); }
.ob-no  .ob-depth { right: 0; background: color-mix(in srgb, var(--danger) 16%, transparent); }
.ob-price { font-family: var(--font-display); font-variant-numeric: tabular-nums; font-weight: 500; color: var(--ink-hi); }
.ob-vol   { text-align: right; font-family: var(--font-display); font-variant-numeric: tabular-nums; color: var(--ink); }
.ob-bids  { color: var(--ink-mute); font-size: var(--size-label); }
.ob-empty { color: var(--ink-faint); font-style: italic; padding: 6px 0; font-size: var(--size-muted); }

.qa-note-bar {
    background: var(--qa-bg);
    border-left: 4px solid var(--warn-accent);
    color: var(--warn);
    padding: 8px 14px;
    border-radius: 4px;
    font-size: 12px;
    margin-bottom: 12px;
}

/* Site-wide indicator when QA mode is on. Deliberately small. */
#qaActiveBanner, #gateOffBanner {
    display: none;
    background: var(--warn-bg);
    border: 1px solid var(--warn-accent);
    color: var(--warn);
    padding: 4px 10px;
    border-radius: 4px;
    font-size: 12px;
    text-align: center;
    margin-bottom: 10px;
}
#qaActiveBanner a, #gateOffBanner a { color: var(--warn); text-decoration: underline; }

/* QA mode toggle block at the top of the QA panel */
.qa-mode-toggle {
    background: var(--surface-panel);
    border: 1px solid var(--warn-accent);
    border-radius: 4px;
    padding: 12px 14px;
    margin-bottom: 14px;
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
}
.qa-mode-toggle .qa-mode-label {
    font-weight: 700;
    color: var(--ink);
}
.qa-mode-toggle .qa-mode-state {
    font-weight: 700;
    padding: 2px 10px;
    border-radius: 10px;
    font-size: 12px;
    text-transform: uppercase;
}
.qa-mode-toggle .qa-mode-state.on  { background: var(--ok-bg); color: var(--ok); }
.qa-mode-toggle .qa-mode-state.off { background: var(--danger-bg); color: var(--danger); }
.qa-mode-toggle button {
    padding: 6px 14px;
    width: auto;
    font-size: var(--size-muted);
    margin: 0;
}
.qa-mode-toggle .qa-mode-source {
    color: var(--ink-mute);
    font-size: 12px;
    margin-left: auto;
}
#qaPanelBody.disabled { display: none; }

/* Visual lock for the Place a Bid panel when acting as a QA user.
   Functional lock is in placeBid() / cancelBid(); this is just the
   "you can see what you can't do" cue. */
#bidPanel.qa-locked input,
#bidPanel.qa-locked button { opacity: 0.5; cursor: not-allowed; }
#qaOffMessage { color: var(--ink); padding: 10px 0; }

/* ============================================================================
   RESPONSIVE — player-facing surfaces only (2026-08-16). Admin stays
   desktop-only on purpose: operator tooling, one audience, and eval
   scorecards were never going to read well at 360px. Target devices:
   360x740 / 393x873 / 414x896 phones (portrait) and 1366x768 laptops
   (which the desktop layout already fits).
   ========================================================================== */

/* ---- Navigation: two rows on phones. Row 1 = identity (balance, name,
   sign out), row 2 = the tab strip, horizontally scrollable when the
   tabs outgrow the width. ---- */
@media (max-width: 1100px) {
    .tab-bar { padding: 0 10px; }
    .tab-bar-right {
        order: -1;                    /* identity row first */
        flex-basis: 100%;
        justify-content: center;      /* centred cluster (Andrew, 2026-08-16) */
        flex-wrap: wrap;
        gap: 10px;
        padding: 10px 0;              /* equidistant above/below the row */
    }
    .tab-strip {
        display: flex;                /* was display:contents on desktop */
        flex-basis: 100%;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;        /* the underline on the active tab is
                                         the scroll affordance; a scrollbar
                                         under the nav reads as clutter */
    }
    .tab-strip::-webkit-scrollbar { display: none; }
    .tab-strip a { white-space: nowrap; padding: 9px 12px; }
    /* Scroll affordance: the right edge fades over the cut-off tab, which
       reads as "more this way". JS clears it at the end of the scroll. */
    .tab-strip {
        mask-image: linear-gradient(to right, black calc(100% - 36px), transparent);
        -webkit-mask-image: linear-gradient(to right, black calc(100% - 36px), transparent);
    }
    .tab-strip.scroll-end { mask-image: none; -webkit-mask-image: none; }
    #tabStripHint {
        display: block; position: absolute; right: 6px; bottom: 8px;
        color: var(--accent); font-size: 16px; pointer-events: none;
        text-shadow: 0 0 6px var(--surface-panel);
    }
    .tab-bar { position: relative; }
    #tabStripHint.scroll-end { display: none; }
}

/* Panels breathe less on small screens */
@media (max-width: 640px) {
    :root { --panel-pad: var(--space-4); }
    body { padding: 0 8px 8px; }
    .site-header { padding-top: 8px; }
    h1 { font-size: 20px; }
}

/* ---- Specific market: stack the YES/NO buttons ---- */
@media (max-width: 480px) {
    .bid-form { grid-template-columns: 1fr; }
    .account-header-card { grid-template-columns: 1fr; }
}

/* ---- Family Options table: two rows per option on phones.
   Row 1: swatch · option · odds · vol · status
   Row 2: Amount [ ] · Price 0.[ ] · Bid YES · Bid NO
   Header row hides; the .fl-label spans (markup-borne, i18n-keyed)
   surface instead. ---- */
.fl-label { display: none; }
@media (max-width: 770px) {
    #familyLegsList table, #familyLegsList tbody { display: block; width: 100%; }
    #familyLegsList thead { display: none; }
    #familyLegsList tr {
        display: flex; flex-wrap: wrap;
        gap: 4px 10px;
        align-items: center;
        padding: 8px 0;
        border-bottom: 1px solid var(--border);
    }
    #familyLegsList td { display: block; border: none; padding: 0; width: auto; }
    /* Cells: 1 swatch · 2 option · 3 odds · 4 vol · 5 status · 6 amount ·
       7 price · 8 buttons. The option is the only grower: when line 1
       runs out of width the stats wrap under it (option becomes the
       title line) - the requested 2-line -> 3-line degradation with no
       extra breakpoint. */
    #familyLegsList td:nth-child(2) { flex: 1 1 auto; min-width: 150px; overflow-wrap: anywhere; }
    #familyLegsList td:nth-child(3), #familyLegsList td:nth-child(4),
    #familyLegsList td:nth-child(5), #familyLegsList td:nth-child(6),
    #familyLegsList td:nth-child(7) { white-space: nowrap; }
    /* Full-width zero-height flex item = a forced line break: the bid
       controls always start their own line. */
    #familyLegsList tr::before { content: ''; order: 9; flex-basis: 100%; height: 0; }
    #familyLegsList td:nth-child(6) { order: 10; }
    #familyLegsList td:nth-child(7) { order: 11; }
    #familyLegsList td:nth-child(8) {
        order: 12; display: flex; gap: 8px; flex: 1 1 auto;
        min-width: 150px; justify-content: flex-end;
    }
    #familyLegsList td:nth-child(8) button { flex: 0 1 110px; width: auto; }
    .fl-label { display: inline; font-size: 11px; color: var(--ink-mute); }
}

/* Desktop family table: uniform column widths after Option, so the data
   columns line up instead of auto-sizing unevenly. */
#familyLegsList th.flw, #familyLegsList td.flw { width: 92px; }

#accountTxPager { display: inline-flex; align-items: center; gap: 6px; margin-left: auto; }
.panel h2 #accountTxPager button:first-of-type { margin-left: 0; }
/* Phone widths: the WHEN/TYPE/AMOUNT table overflows at 360-393 - TYPE
   moves into the expandable detail (always present there) and the main
   row keeps when + amount. */
@media (max-width: 420px) {
    #accountTransactions thead th:nth-child(2),
    #accountTransactions tbody tr > td:nth-child(2) { display: none; }
}

/* ---- My Account, Open Positions: two rows per entry on phones.
   Row 1: market title + side chip; row 2: the labeled numbers.
   From 770 (2026-08-17): at 641-770 the seven-column table left almost
   no room for the title. ---- */
@media (max-width: 770px) {
    #accountOpenPositions table, #accountOpenPositions tbody { display: block; width: 100%; }
    #accountOpenPositions thead { display: none; }
    #accountOpenPositions tr {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        gap: 2px 10px;
        padding: 8px 0;
        border-bottom: 1px solid var(--border);
        align-items: baseline;
    }
    #accountOpenPositions td { display: block; border: none; padding: 0; }
    #accountOpenPositions td:nth-child(1) { grid-column: 1; grid-row: 1; }
    #accountOpenPositions td:nth-child(2) { grid-column: 2; grid-row: 1; text-align: right; }
    #accountOpenPositions td:nth-child(n+3) {
        grid-column: 1 / 3; grid-row: auto;
        display: flex; justify-content: space-between;
        font-size: 13px;
    }
    #accountOpenPositions .fl-label { display: inline; }

    /* Closed Positions: same two-block treatment (it was squeezing seven
       columns into 360px - one character per line in the market cell). */
    #accountClosedPositions table, #accountClosedPositions tbody { display: block; width: 100%; }
    #accountClosedPositions thead { display: none; }
    #accountClosedPositions tr {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        gap: 2px 10px;
        padding: 8px 0;
        border-bottom: 1px solid var(--border);
        align-items: baseline;
    }
    #accountClosedPositions td { display: block; border: none; padding: 0; }
    #accountClosedPositions td:nth-child(1) { grid-column: 1; grid-row: 1; }
    #accountClosedPositions td:nth-child(2) { grid-column: 2; grid-row: 1; text-align: right !important; }
    #accountClosedPositions td:nth-child(n+3) {
        grid-column: 1 / 3; grid-row: auto;
        display: flex; justify-content: space-between;
        font-size: 13px; text-align: left !important;
    }
    #accountClosedPositions .fl-label { display: inline; }
}

/* Long market titles wrap everywhere rather than pushing layouts wide */
.market strong, .market-card .card-question, .question-link {
    overflow-wrap: anywhere;
}

/* Footer pinned to the viewport bottom on short pages - all widths
   (clearest on Question Voting). JS overrides min-height under zoom. */
body { display: flex; flex-direction: column; min-height: 100vh; }
body > * { flex-shrink: 0; }
.site-footer { margin-top: auto; }
.site-footer .footer-left { flex: 1 1 auto; min-width: 0; }
.site-footer .footer-right { margin-left: auto; text-align: right; flex: 0 1 auto; min-width: 0; }
.site-footer .footer-left a, .site-footer .footer-right a { overflow-wrap: anywhere; }
.site-footer .footer-left div, .site-footer .footer-right div { margin: 1px 0; }
@media (max-width: 640px) {
    .site-footer {
        flex-direction: column; align-items: flex-start; gap: 4px;
    }
    .site-footer .footer-right { margin-left: 0; text-align: left; }
    .site-footer .spacer { display: none; }
    /* Scroll-down hint: a fixed fade at the viewport bottom while there is
       more page below; JS removes it at (or near) the end. */
    #scrollDownHint {
        position: fixed; left: 0; right: 0; bottom: 0; height: 28px;
        pointer-events: none; z-index: 500;
        background: linear-gradient(to bottom, transparent, var(--surface-page));
    }
    #scrollDownHint.at-bottom { display: none; }
}
@media (min-width: 641px) {
    #scrollDownHint { display: none; }
}
@media (min-width: 1101px) {
    #tabStripHint { display: none; }
}

/* Large-screen upscale lives in JS (_applyPageZoom in core.js): the CSS
   zoom:calc(100vw/1920px) version silently never applied - zoom does not
   accept length-division calc. JS sets body.style.zoom (1.0 at 1920 ->
   2.0 at 3840, capped) and compensates min-height, since vh units do not
   shrink under zoom. */

/* ============================================================
   PIPE FRAMING (2026-09-04) - hook for the Broodwar-style
   pipe-framed panel treatment. The admin-only preview route
   #account-pipes renders the live My Account page with this
   modifier class on the pane root; the design iterates HERE (plus
   theme-file tokens if new colors are needed), nowhere else.
   Desktop-only by design - phones keep the plain panels.
   ============================================================ */
@media (min-width: 1100px) {
    /* Corners-only framing (Andrew, 2026-09-06 - full-perimeter piping
       judged too much). The brackets are CHROME around the box,
       straddling the panel border from OUTSIDE (the SC unit-panel
       reference). FOUR separate images on purpose: the source sheet is
       mirrored only around its vertical centre and per-corner variants
       are a kept option. Assets are 2x (scripts/build_pipes.py).

       KNOBS live on .pipe-frame (the pane) so the preview page's live
       knob bar can override them with inline styles - a declaration on
       .panel itself would beat the inherited value. Iterate here or on
       #account-pipes; keep the two in sync when committing. */
    .pipe-frame {
        /* FULLY per-corner knobs (Andrew, 2026-09-07 - no control may
           affect more than one corner; the four arts differ and each
           earns its own fit). ox/oy = how far outside the panel edge;
           jog/bh parameterise that corner's red-line path. Defaults =
           Andrew's tuned values. */
        --pipe-tl-w: 100px; --pipe-tl-ox: 5px; --pipe-tl-oy: 6px; --pipe-tl-jog: 12px; --pipe-tl-cut: 8px; --pipe-tl-bh: 36px;
        --pipe-tr-w: 100px; --pipe-tr-ox: 5px; --pipe-tr-oy: 6px; --pipe-tr-jog: 12px; --pipe-tr-cut: 8px; --pipe-tr-bh: 36px;
        --pipe-bl-w: 100px; --pipe-bl-ox: 5px; --pipe-bl-oy: 6px; --pipe-bl-jog: 12px; --pipe-bl-cut: 8px; --pipe-bl-bh: 36px;
        --pipe-br-w: 100px; --pipe-br-ox: 5px; --pipe-br-oy: 6px; --pipe-br-jog: 12px; --pipe-br-cut: 8px; --pipe-br-bh: 36px;
        /* Secondary (tier-2) piping - its own group, uniform. */
        --pipe2-corner-w: 75px; --pipe2-ox: 5px; --pipe2-oy: 6px;
        /* The red line rect's own offsets. */
        --pipe-line-x: 5px; --pipe-line-top: 5px; --pipe-line-bottom: 5px;
    }
    .pipe-frame .panel.pipe-1,
    .pipe-frame .panel.pipe-2 {
        border-radius: 0;
        position: relative;          /* .panel already is; load-bearing here */
        /* Room between stacked panels so outset brackets don't collide. */
        margin-bottom: 36px;
    }
    /* BW's red line ADAPTS to the brackets. Fourth geometry
       (2026-09-07): the block's upper shoulder is BEVELLED in the final
       art, so the square corner into the bypass becomes a small CUT-IN
       diagonal (per-corner --pipe-*-cut) - constant clearance all the
       way around: edge, cut in, bypass past the block, cut out, edge.
       16 layers: 4 edges + per corner cut-in, bypass, cut-out. A 45deg
       gradient band draws "\", 135deg "/"; a band ENDS half-clipped at
       its tile corner, so every straight segment overlaps 1px into the
       neighbouring diagonal tile - the joins read continuous. */
    .pipe-frame .panel.pipe-1::before {
        --j-tl: var(--pipe-tl-jog); --j-tr: var(--pipe-tr-jog);
        --j-bl: var(--pipe-bl-jog); --j-br: var(--pipe-br-jog);
        --c-tl: var(--pipe-tl-cut); --c-tr: var(--pipe-tr-cut);
        --c-bl: var(--pipe-bl-cut); --c-br: var(--pipe-br-cut);
        --b-tl: var(--pipe-tl-bh); --b-tr: var(--pipe-tr-bh);
        --b-bl: var(--pipe-bl-bh); --b-br: var(--pipe-br-bh);
        inset: var(--pipe-line-top, 5px) var(--pipe-line-x, 5px)
               var(--pipe-line-bottom, 5px) var(--pipe-line-x, 5px);
        border: none;
        border-radius: 0;
        background-color: transparent;
        background-image:
            /* edges: top, bottom, left, right */
            linear-gradient(var(--panel-line), var(--panel-line)),
            linear-gradient(var(--panel-line), var(--panel-line)),
            linear-gradient(var(--panel-line), var(--panel-line)),
            linear-gradient(var(--panel-line), var(--panel-line)),
            /* TL: cut-in "/", bypass, cut-out "/" */
            linear-gradient(135deg, transparent calc(50% - 0.5px), var(--panel-line) calc(50% - 0.5px), var(--panel-line) calc(50% + 0.5px), transparent calc(50% + 0.5px)),
            linear-gradient(var(--panel-line), var(--panel-line)),
            linear-gradient(135deg, transparent calc(50% - 0.5px), var(--panel-line) calc(50% - 0.5px), var(--panel-line) calc(50% + 0.5px), transparent calc(50% + 0.5px)),
            /* TR: "\" pair */
            linear-gradient(45deg, transparent calc(50% - 0.5px), var(--panel-line) calc(50% - 0.5px), var(--panel-line) calc(50% + 0.5px), transparent calc(50% + 0.5px)),
            linear-gradient(var(--panel-line), var(--panel-line)),
            linear-gradient(45deg, transparent calc(50% - 0.5px), var(--panel-line) calc(50% - 0.5px), var(--panel-line) calc(50% + 0.5px), transparent calc(50% + 0.5px)),
            /* BL: "\" pair */
            linear-gradient(45deg, transparent calc(50% - 0.5px), var(--panel-line) calc(50% - 0.5px), var(--panel-line) calc(50% + 0.5px), transparent calc(50% + 0.5px)),
            linear-gradient(var(--panel-line), var(--panel-line)),
            linear-gradient(45deg, transparent calc(50% - 0.5px), var(--panel-line) calc(50% - 0.5px), var(--panel-line) calc(50% + 0.5px), transparent calc(50% + 0.5px)),
            /* BR: "/" pair */
            linear-gradient(135deg, transparent calc(50% - 0.5px), var(--panel-line) calc(50% - 0.5px), var(--panel-line) calc(50% + 0.5px), transparent calc(50% + 0.5px)),
            linear-gradient(var(--panel-line), var(--panel-line)),
            linear-gradient(135deg, transparent calc(50% - 0.5px), var(--panel-line) calc(50% - 0.5px), var(--panel-line) calc(50% + 0.5px), transparent calc(50% + 0.5px));
        background-repeat: no-repeat;
        background-position:
            left calc(var(--j-tl) + var(--c-tl) - 1px) top 0,
            left calc(var(--j-bl) + var(--c-bl) - 1px) bottom 0,
            left 0 top calc(var(--b-tl) - 1px),
            right 0 top calc(var(--b-tr) - 1px),
            /* TL */
            left var(--j-tl) top 0,
            left var(--j-tl) top calc(var(--c-tl) - 1px),
            left 0 top calc(var(--b-tl) - var(--j-tl)),
            /* TR */
            right var(--j-tr) top 0,
            right var(--j-tr) top calc(var(--c-tr) - 1px),
            right 0 top calc(var(--b-tr) - var(--j-tr)),
            /* BL */
            left var(--j-bl) bottom 0,
            left var(--j-bl) bottom calc(var(--c-bl) - 1px),
            left 0 bottom calc(var(--b-bl) - var(--j-bl)),
            /* BR */
            right var(--j-br) bottom 0,
            right var(--j-br) bottom calc(var(--c-br) - 1px),
            right 0 bottom calc(var(--b-br) - var(--j-br));
        background-size:
            calc(100% - var(--j-tl) - var(--c-tl) - var(--j-tr) - var(--c-tr) + 2px) 1px,
            calc(100% - var(--j-bl) - var(--c-bl) - var(--j-br) - var(--c-br) + 2px) 1px,
            1px calc(100% - var(--b-tl) - var(--b-bl) + 2px),
            1px calc(100% - var(--b-tr) - var(--b-br) + 2px),
            /* TL */
            var(--c-tl) var(--c-tl),
            1px calc(var(--b-tl) - var(--j-tl) - var(--c-tl) + 2px),
            var(--j-tl) var(--j-tl),
            /* TR */
            var(--c-tr) var(--c-tr),
            1px calc(var(--b-tr) - var(--j-tr) - var(--c-tr) + 2px),
            var(--j-tr) var(--j-tr),
            /* BL */
            var(--c-bl) var(--c-bl),
            1px calc(var(--b-bl) - var(--j-bl) - var(--c-bl) + 2px),
            var(--j-bl) var(--j-bl),
            /* BR */
            var(--c-br) var(--c-br),
            1px calc(var(--b-br) - var(--j-br) - var(--c-br) + 2px),
            var(--j-br) var(--j-br);
    }
    /* ::AFTER: the brackets. Per-corner size + dx/dy nudges (inward
       from the global outset), since the four corner arts differ. */
    .pipe-frame .panel.pipe-1::after {
        content: '';
        position: absolute;
        /* Fixed 40px overhang box; each corner positions itself at its
           OWN outset inside it (outsets above 40px would clip). */
        inset: -40px;
        pointer-events: none;
        z-index: 2;
        background-image:
            url('/static/pipes/corner-tl.png'),
            url('/static/pipes/corner-tr.png'),
            url('/static/pipes/corner-bl.png'),
            url('/static/pipes/corner-br.png');
        background-repeat: no-repeat;
        background-position:
            top calc(40px - var(--pipe-tl-oy)) left calc(40px - var(--pipe-tl-ox)),
            top calc(40px - var(--pipe-tr-oy)) right calc(40px - var(--pipe-tr-ox)),
            bottom calc(40px - var(--pipe-bl-oy)) left calc(40px - var(--pipe-bl-ox)),
            bottom calc(40px - var(--pipe-br-oy)) right calc(40px - var(--pipe-br-ox));
        background-size:
            var(--pipe-tl-w) auto,
            var(--pipe-tr-w) auto,
            var(--pipe-bl-w) auto,
            var(--pipe-br-w) auto;
    }
    /* Tier 2 (2026-09-07): the lighter elbow art for lesser panels -
       no joint block, so the signature line stays its ordinary rect
       (just squared to match). Tier 3 is an unclassed .panel: untouched. */
    .pipe-frame .panel.pipe-2::before {
        border-radius: 0;
        inset: var(--pipe-line-top, 5px) var(--pipe-line-x, 5px)
               var(--pipe-line-bottom, 5px) var(--pipe-line-x, 5px);
    }
    .pipe-frame .panel.pipe-2::after {
        content: '';
        position: absolute;
        inset: calc(-1 * var(--pipe2-oy)) calc(-1 * var(--pipe2-ox));
        pointer-events: none;
        z-index: 2;
        background-image:
            url('/static/pipes/corner2-tl.png'),
            url('/static/pipes/corner2-tr.png'),
            url('/static/pipes/corner2-bl.png'),
            url('/static/pipes/corner2-br.png');
        background-repeat: no-repeat;
        background-position: top left, top right, bottom left, bottom right;
        background-size: var(--pipe2-corner-w) auto;
    }
}

