/* Guardian dashboard — the same universe, denser. Reads the design tokens
   from site.css; everything here is layout + dashboard-only components. */
/* A flex item never shrinks below min-content by default — at 320px the
   widest grid (the mastery heatmap) would push the whole page sideways.
   Let the column shrink; the heatmap then scrolls INSIDE its own box
   (overflow-x below), which is the WCAG-sanctioned shape for data grids. */
#dash-panels { min-width: 0; max-width: 100%; }

.dash-panel {
  background: var(--space-1);
  min-width: 0;
  border: 1px solid var(--ring);
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  margin: 0 0 1rem;
  max-width: 52rem;
  width: 100%;
  box-shadow: var(--shadow-card);
  /* WCAG 2.2 reflow (Stage 19): long unbreakable tokens (source URLs,
     content hashes) wrap instead of widening the page at 320px */
  overflow-wrap: anywhere;
}
.dash-panel h2 { margin-top: 0; font-size: 1.4rem; }
.dash-select {
  min-height: 48px;
  font: inherit;
  font-size: 0.95rem;
  background: var(--space-0);
  color: var(--star);
  border: 1px solid var(--silver);
  border-radius: 8px;
  padding: 0 0.5rem;
}
.dash-button {
  min-height: 48px;
  padding: 0.3rem 0.9rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--blue-up);
  background: transparent;
  color: var(--star);
  cursor: pointer;
  margin: 0.2rem 0.4rem 0.2rem 0;
  font: inherit;
  font-size: 0.95rem;
  transition: border-color 140ms ease, background 140ms ease;
}
.dash-button:hover { background: var(--blue-soft); border-color: var(--blue); }
.dash-button.danger { border-color: #b0532e; color: #e8a48c; }
.dash-button.danger:hover { background: rgba(176, 83, 46, 0.15); }
/* Inline text button that reads as a link (onboarding login/sign-up toggle). */
.link-button {
  min-height: 48px;
  padding: 0 0.15rem;
  border: 0;
  background: transparent;
  color: var(--blue-up);
  cursor: pointer;
  font: inherit;
  text-decoration: underline;
}
.link-button:hover { color: var(--blue); }
.dash-pre {
  background: var(--space-0);
  border: 1px solid var(--ring);
  border-radius: 8px;
  padding: 0.6rem;
  font-size: 0.8rem;
  overflow-x: auto;
  max-height: 18rem;
  color: var(--silver);
}
.heat-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; margin: 0.3rem 0; }
.heat-subject { min-width: 5.5rem; font-weight: 600; color: var(--silver); text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.75rem; }
.heat-cell {
  border: none;
  border-radius: 8px;
  min-height: 48px;
  display: inline-flex;
  align-items: center;
  padding: 0.35rem 0.6rem;
  background: color-mix(in srgb, var(--heat) 16%, var(--space-2));
  border-left: 5px solid var(--heat);
  color: var(--star);
  cursor: pointer;
  font-size: 0.85rem;
  font-family: var(--font-ui);
}
.heat-cell:hover { background: color-mix(in srgb, var(--heat) 28%, var(--space-2)); }
.stuck-row, .wonder-row, .consent-row, .alert-row, .decision-row, .change-row, .citation-row { border-top: 1px solid var(--ring); padding: 0.5rem 0; }
/* Stage 17: entity-field diffs in the changelog read as code */
.change-diff { font-family: ui-monospace, monospace; font-size: 0.8rem; overflow-wrap: anywhere; }
#dash-decision-detail { border-top: 2px solid var(--ring); margin-top: 0.75rem; padding-top: 0.75rem; }
.stuck-head, .wonder-q { margin: 0 0 0.2rem; font-weight: 600; color: var(--star); }
.wonder-q { font-family: var(--font-display); color: var(--champagne); }
.stuck-actions { display: flex; flex-wrap: wrap; }
.subject-toggles { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.subject-toggles .setting-row { display: inline-flex; align-items: center; gap: 0.3rem; }
.alert-row { border-left: 4px solid var(--blue); padding-left: 0.8rem; background: var(--blue-soft); border-radius: 8px; }
.dash-title { font-size: 1.35rem; margin: 0; }

/* ── Stage 20: Family & adults + Plan & billing panels ─────────────────── */
/* Reflow law: these panels must fit 320px with no horizontal scroll — the
   forms wrap and every input yields instead of forcing the page wider. */
.adult-row { border-top: 1px solid var(--ring); padding: 0.5rem 0; }
.adult-controls, .billing-controls { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.35rem; }
.invite-form { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }
.invite-form input, .invite-form select, .billing-controls select { max-width: 100%; min-width: 0; flex: 1 1 12rem; }
.invite-reveal { width: 100%; }
.invite-reveal input { width: 100%; max-width: 100%; box-sizing: border-box; font-family: var(--font-ui); font-size: 0.85rem; }
.plan-row { border-top: 1px solid var(--ring); padding: 0.5rem 0; }
.plan-row label { display: block; margin: 0.35rem 0; }

/* ── Design G1: instruments (the data is the decoration) ────────────────── */

/* mastery grid v2: the fixed legend shares the cells' exact vocabulary */
.heat-legend { display: flex; flex-wrap: wrap; gap: 0.4rem 1.1rem; margin: 0 0 0.7rem; }
.heat-legend-item { display: inline-flex; align-items: center; gap: 0.4rem; color: var(--silver); font-size: 0.85rem; }
.heat-swatch { width: 14px; height: 14px; border-radius: 4px; background: color-mix(in srgb, var(--heat) 32%, var(--space-2)); border-left: 4px solid var(--heat); }

/* evidence popover: the mastery window as filled dots with dates */
.evidence-dots { display: flex; flex-wrap: wrap; gap: 0.7rem; margin: 0.5rem 0; }
.evi-day { display: inline-flex; flex-direction: column; align-items: center; gap: 0.25rem; }
.evi-dot { width: 14px; height: 14px; border-radius: 50%; border: 1.6px solid var(--silver); }
.evi-dot.correct { background: var(--good, #6FD39B); border-color: var(--good, #6FD39B); }
.evi-dot.first-try { box-shadow: 0 0 0 3px rgba(201, 182, 138, 0.45); }
.evi-date { font-size: 0.72rem; color: var(--silver); font-family: ui-monospace, monospace; }

/* stuck feed: the attempt story as a compact timeline ending at the flag */
.stuck-timeline { display: flex; align-items: center; gap: 0.45rem; margin: 0.35rem 0 0.5rem; min-height: 20px; }
.tl-dot { width: 12px; height: 12px; border-radius: 50%; border: 1.6px solid var(--silver); flex: none; }
.tl-dot.correct { background: var(--good, #6FD39B); border-color: var(--good, #6FD39B); }
.tl-flag { display: inline-flex; align-items: flex-start; margin-left: 0.3rem; flex: none; }
.tl-flag::before { content: ""; display: block; width: 0; height: 0; border-left: 9px solid var(--champagne-deep); border-top: 5px solid transparent; border-bottom: 5px solid transparent; }
.tl-flag-post { display: block; width: 2px; height: 16px; background: var(--champagne-deep); }
.stuck-resolved { opacity: 0.75; }

/* year cockpit: a bar that only fills, and a plain subject table. No target
   line, no red, no deadline — the guardian is being informed, not scored. */
.year-summary { margin: 0.4rem 0 0.6rem; }
.year-headline { font-weight: 600; margin: 0 0 0.3rem; }
.year-bar { width: 100%; max-width: 30rem; height: 12px; border-radius: 6px; background: rgba(176, 184, 201, 0.12); overflow: hidden; margin: 0.2rem 0 0.9rem; }
.year-bar-fill { display: block; height: 100%; width: var(--fill, 0%); border-radius: 6px; background: var(--blue-up, #6FA8DC); }
.year-table { border-collapse: collapse; width: 100%; max-width: 48rem; }
.year-table th, .year-table td { text-align: left; padding: 0.28rem 0.6rem 0.28rem 0; border-bottom: 1px solid rgba(176, 184, 201, 0.16); font-weight: 400; }
.year-table th[scope="col"] { font-weight: 600; }
.year-table th[scope="row"] { text-transform: capitalize; }
.year-evidence-established { color: var(--good, #6FD39B); }
.year-evidence-covered { color: var(--blue-up, #6FA8DC); }
.year-evidence-in-progress { color: var(--silver); }
.year-evidence-not-started { color: var(--silver); opacity: 0.8; }
/* A level change the record supports. Stated as a fact with an offer, never a
   warning: no alarm colour, no exclamation, nothing that reads as a problem. */
.year-proposal { margin: 0.9rem 0 0; padding: 0.7rem 0.9rem; border: 1px solid rgba(111, 168, 220, 0.35);
  border-radius: 8px; max-width: 40rem; }
.year-proposal-head { font-weight: 600; margin: 0 0 0.3rem; text-transform: capitalize; }
.year-proposal p { margin: 0 0 0.5rem; }

/* Per-subject placement: the select is the control, and a subject running at a
   level other than the enrolled year is marked so the divergence is visible
   rather than something a guardian has to read the numbers to notice. */
.year-level-select { min-width: 9.5rem; font-size: 0.95em; }
.year-level-placed .year-level-select { border-color: var(--blue-up, #6FA8DC); }
.year-rhythm-steady { color: var(--good, #6FD39B); }
.year-rhythm-light { color: var(--silver); }
.year-rhythm-not-started { color: var(--silver); opacity: 0.8; }

/* rhythm strip: 30 calendar cells, height = blocks, slivers = subjects */
.rhythm-strip { display: flex; align-items: flex-end; gap: 3px; height: 56px; margin: 0.6rem 0; max-width: 30rem; }
.rhythm-cell { flex: 1 1 0; height: 100%; display: flex; align-items: flex-end; background: rgba(176, 184, 201, 0.07); border-radius: 3px; min-width: 4px; }
.rhythm-bar { display: flex; flex-direction: column; width: 100%; height: var(--fill, 25%); border-radius: 3px; overflow: hidden; }
.rhythm-sliver { flex: 1 1 0; background: hsl(var(--subj, 210) 42% 52%); }

/* cost sparkline: nodes per day, champagne alert rule, dotted projection */
.cost-spark { display: block; width: 100%; max-width: 26rem; height: auto; margin: 0.4rem 0; }
.cost-line { fill: none; stroke: var(--blue-up); stroke-width: 1.6; }
.cost-node { fill: var(--star); }
.cost-node:hover { fill: var(--champagne); }
.cost-threshold { stroke: var(--champagne-deep); stroke-width: 1; }
.cost-projection { stroke: var(--silver); stroke-width: 1.2; stroke-dasharray: 3 4; }

/* ── Task-oriented areas (progressive disclosure) ───────────────────────── */
.dash-tabs {
  position: sticky;
  top: 0;
  z-index: 5;
  margin: 0 0 1.25rem;
  padding: 0.5rem 0;
  background: color-mix(in srgb, var(--space-0) 88%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--ring);
}
.dash-tablist {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.dash-tab {
  appearance: none;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--silver);
  font: inherit;
  font-weight: 600;
  font-size: 0.9rem;
  padding: 0.55rem 1rem;
  min-height: 44px;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.dash-tab:hover { color: var(--star); background: var(--space-1); }
.dash-tab[aria-selected="true"] {
  color: var(--space-0);
  background: var(--champagne);
  border-color: var(--champagne-deep);
}
.dash-tab:focus-visible { outline: 2px solid var(--champagne); outline-offset: 2px; }
.dash-area:focus { outline: none; }
.dash-area[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  .dash-tab { transition: none; }
  .dash-tabs { backdrop-filter: none; }
}

/* ── Curriculum & scope view ─────────────────────────────────────────────── */
.scope-summary { color: var(--star); font-size: 1rem; line-height: 1.5; margin: 0 0 0.75rem; }
.scope-legend { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; margin: 0 0 1rem; }
.scope-chip { display: inline-flex; align-items: center; gap: 0.4rem; color: var(--silver); font-size: 0.8rem; }
.scope-dot { width: 0.85rem; height: 0.85rem; border-radius: 4px; border: 1px solid var(--ring); display: inline-block; }
.scope-complete .scope-dot { background: var(--good); }
.scope-in-progress .scope-dot { background: var(--blue); }
.scope-under-evidenced .scope-dot { background: var(--champagne-deep); }
.scope-planned .scope-dot { background: var(--space-2); }

.scope-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; border: 1px solid var(--ring); border-radius: var(--radius); }
.scope-table { border-collapse: collapse; width: 100%; min-width: 640px; font-size: 0.82rem; }
.scope-table caption { text-align: left; color: var(--silver); font-size: 0.8rem; padding: 0.6rem 0.75rem; caption-side: top; }
.scope-table th, .scope-table td { padding: 0.4rem 0.5rem; text-align: center; border-bottom: 1px solid var(--ring); }
.scope-table thead th { color: var(--silver); font-weight: 600; position: sticky; top: 0; background: var(--space-1); }
.scope-corner { text-align: left !important; }
.scope-subject { text-align: left; min-width: 9.5rem; }
.scope-subject-name { display: block; color: var(--star); font-weight: 600; }
.scope-subject-meta { display: block; color: var(--silver); font-size: 0.7rem; }
.scope-cell { color: var(--star); font-variant-numeric: tabular-nums; }
.scope-count { display: inline-block; min-width: 2.4rem; padding: 0.15rem 0.3rem; border-radius: 6px; }
.scope-cell.scope-complete .scope-count { background: color-mix(in srgb, var(--good) 26%, transparent); }
.scope-cell.scope-in-progress .scope-count { background: color-mix(in srgb, var(--blue) 26%, transparent); }
.scope-cell.scope-under-evidenced .scope-count { background: color-mix(in srgb, var(--champagne-deep) 30%, transparent); }
.scope-cell.scope-planned .scope-count { color: var(--silver); }
.scope-cell.scope-not-scoped .scope-count { background: color-mix(in srgb, var(--champagne-deep) 40%, transparent); }
.scope-empty { color: var(--space-2); }
.scope-none { color: var(--silver); opacity: 0.4; }

/* ── Operator console ────────────────────────────────────────────────────── */
.admin-stats { display: flex; flex-wrap: wrap; gap: 0.75rem; margin: 0 0 1.25rem; }
.admin-stat {
  display: flex; flex-direction: column; gap: 0.2rem; padding: 0.75rem 1rem;
  border: 1px solid var(--ring); border-radius: 12px; background: var(--space-1); min-width: 7rem;
}
.admin-stat-value { color: var(--champagne); font-weight: 700; font-size: 1.3rem; font-variant-numeric: tabular-nums; }
.admin-stat-label { color: var(--silver); font-size: 0.72rem; letter-spacing: 0.08em; text-transform: uppercase; }

/* ── Overview: "Today at a glance" decision-first card ───────────────────── */
.dash-today { background: linear-gradient(180deg, color-mix(in srgb, var(--champagne) 8%, var(--space-1)), var(--space-1)); border-color: color-mix(in srgb, var(--champagne) 30%, var(--ring)); }
.today-line { margin: 0.35rem 0; font-size: 1.05rem; color: var(--star); line-height: 1.5; }
.today-learning { font-size: 1.15rem; }
.today-needs { color: var(--silver); }
.today-needs.has-needs { color: var(--champagne); font-weight: 600; }

/* Stage 21: the consent-atomic add-learner form. */
.consent-row { display: flex; align-items: flex-start; gap: 0.5rem; max-width: 46rem; }
.consent-row input[type="checkbox"] { width: 24px; height: 24px; min-width: 24px; margin-top: 0.1rem; }
#onboard-notice { margin: 0.75rem 0 1rem; }
#onboard-notice h3 { margin: 0 0 0.4rem; }

/* §20 drill-down: closed by default — the answer to "show me", not something
   a guardian has to scroll past on every visit. */
.unit-detail { margin: 0.7rem 0 0; padding: 0.5rem 0.8rem; border: 1px solid rgba(176, 184, 201, 0.2); border-radius: 8px; max-width: 52rem; min-width: 0; }
.unit-detail > summary { cursor: pointer; text-transform: capitalize; font-weight: 600; }
/* Five columns of prose cannot fit 320px, and a page that scrolls sideways
   fails WCAG reflow — which this table did the moment it landed. The GRID
   scrolls inside its own box instead, the same shape the mastery heatmap
   uses, so the page itself never moves. */
.unit-goals-scroll, .year-table-scroll { overflow-x: auto; max-width: 100%; }
.year-table-scroll .year-table { min-width: 40rem; }
.unit-detail .unit-goals { margin-top: 0.5rem; font-size: 0.95em; min-width: 34rem; }

/* §26 portfolio: the work shelf inside a unit's drill-down, and the capture
   form under it. Every interactive target here clears 48px (the browser audit
   measures all of them), and the form's fields stay hidden until a file has
   actually been read — a Save button with nothing behind it is a control that
   lies about what it does. */
.unit-portfolio { margin-top: 0.9rem; padding-top: 0.7rem; border-top: 1px solid rgba(176, 184, 201, 0.2); }
.unit-portfolio h4 { margin: 0 0 0.4rem; font-size: 1.05rem; }
.portfolio-list { list-style: none; margin: 0 0 0.8rem; padding: 0; }
.portfolio-item { padding: 0.5rem 0; border-bottom: 1px solid rgba(176, 184, 201, 0.12); }
.portfolio-item:last-child { border-bottom: 0; }
.portfolio-title { margin: 0 0 0.2rem; font-weight: 600; }
.portfolio-transcript { margin: 0.3rem 0; }
.portfolio-transcript > summary { cursor: pointer; min-height: 48px; display: flex; align-items: center; }
.portfolio-transcript pre {
  margin: 0.3rem 0 0;
  padding: 0.5rem;
  background: var(--space-0);
  border: 1px solid rgba(176, 184, 201, 0.2);
  border-radius: 8px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-size: 0.92rem;
}
.portfolio-capture { margin-top: 0.6rem; display: flex; flex-direction: column; gap: 0.35rem; max-width: 40rem; }
.portfolio-capture label { font-size: 0.95rem; }
.portfolio-file { min-height: 48px; font: inherit; font-size: 0.95rem; color: var(--star); }
.portfolio-fields { display: flex; flex-direction: column; gap: 0.35rem; }
.portfolio-fields[hidden] { display: none; }
.portfolio-fields input[type="text"],
.portfolio-fields input[type="date"],
.portfolio-fields select,
.portfolio-fields textarea {
  min-height: 48px;
  font: inherit;
  font-size: 0.95rem;
  background: var(--space-0);
  color: var(--star);
  border: 1px solid var(--silver);
  border-radius: 8px;
  padding: 0.4rem 0.5rem;
  max-width: 100%;
}
.portfolio-goals-head { margin: 0.4rem 0 0.1rem; font-weight: 600; }
.portfolio-goals { display: flex; flex-direction: column; gap: 0.2rem; }
.portfolio-goal { display: flex; align-items: center; gap: 0.5rem; min-height: 48px; }
.portfolio-goal input[type="checkbox"] { width: 24px; height: 24px; min-width: 24px; }
.portfolio-goal label { cursor: pointer; }

/* §26 end-of-year demonstration: the summary a family hands to a reviewer.
   Facts on the left, what is still open below them — the open list is not
   styled as a warning, because an unfinished unit in March is the normal
   shape of a year in progress, not a problem. */
.year-demonstration { margin: 0.6rem 0 0; padding: 0.6rem 0.8rem; border: 1px solid rgba(176, 184, 201, 0.2); border-radius: 8px; max-width: 52rem; }
.demo-facts, .demo-open { margin: 0.3rem 0 0.5rem; padding-left: 1.2rem; }
.demo-facts li, .demo-open li { margin: 0.15rem 0; }
.demo-open-head { margin: 0.5rem 0 0.1rem; font-weight: 600; }
