/* ============================================================================
   components.css — the reusable pieces every section is assembled from.

   OWNERSHIP: Agent A owns the look. The INVENTORY below is the contract with
   Agent B and may only grow, never silently change meaning.
   ============================================================================

   ###########################################################################
   #                          CLASS INVENTORY                                #
   #                                                                         #
   #  THIS IS THE ONLY VOCABULARY A VIEW MAY USE.                            #
   #                                                                         #
   #  Agent B: if you need a class that is not listed here, do not invent it  #
   #  in a view file. Ask A to add it here first, in the same commit.         #
   #                                                                         #
   #  Agent A: if you write a selector, it belongs in this list. A selector   #
   #  that is not listed is dead code.                                       #
   #                                                                         #
   #  Both directions are asserted by pw-audit/tb-static.js: every class used #
   #  in JS or HTML must be defined in some stylesheet, and every class       #
   #  defined in a stylesheet must be used. That pair of checks is what stops #
   #  this build repeating the last one, which shipped 871 lines of CSS that  #
   #  nothing consumed alongside 9 class names that no stylesheet defined.    #
   ###########################################################################

   SHELL (base.css)
     .binder .binder-rings .binder-ring .binder-foot
     .topbar .topbar-inner .topbar-search .topbar-actions
     .brand .brand-mark .brand-text .btn-icon .btn-icon-text
     .tabs .tabs-scroll .tab .tab-emoji .tab-label
     .tabs-nav .tabs-nav--prev .tabs-nav--next   scroll affordance for a mouse
     .topbar-extra                               hidden below 640px; the button
                                                  stays reachable from Settings
     .subtabs .subtab
     .view .splash .splash-mark .splash-word .noscript-card .skip-link .sr-only

   FORMS (base.css)
     .field .field-label .field-hint
     .input .input--area .input--select .input--search
     .input--color    a swatch-shaped <input type="color"> (theme studio)
     .input--mono     tabular/monospace value — password log, scores

   BUTTONS (base.css)
     .btn .btn--brand .btn--sec .btn--danger .btn--ghost .btn--sm .btn--icon
     .btn--block      full width; use inside a modal action stack

   TABLES (base.css)
     .table-wrap .table-wrap--wide .table .table-empty .row-blank .cell-blank
     .table--compact  denser padding for a wide matrix
     .cell-num        right-aligned, tabular figures — scores, money, counts

   SURFACES (this file)
     .card .card--stub .card--flush .card-head .card-title .card-emoji
     .t-strong .t-script                      the two-voice heading (UI.title)
     .card-tools .card-body
     .card-foot       a quiet strip under .card-body (totals, "12 of 24 done")
     .grid .grid--2 .grid--3 .grid--4        responsive auto-fit grids
     .toolbar-spacer                          pushes trailing toolbar actions right
     .stack .stack--tight                     vertical rhythm containers
     .split .split-main .split-rail           content + a narrow side rail
                                              (calendar "upcoming", dashboard)
     .toolbar                                 a row of controls above content

   INDICATORS (this file)
     .pill .pill--brand .pill--mint .pill--amber .pill--danger .pill--info
     .pill--accent .pill--sec .pill--muted
     .level .level--e .level--d .level--p .level--a      rubric badges
     .legend .legend-item                     the key that explains them
     .att .att--p .att--a .att--t .att--e .att--h .att--unmarked
     .stat .stat-label .stat-value .stat-note
     .avatar .avatar-initials
     .bar .bar-fill                           single-value progress meter
     .meter .meter-seg                        stacked distribution bar; put the
                                              share on each segment's own style
                                              attribute via width, and its colour
                                              via a .pill--* style class name
     .note .note--info .note--warn .note--danger
                                              inline callout: "this never leaves
                                              your device", overdue, password
                                              warning. Not a toast.

   CONTROLS (this file)
     .chips .chip .chip.is-on
     .seg .seg-btn .seg-btn.is-on             mutually exclusive segmented control
     .check .check-box .check-label            styled checkbox row
     .switch .switch-input .switch-track .switch-knob .switch-label
                                              on/off preference (Settings)
     .swatches .swatch .swatch.is-on .swatch-name
                                              theme preset picker; the view sets
                                              each button's colour inline as --sw
     .rowbtns                                  right-aligned row action cluster

   FEEDBACK (this file)
     .empty .empty-art .empty-text
     .modal-root .modal-scrim .modal-panel .modal-head .modal-x .modal-body
     .modal-actions .modal-actions--stack .confirm-q
     .toast-root .toast .toast--danger .toast--mint .toast.is-out
     .import-list .stub-note
     .print-preview                            the built print document, shown
                                               scaled down inside a modal

   SET FROM SCRIPT, not by a view (base.css / this file)
     .booting     on <html> until app.js has rendered the first view
     .has-modal   on <html> while a modal is open, to stop the page scrolling

   DECOR (decor.css)            SECTION LAYOUTS (sections.css)
   PRINT (print.css)            — each keeps its own inventory block.

   ---------------------------------------------------------------------------
   NOTES FOR AGENT B

   1. A section colours itself through --sec, which app.js sets from the
      section's hue slot. Nothing above needs a per-section variant: .pill--sec,
      .btn--sec, .chip.is-on, .stat and .card-head already follow it.
   2. .meter is the one place a view sets an inline style, and only ever a
      width percentage. Colour still comes from a class. (Rule 4 holds.)
   3. Anything that belongs to exactly one section is sections.css, not here —
      ask before inventing it in a view file.

   4. REMOVED, deliberately: .card--tape, .paper, .tier/.tier--1..3 and
      .stars/.star/.star--off were all listed above at one point with no
      stylesheet rule behind them. Both view agents reached for them, found
      nothing, and worked around with .pill--* and .bar.

      An inventory entry with no rule behind it is worse than no entry: it
      invites a view to use a class that renders as nothing, which is the exact
      failure this whole file exists to prevent. List them again in the same
      commit a rule appears, not before.
   ========================================================================== */

/* ---------------------------------------------------------------------------
   Surfaces
   --------------------------------------------------------------------------- */

.card {
  background: var(--surface);
  border: 1.5px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

/* White, not a coloured band.

   The printable this competes with puts its pages on white and lets the colour
   live in the heading and the table header row — which is what makes a page of
   it read as a document rather than as an app screen. A tinted band behind the
   title fights the two-voice heading instead of framing it. */
.card-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); flex-wrap: wrap;
  padding: var(--sp-4) var(--sp-4) var(--sp-3);
  background: var(--surface);
  border-bottom: 2.5px solid var(--sec-soft, var(--line));
}

.card-title {
  display: flex; align-items: baseline; gap: var(--sp-2);
  margin: 0; font-size: var(--step-1);
  color: var(--sec-strong, var(--brand-strong));
  flex-wrap: wrap;
}

/* The two-voice heading. UI.title() splits a label into a bold rounded first
   word and a script remainder — CLASS Roster, STUDENT Birthdays — which is the
   signature of the printable this competes with. */
.t-strong {
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
}

.t-script {
  font-family: var(--font-script);
  font-weight: 700;
  /* Caveat sits small on the line and has a lot of ascender, so it needs to be
     stepped up and nudged down to sit level with the cap-height word. */
  font-size: 1.42em;
  line-height: .9;
  position: relative;
  top: .06em;
  color: var(--sec, var(--brand));
}
.card-emoji { font-size: 1.15em; }
.card-tools { display: flex; gap: var(--sp-2); flex-wrap: wrap; }

.card-body { padding: var(--sp-4); }
.card--flush .card-body { padding: 0; }

.card--stub .card-body { color: var(--ink-faint); }
.stub-note { margin: 0; font-style: italic; }

.stack { display: flex; flex-direction: column; gap: var(--sp-4); }

.grid { display: grid; gap: var(--sp-3); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr)); }

.toolbar {
  display: flex; align-items: center; gap: var(--sp-2);
  flex-wrap: wrap;
  margin-bottom: var(--sp-4);
}

/* A control inside a toolbar sizes to its content.
   Without this, `.input { width: 100% }` makes a bare <select> claim the whole
   row, so a date stepper renders as four stacked full-width blocks instead of
   "◀ [date] ▶ Today" — which is what the attendance picker was doing. */
.toolbar .input {
  width: auto;
  min-width: 9rem;
  max-width: 100%;
}
.toolbar .field { flex: 0 1 auto; }

/* A toolbar that ends in actions pushes them to the right on a wide screen and
   lets them fall in line on a narrow one. */
.toolbar-spacer { flex: 1 1 var(--sp-4); }

/* ---------------------------------------------------------------------------
   Indicators
   --------------------------------------------------------------------------- */

.pill {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  padding: .18em .7em;
  background: var(--surface-3); color: var(--ink-soft);
  border-radius: var(--r-pill);
  font-size: var(--step--1); font-weight: 700; white-space: nowrap;
}
.pill--mint   { background: var(--mint-soft);   color: var(--mint); }
.pill--amber  { background: var(--amber-soft);  color: var(--amber); }
.pill--danger { background: var(--danger-soft); color: var(--danger); }
.pill--info   { background: var(--info-soft);   color: var(--info); }
.pill--accent { background: var(--accent-soft); color: var(--accent); }
.pill--sec    { background: var(--sec-soft);    color: var(--sec-strong); }
.pill--muted  { background: var(--surface-3);   color: var(--ink-faint); }

/* Rubric badges. These were referenced as .badge-level-E/D/P/A by the previous
   build and defined nowhere, so every mastery badge and the whole legend
   rendered as unstyled plain text. */
.level {
  display: inline-grid; place-items: center;
  min-width: 2.1rem; min-height: 2.1rem; padding: 0 .4em;
  border-radius: var(--r-sm);
  font-weight: 800; font-size: var(--step--1);
  border: 1.5px solid currentColor;
}
.level--e { background: var(--level-e-soft); color: var(--level-e); }
.level--d { background: var(--level-d-soft); color: var(--level-d); }
.level--p { background: var(--level-p-soft); color: var(--level-p); }
.level--a { background: var(--level-a-soft); color: var(--level-a); }

/* Attendance cells. Unmarked is visibly empty, never green — the previous
   build defaulted a missing record to Present and reported 100% attendance
   for days nobody had touched. */
.att {
  display: inline-grid; place-items: center;
  min-width: 2rem; min-height: 2rem;
  border-radius: var(--r-sm);
  font-weight: 800; font-size: var(--step--1);
  border: 1.5px solid var(--line);
  background: var(--surface);
  color: var(--ink-faint);
}
.att--p { background: var(--mint-soft);   color: var(--att-p); border-color: currentColor; }
.att--a { background: var(--danger-soft); color: var(--att-a); border-color: currentColor; }
.att--t { background: var(--amber-soft);  color: var(--att-t); border-color: currentColor; }
.att--e { background: var(--info-soft);   color: var(--att-e); border-color: currentColor; }
.att--h { background: var(--accent-soft); color: var(--att-h); border-color: currentColor; }
.att--unmarked { background: var(--surface); color: var(--ink-faint); border-style: dashed; }

/* A pastel fill, not just a coloured edge.

   The brightness of the printable this competes with comes from big soft
   colour FILLS — a pastel header strip on each month block, a pastel cell per
   table column. Ours came only from coloured text, which reads far quieter.
   --sec-soft sits at L 0.93 and --sec-strong at 0.44, so the fill is candy and
   the number on it still clears AA comfortably. */
.stat {
  padding: var(--sp-3);
  background: var(--sec-soft, var(--surface-2));
  border: 1.5px solid transparent;
  border-left: 5px solid var(--sec, var(--brand));
  border-radius: var(--r-md);
  text-align: center;
}
.stat .stat-label { color: var(--sec-strong, var(--ink-soft)); }
.stat .stat-note  { color: var(--ink-soft); }

/* Every tile in a row takes its own hue, and so does every card in a grid.

   This is the thing that makes the printable this competes with look like a
   classroom instead of a report: on its birthdays page each month block has a
   different pastel header, and on every page the stat blocks alternate. One
   accent colour for a whole screen is correct for a business dashboard and
   wrong for this shelf.

   Six hues, cycling, driven entirely by the token ladder — so this still
   rotates with whatever brand colour the teacher picks in the theme studio. */
.grid > .stat:nth-child(6n+1), .grid > .card:nth-child(6n+1) { --sec-h: var(--h0);  }
.grid > .stat:nth-child(6n+2), .grid > .card:nth-child(6n+2) { --sec-h: var(--h2);  }
.grid > .stat:nth-child(6n+3), .grid > .card:nth-child(6n+3) { --sec-h: var(--h4);  }
.grid > .stat:nth-child(6n+4), .grid > .card:nth-child(6n+4) { --sec-h: var(--h6);  }
.grid > .stat:nth-child(6n+5), .grid > .card:nth-child(6n+5) { --sec-h: var(--h8);  }
.grid > .stat:nth-child(6n+6), .grid > .card:nth-child(6n+6) { --sec-h: var(--h10); }

/* The ladder recomputes --sec from --sec-h, but only on an element carrying
   [data-sec]. Tiles and cards do not, so they get the same three declarations
   scoped to themselves. Kept next to the cycle above so the two never drift. */
.grid > .stat, .grid > .card {
  --sec:        oklch(var(--sec-l)        var(--sec-c)      var(--sec-h));
  --sec-strong: oklch(var(--sec-strong-l) var(--sec-c)      var(--sec-h));
  --sec-soft:   oklch(var(--sec-soft-l)   var(--sec-soft-c) var(--sec-h));
}
.stat-label { font-size: var(--step--1); font-weight: 700; color: var(--ink-soft); }
.stat-value { font-family: var(--font-display); font-size: var(--step-3); color: var(--sec-strong, var(--brand-strong)); line-height: 1.1; }
.stat-note  { font-size: var(--step--1); color: var(--ink-faint); }

.avatar {
  display: inline-grid; place-items: center;
  width: 2.2rem; height: 2.2rem; flex: none;
  background: var(--sec-soft, var(--brand-soft));
  color: var(--sec-strong, var(--brand-strong));
  border-radius: var(--r-pill);
  font-weight: 800; font-size: var(--step--1);
}
.avatar-initials { line-height: 1; }

.bar {
  height: .55rem; background: var(--surface-3);
  border-radius: var(--r-pill); overflow: hidden;
}
.bar-fill {
  display: block; height: 100%;
  background: var(--sec, var(--brand));
  border-radius: inherit;
  transition: width var(--dur-3) var(--ease);
}

/* ---------------------------------------------------------------------------
   Controls
   --------------------------------------------------------------------------- */

.chips { display: flex; gap: var(--sp-2); flex-wrap: wrap; }

.chip {
  min-height: var(--tap); padding: 0 var(--sp-3);
  background: var(--surface-2); color: var(--ink-soft);
  border: 1.5px solid var(--line); border-radius: var(--r-pill);
  font: inherit; font-weight: 700; font-size: var(--step--1); cursor: pointer;
}
.chip.is-on { background: var(--sec-soft); color: var(--sec-strong); border-color: var(--sec); }

.seg {
  display: inline-flex; padding: 3px; gap: 2px;
  background: var(--surface-2); border: 1.5px solid var(--line);
  border-radius: var(--r-pill);
}
/* var(--tap), not 34px. These are the attendance marking buttons: the one
   control a teacher uses one-handed at 8:05am while holding a clipboard, and
   the one place in the binder where a mis-tap writes wrong data about a child.
   Five of them sit side by side, so they also need a real minimum WIDTH — at
   390px they were rendering 31px wide. */
.seg-btn {
  min-height: var(--tap); min-width: 2.75rem; padding: 0 var(--sp-3);
  background: transparent; color: var(--ink-soft); border: 0;
  border-radius: var(--r-pill);
  font: inherit; font-weight: 700; font-size: var(--step--1); cursor: pointer;
}
.seg-btn.is-on { background: var(--sec, var(--brand)); color: var(--sec-on, var(--on-brand)); }

.check {
  display: flex; align-items: center; gap: var(--sp-2);
  min-height: var(--tap); cursor: pointer;
}
.check-box { width: 1.25rem; height: 1.25rem; accent-color: var(--brand); flex: none; }
.check-label { font-weight: 600; font-size: var(--step--1); }

.rowbtns { display: flex; gap: var(--sp-2); justify-content: flex-end; }

/* ---------------------------------------------------------------------------
   Switch — an on/off preference

   Built on a real <input type="checkbox"> rather than a styled button, so it
   is keyboard-operable and announced correctly with no ARIA of our own. The
   input is visually hidden but still focusable; the ring is drawn on the track.
   --------------------------------------------------------------------------- */

.switch {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  min-height: var(--tap);
  padding: var(--sp-2) 0;
  cursor: pointer;
}

.switch-input {
  position: absolute; width: 1px; height: 1px;
  opacity: 0; margin: 0;
}

.switch-track {
  position: relative; flex: none;
  width: 3.1rem; height: 1.75rem; margin-top: .1rem;
  background: var(--surface-3);
  border: 1.5px solid var(--line-strong);
  border-radius: var(--r-pill);
  transition: background var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease);
}

.switch-knob {
  position: absolute; top: 2px; left: 2px;
  width: 1.35rem; height: 1.35rem;
  background: var(--surface);
  border-radius: 50%;
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-2) var(--ease);
}

.switch-input:checked + .switch-track { background: var(--brand); border-color: var(--brand); }
.switch-input:checked + .switch-track .switch-knob { transform: translateX(1.32rem); }
.switch-input:focus-visible + .switch-track { box-shadow: var(--ring); }

.switch-label {
  font-weight: 700; font-size: var(--step--1);
  line-height: 1.35;
}
.switch-label .field-hint { display: block; font-weight: 500; margin-top: 2px; }

/* ---------------------------------------------------------------------------
   Swatches — the theme preset picker

   Each button carries its own colour as --sw, set inline by the view. That is
   the one place a colour reaches the markup, and it is a computed value from
   Theme.PRESETS rather than a literal, so rule 4 still holds.
   --------------------------------------------------------------------------- */

.swatches {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
  gap: var(--sp-2);
  margin: var(--sp-3) 0;
}

.swatch {
  display: flex; align-items: center; gap: var(--sp-2);
  min-height: var(--tap); padding: var(--sp-2) var(--sp-3);
  background: var(--surface);
  border: 2px solid var(--line);
  border-left: 10px solid var(--sw, var(--brand));
  border-radius: var(--r-md);
  font: inherit; font-weight: 700; font-size: var(--step--1);
  color: var(--ink);
  cursor: pointer; text-align: left;
  transition: transform var(--dur-1) var(--ease), border-color var(--dur-1) var(--ease);
}
.swatch:hover { transform: translateY(-2px); }
.swatch.is-on { border-color: var(--sw, var(--brand)); box-shadow: var(--shadow-sm); }

.swatch-name { min-width: 0; overflow-wrap: anywhere; }

/* ---------------------------------------------------------------------------
   Specialised inputs
   --------------------------------------------------------------------------- */

/* A colour picker shaped like a swatch rather than an OS control. */
.input--color {
  width: 100%; min-width: 5rem; max-width: 9rem;
  height: var(--tap);
  padding: 4px;
  cursor: pointer;
}
.input--color::-webkit-color-swatch-wrapper { padding: 0; }
.input--color::-webkit-color-swatch { border: 0; border-radius: var(--r-sm); }
.input--color::-moz-color-swatch { border: 0; border-radius: var(--r-sm); }

/* Tabular figures for anything read as a column and compared — scores, money,
   and the password log, where a lowercase l and a 1 must not look alike. */
.input--mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: .02em;
}

/* ---------------------------------------------------------------------------
   Feedback
   --------------------------------------------------------------------------- */

.empty {
  display: flex; flex-direction: column; align-items: center;
  gap: var(--sp-3); padding: var(--sp-6) var(--sp-4);
  text-align: center; color: var(--ink-soft);
}
.empty-art { font-size: 2.8rem; }
.empty-text { margin: 0; max-width: 26rem; }

.modal-root { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; padding: var(--sp-4); }
.modal-root[hidden] { display: none; }
.modal-scrim { position: absolute; inset: 0; background: var(--wash); backdrop-filter: blur(3px); }

.modal-panel {
  position: relative;
  width: min(38rem, 100%);
  max-height: min(86dvh, 46rem);
  display: flex; flex-direction: column;
  background: var(--surface);
  border: 2px solid var(--line-strong);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.modal-root[data-size="sm"] .modal-panel { width: min(26rem, 100%); }
.modal-root[data-size="lg"] .modal-panel { width: min(52rem, 100%); }

.modal-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
  padding: var(--sp-4);
  background: var(--brand-soft);
  border-bottom: 1.5px solid var(--line);
}
.modal-head h2 { margin: 0; font-size: var(--step-2); color: var(--brand-strong); }

.modal-x {
  width: var(--tap); height: var(--tap); flex: none;
  background: transparent; border: 0; border-radius: var(--r-pill);
  font-size: var(--step-1); color: var(--ink-soft); cursor: pointer;
}
.modal-x:hover { background: var(--surface-3); }

.modal-body { padding: var(--sp-4); overflow-y: auto; }

.modal-actions { display: flex; gap: var(--sp-2); justify-content: flex-end; flex-wrap: wrap; margin-top: var(--sp-4); }
.modal-actions--stack { flex-direction: column; align-items: stretch; }

.confirm-q { margin: 0; }

/* The print preview. The printable document is real DOM, so showing it costs
   almost nothing — and it is what makes a buyer trust the print button instead
   of burning ten sheets to find out what it does. Scaled down so a Letter page
   fits the modal, and scrollable because a whole binder is 31 sheets. */
.print-preview {
  max-height: 60vh;
  overflow: auto;
  padding: var(--sp-3);
  background: var(--surface-3);
  border: 1.5px solid var(--line);
  border-radius: var(--r-md);
}
.print-preview .print-cover,
.print-preview .print-divider,
.print-preview .print-section {
  background: var(--print-surface);
  color: var(--print-preview-ink);
  margin: 0 auto var(--sp-3);
  padding: var(--sp-4);
  max-width: 42rem;
  border-radius: var(--r-sm);
  box-shadow: var(--shadow-sm);
  min-height: 0;   /* the 9.6in page height is for paper, not for a modal */
}
.import-list { margin: 0 0 var(--sp-3); padding-left: 1.2em; }

.toast-root {
  position: fixed; left: 50%; bottom: var(--sp-5); z-index: 70;
  transform: translateX(-50%);
  display: flex; flex-direction: column; gap: var(--sp-2);
  width: min(24rem, calc(100vw - 2rem));
  pointer-events: none;
}

.toast {
  padding: var(--sp-3) var(--sp-4);
  background: var(--ink); color: var(--surface);
  border-radius: var(--r-md); box-shadow: var(--shadow-lg);
  font-weight: 700; font-size: var(--step--1); text-align: center;
  animation: toast-in var(--dur-2) var(--ease);
}
.toast--danger { background: var(--danger); color: var(--surface); }
.toast--mint   { background: var(--mint);   color: var(--surface); }
.toast.is-out  { opacity: 0; transform: translateY(6px); transition: all var(--dur-3) var(--ease); }

@keyframes toast-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* Nothing behind an open modal should scroll. */
.has-modal body { overflow: hidden; }

/* ---------------------------------------------------------------------------
   Layout: content plus a narrow rail

   The calendar's "coming up" list and the cover's "needs you this week" both
   want to sit beside the main content on a desktop and fall underneath it on a
   phone. One grid, one breakpoint, no per-section CSS.
   --------------------------------------------------------------------------- */

.split { display: grid; gap: var(--sp-4); align-items: start; }
.split-main { min-width: 0; }   /* lets a wide table scroll instead of stretching the grid */
.split-rail { min-width: 0; }

@media (min-width: 950px) {
  .split { grid-template-columns: minmax(0, 1fr) 20rem; }
}

/* ---------------------------------------------------------------------------
   Inline callouts

   A .note is a persistent statement attached to the content — "this never
   leaves your device", "3 follow-ups outstanding", "printing this sheet puts
   your passwords on paper". A toast is transient and is dismissed by time; a
   note stays until the situation it describes changes. They are not
   interchangeable, and using a toast where a note belongs is how a warning
   gets missed.
   --------------------------------------------------------------------------- */

.note {
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  border-left: 5px solid var(--line-strong);
  background: var(--surface-2);
  color: var(--ink);
  font-size: var(--step--1);
}
.note + .note { margin-top: var(--sp-2); }
.note p:last-child { margin-bottom: 0; }

.note--info   { background: var(--info-soft);   border-left-color: var(--info); }
.note--warn   { background: var(--amber-soft);  border-left-color: var(--amber); }
.note--danger { background: var(--danger-soft); border-left-color: var(--danger); }

/* ---------------------------------------------------------------------------
   Legend — the key that explains a set of badges
   --------------------------------------------------------------------------- */

.legend {
  display: flex; flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
  align-items: center;
  margin-top: var(--sp-3);
  font-size: var(--step--1);
  color: var(--ink-soft);
}
.legend-item { display: inline-flex; align-items: center; gap: var(--sp-2); }

/* ---------------------------------------------------------------------------
   Meter — a stacked distribution bar

   Used for "how many of the class are at each rubric level" and "NI / IP / M"
   on a standard. Each segment carries its share as an inline width and its
   colour as a .pill--* class, so a view never names a colour. (Rule 4.)
   --------------------------------------------------------------------------- */

.meter {
  display: flex;
  height: .7rem;
  border-radius: var(--r-pill);
  overflow: hidden;
  background: var(--surface-3);
}
.meter-seg { height: 100%; min-width: 0; transition: width var(--dur-3) var(--ease); }

/* The pill palette doubles as the meter palette, so a segment tinted
   .pill--mint matches the mint badge it is counting. */
.meter-seg.pill--mint   { background: var(--mint); }
.meter-seg.pill--amber  { background: var(--amber); }
.meter-seg.pill--danger { background: var(--danger); }
.meter-seg.pill--info   { background: var(--info); }
.meter-seg.pill--accent { background: var(--accent); }
.meter-seg.pill--sec    { background: var(--sec, var(--brand)); }
.meter-seg.pill--brand  { background: var(--brand); }
.meter-seg.pill--muted  { background: var(--line-strong); }

.pill--brand { background: var(--brand-soft); color: var(--brand-strong); }

/* ---------------------------------------------------------------------------
   Card footer — a quiet strip under the body for totals and a primary action
   --------------------------------------------------------------------------- */

.card-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-4);
  border-top: 1.5px solid var(--line);
  background: var(--surface-2);
  font-size: var(--step--1);
}
