/* This application's own styling: rules for things only this application has.

   The shell's look is the library's shell.css and the tokens this application overrides are in
   theme.css, which holds tokens only. Every rule, including one that overrides a rule of the
   shell's, is here. */

/* ---- Tier pills: the pill says which rank, this says what a tier looks like ----------------------
   A tint and an ink per tier, in both modes; the digit is always inside the pill, so colour is never
   the only channel. Tier 2 and 3 keep the hues the row tint taught, tier 1 is a muted green, and a 0
   is hollow: the honest zero of docs\design-tier-domains.md §6. */

:root {
    --tier-1-tint: #D6E9D2;
    --tier-1-ink: #2F5E2B;
    --tier-2-tint: #B9D4EC;
    --tier-2-ink: #1F4E79;
    --tier-3-tint: #CDB8E0;
    --tier-3-ink: #4B2C6E;
    /* The selected row of a two-pane list: a warm tint against the shell's blue hover, so the row
       being shown and the row under the pointer never read as the same thing. */
    --row-selected: #fbefcf;
    --row-selected-hover: #f7e4b0;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --tier-1-tint: rgba(76, 140, 70, .38);
        --tier-1-ink: #C4E8BE;
        --tier-2-tint: rgba(0, 150, 155, .38);
        --tier-2-ink: #A9E4E6;
        --tier-3-tint: rgba(110, 72, 160, .55);
        --tier-3-ink: #DFCBF3;
        --row-selected: rgba(232, 176, 64, .22);
        --row-selected-hover: rgba(232, 176, 64, .34);
    }
}

:root[data-theme="dark"] {
    --tier-1-tint: rgba(76, 140, 70, .38);
    --tier-1-ink: #C4E8BE;
    --tier-2-tint: rgba(0, 150, 155, .38);
    --tier-2-ink: #A9E4E6;
    --tier-3-tint: rgba(110, 72, 160, .55);
    --tier-3-ink: #DFCBF3;
    --row-selected: rgba(232, 176, 64, .22);
    --row-selected-hover: rgba(232, 176, 64, .34);
}

/* ---- The code map: a district's codes beside each subtype ----------------------------------------
   A form table per primary inside the frame; the shell draws the tables. The subtype column is one width
   in every table, sized to the longest name on the page, the names right-aligned against the field, so
   the code fields line up in one column down the page. */
:root { --code-map-name-w: 10rem; }
[data-meliora-code-map] .form-table td:first-child { width: var(--code-map-name-w); text-align: right; }
[data-meliora-code-map] .form-table th:first-child { text-align: right; }

/* The preview's running score, once app.js has moved it into the heading: pinned to the heading's far
   edge, clear of the name, large enough to read at a glance while a case worker clicks through the
   answers. Absolute, so the heading keeps its height whether the score is there or not; the dialog's
   heading grows to its header's width so the far edge is the panel's, not the name's. */
h1:has(.screener-score), [data-meliora-dialog-header] h2:has(.screener-score) { position: relative; padding-right: 11rem; }
[data-meliora-dialog-header] h2:has(.screener-score) { flex: 1 1 auto; }
h1 .screener-score, h2 .screener-score { position: absolute; right: 0; top: 50%; transform: translateY(-50%); font-size: .95em; font-weight: 600; line-height: 1; color: var(--ink-2); white-space: nowrap; }


.pill.tier { min-width: 1.7rem; text-align: center; }
.pill.tier[data-tier="1"] { background: var(--tier-1-tint); color: var(--tier-1-ink); }
.pill.tier[data-tier="2"] { background: var(--tier-2-tint); color: var(--tier-2-ink); }
.pill.tier[data-tier="3"] { background: var(--tier-3-tint); color: var(--tier-3-ink); }
.pill.tier[data-tier="0"] { background: transparent; color: var(--ink-2); box-shadow: inset 0 0 0 1px var(--line-2); }

/* ---- The front door's art panel: the logo's peaks, a ridge behind them, the sun, the trend line, the creed
   The markup is Views\Shared\_AuthArt.cshtml, this application's copy of the library's partial; the
   panel and its ground are the library's and theme.css's. The peaks are the logo itself and never
   move; the ridge behind them drifts and the sun breathes, so depth comes from what moves against
   what does not; the trend line draws itself once from the summit and its nodes swell together
   when it lands. Only a scene the partial marks live moves: the sign-in page and the lock screen. */

.auth-art .auth-scene { position: absolute; inset: 0; width: 100%; height: 100%; }

.auth-art .ridge { will-change: transform; }
/* The ridge behind the peaks takes the brand purple the peaks are painted in, dimmed: on the navy
   ground a navy ridge is invisible. */
.auth-art .ridge-back { fill: #4A1C7C; opacity: .28; }
.auth-art .live .ridge-back { animation: auth-drift-back 90s ease-in-out infinite; }
.auth-art .live .sun { transform-box: fill-box; transform-origin: center; animation: auth-breathe 12s ease-in-out infinite; }

@keyframes auth-drift-back {
    0%, 100% { transform: translateX(0); }
    50%      { transform: translateX(26px); }
}
@keyframes auth-breathe {
    0%, 100% { transform: scale(1); opacity: .85; }
    50%      { transform: scale(1.06); opacity: 1; }
}

/* The polyline's length, so the dash draws it end to end without a script to measure it. The draw is
   LINEAR so that a node's delay is the draw's start plus its share of the length times the duration:
   each node appears just as the line reaches it. Change the points and these delays change with them. */
.auth-art .live .trend {
    stroke-dasharray: 652;
    stroke-dashoffset: 652;
    animation: auth-draw 3.4s linear .35s forwards;
}
.auth-art .live .trend-node {
    transform-box: fill-box;
    transform-origin: center;
    opacity: 0;
    animation: auth-node-in .35s ease-out forwards, auth-node-swell .75s cubic-bezier(.34, 1.4, .5, 1) 4s;
}
.auth-art .live .trend-node:nth-child(1) { animation-delay: .4s, 4s; }
.auth-art .live .trend-node:nth-child(2) { animation-delay: .92s, 4s; }
.auth-art .live .trend-node:nth-child(3) { animation-delay: 1.7s, 4s; }
.auth-art .live .trend-node:nth-child(4) { animation-delay: 1.88s, 4s; }
.auth-art .live .trend-node:nth-child(5) { animation-delay: 2.62s, 4s; }
.auth-art .live .trend-node:nth-child(6) { animation-delay: 2.96s, 4s; }
.auth-art .live .trend-node:nth-child(7) { animation-delay: 3.35s, 4s; }
.auth-art .live .trend-node:nth-child(8) { animation-delay: 3.8s, 4s; }

@keyframes auth-draw { to { stroke-dashoffset: 0; } }
@keyframes auth-node-in {
    from { opacity: 0; transform: scale(.3); }
    to   { opacity: 1; transform: scale(1); }
}
@keyframes auth-node-swell {
    0%   { transform: scale(1); }
    45%  { transform: scale(1.55); }
    100% { transform: scale(1); }
}

/* The creed sits in the sky, clear of the ridgeline even on a short window. */
.auth-art .creed {
    position: absolute;
    left: 2.75rem;
    right: 2.75rem;
    top: 2.5rem;
    margin: 0;
    z-index: 2;
    text-transform: uppercase;
    letter-spacing: .13em;
}
.auth-art .creed span {
    display: block;
    font-size: 1.1rem;
    line-height: 1.52;
    color: rgba(255, 255, 255, .62);
}
.auth-art .creed .creed-last {
    position: relative;
    margin-top: .7rem;
    padding-top: .8rem;
}
/* The yellow rule is a pseudo-element on the last row's wrapper rather than a border on the line, so
   the live scene can draw it left to right while the line inside rises without it. */
.auth-art .creed .creed-last::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    height: 2px;
    width: 100%;
    background: #D0C335;
}
.auth-art .creed em {
    display: block;
    font-style: normal;
    font-size: 1.35rem;
    line-height: 1.52;
    color: #fff;
}

/* The creed's entrance, on the same pages as the line and timed to end with it (the draw ends at
   3.75s): the three rows start layered on the first; the second and third fall together at one
   speed, so the second is in place while the third is still falling; the rule draws from the left
   on its own row; the last line rises from a third of the way down the page while it fades in. */
.auth-art .creed.live span:nth-child(2) { animation: auth-fall-one 1.7s cubic-bezier(.22, .61, .36, 1) .35s both; }
.auth-art .creed.live span:nth-child(3) { animation: auth-fall-two 3.4s cubic-bezier(.22, .61, .36, 1) .35s both; }
.auth-art .creed.live .creed-last::before { animation: auth-rule 3.4s cubic-bezier(.22, .61, .36, 1) .35s both; }
.auth-art .creed.live em { animation: auth-rise 3.4s cubic-bezier(.22, .61, .36, 1) .35s both; }

@keyframes auth-fall-one { from { transform: translateY(-100%); } to { transform: translateY(0); } }
@keyframes auth-fall-two { from { transform: translateY(-200%); } to { transform: translateY(0); } }
@keyframes auth-rule { from { width: 0; } to { width: 100%; } }
@keyframes auth-rise {
    from { opacity: 0; transform: translateY(33vh); }
    to   { opacity: 1; transform: translateY(0); }
}

@media (max-height: 52rem) {
    .auth-art .creed { top: 2rem; }
    .auth-art .creed span { font-size: 1rem; line-height: 1.45; }
    .auth-art .creed em { font-size: 1.2rem; line-height: 1.45; }
}

@media (prefers-reduced-motion: reduce) {
    .auth-art .live .ridge-back, .auth-art .live .sun { animation: none; }
    .auth-art .live .trend { stroke-dasharray: none; stroke-dashoffset: 0; animation: none; }
    .auth-art .live .trend-node { opacity: 1; animation: none; }
    .auth-art .creed.live span, .auth-art .creed.live em, .auth-art .creed.live .creed-last::before { animation: none; }
}

/* ---- The front door: the logo's own navy behind the art, and the mark at the size the mockup drew it.
   WHY navy and not the brand purple: the logo's peaks are painted in the brand purple, so on a purple
   ground the A disappears; on the navy the logo itself uses for its foot, every colour in it reads. */
.auth-art { background: linear-gradient(160deg, #062744 0%, #0E3D68 50%, #1E5F92 100%); }
.anonymous .brand img { width: 17.5rem; height: auto; }
[data-scene="lock"] .anonymous { background: linear-gradient(160deg, #4A1C7C 0%, #380F5E 45%, #28083F 100%); }

/* The lookups screen's table picker: the shell's own buttons in a row, the chosen table solid and the rest ghosted,
   so the selection reads the way the Theme button does. */
.lookup-picker {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    margin: 0 0 1.1rem;
    padding: 0 0 .75rem;
    border-bottom: 1px solid var(--line);
}

/* Sized like the toolbar's Search and Clear, not the header's Theme. */
.lookup-picker .btn { padding: .22rem .6rem; font-size: .8rem; line-height: 1.4; }

/* An unchosen table sits on the shell's ghost fill rather than showing the page through it. */
.lookup-picker .btn.ghost { background: var(--ghost-fill); }
.lookup-picker .btn.ghost:hover { background: var(--ghost-fill-hover); }

.lookup-picker a[aria-current="page"] { cursor: default; }

/* The rendered screener, on the preview and later the answer page. */
.screener-render .screener-instructions { font-weight: 600; }
.screener-question { border: 0; border-top: 1px solid var(--line); padding: .6rem 0; margin: 0; min-width: 0; }
.screener-question > legend { font-weight: 600; padding: 0; }
.screener-choices { display: flex; flex-wrap: wrap; gap: .4rem 1.2rem; }
.screener-choice { display: inline-flex; align-items: center; gap: .35rem; }
/* A Yes/No question's description: the box under the two radios while answering, the text when read. */
.screener-detail { margin-top: .4rem; }
.screener-detail .note { min-height: 4.5rem; }
.screener-detail-text { margin: .4rem 0 0; white-space: pre-wrap; }

/* The answer form as it is filled, on the browser's own :has(): a question still to answer sits on a warm
   band with its legend in the warn ink, and once an option is chosen the band goes, the chosen option
   reads bold in the accent and the others step back. Colour never stands alone: the band and the weight
   are the second channel. The rule and the padding are constant so answering shifts nothing sideways.
   The answer form only: the authoring preview and the completed sheet have nothing to answer. */
[data-meliora-screener-answer] .screener-question { border-left: 3px solid transparent; padding-left: .6rem; }
[data-meliora-screener-answer] .screener-question:not(:has(input:checked)) { background: var(--warn-tint); border-left-color: var(--warn); }
[data-meliora-screener-answer] .screener-question:not(:has(input:checked)) > legend { color: var(--warn); }
[data-meliora-screener-answer] .screener-question:has(input:checked) .screener-choice { color: var(--ink-2); }
[data-meliora-screener-answer] .screener-question .screener-choice:has(input:checked) { color: var(--accent-ink); font-weight: 600; }

/* A SAVED SURVEY SHEET (its inputs disabled) dims the answers that were not chosen, so the chosen one reads at a glance (Todd, 2026-10-30). */
[data-meliora-survey-sheet] .screener-choice:has(input:disabled:not(:checked)) { color: var(--ink-3); opacity: .6; }
[data-meliora-survey-sheet] .screener-choice:has(input:disabled:checked) { color: var(--ink); font-weight: 600; }


/* The running score on the preview: one quiet line that holds its place, shown once something is chosen. */
.screener-score { margin: .2rem 0 .6rem; font-weight: 600; color: var(--ink-2); }

/* The New Screener page: screeners as chips, the chosen one solid like a picker button; the description area; the picker. */
/* The screener's Administration card reads across four columns, the Notes control alone in the fourth on
   an open administration, centred top to bottom against the row beside it. */
[data-meliora-screener-detail] .form-grid,
[data-meliora-group-detail] .form-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
[data-meliora-screener-detail] .screener-notes,
[data-meliora-group-detail] .record-notes { align-self: stretch; display: flex; align-items: center; }
[data-meliora-group-detail] .group-description { grid-column: 1 / -1; max-width: none; }
/* The Result card: the three facts larger than the facts around them, and the controls that follow from
   the result, Download and Notes, in the fourth column at the card's right, level with the values. */
.form-frame fieldset[data-meliora-screener-result] { background: var(--accent-tint); }
[data-meliora-screener-result] .form-grid { grid-template-columns: repeat(3, minmax(0, 1fr)) auto; align-items: end; }
[data-meliora-screener-result] .field .label { font-size: 1rem; }
[data-meliora-screener-result] .field .value { font-size: 1.3rem; font-weight: 600; }
[data-meliora-screener-result] .screener-result-controls { display: flex; gap: .6rem; align-items: center; justify-self: end; }
/* The Archive and End Group cards: the danger card with a field in it, the field above its control. */
.form-danger.screener-archive, .form-danger.group-end, .form-danger.cssrs-delete { grid-column: 1 / -1; }
.form-danger.cssrs-delete .form-delete button { white-space: nowrap; }
.form-danger.screener-archive > .field, .form-danger.group-end > .field { margin: .2rem 0 .8rem; max-width: var(--form-w); }
.form-danger.screener-archive .note { min-height: 4.5rem; }
/* The sitting's three fields on one row above the questions: the day, the role, the name. */
[data-meliora-screener-answer] [data-meliora-screener-respondent-fields] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* A fact in the answer form's Status card takes the frame's fact label, which the shell gives only a read-only form. */
[data-meliora-screener-answer] [data-meliora-form-status] .field .label { display: block; font-weight: 600; font-size: .85rem; color: var(--ink-2); margin-bottom: .3rem; }

/* The three sections of New Screener are the frame's cards; the chips and the picker sit inside them. */
.screener-chips input[type="radio"] { position: absolute; opacity: 0; width: 0; height: 0; }
.screener-chip { display: inline-block; margin: 0 .5rem .5rem 0; padding: .3rem .8rem; font-size: .85rem; font-weight: 600; border: 1px solid var(--line); border-radius: var(--radius); background: var(--ghost-fill); color: var(--ink-2); cursor: pointer; }
.screener-chip:hover { background: var(--ghost-fill-hover); color: var(--ink); }
.screener-chips input[type="radio"]:checked + .screener-chip { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.screener-chips input[type="radio"]:focus-visible + .screener-chip { outline: 2px solid var(--accent); outline-offset: 2px; }
.screener-chips.invalid > legend { color: var(--danger); }
/* The description box under the chips: the card's whole width and one fixed height, so reading the chips
   changes what is in the box and never the card. Disabled because nobody types in it. */
.screener-chips [data-meliora-screener-description-field] { max-width: none; margin: .4rem 0 0; }
.screener-chips [data-meliora-screener-description] { display: block; width: 100%; height: 6.25rem; resize: none; color: var(--ink-2); }
.student-picker.invalid > legend { color: var(--danger); }
.student-tools { display: flex; align-items: center; gap: .6rem; margin: 0 0 .6rem; }
.student-filter { display: block; margin: 0; max-width: 22rem; }
/* The row's checkbox is the form value and the keyboard's stop, drawn as nothing; the tint says chosen. */
.student-picker .row-select .row-box { position: absolute; opacity: 0; width: 0; height: 0; margin: 0; }
.student-picker .row-select tbody tr:has(.row-box:focus-visible) { outline: 2px solid var(--accent); outline-offset: -2px; }
.student-picker .row-select td, .student-picker .row-select th { padding-top: .25rem; padding-bottom: .25rem; white-space: nowrap; }
/* A checked student's row reads as chosen, on the tint the group's Students list gives the placement showing. */
.student-picker .row-select tbody tr:has(input:checked) td { background: var(--row-selected); }
.student-picker .row-select tbody tr.selectable:has(input:checked):hover td,
.student-picker .row-select tbody tr.selectable:has(input:checked):focus-within td { background: var(--row-selected-hover); }
.student-picker label { cursor: pointer; }

/* THE GROUP PAGES: the Students two-pane, the placement tabs, and the outcome bars. See docs\design-interventions.md §5 and §7. */
.two-pane { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 1.5rem; align-items: start; }
@media (max-width: 60rem) { .two-pane { grid-template-columns: minmax(0, 1fr); } }
.pane-list table { width: 100%; }
.pane-detail > h2 { margin: 0 0 .6rem; font-size: 1.1rem; }
.pane-detail > h2 .muted { font-weight: 400; font-size: .9rem; margin-left: .5rem; }
.pane-detail .lookup-picker { margin-bottom: 1rem; }
[data-meliora-placements] tbody tr[aria-current="true"] { background: var(--row-selected); }
/* A student's programs read as one run of codes; the full names are on hover. */
[data-meliora-placements] td[data-programs] { white-space: nowrap; }
[data-meliora-placements] tbody tr.selectable[aria-current="true"]:hover,
[data-meliora-placements] tbody tr.selectable[aria-current="true"]:focus-within { background: var(--row-selected-hover); }
/* The attendance column, last in the placements list: a count over a count never breaks across lines. */
[data-meliora-placements] th:last-child, [data-meliora-placements] td:last-child { white-space: nowrap; }
.flag { color: var(--danger); font-size: .8rem; font-weight: 600; }
/* The New Intervention row: the tiers, a hairline, the types; each group led by a small word. */
.chooser-row { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 0; margin: 0 0 1.1rem; padding: 0 0 .75rem; border-bottom: 1px solid var(--line); }
.chooser-row .lookup-picker { margin: 0; padding: 0; border-bottom: 0; align-items: center; }
.chooser-row .lookup-picker + .lookup-picker { border-left: 1px solid var(--line); margin-left: .8rem; padding-left: 1.3rem; }
.chooser-row-label { font-size: .7rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-2); margin-right: .3rem; }
.tier-pills a[data-tier="1"][aria-current="page"] { background: var(--tier-1-tint); color: var(--tier-1-ink); border-color: var(--tier-1-ink); }
.tier-pills a[data-tier="2"][aria-current="page"] { background: var(--tier-2-tint); color: var(--tier-2-ink); border-color: var(--tier-2-ink); }
.tier-pills a[data-tier="3"][aria-current="page"] { background: var(--tier-3-tint); color: var(--tier-3-ink); border-color: var(--tier-3-ink); }
/* The Criteria link: a small ghost button with the new-tab glyph, on the Intervention label's line of a group's card, and in the top right
   corner of New Intervention's Intervention card, clear of the card's outline. */

.btn.mini, .btn.criteria { padding: .12rem .5rem; font-size: .76rem; line-height: 1.4; margin-left: .6rem; vertical-align: middle; white-space: nowrap; font-weight: 500; }
.btn.criteria .ext { font-size: .85em; margin-left: .15rem; }
.criteria-row { display: flex; justify-content: space-between; align-items: baseline; gap: .6rem; }
.criteria-row .btn.criteria { margin-left: 0; }
.screener-chips { position: relative; }
.screener-chips > .btn.criteria { position: absolute; top: .28rem; right: .9rem; margin-left: 0; }
/* TEMPORARY: the dashboards' absence trend card is hidden for the stakeholder demo videos (Todd's word). Everything behind it stays
   built, drawn and tested; delete this one rule to show it again. */
.trend-card[data-meliora-trend-kind="absences"] { display: none; }
/* While it is hidden, the tier card keeps its own width with open space to its right (Todd's word) rather than taking the row; goes with the rule above. */
.chart-row > .trend-card[data-meliora-trend-kind="tiers"] { flex: 0 1 auto; }

/* The group page's two rollup cards on one row, together as wide as the Group card above them, stacking when the page is narrow. */
.group-outcomes { display: flex; gap: 1rem; align-items: stretch; }
.group-outcomes > fieldset[data-meliora-form-section] { flex: 1 1 0; min-width: 0; }
@media (max-width: 60rem) { .group-outcomes { flex-direction: column; } }
/* The words above the bars: the sentence, then the quieter score line. */
.outcome-narrative { margin: 0 0 .35rem; }
.outcome-scores { margin: 0 0 .9rem; color: var(--ink-2); font-size: .9rem; font-variant-numeric: tabular-nums; }
.outcome-pair { margin: 0 0 1.2rem; }
.outcome-pair h3 { margin: 0 0 .4rem; font-size: .95rem; }
.outcome-change { margin-left: .5rem; font-weight: 700; }
.outcome-change.better, .outcome-fill.post.better { color: var(--ok, #2f7d32); }
.outcome-change.worse, .outcome-fill.post.worse { color: var(--danger); }
.outcome-bars { display: grid; gap: .3rem; }
.outcome-bar { display: grid; grid-template-columns: 3rem minmax(0, 1fr) 3rem; align-items: center; gap: .5rem; }
.outcome-label { color: var(--ink-2); font-size: .85rem; }
.outcome-fill { display: block; height: .9rem; min-width: 2px; border-radius: 2px; background: currentColor; color: var(--accent); }
.outcome-fill.pre { color: var(--ink-3, var(--ink-2)); }
.outcome-fill.post.better { background: currentColor; }
.outcome-value { text-align: right; font-variant-numeric: tabular-nums; }

/* ---- The student search on the sub row: wider than a bare search box, since a name has two words. */
[data-meliora-student-search] input[type=search] { width: 17rem; }

/* ---- The student page (Todd, 2026-10-30): a header band, then cards on rows -----------------------
   The band carries the name and the facts as chips, the record controls on its right. Below it the
   cards sit on rows that wrap when the window narrows, each card as wide as its row gives it. */
.student-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-start; gap: .6rem 1.5rem; margin: 0 0 1.25rem; }
.student-head-main { flex: 1 1 28rem; min-width: 0; }
.student-head h1 { margin-bottom: .2rem; }
.student-head .muted { margin: 0; }
.student-head-actions { flex: 0 0 auto; margin: .35rem 0 0 auto; }
.student-demographics { width: max-content; max-width: 100%; margin: .25rem 0 0; }
.student-facts { list-style: none; display: flex; flex-wrap: wrap; gap: .3rem 1.4rem; margin: 0; padding: 0; color: var(--ink-2); font-size: .95rem; }
[data-meliora-tier-history] td.nowrap { white-space: nowrap; }
.student-facts .fact-label { color: var(--ink-3); font-size: .8rem; text-transform: uppercase; letter-spacing: .06em; margin-inline-end: .4rem; }
.student-facts .fact-quiet { color: var(--ink-3); }
.student-facts + .student-facts { margin-top: .4rem; }
/* The main block: the tier history on the left, a stack of casework cards on the right; one column when narrow. */
.student-main { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); column-gap: 1.5rem; align-items: start; }
.student-main > .form-frame, .student-stack > .form-frame { margin-top: 0; }
.student-stack table { width: 100%; font-size: .9rem; }
.student-stack td, .student-stack th { padding: .2rem .45rem; }
.student-compact-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .3rem; font-size: .92rem; }
@media (max-width: 64rem) { .student-main { grid-template-columns: minmax(0, 1fr); } }
/* A row of cards starts and ends at the same points whatever their number: each takes an equal share, and the cards stand the row's height. */
.student-row { display: flex; flex-wrap: wrap; align-items: stretch; gap: 0 1.5rem; }
.student-row > .form-frame { flex: 1 1 0; min-width: 14rem; display: flex; flex-direction: column; }
.student-row > .form-frame + .form-frame { margin-top: 0; }
.student-row > .form-frame > fieldset[data-meliora-form-section] { flex: 1 1 auto; }
/* The tier path: one small line above the history table, as wide as the card allows up to a reading width. */
.tier-path { margin: .4rem 0 .8rem; }
.tier-path svg.linechart { width: 100%; max-width: 30rem; }
/* The casework cards' tables and the placements list. */
.student-card-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.student-placements { list-style: none; margin: 0; padding: 0; display: grid; gap: .9rem; }
.student-placement-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .7rem; }
.student-placement-facts { display: flex; flex-wrap: wrap; gap: .2rem 1.2rem; font-size: .9rem; margin: .15rem 0 .35rem; }
.student-placements .outcome-pair { max-width: 28rem; }
/* A form folded behind its button: the summary reads as the button, the form opens in place beneath. */
.student-fold > summary { list-style: none; cursor: pointer; display: inline-block; margin-top: .9rem; }
.student-fold > summary::-webkit-details-marker { display: none; }
.student-fold[open] > summary { margin-bottom: .4rem; }

/* ---- The BTA page: the list of screens beside the screen showing ----------------------------------
   The left-hand list is the walkthrough's own device: every screen in order, the done ones ticked, the
   current one lit, Part 2 struck on the emergency path, the ones ahead dim. The progress bar above it
   is the workbook's ask. The screen itself is a form on the frame. docs\design-bta.md section 3.8. */
.bta-page { display: grid; grid-template-columns: 15rem minmax(0, 1fr); gap: 1.5rem; align-items: start; max-width: var(--form-w); }
.bta-screens { position: sticky; top: 1rem; }
.bta-screens ol { list-style: none; margin: 0; padding: 0; display: grid; gap: .15rem; }
.bta-screens .bta-part { margin-top: .6rem; font-family: var(--font-mono); font-size: var(--card-label-size); letter-spacing: .13em; text-transform: uppercase; color: var(--ink-3); }
.bta-screens li[data-screen] { padding: .3rem .6rem; border-radius: .35rem; border-left: 3px solid transparent; }
.bta-screens li[data-screen] a { color: inherit; text-decoration: none; }
.bta-screens li[data-state="done"] { color: var(--ok); }
.bta-screens li[data-state="done"]::before { content: "\2713\00a0"; }
.bta-screens li[data-state="current"] { background: var(--accent-tint); border-left-color: var(--accent); color: var(--accent-ink); font-weight: 600; }
.bta-screens li[data-state="open"] { color: var(--ink); }
.bta-screens li[data-state="ahead"] { color: var(--ink-3); }
.bta-screens li[data-state="struck"] { color: var(--ink-3); text-decoration: line-through; }
.bta-progress { display: grid; gap: .3rem; margin-bottom: .6rem; font-size: .85rem; }
.bta-progress svg { width: 100%; height: .6rem; display: block; }
.bta-group-row + .bta-group-row { margin-top: .8rem; padding-top: .8rem; border-top: 1px solid var(--line-2); }
.bta-group-heading { margin: 0 0 .4rem; font-size: .9rem; color: var(--ink-2); }
.bta-options { display: grid; gap: .3rem; }
.bta-option { display: flex; align-items: center; gap: .5rem; font-weight: 400; }
@media (max-width: 48rem) { .bta-page { grid-template-columns: minmax(0, 1fr); } .bta-screens { position: static; } }
/* The determination's meter and scored answers, and the signers' rows. */
.bta-meter { display: grid; gap: .3rem; margin: .8rem 0; max-width: 32rem; }
.bta-meter svg { width: 100%; height: .9rem; display: block; }
.bta-meter-bands { display: flex; justify-content: space-between; font-size: .8rem; color: var(--ink-3); }
.bta-scored { margin-top: .6rem; }
.bta-scored td.num { text-align: right; font-variant-numeric: tabular-nums; }
.bta-signer + .bta-signer { margin-top: .4rem; padding-top: .4rem; border-top: 1px solid var(--line-2); }
.bta-steps-missing { margin: 0 0 .4rem; padding-left: 1.2rem; color: var(--warn, var(--ink-2)); }
.bta-steps-missing li + li { margin-top: .2rem; }
