/*
 * Stronk — "bold strength dashboard" design system.
 *
 * One stylesheet, CSS-variable driven. High-contrast, heavy display headings,
 * oversized metrics, a vivid energy accent. The dark palette lives in :root and
 * is the default; `html[data-theme="light"]` and `html[data-theme="frog-mage"]`
 * redefine the same role variables. `<html data-theme>` is rendered from the
 * user's `theme` preference in base.html.twig.
 */

/* --- Themes ---------------------------------------------------------------- */

:root {
    /* Dark (default look): near-black canvas, vivid orange energy accent. */
    --bg: #08090c;
    --card: #14161d;
    --elevated: #1b1e27;
    --border: #2a2f3b;
    --inset: #0d0f14;
    --text: #f2f4f8;
    --muted: #8b93a4;
    --accent: #ff7a3d;
    --accent-2: #f2570f;
    --on-accent: #fff;
    --ok: #4ec77f;
    --err-bg: #2a1717;
    --err-border: #6b2b2b;
    --err-text: #f5b8b8;
    --ok-bg: #12251a;
    --ok-border: #2c4a36;
    --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 6px 20px rgba(0, 0, 0, .25);

    /* Spacing scale. Tune these to change global density. */
    --space-1: 4px;
    --space-2: 6px;
    --space-3: 9px;
    --space-4: 13px;
    --space-5: 16px;
    --space-6: 20px;
    --space-7: 26px;

    --radius: 14px;
    --radius-sm: 9px;

    --font: -apple-system, system-ui, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
}

html[data-theme="light"] {
    --bg: #f4f5f7;
    --card: #ffffff;
    --elevated: #ffffff;
    --border: #e2e4ea;
    --inset: #eef0f4;
    --text: #0c0e14;
    --muted: #5a6373;
    --accent: #ea580c;
    --accent-2: #ea580c;
    --on-accent: #fff;
    --ok: #2a9d5c;
    --err-bg: #fdecec;
    --err-border: #e7b4b4;
    --err-text: #8a2b2b;
    --ok-bg: #e8f6ee;
    --ok-border: #b6e0c6;
    --shadow: 0 1px 2px rgba(16, 24, 40, .06), 0 6px 18px rgba(16, 24, 40, .06);
}

/* "Frog mage" — swampy moss greens with an arcane-purple spellcaster accent. */
html[data-theme="frog-mage"] {
    --bg: #0a130c;
    --card: #14231a;
    --elevated: #1a2c20;
    --border: #2c4231;
    --inset: #0a120c;
    --text: #eaf3e5;
    --muted: #93ab95;
    --accent: #9bf06a;
    --accent-2: #6b4fd6;
    --on-accent: #0a130c;
    --ok: #74d98a;
    --err-bg: #2a1a1a;
    --err-border: #6b2b2b;
    --err-text: #f3c0c0;
    --ok-bg: #12271a;
    --ok-border: #2f5a3a;
    --shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 6px 20px rgba(0, 0, 0, .3);
}

/* "STRONK" — Russian Suprematism / Malevich's Black Square. A warm cream canvas,
   solid-black blocks, crimson/oxblood accents, and strictly flat, hard edges:
   zero gradients, shadows, or rounded corners. Beyond recolouring the 17 role
   variables it flattens the radius tokens to 0 and adds the structural rules in
   the "Suprematist overrides" section at the end of this file. */
html[data-theme="stronk"] {
    --bg: #f4f1ea;
    --card: #f4f1ea;
    --elevated: #eae6da;
    --border: #000000;
    --inset: #eae6da;
    --text: #000000;
    --muted: #5b5346;
    --accent: #a31d1d;
    --accent-2: #8b0000;
    --on-accent: #f4f1ea;
    --ok: #2e5e3a;
    --err-bg: #f1e1de;
    --err-border: #8b0000;
    --err-text: #8b0000;
    --ok-bg: #e7efe5;
    --ok-border: #2e5e3a;
    --shadow: none;

    /* Suprematism is flat: no rounded corners anywhere. */
    --radius: 0;
    --radius-sm: 0;

    --font: "Helvetica Neue", Helvetica, Arial, system-ui, sans-serif;
}

/* --- Base ------------------------------------------------------------------ */

* {
    box-sizing: border-box;
}

body {
    margin: 0;
    font: 15px/1.5 var(--font);
    background: var(--bg);
    color: var(--text);
    -webkit-font-smoothing: antialiased;
    transition: background-color .2s ease, color .2s ease;
}

.wrap {
    max-width: 1180px;
    margin: 0 auto;
    padding: var(--space-7) var(--space-6) 56px;
}

a {
    color: var(--accent);
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}

/* Display headings: heavy, uppercase, tightly tracked — the "loud" dashboard voice. */
h1,
h2 {
    text-transform: uppercase;
    letter-spacing: .01em;
    line-height: 1.15;
}

h1 {
    font-size: 1.7rem;
    font-weight: 800;
    margin: 0 0 .5em;
}

h2 {
    font-size: 1.15rem;
    font-weight: 700;
    margin: 1.2em 0 .5em;
    padding-bottom: 6px;
    border-bottom: 2px solid var(--border);
}

h3 {
    font-size: 1.05rem;
    font-weight: 700;
    margin: 1em 0 .3em;
}

.meta {
    color: var(--muted);
    font-size: .9rem;
}

.error {
    color: var(--err-text);
}

code {
    background: var(--inset);
    padding: 1px 5px;
    border-radius: 4px;
    font-size: .9em;
}

/* --- Top nav --------------------------------------------------------------- */

.topnav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-7);
    margin-bottom: var(--space-7);
    padding-bottom: var(--space-4);
    border-bottom: 2px solid var(--border);
}

.topnav .brand {
    font-size: 1.3rem;
    font-weight: 900;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text);
    text-decoration: none;
}

.topnav .brand::after {
    content: "";
    display: inline-block;
    width: .42em;
    height: .42em;
    margin-left: .12em;
    border-radius: 2px;
    background: var(--accent);
    vertical-align: baseline;
}

.topnav nav {
    display: flex;
    align-items: center;
    gap: var(--space-6);
    flex-wrap: wrap;
}

/* Hamburger button — hidden on wide screens, shown under the nav breakpoint. */
.nav-toggle {
    display: none;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    background: transparent;
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.nav-toggle:hover {
    background: var(--inset);
}

.nav-toggle-bars,
.nav-toggle-bars::before,
.nav-toggle-bars::after {
    display: block;
    width: 20px;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
}

.nav-toggle-bars {
    position: relative;
}

.nav-toggle-bars::before {
    content: "";
    position: absolute;
    left: 0;
    top: -6px;
}

.nav-toggle-bars::after {
    content: "";
    position: absolute;
    left: 0;
    top: 6px;
}

/* Sub-navigation (e.g. the /exercises Manage · Tier list views). */
.subnav {
    display: flex;
    align-items: center;
    gap: var(--space-6);
    flex-wrap: wrap;
    margin-bottom: var(--space-5);
}

/* The link for the page you're on reads bolder with an accent underline. */
.topnav nav a.active,
.admin-nav a.active,
.subnav a.active {
    color: var(--text);
    font-weight: 600;
    text-decoration: underline;
    text-decoration-color: var(--accent);
    text-decoration-thickness: 2px;
    text-underline-offset: 4px;
}

/* A filter control (gym filter, /recent muscle filter), not page nav — render it
   as a segmented row of pill chips so it reads distinctly from the plain-link
   subnavs. Works for link chips (server round-trip) and button chips (on-the-fly). */
.chip-filter {
    gap: var(--space-3);
}

.chip-filter a,
.chip-filter button {
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 3px 12px;
    background: var(--inset);
    color: var(--muted);
    font: inherit;
    font-weight: 500;
    line-height: 1.5;
    cursor: pointer;
    text-decoration: none;
    transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}

.chip-filter a:hover,
.chip-filter button:hover {
    background: var(--card);
    border-color: var(--muted);
    color: var(--text);
    text-decoration: none;
}

/* Selected chip = a filled accent segment; override the shared underline/active. */
.chip-filter a.active,
.chip-filter button.active {
    background: var(--accent-2);
    border-color: var(--accent-2);
    color: var(--on-accent);
    text-decoration: none;
}

/* --- Cards ----------------------------------------------------------------- */

.card,
section {
    background: var(--card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--space-5) var(--space-6);
    margin: var(--space-4) 0;
    box-shadow: var(--shadow);
}

/* Section headings sit flush with the top of their card. */
section > :first-child {
    margin-top: 0;
}

/* --- Buttons --------------------------------------------------------------- */

button,
.btn {
    display: inline-block;
    font: inherit;
    font-size: .9rem;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    border: none;
    border-radius: var(--radius-sm);
    padding: 7px 14px;
    background: var(--accent-2);
    color: var(--on-accent);
    transition: background-color .15s ease, opacity .15s ease, transform .05s ease;
}

button:hover,
.btn:hover {
    background: var(--accent);
}

button:active,
.btn:active {
    transform: translateY(1px);
}

button.secondary,
.btn.secondary {
    background: transparent;
    color: var(--accent);
    border: 1px solid var(--border);
}

button.secondary:hover,
.btn.secondary:hover {
    background: var(--inset);
}

button.danger,
.btn.danger {
    background: transparent;
    color: var(--err-text);
    border: 1px solid var(--err-border);
}

button.danger:hover,
.btn.danger:hover {
    background: var(--err-bg);
}

button:disabled,
.btn:disabled {
    opacity: .5;
    cursor: progress;
}

/* --- Forms ----------------------------------------------------------------- */

label {
    display: block;
    margin: var(--space-3) 0 var(--space-1);
    color: var(--muted);
    font-size: .9rem;
}

/* Inline labels that wrap a checkbox/radio read as one control. */
label:has(> input[type="checkbox"]),
label:has(> input[type="radio"]) {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--text);
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
textarea,
select {
    font: inherit;
    color: var(--text);
    background: var(--inset);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: 7px 11px;
    max-width: 100%;
}

input[type="text"],
input[type="email"],
input[type="password"],
textarea {
    width: 100%;
}

/* Inputs sitting inline inside table forms should not stretch full width. */
td input[type="text"],
td input[type="email"],
td input[type="password"] {
    width: auto;
}

textarea {
    line-height: 1.5;
    resize: vertical;
    min-height: 56px;
}

input:focus,
textarea:focus,
select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent);
}

input[type="checkbox"],
input[type="radio"] {
    width: 16px;
    height: 16px;
    accent-color: var(--accent-2);
}

fieldset {
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: var(--space-3) var(--space-5);
    margin: var(--space-4) 0;
}

legend {
    color: var(--muted);
    font-size: .9rem;
    padding: 0 6px;
}

/* Buttons get a little breathing room from the controls above them. */
form button {
    margin-top: var(--space-3);
}

td form button,
form button + button {
    margin-top: 0;
}

/* The two History sync forms sit side by side rather than stacking. */
.sync-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    align-items: center;
}
.sync-actions form {
    margin: 0;
}
.sync-actions form button {
    margin-top: 0;
}

/* The per-workout gym picker sits on one line under the workout heading. The
   select auto-submits; the button is the no-JS fallback. */
.workout-gym {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    align-items: center;
    margin: 0 0 var(--space-3);
    font-size: 0.9rem;
}
.workout-gym button {
    margin-top: 0;
}

/* --- AI feedback form ------------------------------------------------------ */

/* A short, focused task form reads better constrained than stretched across the page. */
.feedback-form {
    max-width: 620px;
}

/* The sign-in screen is a couple of fields — a narrow column centered on the page. */
.auth {
    max-width: 360px;
    margin: 8vh auto 0;
}

.auth h1 {
    text-align: center;
}

/* Keep the "remember me" checkbox inline with its label rather than stacking
   like the full-width auth inputs above it. */
.auth .remember-me {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-weight: 400;
    cursor: pointer;
}
.auth .remember-me input {
    margin: 0;
}

/* The two request modes as side-by-side selectable cards. */
.mode-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-4);
    margin: var(--space-4) 0;
}

.mode-grid .radio-card {
    display: block;
    margin: 0;
    padding: var(--space-4) var(--space-5);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: border-color .15s ease, background-color .15s ease;
}

.mode-grid .radio-card:has(:checked) {
    border-color: var(--accent);
    background: var(--inset);
}

.radio-card .rc-title {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--text);
    font-weight: 600;
}

.radio-card .rc-hint {
    display: block;
    margin-top: 3px;
    margin-left: 24px; /* align under the title, clear of the radio */
    color: var(--muted);
    font-size: .85rem;
}

/* The optional next-workout toggle is secondary — a single compact row:
   checkbox + inline gym. The :not([hidden]) guard keeps the JS `.hidden = true`
   working; a bare `display: flex` would override the UA [hidden] rule. */
.next-session:not([hidden]) {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: var(--space-4) 0;
    font-size: 1rem;
}
/* One sentence, one type size: the generic `label` rule (.9rem, muted) would
   otherwise shrink half the words and, through `font: inherit`, the selects with
   them — leaving their dashed underlines sitting at different heights. Scoped to
   the sentence itself; the session-note label below stays a normal field label. */
.next-session .ns-toggle,
.next-session .ns-gym label {
    font-size: inherit;
    line-height: inherit;
}
.next-session .ns-gym:not([hidden]) {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}
/* "at" is a word in the sentence, not a field label, so it takes the body colour. */
.next-session .ns-gym label {
    color: var(--text);
    margin: 0;
}

/* "+ add note" reveals the collapsed textarea. It's a button, so it picks up the
   form's button margin — drop it so it sits on the sentence's centre line. */
.next-session .ns-note-toggle {
    margin: 0;
    /* Same size and weight as the words around it, just muted — it's an aside in the
       sentence, not a call to action. */
    font-size: inherit;
    font-weight: inherit;
    color: var(--muted);
}
.next-session .ns-note-toggle:hover {
    color: var(--accent);
}
/* The base `button` rule's display: inline-block outranks the UA [hidden] rule, so
   restate it — otherwise the button stays on screen after it's been used. */
.next-session .ns-note-toggle[hidden] {
    display: none;
}

/* The note is a field, not part of the sentence — keep it on its own line now that
   the shrunk selects leave room beside them. */
.next-session .ns-note:not([hidden]) {
    flex: 0 0 100%;
}
.next-session .ns-note label {
    margin-top: 0;
}

/* "Suggest [today's ▾] workout" — the day picker sits inside the sentence, so it is
   styled as clickable text rather than as a form control. It stays a real <select>:
   native keyboard/touch behaviour, and it works with JS off. (Clicking it doesn't
   toggle the surrounding label's checkbox — a select is interactive content, which
   swallows the label activation.) */
.next-session .ns-toggle {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    /* No label margin: the generic rule's uneven 9px/4px would centre this half of
       the sentence 2.5px lower than the "at [gym]" half next to it. */
    margin: 0;
}
/* "Include workouts from the [last 1 month ▾]" — same sentence treatment as the
   day picker above, so the window reads as text, not as a form field. */
.window-line {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: var(--space-4) 0;
    color: var(--text);
    font-size: 1rem;
}

.inline-select {
    /* Hug the *selected* option: a select is otherwise as wide as its longest one,
       which left "Suggest today's ———————— workout" trailing a dash across the gap.
       Browsers without field-sizing simply keep that wider box. */
    field-sizing: content;
    width: auto;
    margin: 0;
    padding: 0 var(--space-1);
    border: 0;
    border-bottom: 1px dashed currentColor;
    border-radius: 0;
    background: transparent;
    color: var(--accent);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}
.inline-select:disabled {
    color: var(--muted);
    cursor: default;
}

/* --- Account page ---------------------------------------------------------- */

.account-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-4);
    align-items: start;          /* columns keep their natural heights */
}

/* Each grid cell is a vertical stack of cards, so the two columns pack
   independently (the tall Preferences card doesn't leave a gap opposite it). */
.account-col {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
}

.account-grid .field-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-4);
    align-items: flex-end;        /* label-stacked fields + button line up at the bottom */
}

.account-grid .field-row .field {
    flex: 1 1 0;
    min-width: 8ch;               /* keeps number/password fields from collapsing */
}

/* Field labels read as headings for their control, not as muted hint text. */
.account-grid .field label {
    margin: 0 0 var(--space-2);
    color: var(--text);
    font-size: .95rem;
    font-weight: 600;
}
/* …except a label that wraps its own checkbox reads as one inline control
   (the heading rule above outranks the generic checkbox rule, so restate it). */
.account-grid .field label:has(> input[type="checkbox"]) {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
}
.account-grid .field-row input,
.account-grid .field-row select { width: 100%; }
/* …but a checkbox stays its intrinsic size, not stretched to fill the row. */
.account-grid .field-row input[type="checkbox"] { width: auto; }

/* Breathing room between stacked rows (and above their help text). */
.account-grid form .field-row + .field-row { margin-top: var(--space-5); }
.account-grid .field .meta { margin-top: var(--space-2); }

/* Buttons that share a row with an input shouldn't push down. */
.account-grid .field-row button { margin-top: 0; }

/* --- Tables ---------------------------------------------------------------- */

/* Wide data tables scroll inside their card on narrow screens instead of blowing
   out the page — the body never scrolls sideways. */
.table-wrap {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

table {
    width: 100%;
    border-collapse: collapse;
    margin: var(--space-2) 0;
    font-size: .95rem;
}

th,
td {
    text-align: left;
    padding: var(--space-2) var(--space-3);
    border-bottom: 1px solid var(--border);
    vertical-align: top;
}

thead th {
    color: var(--muted);
    font-size: .78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .05em;
}

/* Inline action forms inside table cells stay on the same row. */
td form.row-actions {
    display: inline-flex; /* sits on one line next to the Exclude toggle */
    align-items: center;
    flex-wrap: wrap; /* graceful if a narrow window can't fit one line */
    gap: 6px;
    margin: 0;
    vertical-align: middle;
}

/* Kill the block-label margins that would otherwise stack the controls. */
td form.row-actions label {
    margin: 0;
}

td form.row-actions select {
    max-width: 180px;
}

/* Zebra hover makes a long editable table easier to scan. */
tbody tr:hover {
    background: var(--inset);
}

/* Manage rows read clean at rest; the edit form appears on row hover. */
.exercise-table .row-actions {
    visibility: hidden; /* reserve the cell's width → no layout shift on reveal */
}

.exercise-table tr:hover .row-actions,
.exercise-table tr:focus-within .row-actions {
    visibility: visible;
}

/* An excluded row needs no tier/override editor — only its Include toggle. */
.exercise-table tr.excluded .row-actions {
    display: none;
}

/* Client-side equipment filter hides non-matching rows / emptied groups. */
.filtered-out {
    display: none !important;
}

/* Always-visible one-click Exclude/Include toggle; sits inline before the hover edit form. */
.row-exclude {
    display: inline-flex;
    align-items: center;
    vertical-align: middle;
    margin: 0 8px 0 0;
}
button.linklike {
    background: none;
    border: none;
    padding: 0;
    color: var(--accent);
    font: inherit;
    font-size: .82rem;
    cursor: pointer;
    text-decoration: underline;
}
button.linklike:hover {
    background: none;
    opacity: .8;
}

/* Transient "Saved ✓" confirmation after an in-place (AJAX) row save; fades out. */
.row-saved {
    color: var(--accent);
    font-size: .78rem;
    font-weight: 600;
    opacity: 0;
    transition: opacity .4s ease;
    pointer-events: none;
}
.row-saved.show {
    opacity: 1;
    transition: none; /* appear instantly, then fade via the animation below */
    animation: row-saved-fade 1.6s ease forwards;
}
@keyframes row-saved-fade {
    0%, 40% { opacity: 1; }
    100% { opacity: 0; }
}

/* Fixed layout + declared widths so every muscle-group table shares the same
   column geometry — the stacked group tables line up as one aligned grid
   instead of each auto-sizing to its own content. */
.exercise-table {
    table-layout: fixed;
}
.exercise-table th:nth-child(1), .exercise-table td:nth-child(1) { width: 24%; } /* Exercise */
.exercise-table th:nth-child(2), .exercise-table td:nth-child(2) { width: 16%; } /* Equipment */
.exercise-table th.tier { width: 9%; }                                           /* llm / Nippard */
.exercise-table th:nth-child(5), .exercise-table td:nth-child(5) { width: 42%; } /* actions */

/* The single-letter tier columns (llm / Nippard / my-tier) read better centered. */
.exercise-table td.tier,
.exercise-table th.tier {
    text-align: center;
}

/* Colored tier badges (S/A/B/C/D/F, no E) — self-contained bright bg + dark text so they
   read identically across the dark/light/frog-mage themes. */
.badge {
    display: inline-block; min-width: 22px; padding: 1px 6px; border-radius: 5px;
    font-weight: 700; font-size: .78rem; color: #0d0f13; text-align: center;
}
.badge.none { background: transparent; color: var(--muted); font-weight: 400; }
.tier-S { background: #ff5d73; } .tier-A { background: #ffa14a; } .tier-B { background: #ffd24a; }
.tier-C { background: #7fd1a0; } .tier-D { background: #8aa0c0; } .tier-F { background: #b58ad0; }

/* Feedback-job status pills (same bright-bg/dark-text scheme as tiers). */
.status-pending { background: #8aa0c0; } .status-running { background: #ffd24a; }
.status-completed { background: #7fd1a0; } .status-failed { background: #ff5d73; }
.status-cancelled { background: #b0b4bb; }

/* "from cache" pill on a reused (non-billed) feedback review. */
.badge-cache { background: #7fd1a0; }

/* Reload-surviving "in progress" placeholder on /feedback. */
.job-card { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 1rem 1.1rem; margin: 1rem 0; }
.job-card h2 { margin: 0 0 .5rem; font-size: 1.05rem; }
.job-card dl { display: grid; grid-template-columns: max-content 1fr; gap: .25rem .75rem; margin: .5rem 0 0; }
.job-card dt { color: var(--muted); }
.job-card dd { margin: 0; }
.job-card .live-status { margin-top: .75rem; }

/* Older-feedback archive: one linked row per past coaching review. */
.feedback-history { list-style: none; margin: 1rem 0; padding: 0; }
.feedback-history li + li { margin-top: .5rem; }
.feedback-history a {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .25rem .75rem;
    padding: .6rem .8rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    text-decoration: none;
}
.feedback-history a:hover { background: var(--inset); }
.feedback-history .fh-date { font-weight: 600; }
.feedback-history .fh-meta { color: var(--muted); }

/* Chat about one suggested workout (/feedback/{id}). */
.routine-chat { margin-top: 2rem; }
.chat-thread {
    list-style: none;
    margin: 0 0 1rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .75rem;
}
.chat-msg {
    max-width: 46rem;
    padding: .6rem .85rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--card);
}
/* The trainee's own turns sit right and read as quoted input. */
.chat-msg.chat-user {
    align-self: flex-end;
    background: var(--inset);
}
.chat-msg.chat-pending { opacity: .6; }
.chat-who {
    margin: 0 0 .25rem;
    font-weight: 600;
    font-size: .85rem;
}
.chat-who .meta { font-weight: 400; margin-left: .4rem; }
.chat-body > :first-child { margin-top: 0; }
.chat-body > :last-child { margin-bottom: 0; }
.chat-form textarea { width: 100%; }

/* Label kept for screen readers where the placeholder carries the visible hint. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* Tint a set manual-tier <select> so its value reads at a glance. */
.tier-select.sel-tier-S { border-color: #ff5d73; color: #ff8593; }
.tier-select.sel-tier-A { border-color: #ffa14a; color: #ffb877; }
.tier-select.sel-tier-B { border-color: #ffd24a; color: #e7c25f; }
.tier-select.sel-tier-C { border-color: #7fd1a0; color: #8fd9ad; }
.tier-select.sel-tier-D { border-color: #8aa0c0; color: #a3b4cc; }
.tier-select.sel-tier-F { border-color: #b58ad0; color: #c8a4e0; }

/* Tier-list view: each tier's exercises as a scannable column — name (linked to its
   history when logged) with the ranking rationale as muted secondary text beneath. */
.tier-list { list-style: none; margin: .25rem 0 0; padding: 0; }
.tier-list li { padding: .3rem 0; border-top: 1px solid var(--border); }
.tier-list li:first-child { border-top: 0; }
.tier-list .name { font-weight: 600; }
.tier-list .rationale { display: block; margin-top: .1rem; color: var(--muted); font-size: .85rem; }

/* Excluded-from-planning rows sink to the bottom of their group and fade back
   so the active catalog reads first; hovering brings a row back to full opacity. */
tr.excluded td {
    color: var(--muted);
    opacity: 0.4;
}
tr.excluded:hover td {
    opacity: 1;
}

/* Group section header: title on the left, the Exclude/Include-all toggle on the right. */
.group-head { display: flex; align-items: baseline; gap: .75rem; }
.group-actions { margin-left: auto; }

/* Rule-based bulk-exclude presets: a wrapping row of one-shot buttons. */
.presets { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin: var(--space-3) 0; }
.presets .meta { flex-basis: 100%; margin: 0; }
.preset-action { margin: 0; }

/* --- Stats tables ---------------------------------------------------------- */

/* Numeric stat columns (everything after the first label column) read better
   right-aligned and tabular; the all-time figures get the KPI treatment (heavy,
   full-contrast), while the "last N months" columns (.lx) are dimmed to sit
   behind them. */
.stats-table td:not(:first-child),
.stats-table th:not(:first-child) {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.stats-table td:not(:first-child):not(.lx) {
    font-weight: 700;
    color: var(--text);
}

.stats-table .lx {
    color: var(--muted);
    font-weight: 400;
}

/* Pulley exercises get their own section: a heading per exercise above its
   per-gym sub-table. */
.stats-pulley-ex {
    margin-top: var(--space-4);
}

.stats-pulley-ex h3 {
    margin-bottom: 0;
    text-transform: none;
}

/* --- Flash / status messages ----------------------------------------------- */

.flash,
.error[role="alert"] {
    border: 1px solid var(--border);
    border-left: 4px solid var(--accent);
    border-radius: var(--radius-sm);
    padding: var(--space-3) var(--space-6);
    margin: var(--space-4) 0;
    background: var(--card);
}

.flash-success {
    background: var(--ok-bg);
    border-color: var(--ok-border);
    border-left-color: var(--ok);
}

.flash-error,
.flash-warning {
    background: var(--err-bg);
    border-color: var(--err-border);
    border-left-color: var(--err-border);
    color: var(--err-text);
}

/* --- Onboarding banner ----------------------------------------------------- */

.onboarding {
    border: 1px solid var(--accent);
    border-radius: var(--radius);
    padding: var(--space-4) var(--space-6);
    margin: var(--space-4) 0;
    background: var(--card);
}

.onboarding-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
}

.onboarding-head h2 {
    margin: 0;
    font-size: 1.05rem;
    border-bottom: none;
    padding-bottom: 0;
}

.onboarding-progress {
    color: var(--muted);
    font-size: 0.85rem;
    white-space: nowrap;
}

.onboarding-intro {
    margin: var(--space-2) 0 var(--space-3);
    color: var(--muted);
    font-size: 0.9rem;
}

.onboarding-steps {
    margin: 0;
    padding: 0;
    list-style: none;
}

.onboarding-steps li {
    position: relative;
    padding: var(--space-2) 0 var(--space-2) 1.75em;
}

.onboarding-steps li::before {
    content: "○";
    position: absolute;
    left: 0;
    top: var(--space-2);
    color: var(--muted);
}

/* Strikethrough is set on the text only, so the ✓/○ marker stays crisp. */
.onboarding-steps li.done span {
    color: var(--muted);
    text-decoration: line-through;
}

.onboarding-steps li.done::before {
    content: "✓";
    color: var(--accent);
}

.onboarding-steps li.done span a {
    color: var(--muted);
}

/* --- Announcements ("what's new") ------------------------------------------ */
/* Same card treatment as the onboarding banner — it sits in the same slot and
   competes with it for attention only while both are unfinished. */

.announcements {
    border: 1px solid var(--accent);
    border-radius: var(--radius);
    padding: var(--space-4) var(--space-6);
    margin: var(--space-4) 0;
    background: var(--card);
}

.announcements-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-3);
}

.announcements-head h2 {
    margin: 0;
    font-size: 1.05rem;
    border-bottom: none;
    padding-bottom: 0;
}

.announcement + .announcement {
    border-top: 1px solid var(--border);
    margin-top: var(--space-3);
    padding-top: var(--space-3);
}

.announcement h3 {
    margin: var(--space-3) 0 var(--space-2);
    font-size: 1rem;
}

/* Archive rows: the /whats-new page reuses .announcement but heads each with h2. */
.announcement h2 {
    margin: var(--space-4) 0 0;
    font-size: 1.05rem;
}

/* Unread marker in the archive. */
.badge-new { background: #ffd24a; }

/* Unread count riding on the "What's new" nav link. */
.nav-badge {
    display: inline-block;
    min-width: 1.4em;
    padding: 0 .4em;
    border-radius: 999px;
    background: var(--accent);
    color: var(--bg);
    font-size: .75rem;
    font-weight: 700;
    text-align: center;
}

/* --- Admin nav ------------------------------------------------------------- */

.admin-nav {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-4);
    margin: 0 0 var(--space-6);
    padding: var(--space-3) var(--space-5);
    background: var(--inset);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    font-size: .95rem;
}

/* --- Admin dashboard ------------------------------------------------------- */

/* The two short panels (recent logins, announcements) sit side by side on a wide
   screen and stack below the breakpoint — same shape as .account-grid. Their rows
   are unrelated, so the columns keep their natural heights rather than matching. */
.dash-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-4);
    align-items: start;
}

/* --- Rendered feedback (markdown) + suggested routine ---------------------- */

.feedback-md {
    margin: 0;
    /* AI prose can carry long URLs/tokens; break them so they never widen the page. */
    overflow-wrap: break-word;
}

/* Markdown tables/code blocks can be wider than a phone screen — let them scroll
   inside their own box instead of pushing the whole page past the viewport. */
.feedback-md table,
.feedback-md pre {
    display: block;
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.feedback-md > :first-child {
    margin-top: 0;
}

.feedback-md > :last-child {
    margin-bottom: 0;
}

/* AI-authored and content headings stay sentence-case — the display uppercase
   is for the app's own UI headings, not generated prose. */
.feedback-md h1,
.feedback-md h2,
.feedback-md h3,
.suggested-routine h3 {
    text-transform: none;
    letter-spacing: normal;
    line-height: 1.3;
}

.feedback-md h2 {
    font-weight: 700;
}

.feedback-md code {
    background: var(--inset);
    padding: 1px 5px;
    border-radius: 4px;
}

.feedback-md hr {
    border: none;
    border-top: 1px solid var(--border);
    margin: 1em 0;
}

.suggested-routine ul {
    padding-left: 1.3em;
}

.suggested-routine li {
    margin: .2em 0;
}

/* --- Admin AI log --------------------------------------------------------- */

.copy-block {
    margin: 0 0 var(--space-5);
}

.copy-btn {
    font-size: .85rem;
    padding: var(--space-2) var(--space-4);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    background: var(--inset);
    color: inherit;
    cursor: pointer;
}

.copy-btn:hover {
    border-color: var(--accent, var(--border));
}

.ai-payload {
    background: var(--inset);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: var(--space-4);
    margin: 0 0 var(--space-5);
    white-space: pre-wrap;
    word-break: break-word;
    overflow-x: auto;
    font-size: .85rem;
    line-height: 1.45;
    max-height: 32rem;
}

.pager {
    display: flex;
    align-items: center;
    gap: var(--space-4);
}

/* --- Gym reorder ---------------------------------------------------------- */

.gym-order {
    white-space: nowrap;
}

.gym-table .drag-handle {
    cursor: grab;
    color: var(--muted);
    padding-right: var(--space-2);
    user-select: none;
}

.gym-table tr[draggable="true"] {
    cursor: grab;
}

.gym-table tr.dragging {
    opacity: .5;
}

.move-buttons button {
    padding: 0 6px;
    line-height: 1.4;
}

.move-buttons button[disabled] {
    opacity: .35;
    cursor: default;
}

/* --- Responsive ------------------------------------------------------------ */

/* Nav: below the breakpoint the links collapse behind the ☰ hamburger. */
@media (max-width: 760px) {
    .nav-toggle {
        display: inline-flex;
    }

    .topnav nav {
        display: none;
        order: 3;                 /* drop below the brand + button row */
        flex-direction: column;
        align-items: stretch;
        width: 100%;
        gap: 0;
        margin-top: var(--space-3);
        border-top: 1px solid var(--border);
    }

    .topnav nav.open {
        display: flex;
    }

    .topnav nav a {
        padding: var(--space-3) var(--space-1);
        border-bottom: 1px solid var(--border);
    }

    .topnav nav a:last-child {
        border-bottom: none;
    }
}

/* Phone: tighten the density and type scale so the dashboard stays readable. */
@media (max-width: 640px) {
    :root {
        --space-5: 13px;
        --space-6: 15px;
        --space-7: 18px;
    }

    body {
        font-size: 14px;
    }

    .wrap {
        padding: var(--space-6) var(--space-4) 44px;
    }

    h1 {
        font-size: 1.4rem;
    }

    h2 {
        font-size: 1.05rem;
    }

    .card,
    section {
        padding: var(--space-4) var(--space-5);
    }
}

/* Feedback request-mode cards stack on a narrow screen. */
@media (max-width: 520px) {
    .mode-grid {
        grid-template-columns: 1fr;
    }
}

/* Account and admin-dashboard two-column layouts collapse to a single stack. */
@media (max-width: 720px) {
    .account-grid,
    .dash-grid {
        grid-template-columns: 1fr;
    }
}

/* --- STRONK (Suprematist) structural overrides ----------------------------- */
/* The palette + radius/shadow tokens are set in the html[data-theme="stronk"]
   variable block near the top. These rules add the hard-edged, block-based
   composition the tokens alone can't express — kept here so they never touch the
   other three themes. */

/* STRONK never shouts in all-caps — sentence-case everywhere, overriding the
   display headings, brand, table headers and buttons that uppercase elsewhere. */
html[data-theme="stronk"] h1,
html[data-theme="stronk"] h2,
html[data-theme="stronk"] .topnav .brand,
html[data-theme="stronk"] thead th,
html[data-theme="stronk"] button:not(.linklike),
html[data-theme="stronk"] .btn {
    text-transform: none;
}

/* Square off the roundness that components hardcode (the radius tokens don't reach). */
html[data-theme="stronk"] #gym-filter a,
html[data-theme="stronk"] .badge,
html[data-theme="stronk"] code,
html[data-theme="stronk"] .feedback-md code {
    border-radius: 0;
}

/* Section headers become solid black blocks with cream text — the signature move.
   `> h2` (direct child only) hits card/section titles but spares nested content
   headings (.feedback-md h2, .job-card h2, .onboarding-head h2 stay plain black). */
html[data-theme="stronk"] section > h2 {
    background: #000;
    color: var(--bg);
    padding: .28em .5em;
    border-bottom: none;
    font-weight: 900;
}

/* Page titles read as heavy black slabs with a crimson Suprematist bar. */
html[data-theme="stronk"] h1 {
    font-size: 2.4rem;
    font-weight: 900;
    letter-spacing: -.01em;
    border-left: 10px solid var(--accent);
    padding-left: .28em;
}
html[data-theme="stronk"] .auth h1 {
    border-left: none;
    padding-left: 0;
}

/* Massive flat numbers for the all-time KPI figures (e.g. "180kg"). */
html[data-theme="stronk"] .stats-table td:not(:first-child):not(.lx) {
    font-size: 1.35rem;
    font-weight: 900;
    line-height: 1.1;
}

/* Heavy flat black-bordered blocks; no depth. */
html[data-theme="stronk"] .card,
html[data-theme="stronk"] section {
    border-width: 2px;
}

/* Buttons are flat crimson rectangles (the linklike table buttons stay quiet). */
html[data-theme="stronk"] button:not(.linklike),
html[data-theme="stronk"] .btn {
    font-weight: 800;
    letter-spacing: .03em;
}
html[data-theme="stronk"] button.secondary,
html[data-theme="stronk"] .btn.secondary,
html[data-theme="stronk"] button.danger,
html[data-theme="stronk"] .btn.danger {
    border-width: 2px;
}

/* Flat focus: a hard crimson edge instead of the accent glow. */
html[data-theme="stronk"] input:focus,
html[data-theme="stronk"] textarea:focus,
html[data-theme="stronk"] select:focus {
    box-shadow: none;
    border-color: var(--accent);
}

/* The brand mark is a hard crimson square — the Malevich nod. */
html[data-theme="stronk"] .topnav .brand::after {
    border-radius: 0;
    background: var(--accent);
}

/* A heavier crimson bar on flash/alert blocks. */
html[data-theme="stronk"] .flash,
html[data-theme="stronk"] .error[role="alert"] {
    border-left-width: 6px;
}

/* --- Training generator --------------------------------------------------- */
.soreness-panel {
    margin: var(--space-6) 0;
}

.soreness-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--space-2);
}

.baseline-picker {
    display: inline-flex;
    align-items: baseline;
    gap: var(--space-2);
}

.soreness-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
}

.soreness-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border);
    border-left: 5px solid var(--muted);
    border-radius: var(--radius-sm);
    background: var(--inset);
    min-width: 8.5rem;
}

.soreness-item .sm-muscle {
    font-weight: 700;
}

.soreness-item .sm-level {
    font-size: .9em;
}

/* Level accents — a warm ramp from fresh (calm) to very sore (hot). Kept as a
   left border + text tint so they read on every theme without a solid fill. */
.soreness-fresh    { border-left-color: #3fb27f; }
.soreness-mild     { border-left-color: #86c34a; }
.soreness-moderate { border-left-color: #e0b93a; }
.soreness-sore     { border-left-color: #e8863a; }
.soreness-very_sore{ border-left-color: #e05656; }

.soreness-fresh    .sm-level { color: #3fb27f; }
.soreness-mild     .sm-level { color: #86c34a; }
.soreness-moderate .sm-level { color: #e0b93a; }
.soreness-sore     .sm-level { color: #e8863a; }
.soreness-very_sore .sm-level { color: #e05656; }

.soreness-pill {
    display: inline-block;
    margin-left: var(--space-2);
    padding: 1px 8px;
    border-radius: 999px;
    font-size: .78em;
    font-weight: 700;
    color: #fff;
    vertical-align: middle;
}

.soreness-pill.soreness-fresh    { background: #3fb27f; }
.soreness-pill.soreness-mild     { background: #86c34a; }
.soreness-pill.soreness-moderate { background: #caa521; color: #1a1a1a; }
.soreness-pill.soreness-sore     { background: #e8863a; }
.soreness-pill.soreness-very_sore{ background: #e05656; }

.generator-form .gen-line {
    display: block;
    margin: var(--space-5) 0;
    font-size: 1.05em;
}

.gen-mode {
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: var(--space-4) var(--space-5);
    margin: var(--space-5) 0;
}

.gen-mode legend {
    font-weight: 700;
    padding: 0 var(--space-2);
}

.radio-inline {
    display: block;
    margin: var(--space-2) 0;
}

.gen-groups {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
    gap: var(--space-4);
    margin: var(--space-4) 0;
}

.gen-muscle {
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    padding: var(--space-3) var(--space-4);
}

.gen-muscle legend {
    padding: 0;
}

.gen-muscle-head {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-weight: 700;
    cursor: pointer;
}

.gen-exercises {
    margin-top: var(--space-3);
    padding-top: var(--space-3);
    border-top: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.gen-ex {
    font-weight: 400;
    display: flex;
    gap: var(--space-2);
    align-items: baseline;
}

.gen-actions {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    margin-top: var(--space-5);
}

.gen-recent {
    margin-top: var(--space-7);
}
