/* Single responsive stylesheet — mobile-first, one column under 640px.
   Direction: "the ballot". The site's one artifact is a question with lettered
   options A–J (the export format, and how options read on the conference
   projector), so the letter is the signature: a mono chip on every option list.
   Self-hosted fonts — every rule falls back to the system stack, and nothing
   is measured in a way that shifts if the woff2 files never arrive. */

@font-face {
    font-family: 'Archivo';
    src: url('/assets/fonts/archivo-latin.woff2') format('woff2');
    font-weight: 500 700;   /* variable file: one woff2 covers the range */
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'IBM Plex Mono';
    src: url('/assets/fonts/plexmono-500-latin.woff2') format('woff2');
    font-weight: 500;
    font-style: normal;
    font-display: swap;
}

:root {
    --ink: #16263c;
    --brand: #1a4d8f;
    --brand-tint: #eaf0f8;
    --paper: #f2f3f6;
    --card: #ffffff;
    --rule: #dbe0e8;
    --text: #1c2430;
    --muted: #55627a;
    --pending: #8a5a00;
    --ok: #1b6e3c;
    --error: #b3261e;

    --display: 'Archivo', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    --body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    --mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
* { box-sizing: border-box; }
body {
    margin: 0;
    font-family: var(--body);
    background: var(--paper);
    color: var(--text);
    font-size: 16px;
    line-height: 1.5;
}

/* Keyboard floor: one visible ring everywhere, on every interactive element. */
:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 3px; }
header :focus-visible, .impersonating :focus-visible { outline-color: #fff; }
.skip-link {
    position: absolute; left: -9999px;
    background: #fff; color: var(--ink); padding: 0.6rem 1rem; z-index: 20;
}
.skip-link:focus { left: 0.5rem; top: 0.5rem; }

/* ---- header ------------------------------------------------------------ */
header {
    background: var(--ink);
    color: #fff;
    padding: 0.6rem 1rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 1.5rem;
    align-items: center;
}
header .brand {
    font-family: var(--display);
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: 0.01em;
    display: flex; align-items: baseline; gap: 0.5rem;
}
header .brand .year {
    font-family: var(--mono);
    font-size: 0.75rem;
    padding: 0.1rem 0.35rem;
    border: 1px solid rgba(255, 255, 255, 0.45);
    border-radius: 3px;
}
header nav { display: flex; flex-wrap: wrap; align-items: center; gap: 0.15rem 0.4rem; }
header nav a {
    color: #fff; text-decoration: none;
    padding: 0.5rem 0.6rem; border-radius: 5px;
    min-height: 44px; display: inline-flex; align-items: center;   /* touch-sized */
}
header nav a:hover { background: rgba(255, 255, 255, 0.12); }
header nav a.active, header nav a[aria-current="page"] {
    background: rgba(255, 255, 255, 0.16);
    font-weight: 700;
}
header .account { margin-left: auto; }
header .account a { color: #cfd8e6; font-size: 0.9rem; }
@media (max-width: 640px) {
    /* Two header rows on a phone, not three: brand + account share the top
       line, the nav takes the one below. */
    header .brand { order: 1; }
    header .account { order: 2; }
    header nav { order: 3; flex-basis: 100%; }
}

/* Admin's five links collapse behind a disclosure — no JS, no crowded bar. */
.admin-menu { position: relative; }
.admin-menu > summary {
    list-style: none; cursor: pointer;
    padding: 0.5rem 0.6rem; border-radius: 5px;
    min-height: 44px; display: inline-flex; align-items: center; gap: 0.3rem;
}
.admin-menu > summary::-webkit-details-marker { display: none; }
.admin-menu > summary::after { content: '▾'; font-size: 0.8em; }
.admin-menu > summary:hover, .admin-menu[open] > summary { background: rgba(255, 255, 255, 0.16); }
.admin-menu .admin-links {
    display: flex; flex-direction: column;
    background: var(--ink);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 6px;
    padding: 0.25rem;
    min-width: 12rem;
}
@media (min-width: 700px) {
    .admin-menu .admin-links { position: absolute; top: 100%; left: 0; z-index: 15; }
}

/* Impersonation banner — writes are live as the target user, so it stays on screen. */
.impersonating {
    position: sticky; top: 0; z-index: 10;
    background: var(--error); color: #fff;
    padding: 0.6rem 1rem; font-size: 0.95rem;
}
.impersonating a { color: #fff; font-weight: 700; }

/* ---- layout ------------------------------------------------------------
   Three widths, by what the page is for: data-dense pages run fluid to the
   window, everything else keeps a readable column, and form fields cap
   themselves (below) so a wider page never means a 900px-wide text input. */
main { width: 100%; max-width: 56rem; margin: 0 auto; padding: 1.25rem clamp(1rem, 3vw, 2.5rem) 3rem; }
main.ballot { max-width: 48rem; }
main.wide { max-width: min(100%, 1700px); }
.workspace { display: grid; grid-template-columns: minmax(220px, 1fr) minmax(0, 2fr) minmax(300px, 1.25fr); gap: clamp(1rem, 2vw, 2rem); align-items: start; }
.workspace .panel h2:first-child { margin-top: 0; }
/* Prior years scrolls on its own so the form stays put next to it — a company
   with 70 prior questions made the whole page 35 screens tall. */
.workspace .panel-scroll { position: sticky; top: 1rem; max-height: calc(100vh - 2rem); overflow-y: auto; }
.how-it-works { margin: 0 0 1.5rem; }
.how-it-works > summary { cursor: pointer; font-weight: 700; }
.how-it-works p { max-width: 60rem; }
.year > summary { cursor: pointer; }
.year > summary h3 { display: inline; }
.card > details > summary { cursor: pointer; color: var(--muted); font-size: 0.85rem; }
@media (max-width: 900px) {
    .workspace { grid-template-columns: 1fr; }
    /* Phones get the form first — otherwise you scroll past every prior-year
       question before you can type one. */
    .workspace .panel-form { order: -1; }
    .workspace .panel-scroll { position: static; max-height: none; overflow: visible; }
}

h1, h2, h3 { font-family: var(--display); font-weight: 700; letter-spacing: -0.01em; }
h1 { font-size: 1.75rem; line-height: 1.2; margin: 0 0 1rem; }
h2 { font-size: 1.15rem; margin-top: 2rem; }
h3 { font-size: 0.8rem; font-family: var(--mono); font-weight: 500; color: var(--muted);
     text-transform: uppercase; letter-spacing: 0.06em; margin: 1.25rem 0 0.4rem; }

footer {
    margin: 0 clamp(1rem, 3vw, 2.5rem); padding: 1.5rem 0 2.5rem;
    border-top: 1px solid var(--rule);
    color: var(--muted); font-size: 0.85rem;
}

/* ---- forms ------------------------------------------------------------- */
/* Tables earn the full window on a wide page; forms never do. */
form { background: var(--card); padding: 1.1rem; border-radius: 8px; margin: 1rem 0; border: 1px solid var(--rule); max-width: 52rem; }
form.inline, form.bare { background: none; padding: 0; margin: 0; border: 0; }
/* A form inside a card or a table cell is content, not a second card. */
.card > form { background: none; padding: 0; border: 0; }
td > form { background: none; padding: 0; border: 0; margin: 0; }
form.inline { display: inline; }
label { display: block; margin: 0.85rem 0; font-weight: 600; }
label.checkbox { font-weight: 400; display: flex; gap: 0.5rem; align-items: flex-start; }
input[type=text], input[type=email], input[type=password],
input[type=number], input[type=date], textarea, select {
    display: block;
    width: 100%;
    max-width: 44rem;      /* a wider page must not mean a wider text field */
    margin-top: 0.3rem;
    padding: 0.65rem;
    font-size: 1rem;
    border: 1px solid #c6ccd4;
    border-radius: 6px;
    font-family: inherit;
    font-weight: 400;
    background: #fff;
    color: var(--text);
}
input[type=file] { margin-top: 0.3rem; font-size: 0.95rem; }
/* Fixed-length values: a date and a question number never need a prose-width box. */
input[type=date] { max-width: 14rem; }
/* Inside an already-bounded container the cap is redundant — it just leaves a gap. */
.card input, .card textarea, .card select,
main.ballot input, main.ballot textarea { max-width: none; }
textarea { line-height: 1.45; }

/* ---- rich-text editor (WYSIWYG email bodies, progressive enhancement) ------ */
.rte-toolbar {
    display: flex; flex-wrap: wrap; gap: 0.3rem;
    margin-top: 0.3rem; padding: 0.35rem;
    border: 1px solid var(--rule); border-bottom: none;
    border-radius: 6px 6px 0 0; background: var(--paper);
}
.rte-toolbar button {                       /* compact, secondary — not the page's big brand buttons */
    font-family: var(--body); font-weight: 600; font-size: 0.85rem; line-height: 1.2;
    padding: 0.3rem 0.55rem; background: var(--card); color: var(--brand);
    border: 1px solid var(--rule); border-radius: 4px;
}
.rte-toolbar button:hover { background: var(--brand-tint); border-color: var(--brand); }
.rte-editor {
    border: 1px solid #c6ccd4; border-radius: 0 0 6px 6px;
    padding: 0.65rem; min-height: 12rem; max-width: 44rem;
    background: #fff; color: var(--text); line-height: 1.45; overflow-y: auto;
    font-weight: 400;   /* normal base — else execCommand('bold') sees 600 as "already bold" and toggles OFF */
}
.rte-editor:focus-visible { outline-offset: -2px; }
.card .rte-editor, main.ballot .rte-editor { max-width: none; }

button, a.button {
    font-family: var(--display);
    font-weight: 600;
    background: var(--brand);
    color: #fff;
    border: 1px solid var(--brand);
    border-radius: 6px;
    padding: 0.7rem 1.4rem;      /* touch-sized */
    font-size: 1rem;
    line-height: 1.2;
    cursor: pointer;
    display: inline-block;
    text-decoration: none;
    text-align: center;
}
button:hover, a.button:hover { background: #16407a; border-color: #16407a; }
button:active, a.button:active { transform: translateY(1px); }
button.danger { background: var(--error); border-color: var(--error); }
button.danger:hover { background: #94201a; border-color: #94201a; }
.btn-secondary, a.button.btn-secondary {
    background: none; color: var(--brand); border: 1px solid var(--rule);
}
.btn-secondary:hover, a.button.btn-secondary:hover { background: var(--brand-tint); border-color: var(--brand); color: var(--brand); }
button.link-button {
    font-family: var(--body); font-weight: 400;
    background: none; border: 0;
    color: var(--error);
    padding: 0.25rem 0;
    text-decoration: underline;
}
button.link-button:hover { background: none; color: #94201a; }

/* ---- messages ---------------------------------------------------------- */
.flash, .error, .notice {
    padding: 0.7rem 0.9rem; border-radius: 6px; margin: 1rem 0;
    border-left: 4px solid;
}
.flash  { background: #e7f0e9; color: var(--ok); border-color: var(--ok); }
.error  { background: #f8e5e4; color: var(--error); border-color: var(--error); }
.notice { background: #edf0f5; color: var(--ink); border-color: var(--muted); }
/* A confirmation to glance at, not a banner to read: fixed, so it never reflows the
   page under a reviewer working through the queue. Bottom-right rather than under the
   header, whose height changes with the nav's wrapping. It fades itself out; with
   prefers-reduced-motion the global animation reset keeps it until the next page. */
.toast {
    position: fixed; z-index: 30;
    right: clamp(1rem, 3vw, 2.5rem); bottom: 1.25rem;
    margin: 0; max-width: min(24rem, calc(100vw - 2rem));
    box-shadow: 0 2px 10px rgba(22, 38, 60, 0.18);
    animation: toast-out 0.4s ease 4s forwards;
}
@keyframes toast-out { to { opacity: 0; visibility: hidden; } }
.lede { font-size: 1.05rem; color: var(--muted); max-width: 52ch; margin: -0.25rem 0 1.25rem; }
.privacy { color: var(--muted); font-size: 0.85rem; }
.privacy summary { cursor: pointer; }
.meta { color: var(--muted); font-size: 0.9rem; }
.meta a { color: var(--brand); }

/* ---- cards + the lettered option list (the signature) ------------------ */
.card {
    background: var(--card); border-radius: 8px; padding: 1rem;
    margin: 0.85rem 0;
    border: 1px solid var(--rule); border-left: 4px solid var(--rule);
}
.card.status-approved { border-left-color: var(--ok); }
.card.status-rejected { border-left-color: var(--error); }
.card.status-pending  { border-left-color: var(--pending); }
.card.status-merged, .card.status-split { border-left-color: var(--brand); }
.card > p:first-child { margin-top: 0; }
.card-actions { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; }

/* A/B/C… — the same lettering the export and the projector use. */
.card > ul, .hint-options {
    list-style: none; counter-reset: opt;
    padding-left: 0; margin: 0.6rem 0;
}
.card > ul > li, .hint-options > li {
    counter-increment: opt;
    display: grid; grid-template-columns: 1.5rem 1fr; gap: 0.55rem;
    align-items: baseline;
    padding: 0.15rem 0;
}
.card > ul > li::before, .hint-options > li::before {
    content: counter(opt, upper-alpha);
    font-family: var(--mono); font-size: 0.78rem; font-weight: 500;
    color: var(--muted);
    border: 1px solid var(--rule); border-radius: 3px;
    text-align: center; padding: 0.05rem 0;
}

/* ---- status pill ------------------------------------------------------- */
.pill {
    font-family: var(--mono); font-size: 0.72rem; font-weight: 500;
    text-transform: uppercase; letter-spacing: 0.06em;
    padding: 0.15rem 0.45rem; border-radius: 3px;
    border: 1px solid currentColor;
    white-space: nowrap;
}
.pill.status-pending, .pill.unanswered { color: var(--pending); background: #fdf6e6; }
.pill.status-approved, .pill.answered  { color: var(--ok); background: #e7f0e9; }
.pill.status-rejected { color: var(--error); background: #f8e5e4; }
.pill.status-merged, .pill.status-split { color: var(--brand); background: var(--brand-tint); }

/* ---- review queue: legal-review rating, list pane, split block ---------- */
/* The rating is a .pill variant, not a new component — same chip, three colours. */
.pill.flag-red   { color: var(--error);   background: #f8e5e4; }
.pill.flag-amber { color: var(--pending); background: #fdf6e6; }
.pill.flag-green { color: var(--ok);      background: #e7f0e9; }

/* Multi-part badges. Two are guesses the page is making about the text (a hint, so
   they read quieter than a status) and one is a fact the reviewer recorded, so
   "Part 2 of 3" carries the brand colour the other structural links use. */
.pill.mp-part,
.pill.mp-multi     { color: var(--brand); background: var(--brand-tint); }
/* Dashed = a hint from the text, not a stored fact — same reading as the two above it. */
.pill.mp-followup,
.pill.mp-compound,
.pill.mp-multiselect { color: var(--muted); background: transparent; border-style: dashed; }

.multipart-notice { margin: 0.6rem 0; }
.multipart-notice p { margin: 0.25rem 0; }
.group-block { margin-top: 1.25rem; }
.group-block > summary { cursor: pointer; font-weight: 600; }
.group-members { margin: 0.5rem 0; padding-left: 1.4rem; }
.group-members > li { margin-bottom: 0.35rem; }
.group-members .is-this, .is-this { font-weight: 600; }
.group-picks {
    border: 1px solid var(--rule); border-radius: 6px;
    padding: 0.5rem 0.8rem; margin: 0.75rem 0;
}
.group-picks legend { font-size: 0.8rem; color: var(--muted); padding: 0 0.3rem; }
.group-picks .checkbox { display: block; margin-bottom: 0.35rem; }

/* Two panes, not questions.php's three. The list gets enough room for a question to
   read at two lines; the editor takes the rest. Guarded by min-width because the
   collapse-to-one-column rule below is less specific than this and would lose to it. */
@media (min-width: 901px) {
    /* Cap the editor at roughly one textbox (44rem) plus the card padding on either
       side, and hand every remaining pixel to the queue — the editor's widest field
       is a 3-row textarea, so extra column width there was blank space and the same
       width in the queue is another line of questions on screen. */
    .workspace.review { grid-template-columns: minmax(320px, 1fr) minmax(0, 48rem); }
    /* Both panes scroll themselves, so the page stays about one screen tall however
       long the queue gets — the whole point of the two-pane layout. */
    .workspace.review .panel-form {
        position: sticky; top: 1rem;
        max-height: calc(100vh - 2rem); overflow-y: auto;
    }
    /* The queue is the other half of the same workspace, so it sits on the same
       surface as the editor. Bare on the page background it read as an unfinished
       column next to a card. */
    .workspace.review > .panel-scroll {
        background: var(--card); border: 1px solid var(--rule);
        border-radius: 8px; padding: 1rem;
    }
    /* Card margin would drop the editor a row below the queue's first line. */
    .workspace.review .panel-form > .card { margin-top: 0; }
    /* The decision buttons never leave the screen. The pane is sized to fit an
       ordinary question whole, but a long one with 10 options plus similar-question
       hints can still outrun the viewport, and a reviewer with minutes per question
       must not have to scroll to find Approve. */
    .workspace.review .decide-actions {
        position: sticky; bottom: 0; z-index: 1;
        margin: 0.75rem -1rem 0; padding: 0.6rem 1rem;   /* -1rem = the card's padding */
        background: var(--card); border-top: 1px solid var(--rule);
    }
}
/* Grow with their content instead of scrolling inside a fixed box (rows= is the
   floor and the fallback for browsers without it). */
.panel-form textarea { field-sizing: content; max-height: 60vh; }
/* The pending tab is an app shell, not a document: body and main are flex columns so
   the two panes take exactly the space the header, title, tabs and CSV block leave, and
   nothing needs the WINDOW scrolled first. Before this the panes were 100vh tall starting
   270px down the page, so the buttons under a 10-option question sat below the fold and
   the reviewer scrolled twice — window, then pane — for every question. */
@media (min-width: 901px) {
    body:has(main.review-shell) { height: 100dvh; overflow: hidden; display: flex; flex-direction: column; }
    body:has(main.review-shell) > footer { display: none; }   /* unreachable anyway, and this is a tool */
    main.review-shell { flex: 1; min-height: 0; display: flex; flex-direction: column; padding: 0.75rem clamp(1rem, 3vw, 2.5rem); }
    /* Every pixel above the panes is a pixel of question the reviewer has to scroll for.
       The h1 repeats what the nav's active link and the tabs already say, so it goes to
       screen readers only; the rest just loses its margins. */
    main.review-shell > h1 {
        position: absolute; width: 1px; height: 1px;
        clip-path: inset(50%); overflow: hidden; white-space: nowrap; margin: 0;
    }
    main.review-shell > .tabs { margin-bottom: 0.6rem; }
    main.review-shell > .csv-round-trip { margin: 0 0 0.75rem; }
    main.review-shell .workspace.review { flex: 1; min-height: 0; align-items: stretch; }
    /* Each pane is exactly the row height and scrolls itself; kills the sticky/100vh
       sizing from the rules above, which assumed the pane started at the window top.
       relative, NOT static: the queue's scroll-restore reads .qrow.selected's offsetTop,
       which is only relative to the pane while the pane is a positioned element. */
    main.review-shell .workspace.review > .panel {
        position: relative; height: 100%; max-height: none; overflow-y: auto;
    }
}

/* The shortcut legend rides the right edge of the button row, so it costs no extra line.
   Hidden on the phone layout, which has no keyboard to press. */
.shortcut-hint { margin-left: auto; font-size: 0.75rem; }
.shortcut-hint kbd {
    font-family: var(--mono); font-size: 0.7rem; padding: 0.05rem 0.3rem; margin: 0 0.1rem;
    border: 1px solid var(--rule); border-bottom-width: 2px; border-radius: 4px;
    background: var(--paper); color: var(--muted);
}
@media (max-width: 900px) { .shortcut-hint { display: none; } }
/* An auxiliary tool, not the page: full-bleed it was a 1700px-wide empty slab. */
.csv-round-trip { max-width: 52rem; }

/* Filters ride the top of the scrolling queue pane so they stay reachable however
   far down the list you are, and collapse to a one-line summary when the reviewer
   wants the full pane for questions (state remembered in localStorage). */
.filter-panel {
    position: sticky; top: -1rem;      /* -1rem cancels the panel's own 1rem padding */
    margin: -1rem -1rem 0.75rem;       /* bleed to the card edges so nothing shows through behind it */
    padding: 0.75rem 1rem 0.5rem;
    background: var(--card);
    border-bottom: 1px solid var(--rule);
    z-index: 2;
}
.filter-panel > summary {
    cursor: pointer; font-weight: 700; font-family: var(--display);
    font-size: 0.95rem; padding: 0.15rem 0;
    list-style: none;
}
.filter-panel > summary::-webkit-details-marker { display: none; }
.filter-panel > summary::before {
    content: "▾"; display: inline-block; width: 1em;
    color: var(--muted); transition: transform 0.15s;
}
.filter-panel:not([open]) > summary::before { transform: rotate(-90deg); }
.filter-panel > summary .meta { float: right; font-weight: 400; }
/* When open the filters can be taller than the viewport (long company list); let them
   scroll inside the sticky header rather than pushing the queue off-screen. */
.filter-panel[open] > .filter-bar { max-height: calc(100vh - 8rem); overflow-y: auto; padding-top: 0.5rem; }
/* Pacing: how much of the pile is decided, in the one strip that is always visible
   whether the filters are open or shut. Native <progress> — no widget, no script. */
.queue-progress {
    display: block; width: 100%; height: 4px; margin: 0.4rem 0 0.15rem;
    appearance: none; border: 0; background: var(--rule); border-radius: 2px;
}
.queue-progress::-webkit-progress-bar { background: var(--rule); border-radius: 2px; }
.queue-progress::-webkit-progress-value { background: var(--ok); border-radius: 2px; }
.queue-progress::-moz-progress-bar { background: var(--ok); border-radius: 2px; }
.filter-panel > summary .progress-label { float: none; font-size: 0.72rem; font-weight: 400; }
/* Dense on purpose: every row this bar costs is a question off the visible queue. */
.filter-bar { margin-bottom: 0.75rem; }
.filter-bar label { margin: 0.5rem 0; font-size: 0.8rem; }
.filter-bar input, .filter-bar select { padding: 0.35rem 0.45rem; font-size: 0.9rem; }
.filter-bar .checkbox { font-weight: 400; font-size: 0.85rem; margin: 0.3rem 0; }
.filter-bar p { margin: 0.5rem 0; }
.filter-bar button { padding: 0.45rem 1.1rem; font-size: 0.9rem; }
/* Grid, not wrapping flex: flex-grow stretched the lone field on the last row to the
   full width of the bar, so the same four controls rendered at three sizes. Grid rows
   share their tracks, so a field is one column wide wherever it lands. */
.filter-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr)); gap: 0.6rem 0.75rem; }
.filter-row > label { margin: 0; }
/* Two things of honestly different lengths — a question number and a sentence — so
   fixed + fluid rather than equal thirds. Labels, fields and hints still line up. */
.decide-row { grid-template-columns: minmax(0, 12rem) minmax(0, 1fr); align-items: start; }
@media (max-width: 640px) { .decide-row { grid-template-columns: 1fr; } }
.decide-row .meta { display: block; font-weight: 400; font-size: 0.8rem; margin-top: 0.2rem; }
.chips { display: flex; flex-wrap: wrap; gap: 0.3rem; margin: 0 0 0.6rem; }
.chip {
    font-family: var(--mono); font-size: 0.72rem; font-weight: 500;
    text-transform: uppercase; letter-spacing: 0.05em;
    padding: 0.25rem 0.5rem; border-radius: 3px;
    border: 1px solid var(--rule); background: var(--card);
    color: var(--muted); text-decoration: none; white-space: nowrap;
}
.chip.flag-red   { color: var(--error); }
.chip.flag-amber { color: var(--pending); }
.chip.flag-green { color: var(--ok); }
.chip.active { border-color: currentColor; background: var(--brand-tint); font-weight: 700; }
.chip:hover { border-color: var(--brand); }

.qlist { list-style: none; padding: 0; margin: 0; }
.qrow {
    display: block; padding: 0.5rem 0.6rem;
    border-bottom: 1px solid var(--rule);
    color: var(--text); text-decoration: none;
}
.qrow:hover { background: var(--brand-tint); }
.qrow.selected { background: var(--brand-tint); box-shadow: inset 3px 0 0 var(--brand); }
.qrow-meta { display: block; color: var(--muted); font-size: 0.78rem; margin-bottom: 0.15rem; }
.qrow-meta .pill { font-size: 0.62rem; padding: 0.05rem 0.3rem; }
/* Clamp in CSS, never with mb_strimwidth: the full question text has to reach the
   markup for the queue-ordering assertion in tests/e2e.sh to find it. */
.qrow-text {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; line-height: 1.35;
}
.legal-note { border-left: 3px solid var(--rule); padding-left: 0.6rem; }
.qrow-legal-note {
    display: block; color: var(--muted); font-size: 0.75rem;
    margin-top: 0.25rem; padding-left: 0.6rem;
    border-left: 2px solid var(--rule); line-height: 1.35;
}
.csv-round-trip > summary { cursor: pointer; font-weight: 700; font-family: var(--display); }

.decide-actions { gap: 0.5rem 0.75rem; margin-top: 1.25rem; }
/* A gap, not a shove to the far edge: reject reads as the separate one on a
   1440px row without floating loose from the decision it belongs to. */
.decide-actions .danger { margin-left: 1rem; }
.split-block { margin-top: 1.25rem; }
.split-block > summary, .hints > summary { cursor: pointer; font-weight: 600; }
.split-parts { display: grid; gap: 0.75rem; margin: 0.75rem 0; }
.split-part {
    border: 1px solid var(--rule); border-radius: 6px;
    padding: 0.6rem 0.9rem; margin: 0; background: var(--paper);
}
.split-part legend {
    font-family: var(--mono); font-size: 0.72rem; font-weight: 500;
    text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted);
    padding: 0 0.3rem;
}

.q-index { list-style: none; padding-left: 0; margin: 0.25rem 0 1.5rem; }
.q-index li { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; padding: 0.6rem 0; border-bottom: 1px solid var(--rule); }
.q-index .pill { flex: none; }
.q-index a { color: var(--text); }

/* ---- survey: the ballot ------------------------------------------------ */
/* The question is this page's heading, so the page title steps back to an
   eyebrow and the form drops its card — the ballot sits on the page itself. */
main.ballot h1 {
    font-family: var(--mono); font-size: 0.78rem; font-weight: 500;
    text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted);
    margin-bottom: 0.6rem;
}
main.ballot form { background: none; border: 0; padding: 0; }
.q { font-size: 1.5rem; line-height: 1.25; margin: 0.25rem 0 1rem; }
.q small { display: block; font-family: var(--mono); font-size: 0.78rem; font-weight: 500;
           color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; margin-top: 0.4rem; }

.progress-line { display: flex; align-items: center; gap: 0.75rem; margin: 0 0 0.5rem; }
progress {
    flex: 1; height: 6px; min-width: 6rem;
    border: 0; border-radius: 3px; background: var(--rule);
    appearance: none; -webkit-appearance: none;
}
progress::-webkit-progress-bar { background: var(--rule); border-radius: 3px; }
progress::-webkit-progress-value { background: var(--brand); border-radius: 3px; }
progress::-moz-progress-bar { background: var(--brand); border-radius: 3px; }
.counter { font-family: var(--mono); font-size: 0.85rem; font-weight: 500; color: var(--muted); white-space: nowrap; }

.options { counter-reset: opt; margin: 1rem 0; }
label.option {
    counter-increment: opt;
    font-weight: 400;
    display: grid; grid-template-columns: 1.9rem 1.15rem 1fr; gap: 0.7rem;
    align-items: center;
    margin: 0 0 -1px;                 /* rows share one hairline */
    padding: 0.85rem 0.9rem;
    min-height: 52px;                 /* comfortable phone target */
    border: 1px solid var(--rule);
    background: var(--card);
    cursor: pointer;
}
.options label.option:first-of-type { border-radius: 6px 6px 0 0; }
.options label.option:last-of-type { border-radius: 0 0 6px 6px; margin-bottom: 0; }
label.option::before {
    content: counter(opt, upper-alpha);
    font-family: var(--mono); font-size: 0.85rem; font-weight: 500;
    color: var(--muted);
    border: 1px solid var(--rule); border-radius: 3px;
    text-align: center; padding: 0.15rem 0;
}
label.option:hover { background: var(--brand-tint); }
/* :has() is why the radio/checkbox itself stays visible in the row — on an old
   browser without it you lose the row tint, not the answer's checked state. */
label.option:has(input:checked) {
    border-color: var(--brand);
    background: var(--brand-tint);
    position: relative; z-index: 1;    /* keep the navy edge above the shared hairline */
    font-weight: 600;
}
label.option:has(input:checked)::before { color: var(--brand); border-color: var(--brand); background: #fff; }
label.option:has(input:focus-visible) { outline: 2px solid var(--brand); outline-offset: 2px; z-index: 2; }
label.option input { width: 1.15rem; height: 1.15rem; margin: 0; accent-color: var(--brand); }
.other-text { margin: 0.75rem 0 0; }

/* ---- tabs, hints ------------------------------------------------------- */
.tabs { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 1.25rem 0; }
.tabs a {
    font-family: var(--display); font-weight: 600; font-size: 0.95rem;
    padding: 0.55rem 0.95rem; border-radius: 6px;
    background: var(--card); border: 1px solid var(--rule);
    text-decoration: none; color: var(--text);
}
.tabs a:hover { border-color: var(--brand); color: var(--brand); }
.tabs a.active { background: var(--brand); border-color: var(--brand); color: #fff; }
.hints { background: #fdf6e6; border: 1px solid #efe0bd; border-radius: 6px; padding: 0.6rem 0.9rem; margin: 0.75rem 0; }
.hints > ul { margin: 0.25rem 0; padding-left: 1.2rem; }
.hints > ul > li { margin-bottom: 0.6rem; }
a.active { font-weight: 700; }
a { color: var(--brand); }

/* ---- tables ------------------------------------------------------------ */
table { width: 100%; border-collapse: collapse; background: var(--card); border: 1px solid var(--rule); border-radius: 8px; }
th, td { text-align: left; padding: 0.55rem 0.6rem; border-bottom: 1px solid var(--rule); font-size: 0.9rem; vertical-align: top; }
th {
    font-family: var(--mono); font-size: 0.72rem; font-weight: 500;
    text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted);
    white-space: nowrap;
}
tr:last-child td { border-bottom: 0; }
/* Free-text columns get room; everything else stays on one line. */
td.wrap, th.wrap { min-width: 20rem; }

@media (max-width: 640px) {
    /* Scroll the table instead of stacking it: stacking dropped the <th>
       labels entirely, leaving unlabeled values. */
    table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
    td, th { white-space: nowrap; }
    td.wrap, th.wrap { white-space: normal; min-width: 16rem; }
    .card > ul > li, .hint-options > li { align-items: start; }
}

@media (prefers-reduced-motion: reduce) {
    * { animation: none !important; transition: none !important; }
    button:active, a.button:active { transform: none; }
}
