﻿/* =========================================
   Omnia WebUI - Shell Layout
   ========================================= */

:root {
    --shell-sidebar-width: 260px;
    --shell-border-color: #ddd;
    --shell-nav-bg: #f3f3f3;
    --shell-backdrop-bg: rgba(0, 0, 0, 0.4);
}

/* Base reset */
html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

/* App shell */
.app-shell {
    height: 100vh; /* important: header + body fits viewport */
    display: flex;
    flex-direction: column;
}

/* Header */
.app-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.5rem 1rem;
    border-bottom: 1px solid var(--shell-border-color);
    background-color: #ffffff;
}

.app-title {
    font-weight: 600;
    font-size: 1.1rem;
}

.app-header-right {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Body: sidebar + content */
.app-body {
    flex: 1;
    min-height: 0; /* important: enables inner scrolling */
    display: flex;
    width: 100%;
    overflow: hidden; /* prevent page scroll; content scrolls inside app-content */
    position: relative;
}

/* Navigation wrapper around Syncfusion sidebar */
.app-nav {
    background-color: var(--shell-nav-bg);
    flex-shrink: 0;
}

    .app-nav .e-sidebar {
        background-color: var(--shell-nav-bg);
        border-right: 1px solid #dee2e6;
    }

/* Sidebar content wrap — relative-positioned anchor for the edge toggle. */
.app-nav-content {
    position: relative;
    height: 100%;
}

/* Edge-mounted "hide menu" chevron — sits on the menu's right border.
   Slim tab (14×42), tucked into the top-right corner of the sidebar.
   Height matches the LEVEL 1 YEAR-tile (the red SCHOOL banner) so the
   two visually line up. Pairs with .app-nav-expand-tab below. */
.app-nav-edge-toggle {
    position: absolute;
    top: 0;
    right: 0;
    width: 14px;
    height: 42px;
    padding: 0;
    margin: 0;
    background: #f1f1f1;
    border: 1px solid #d0d0d0;
    border-radius: 0;
    color: #555;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    z-index: 2;
    transition: background 0.12s;
}

.app-nav-edge-toggle:hover {
    background: #e5e5e5;
}

/* Re-expand tab — visible when the main menu is closed. Same slim
   shape as the edge-toggle, anchored flush to the body's left edge —
   the breathing room sits on its right (the .ou-picker margin rule
   below), not the left. Dropped 10px so it aligns with the ALL
   SCHOOLS title row rather than poking above it. Click re-opens the
   menu. Stacks with the schools-list re-expand tab via the :has()
   rule further down. */
.app-nav-expand-tab {
    position: absolute;
    top: 10px;
    left: 0;
    width: 14px;
    height: 42px;
    padding: 0;
    margin: 0;
    background: #f1f1f1;
    border: 1px solid #d0d0d0;
    border-radius: 0;
    color: #555;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    z-index: 3;
    transition: background 0.12s;
}

.app-nav-expand-tab:hover {
    background: #e5e5e5;
}

/* When the main menu is also collapsed, push the schools re-expand
   tab (.sidebar-toggle, owned per-page in dashboard / assessments /
   allocation pages) down so the two tabs stack instead of colliding
   at top-left of the content area. 46px = 42 tab + 4 gap. Uses
   :has() — supported in all currently-shipping evergreen browsers;
   on the off-chance the user is on an old build the tabs will
   overlap rather than break layout. 56px = 10 top offset + 42 tab
   + 4 gap. */
.app-shell:has(.app-nav:not(.app-nav-open)) .sidebar-toggle {
    margin-top: 56px;
}

/* When the main menu is collapsed, its re-expand tab occupies the content's
   top-left corner — exactly where the org-unit picker sits (docked compact
   picker on picker-docked pages, or the pinned full list's "ALL SCHOOLS"
   heading). Shift the picker right so the tab stays visible and the heading
   isn't clipped, and grow the offsets that align content to the compact
   picker's right edge by the same amount so nothing overlaps. The tab is
   flush left and 14px wide; the picker's host column starts at x=12
   (slice padding), so the 8px margin puts the panel at x=20 — a 6px gap
   on the tab's right, which is where its breathing room lives now that
   the left inset is gone. The doubled .picker-docked class out-ranks
   the per-page scoped offset rules (which carry two scope attributes). */
.app-shell:has(.app-nav:not(.app-nav-open)) .ou-picker {
    margin-left: 8px;
}

.app-shell:has(.app-nav:not(.app-nav-open)) .picker-docked.picker-docked .page-top-row {
    margin-left: calc(var(--admin-col-schools) + 8px);
}

.app-shell:has(.app-nav:not(.app-nav-open)) .schools-slice.picker-docked.picker-docked .schools-right {
    margin-left: calc(var(--admin-col-schools) + 1rem + 8px);
}

/* Optional legacy nav list styling (kept to avoid breaking anything) */
.app-nav-list {
    list-style: none;
    margin: 0;
    padding: 0.5rem;
}

    .app-nav-list li {
        margin-bottom: 0.25rem;
    }

    .app-nav-list a {
        display: block;
        padding: 0.5rem 0.75rem;
        border-radius: 0.375rem;
        text-decoration: none;
        color: #333;
        transition: background-color 0.2s;
    }

        .app-nav-list a:hover {
            background-color: #e0e0e0;
        }

        .app-nav-list a.active {
            font-weight: 600;
            background-color: #e3f2fd;
            color: #0d47a1;
        }

/* Content area
   v04: padding stripped here so admin pages can run flush to the viewport.
   Per-page slices (.dashboard-slice / .student-slice / .assessment-slice)
   own their own outer padding. Old default was 1rem, which stacked with
   .shell-frame-body's 1rem and the slice padding to ~36px on the left and
   ~64px on top before the actual content started. */
.app-content {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-width: 0; /* standard flexbox fix */
    min-height: 0;
    overflow-y: auto; /* scroll inside content only */
    position: relative;
    padding: 0;
}

/* Mobile toggle button */
.nav-toggle {
    background: none;
    border: none;
    font-size: 1.5rem;
    padding: 0.25rem 0.5rem;
    cursor: pointer;
    color: #333;
}

/* Simple utility card (kept to avoid breaking anything) */
.card {
    padding: 1rem;
    border-radius: 0.5rem;
    border: 1px solid #e0e0e0;
    background-color: #fff;
    margin-bottom: 1rem;
}

/* Touch targets */
button, .btn, .e-btn {
    min-height: 40px;
}

/* Backdrop (mobile overlay) */
.app-backdrop {
    position: fixed;
    inset: 0;
    background-color: var(--shell-backdrop-bg);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
    z-index: 999; /* below sidebar, above content */
}

    .app-backdrop.app-backdrop-visible {
        opacity: 1;
        pointer-events: auto;
    }

/* --- DESKTOP (Min-width: 769px) --- */
@media (min-width: 769px) {

    .app-backdrop {
        display: none !important;
    }

    .app-nav {
        height: 100%;
        position: relative;
        z-index: 1;
        width: 0;
        overflow: hidden;
        transition: width 0.3s ease;
    }

    .app-nav.app-nav-open {
        width: var(--shell-sidebar-width);
    }

        .app-nav .e-sidebar {
            position: absolute !important;
            top: 0;
            bottom: 0;
            left: 0;
            width: var(--shell-sidebar-width) !important;
            transform: none !important;
            z-index: auto !important;
            box-shadow: none !important;
        }
}

/* --- MOBILE (Max-width: 768px) --- */
@media (max-width: 768px) {

    .app-nav {
        width: 0;
        flex: 0 0 0;
    }

        .app-nav .e-sidebar {
            position: fixed !important;
            top: 0;
            bottom: 0;
            left: 0;
            width: var(--shell-sidebar-width) !important;
            z-index: 1000 !important; /* above backdrop */
            transform: translateX(-100%);
            transition: transform 0.3s ease-in-out;
            box-shadow: 4px 0 10px rgba(0,0,0,0.1);
        }

            .app-nav.app-nav-open .e-sidebar,
            .app-nav .e-sidebar.e-open {
                transform: translateX(0) !important;
            }
}


.P4 {
    --runner-font-scale: 0.8;
}

.P6 {
    --runner-font-scale: 1;
}

.P8 {
    --runner-font-scale: 1.2;
}
/* =========================================
   Stefan admin-search (shared) — 200 × 30, grey magnifying-glass on the left,
   14 px inset from top-right of its column box. Consistent across every admin page.
   ========================================= */
.admin-search {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    width: var(--admin-search-box-w);    /* 200px */
    height: var(--admin-search-box-h);   /* 30px */
    padding: 0 10px;
    background: #fff;
    border: 1px solid #d0d0d0;
    border-radius: 0;
    box-sizing: border-box;
    font-family: var(--admin-font);
    color: var(--admin-charcoal);
}

.admin-search .admin-search-icon {
    color: #888;
    font-size: 13px;
    flex: 0 0 auto;
}

.admin-search .admin-search-input {
    flex: 1 1 auto;
    min-width: 0;
    border: none;
    outline: none;
    background: transparent;
    font-family: var(--admin-font);
    font-size: 13px;
    color: var(--admin-charcoal);
    padding: 0;
}

.admin-search .admin-search-input::placeholder {
    color: #9a9a9a;
}

/* ── Shared box-toggle button (Phase P) ──
   The square 24 × 24 "+" / "−" frame used on every expand/collapse toggle
   across admin pages: class cards, panel headers, validation panels, etc.
   Use this class instead of copying the same rule into each scoped .razor.css.
   Pair with the stable two-span icon pattern so Font Awesome's SVG swap
   doesn't break Blazor's DOM diff — see the "Box open / close" section in
   .claude/skills/admin-ui-design/SKILL.md. */
.admin-box-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--admin-toggle-size);
    height: var(--admin-toggle-size);
    min-height: var(--admin-toggle-size);            /* beat global button min-height */
    padding: 0;
    border: 1px solid var(--admin-toggle-stroke);
    background: var(--admin-toggle-fill);
    color: var(--admin-toggle-symbol);                /* v04: darker grey, NOT charcoal */
    border-radius: 0;
    cursor: pointer;
    font-size: 12px;
    box-sizing: border-box;
    line-height: 1;
}

.admin-box-toggle:hover {
    background: var(--admin-surface-hover-strong);
}

/* Constrain the FA glyph inside the toggle so the SVG replacement doesn't
   balloon to fill the 24×24 frame. Matches the .alerts-chevron pattern. */
.admin-box-toggle > span > i,
.admin-box-toggle > span > svg {
    font-size: 12px;
    width: 12px;
    height: 12px;
}

/* ── Stefan v04 button hierarchy ──
   Three sizes (Button 1 / 2 / 3), all sharing Subheading-2 type and zero radius.
   Per-button fill colour and width is set on the host class — these classes
   only normalise the height, type, gap, and padding so that every admin
   button picks the same baseline. See SKILL.md → "Button hierarchy". */
.admin-btn-1, .admin-btn-2, .admin-btn-3 {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 0 12px;
    font-family: var(--admin-font);
    font-size: var(--admin-sub2-size);                 /* 12px */
    font-weight: var(--admin-sub2-weight);             /* 700 */
    letter-spacing: var(--admin-sub2-tracking);        /* 0.5px */
    text-transform: uppercase;
    border-radius: 0;
    box-sizing: border-box;
    cursor: pointer;
    white-space: nowrap;
}
.admin-btn-1 { height: var(--admin-btn1-h); min-height: var(--admin-btn1-h); }
.admin-btn-2 { height: var(--admin-btn2-h); min-height: var(--admin-btn2-h); }
.admin-btn-3 { height: var(--admin-btn3-h); min-height: var(--admin-btn3-h); }

/* ── "+ ADD NEW …" action buttons (ADD NEW CLASS / ADD NEW STAFF) ──
   Charcoal fill so they match ADD NEW STUDENT (.btn-add-student) for the
   cross-page consistency their own scoped comments call for. .btn-add-class
   is used by both Classes.razor and Teachers.razor, where the scoped CSS only
   sets `margin-left: auto`; the fill belongs here (global) so both pick it up.
   Base .admin-btn-3 carries no background, so without this they fell back to a
   transparent/light button — the odd-one-out a tour or hover draws attention to. */
.btn-add-class {
    background: var(--admin-charcoal);
    color: var(--admin-white);
    border: 1px solid var(--admin-charcoal);
    transition: background 0.15s, border-color 0.15s;
}
.btn-add-class > i { color: var(--admin-white); }
.btn-add-class:hover:not(:disabled) {
    background: #000;
    border-color: #000;
}

/* ── Stefan v04 page-top row ──
   Shared layout for the first row of every admin page. School Header on the
   left (flex: 1), User Settings strip on the right (auto width), 30 px gap
   between them per Stefan's spec. Used by SchoolDashboard, AssessmentDashboard,
   StudentDashboard, and any future page that follows the same pattern. */
.page-top-row {
    display: flex;
    align-items: flex-start;
    gap: 30px;
    margin-bottom: 8px;
}

.page-top-row > .school-header-panel {
    flex: 1;
    min-width: 0;
    margin-bottom: 0;                            /* gap handled by .page-top-row */
    margin-right: 0;                             /* no absolute strip to dodge */
}

/* ── Inline schools-list collapse chevron ──
   Lives inside OrgUnitPickerPanel's HeaderActions slot (right-flushed beside
   "ALL SCHOOLS"). Same 24×24 charcoal chevron as the external .sidebar-toggle
   so the two render identically — only the layout differs (inline flex row
   vs grid column). Defined here so every admin page that hosts the picker
   inherits the same look without each scoped CSS having to redeclare it. */
.sidebar-toggle-inline {
    width: var(--admin-toggle-size);
    height: var(--admin-toggle-size);
    min-height: var(--admin-toggle-size);
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--admin-toggle-fill);
    border: 1px solid var(--admin-toggle-stroke);
    border-radius: 0;
    font-size: 12px;
    color: var(--admin-toggle-symbol);
    cursor: pointer;
    flex-shrink: 0;
    transition: background 0.15s;
}

.sidebar-toggle-inline:hover {
    background: var(--admin-surface-hover-strong);
}

/* ── Stacked-bar count label ──
   Tiny count rendered inside each segment of the class-card stacked bars
   (dashboard, assessments dashboard, students page). White text with a
   subtle shadow so it reads on top of any segment colour. Segments that
   are too narrow will clip the count via overflow:hidden on the seg. */
.bar-seg-count {
    color: var(--admin-white);
    font-size: 9px;
    font-weight: 700;
    line-height: 1;
    white-space: nowrap;
    pointer-events: none;
    text-shadow: 0 0 2px rgba(0, 0, 0, 0.45);
}

/* Shared loading-state for the student list panels (Students / Assessments
   / Dashboard pages). Parent flips `_isListLoading` true on a list reload;
   the panel passes it through to its root div so the grid dims and stops
   responding to clicks until the new data lands. Quick fade-in on opacity
   gives a subtle "something is happening" cue without a full spinner. */
.student-grid-panel.is-loading {
    opacity: 0.4;
    pointer-events: none;
    transition: opacity 0.12s ease-out;
    cursor: progress;
}

/* ── Marker room: the answer is the subject of the card ──────────────
   A marker reads the student's answer, weighs it against the rubric and
   scores it. Everything else on the card — badges, counts, the
   coordinator's pre-mark — is apparatus around it, so the answer gets the
   size and contrast and the apparatus stays quiet (client feedback
   2026-08-18: the answer did not stand out).
   Global rather than a scoped .razor.css: this markup is emitted from a
   RenderFragment, and a new scoped stylesheet also needs the static-asset
   manifest rebuilt — neither is worth the risk six days from marking day. */
.answer-text {
    /* Scaled by the shared A-/A+ control (AnswerFontSizeControl): the host
       page sets --answer-font-scale; unset = 1 and nothing changes. */
    font-size: calc(1.15rem * var(--answer-font-scale, 1));
    line-height: 1.55;
    white-space: pre-wrap;
    padding: 0.5rem 0.75rem;
    border-left: 3px solid #0d6efd;
    background-color: rgba(13, 110, 253, 0.04);
    border-radius: 0.25rem;
}

/* Inside a block card every member is an answer beside its include tick —
   same treatment, tightened so a 25-member block stays a readable list. */
.answer-text-member {
    display: block;
    font-size: calc(1.05rem * var(--answer-font-scale, 1));
    padding: 0.35rem 0.6rem;
    margin-bottom: 0.25rem;
    cursor: pointer;
}

/* Wording judgement tints — row backgrounds in a block that is partly
   judged or carries mixed scores, so the coordinator sees AT A GLANCE
   which wordings still need her and which score each one already holds.
   One consistent mapping everywhere: unjudged = amber (attention), each
   score = its own very light colour, NA = grey, mixed-within-wording =
   orange. Far lighter than the word-highlight tints, which sit on words
   INSIDE these rows — the two layers must compose, not compete. */
.wj-unjudged { background-color: rgba(255, 193, 7, 0.16); border-radius: 3px; }
.wj-score-0 { background-color: rgba(220, 53, 69, 0.07); border-radius: 3px; }
.wj-score-1 { background-color: rgba(13, 110, 253, 0.07); border-radius: 3px; }
.wj-score-2 { background-color: rgba(25, 135, 84, 0.08); border-radius: 3px; }
.wj-score-3 { background-color: rgba(111, 66, 193, 0.08); border-radius: 3px; }
.wj-na { background-color: rgba(108, 117, 125, 0.10); border-radius: 3px; }
.wj-mixed { background-color: rgba(253, 126, 20, 0.10); border-radius: 3px; }
.wj-judged { background-color: rgba(32, 201, 151, 0.08); border-radius: 3px; }

/* The question fold control. A text triangle at link size read as
   decoration next to the item code, not as the thing that opens the card —
   so it is now a real target: a 2rem bordered button with a chevron that
   ROTATES rather than swapping glyph, because the movement is what says
   "this opens and shuts". Inline SVG, not the Font Awesome loaded from a
   CDN: a school network blocking that CDN must not leave a marker with an
   invisible control. */
.marking-fold {
    display: inline-flex;
    align-items: center;
    gap: .55rem;
    background: none;
    border: 0;
    padding: 0;
    text-align: left;
    color: inherit;
}

.marking-fold__chevron {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: 50%;
    background: var(--bs-tertiary-bg, #f8f9fa);
    color: var(--bs-secondary-color, #6c757d);
    transition: transform .15s ease-in-out, background-color .15s ease-in-out, color .15s ease-in-out;
}

/* Open = pointing down at the work it revealed. */
.marking-fold[aria-expanded="true"] .marking-fold__chevron {
    transform: rotate(90deg);
    background: var(--bs-primary-bg-subtle, #cfe2ff);
    border-color: var(--bs-primary-border-subtle, #9ec5fe);
    color: var(--bs-primary, #0d6efd);
}

.marking-fold:hover .marking-fold__chevron,
.marking-fold:focus-visible .marking-fold__chevron {
    background: var(--bs-primary-bg-subtle, #cfe2ff);
    color: var(--bs-primary, #0d6efd);
}

.marking-fold:focus-visible {
    outline: 2px solid var(--bs-primary, #0d6efd);
    outline-offset: 2px;
    border-radius: .25rem;
}

/* A rotating control is decoration to anyone who has asked for less of it. */
@media (prefers-reduced-motion: reduce) {
    .marking-fold__chevron { transition: none; }
}

/* The question stem, wherever a marker meets it. The item code names the
   question to the system; THIS names it to the person about to read several
   hundred answers written to it, so on a card crowded with codes, counts and
   badges it has to be the thing the eye lands on first. Sized above the body
   text rather than coloured: it is prose to be read, not a status to be
   decoded, and colour here would compete with the highlight aid below. */
.marking-stem {
    font-size: 1.15rem;
    font-weight: 600;
    line-height: 1.35;
    color: var(--bs-emphasis-color, #000);
}

/* Word highlighting — the legacy marking tool's four-colour aid. Soft
   backgrounds, not text colour: the answer must stay readable as prose
   while the marker's eye is drawn. Blue = word from the question (parroting
   the stem earns nothing), green = likely part of a correct answer, red =
   likely incorrect / negating, yellow = neutral. */
.hl-q  { background-color: rgba(13, 110, 253, 0.18); border-radius: 2px; }
.hl-ok { background-color: rgba(25, 135, 84, 0.22); border-radius: 2px; }
.hl-no { background-color: rgba(220, 53, 69, 0.22); border-radius: 2px; }
.hl-neu { background-color: rgba(255, 193, 7, 0.30); border-radius: 2px; }

/* A search hit is a DIFFERENT AXIS from the word colours — "you asked for
   this word", not "this word means something". A plain <mark> renders
   browser-yellow, which is the neutral colour, so a searched word read as
   a lexicon judgement (Patrick, 2026-08-21). Underline rather than fill:
   it sits on top of any of the four backgrounds without competing with
   one, and survives inside a coloured span. */
mark.hl-term {
    background-color: transparent;
    color: inherit;
    font-weight: 600;
    text-decoration: underline;
    text-decoration-color: #6f42c1;
    text-decoration-thickness: 2px;
    text-underline-offset: 2px;
    padding: 0;
}

/* Unticked: leaving the block's one decision. Still fully readable, but it
   stops claiming to be part of what is being scored. */
.answer-text-member.text-muted {
    border-left-color: #6c757d;
    background-color: rgba(108, 117, 125, 0.05);
}

/* Opt-in scaling for answer text that is not a marker card — the answer
   browser's list rows and block wordings, the review pane. Same variable,
   same control. */
.answer-scaled {
    font-size: calc(1rem * var(--answer-font-scale, 1));
}

/* ── Marking Key splitter (2026-08-21) ───────────────────────────────────
   The marker drags the bar between the answers and the rubric. Two rules
   carry the whole thing: height stays AUTO so the panes grow with the
   answer list and the PAGE keeps its single scrollbar, and panes stay
   overflow-VISIBLE so the rubric rail's position:sticky still has room to
   travel (a pane with its own scroller would trap it — the very failure
   align-self: stretch was added to fix). Collapsed = the Hide button's
   "whole width back": zero right pane, no bar. */
.mk-splitter.e-splitter {
    border: none;
    background: transparent;
    height: auto !important;
    overflow: visible !important;
}
.mk-splitter.e-splitter > .e-pane {
    overflow: visible !important;
    height: auto !important;
}
.mk-splitter.e-splitter > .e-pane:first-child {
    padding-right: 1rem;
}
.mk-splitter.e-splitter > .e-split-bar {
    background-color: transparent;
    height: auto !important;
}
.mk-splitter-collapsed.e-splitter > .e-pane:last-child {
    flex-basis: 0 !important;
    max-width: 0 !important;
    padding: 0 !important;
    overflow: hidden !important;
}
.mk-splitter-collapsed.e-splitter > .e-split-bar {
    display: none !important;
}

/* ── Marking-room table pills (2026-08-22) ──────────────────────────
   One row per table: name, seat count, and a remove. Built as inline-flex
   with nowrap because the previous version was a .badge holding a
   Bootstrap .btn-close — a fixed-size box that wrapped onto its own line
   and made every pill two lines tall. Everything here is sized in em off
   the pill's own font-size, so the control can never out-grow its pill. */
.mk-table-pill {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    white-space: nowrap;
    font-size: .8125rem;
    line-height: 1.4;
    /* Fixed height: the pill's size must not depend on WHICH control it
       carries — the seated pill (span ×) and the removable pill (button ×)
       have to be identical boxes (Patrick, 2026-08-24). */
    height: 1.75rem;
    padding: 0 .5rem;
    border: 1px solid var(--bs-border-color, #dee2e6);
    border-radius: 999px;
    background-color: var(--bs-tertiary-bg, #f8f9fa);
    color: var(--bs-body-color, #212529);
}

.mk-table-pill--arming {
    border-color: var(--bs-danger-border-subtle, #f1aeb5);
    background-color: var(--bs-danger-bg-subtle, #f8d7da);
}

.mk-table-pill__name {
    font-weight: 600;
}

/* The seat count is context, not the label — it recedes. */
.mk-table-pill__seats {
    color: var(--bs-secondary-color, #6c757d);
}

.mk-table-pill__remove,
.mk-table-pill__blocked {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* rem, not em, and font: inherit first: a <button> does NOT inherit the
       pill's font — the browser hands it its own, larger one — so em sizing
       made every removable pill bigger than the seated one, whose × is a
       span and inherits properly. This was the size drift Patrick saw:
       Room 1 (seated) was the only pill at the intended size. */
    font: inherit;
    appearance: none;
    width: 1rem;
    height: 1rem;
    flex: 0 0 auto;
    font-size: .9rem;
    line-height: 1;
    border: 0;
    border-radius: 50%;
    background: transparent;
    padding: 0;
}

.mk-table-pill__remove {
    color: var(--bs-secondary-color, #6c757d);
    cursor: pointer;
}

.mk-table-pill__remove:hover:not(:disabled),
.mk-table-pill__remove:focus-visible {
    color: var(--bs-danger, #dc3545);
    background-color: var(--bs-danger-bg-subtle, #f8d7da);
}

.mk-table-pill__remove:disabled {
    opacity: .4;
    cursor: default;
}

/* Seated: shown so the pill's shape does not jump, dimmed so it never
   reads as available. The title carries the reason. */
.mk-table-pill__blocked {
    color: var(--bs-secondary-color, #6c757d);
    opacity: .35;
    cursor: not-allowed;
}

/* The question header's reading-band pills CLAIM a batch (2026-08-24). They
   were inert labels sitting directly above cluster rows whose identically
   shaped bands did claim — one shape, two behaviours. Now they are buttons,
   and they have to LOOK like something you press: a badge alone reads as a
   label no matter what element carries it.

   font-family, not the `font` shorthand: .badge sets its own font-size and
   weight, and the shorthand would blow both away. A <button> still does not
   inherit the family (see .mk-table-pill__remove above for the same trap). */
.mk-band-pill {
    font-family: inherit;
    appearance: none;
    cursor: pointer;
    /* The affordance: a hairline ring in the pill's own ink, so the pill
       reads as pressable without breaking the solid colour that ties it to
       the cluster bands below. */
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .45);
    transition: filter .12s ease-in-out, box-shadow .12s ease-in-out;
}

.mk-band-pill:hover:not(:disabled),
.mk-band-pill:focus-visible {
    filter: brightness(1.08);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .7), 0 0 0 .2rem rgba(13, 110, 253, .25);
}

.mk-band-pill:active:not(:disabled) {
    filter: brightness(.94);
}

/* Disabled only while a claim is in flight — it must read as "wait", never
   as "this band is empty" (the empty bands are not rendered at all). */
.mk-band-pill:disabled {
    cursor: wait;
    opacity: .65;
}

/* SCORE BUTTONS: FOCUS MUST NOT LOOK LIKE A MARK (marker, 2026-08-24).

   Bootstrap's `.btn:focus-visible` paints an outline button with
   `--bs-btn-hover-bg` — for .btn-outline-primary that is the SAME solid blue
   as .btn-primary, which is exactly how this page says "this score is the
   one chosen". So a button that merely held keyboard focus was
   indistinguishable from a score that had been given.

   Auto-advance made that a live-marking problem rather than a curiosity: the
   marker scores, the window steps to the next wording, and because Blazor
   reuses the button element in that position, the focus — and the filled
   look — rides across onto the NEXT question's score row. Markers saw the
   previous answer's mark sitting on a question they had not judged yet, and
   clicking anywhere on the page (which moves focus) made it vanish.

   The fill is reserved for the mark. Focus gets a ring, which is what a
   focus indicator is for, and stays clearly visible for keyboard users. */
.mk-score-group .btn-outline-primary:focus-visible {
    color: var(--bs-btn-color);
    background-color: transparent;
    border-color: var(--bs-btn-border-color);
    box-shadow: 0 0 0 .2rem rgba(13, 110, 253, .4);
}

/* Hover keeps Bootstrap's fill — a hover is transient and tracks the pointer
   the marker is looking at, so it cannot be mistaken for a saved state the
   way a sticky focus could. */
