.report-container {
  max-width: min(94vw, 1040px);
  padding-top: 40px;
  padding-bottom: 80px;
}

/* The base .section-sub (css/style.css) is built for centered landing-page
   copy — max-width: 56ch + margin: 0 auto, which visibly offsets every
   report paragraph ~180px right of its own heading, since the report's
   sections are left-aligned, not centered. Every report page (Cognitive,
   Spelling, Maths, the sample report) reuses .section-sub, so this
   override belongs here rather than in each JS file's inline styles. */
.report-container .section-sub {
  max-width: none;
  margin: 0 0 12px;
  text-align: left;
}

.report-brand-footer {
  text-align: center;
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-weight: 700;
  font-size: 14px;
  color: var(--navy-dark);
  margin: 32px 0 0;
}
.report-brand-footer span { color: var(--teal); }

.report-header-actions {
  display: flex;
  align-items: center;
  gap: 20px;
}
#report-download-btn {
  padding: 8px 16px;
  font-size: 14px;
}

.report-header {
  text-align: center;
  margin-bottom: 32px;
}
.report-header h1 {
  font-size: 30px;
  color: var(--navy-dark);
  margin-bottom: 6px;
}
.report-intro-line {
  font-size: 14px;
  color: var(--text-dark);
  font-style: italic;
  margin-top: -12px;
}

.report-credibility-badge {
  text-align: center;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--teal);
  margin: -8px 0 20px;
}

.domain-icon {
  width: 16px;
  height: 16px;
  vertical-align: -3px;
  margin-right: 6px;
  flex-shrink: 0;
  color: var(--navy-dark);
}

/* At a glance (2026-08-13) — the report's centrepiece. A matched pair of
   headline cards (strength / growth), then all six areas ranked, then a
   legend that finally names the average marker and the three colours. */
.glance-cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px;
  margin-bottom: 24px;
}
.glance-card {
  background: #fff;
  border: 1px solid var(--border);
  border-top: 3px solid var(--border);
  border-radius: 12px;
  padding: 16px 18px;
}
.glance-strength { border-top-color: var(--teal); }
.glance-growth { border-top-color: var(--amber); }
.glance-card-label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-muted);
  margin: 0 0 6px;
}
.glance-card-label .domain-icon { width: 16px; height: 16px; margin: 0; }
.glance-strength .domain-icon { color: var(--teal); }
.glance-growth .domain-icon { color: var(--amber-dark); }
.glance-card-name {
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-size: 18px;
  font-weight: 700;
  color: var(--navy-dark);
  margin: 0 0 8px;
  line-height: 1.2;
}
.glance-card-meta { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; margin: 0; }
.glance-card-score {
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-size: 22px;
  font-weight: 700;
  color: var(--navy-dark);
  font-variant-numeric: tabular-nums;
}
.glance-card-of { font-size: 12px; color: var(--text-muted); }
.glance-card-delta {
  margin-left: auto;
  font-size: 11.5px;
  font-weight: 700;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.glance-strength .glance-card-delta { color: var(--teal); }
.glance-growth .glance-card-delta { color: var(--amber-dark); }

.glance-bars-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-muted);
  margin: 0 0 12px;
}
.score-bar-value {
  flex: 0 0 34px;
  text-align: right;
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-size: 14px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--navy-dark);
}
.score-value-strength { color: var(--teal); }
.score-value-growth { color: var(--amber-dark); }

.glance-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.glance-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 11.5px;
  color: var(--text-muted);
}
.glance-swatch { width: 12px; height: 8px; border-radius: 999px; flex-shrink: 0; }
.sw-strength { background: var(--teal); }
.sw-typical { background: var(--navy); }
.sw-growth { background: var(--amber); }
/* Hero card inside At a glance — the working-memory digit span, the one
   figure in the report tied to a single repeatable task. */
.glance-hero {
  margin-top: 18px;
  background: #fff;
  border: 1px solid var(--border);
  border-left: 3px solid var(--teal);
  border-radius: 10px;
  padding: 14px 16px;
}
.glance-hero-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--teal);
  margin: 0 0 8px;
}
.glance-hero-body p { margin: 0; font-size: 13.5px; line-height: 1.6; color: var(--text-muted); }
.glance-hero-body p strong { color: var(--navy-dark); }
.glance-hero-body > div,
.glance-hero-body > .report-stream-note { background: none; padding: 0; margin: 0; }
.glance-marker-key {
  width: 2px;
  height: 13px;
  background: var(--text-dark);
  opacity: 0.45;
  flex-shrink: 0;
}
@media (max-width: 560px) {
  .glance-cards { grid-template-columns: 1fr; }
  .glance-card-delta { margin-left: 0; }
}

.report-disclaimer {
  background: #fff;
  border: 1px solid var(--border);
  border-left: 4px solid var(--navy);
  border-radius: 10px;
  padding: 16px 20px;
  margin-bottom: 24px;
  font-size: 13.5px;
  color: var(--text-muted);
}

.exam-early-banner {
  background: rgba(243, 113, 48, 0.12);
  border: 1px solid rgba(243, 113, 48, 0.35);
  color: var(--amber-dark);
  border-radius: 10px;
  padding: 12px 16px;
  font-size: 13.5px;
  margin-bottom: 20px;
  text-align: left;
}

.report-section {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 32px;
  margin-bottom: 24px;
}
.report-section h2 {
  font-size: 20px;
  color: var(--navy-dark);
  margin-bottom: 16px;
}
.report-subhead {
  font-size: 15px;
  color: var(--teal);
  margin: 20px 0 10px;
}

.report-key-takeaway {
  background: var(--bg-light);
  border-radius: 12px;
  padding: 14px 18px;
  margin-bottom: 20px;
  font-size: 15px;
}

.report-at-a-glance {
  background: linear-gradient(120deg, rgba(15, 123, 138, 0.07), rgba(243, 113, 48, 0.08));
}
.report-glance-note {
  font-size: 12px;
  color: var(--text-muted);
  text-align: center;
  margin: 16px 0 0;
}

.score-bars {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.score-bar-row {
  display: flex;
  align-items: center;
  gap: 14px;
}
.score-bar-label {
  flex: 0 0 150px;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--navy-dark);
}
.score-bar-label .domain-icon { margin-right: 0; }
.score-bar-track {
  position: relative;
  flex: 1;
  height: 14px;
  background: rgba(40, 41, 114, 0.08);
  border-radius: 999px;
  overflow: visible;
}
.score-bar-fill {
  height: 100%;
  border-radius: 999px;
}
.score-bar-strength { background: var(--teal); }
.score-bar-typical { background: var(--navy); }
.score-bar-growth { background: var(--amber); }
.score-bar-avg-marker {
  position: absolute;
  top: -3px;
  bottom: -3px;
  width: 2px;
  background: var(--text-dark);
  opacity: 0.4;
}

.report-activity-list {
  list-style: none;
  margin: 0 0 8px;
  padding-left: 0;
  color: var(--text-dark);
  font-size: 14.5px;
}
.report-activity-list li {
  position: relative;
  margin-bottom: 8px;
  padding-left: 26px;
}
.report-activity-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 2px;
  width: 15px;
  height: 15px;
  border: 2px solid var(--border);
  border-radius: 4px;
  background: #fff;
}

.report-growth-note {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  font-size: 13.5px;
  color: var(--text-muted);
  font-style: italic;
}

.report-appendix { background: var(--bg-light); }
.report-score-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  margin-top: 12px;
}
.report-score-table th {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 2px solid var(--border);
  color: var(--navy-dark);
}
.report-score-table td {
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
}

/* Appendix (2026-08-13) — one merged table behind a toggle. It was two
   tables listing the same six domains (twelve rows for six domains'
   worth of numbers) plus two notes, always expanded, in a section whose
   own intro says it is for teachers and professionals. */
.apx-collapse {
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  background: #fff;
  margin-bottom: 14px;
}
.apx-collapse > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 15px;
  cursor: pointer;
  list-style: none;
  transition: background 0.15s ease;
}
.apx-collapse > summary::-webkit-details-marker { display: none; }
.apx-collapse > summary:hover { background: var(--bg-light); }
.apx-collapse > summary::before {
  content: '\25BE';
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: rgba(40, 41, 114, 0.09);
  color: var(--navy);
  font-size: 10px;
  transition: transform 0.15s ease;
}
.apx-collapse[open] > summary::before { transform: rotate(180deg); }
.apx-summary-title { font-size: 13px; font-weight: 700; color: var(--navy-dark); }
.apx-summary-hint { margin-left: auto; font-size: 11.5px; color: var(--text-muted); }
.apx-body { padding: 4px 15px 14px; border-top: 1px solid var(--border); }
.apx-body .auth-sub { font-size: 12.5px; margin: 12px 0 0; }

.apx-table { font-size: 13px; margin-top: 12px; }
.apx-table th {
  padding: 0 10px 7px;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.apx-table td { padding: 8px 10px; border-bottom: 1px solid var(--border); }
.apx-table tr:last-child td { border-bottom: none; }
.apx-domain { color: var(--navy-dark); font-weight: 600; }
.apx-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.apx-score { font-weight: 700; color: var(--navy-dark); }
.apx-up { color: var(--teal); font-weight: 700; }
.apx-down { color: var(--amber-dark); font-weight: 700; }
@media (prefers-reduced-motion: reduce) {
  .apx-collapse > summary, .apx-collapse > summary::before { transition: none; }
}
/* Printing to PDF should never hide the numbers behind a toggle. */
@media print {
  .apx-collapse > summary { display: none; }
  .apx-body { padding: 0; border-top: none; }
  .apx-collapse { border: none; }
}


.report-glossary p { font-size: 13.5px; color: var(--text-muted); margin-bottom: 10px; }

/* Radar/spider chart — a second read on the same 6 scores as the bars */
/* Radar (2026-08-13) — bigger, with a scale, a dashed own-average ring
   and per-vertex scores. The colour bands match the At-a-glance bars so
   the two views of the same six numbers can't read as different claims. */
.radar-chart-wrap {
  display: flex;
  justify-content: center;
  padding: 4px 0 0;
}
.radar-chart {
  width: 100%;
  max-width: 520px;
  height: auto;
  overflow: visible;
}
.radar-grid-ring {
  fill: none;
  stroke: var(--border);
  stroke-width: 1;
}
.radar-axis-line {
  stroke: var(--border);
  stroke-width: 1;
}
.radar-ring-label {
  font-size: 9.5px;
  fill: var(--text-muted);
  font-family: 'Inter', Arial, Helvetica, sans-serif;
  font-variant-numeric: tabular-nums;
}
.radar-avg-ring {
  fill: none;
  stroke: var(--text-dark);
  stroke-width: 1.5;
  stroke-dasharray: 5 4;
  opacity: 0.5;
}
.radar-data-shape {
  fill: rgba(15, 123, 138, 0.16);
  stroke: var(--teal);
  stroke-width: 2.5;
  stroke-linejoin: round;
}
.radar-data-dot { fill: var(--navy-dark); }
.radar-dot-strength { fill: var(--teal); }
.radar-dot-typical { fill: var(--navy); }
.radar-dot-growth { fill: var(--amber-dark); }
.radar-label {
  font-size: 11.5px;
  font-weight: 600;
  fill: var(--navy-dark);
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
}
.radar-label-score {
  font-size: 13px;
  font-weight: 700;
  fill: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.radar-score-strength { fill: var(--teal); }
.radar-score-typical { fill: var(--navy); }
.radar-score-growth { fill: var(--amber-dark); }
.radar-legend { justify-content: center; }
.radar-avg-key {
  width: 16px;
  height: 0;
  border-top: 2px dashed var(--text-dark);
  opacity: 0.5;
  flex-shrink: 0;
}

/* Stream-leaning note — a soft, non-deterministic aside, visually distinct
   from the italic/muted growth-note so it doesn't read as a caveat */
/* "What we found" (2026-08-13) — leads with the pair, then the remaining
   areas, every one a TINTED block coloured by its band. Same three colours
   as the At-a-glance bars, the radar dots and the level track, so the
   whole report speaks one colour language. */
.wf-pair {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px;
  margin-bottom: 22px;
}
.wf-hero { border-radius: 12px; padding: 16px 18px; }
.wf-hero-label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  margin: 0 0 6px;
}
.wf-hero-label .domain-icon { width: 16px; height: 16px; margin: 0; vertical-align: 0; }
.wf-hero-name {
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-size: 19px;
  font-weight: 700;
  margin: 0 0 4px;
  line-height: 1.2;
}
.wf-hero-meta {
  font-size: 12.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  margin: 0 0 10px;
}
.wf-hero-meta span { font-weight: 600; opacity: 0.75; }
.wf-hero-text { font-size: 13.5px; line-height: 1.6; margin: 0; }

.wf-rest-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-muted);
  margin: 0 0 12px;
}
/* Columns follow the card count - see COUNTED_GRIDS in js/auth.js. Fixed at
   two, Spelling put five cards in here and got 2 + 2 + 1. Two stays the
   fallback for the moment before the stamp lands. */
.wf-rest {
  display: grid;
  grid-template-columns: repeat(var(--tiles-mid, 2), minmax(0, 1fr));
  gap: 12px;
}
.wf-block { border-radius: 10px; padding: 13px 15px; }
.wf-block-name {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-size: 14.5px;
  font-weight: 700;
  margin: 0 0 5px;
}
.wf-block-name .domain-icon { width: 16px; height: 16px; margin: 0; vertical-align: 0; }
.wf-block-score {
  margin-left: auto;
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.wf-block-text { font-size: 12.5px; line-height: 1.55; margin: 0; }

/* Tints, AS TOKENS (2026-08-31). Text takes the darkest stop of the same
   family rather than a generic grey, so each block stays legible on its
   own ground.

   Why tokens and not twenty rules. This palette is written for a light
   card, and Spelling's copy of the section sits on a navy hero, so the
   whole thing is restated for a dark ground further down. That
   restatement used to be twenty separate declarations - and the print
   stylesheet, which puts the section back on white paper, reset three of
   them and left the other seventeen alone. The result was a printed
   report with white skill names on white paper, #DDE1F2 body text at
   1.2:1, and an invisible benchmark notch. Four values per band now, and
   a ground can only be got wrong all at once.

   The accent uses the -on-wash pair: a band's accent sits on that band's
   own tint, which lifts the ground enough to fail AA on the plain hue. */
.wf-strength {
  --wf-tint: rgba(15, 123, 138, 0.10);
  --wf-accent: var(--teal-on-wash);
  --wf-name: #0d4f49;
  --wf-body: #1d5e58;
}
.wf-growth {
  --wf-tint: rgba(243, 113, 48, 0.16);
  --wf-accent: var(--amber-on-wash);
  --wf-name: #7a4e08;
  --wf-body: #8a5c14;
}
.wf-typical {
  --wf-tint: rgba(40, 41, 114, 0.07);
  --wf-accent: var(--navy);
  --wf-name: var(--navy-dark);
  --wf-body: #3d5468;
}
/* The role of the two hero cards - best and hardest - reads down the
   card edge and in the label. It is deliberately NOT the band: a child
   below the benchmark in every skill puts both cards in the growth band,
   and with the band owning the label they came out identically amber,
   the best and the hardest looking the same. The band keeps the bar and
   the numbers. */
.wf-hero.is-best { --wf-role: var(--teal-on-wash); }
.wf-hero.is-hardest { --wf-role: var(--amber-on-wash); }

.wf-hero, .wf-block {
  background: var(--wf-tint);
  /* The bar's two grounds: the track it sits in, and the notch marking
     the benchmark. The notch has to read against the track AND against
     the coloured fill it crosses, so it carries a halo in the ground
     colour rather than trusting one of the two. */
  --wf-track: rgba(40, 41, 114, 0.22);
  --wf-notch: var(--navy-dark);
  --wf-halo: #fff;
  --wf-note: var(--text-muted);
}
.wf-hero-name, .wf-block-name { color: var(--wf-name); }
.wf-hero-text, .wf-block-text { color: var(--wf-body); }
/* After the name rule on purpose - the score is a child of the name. */
.wf-hero-label, .wf-hero-meta, .wf-block-score,
.wf-hero-label .domain-icon, .wf-block-name .domain-icon { color: var(--wf-accent); }

.wf-hero.is-best, .wf-hero.is-hardest { border-left: 3px solid var(--wf-role); }
.wf-hero.is-best .wf-hero-label, .wf-hero.is-best .wf-hero-label .domain-icon,
.wf-hero.is-hardest .wf-hero-label,
.wf-hero.is-hardest .wf-hero-label .domain-icon { color: var(--wf-role); }

@media (max-width: 620px) {
  .wf-pair, .wf-rest { grid-template-columns: 1fr; }
  .wf-block-score { margin-left: auto; }
}


/* Response time (2026-08-13) — a bar strip, not a two-column table. Six
   times listed as text gave no sense of the gaps between them.
   ONE NEUTRAL NAVY RAMP on purpose: time is not good or bad, so the
   teal/amber bands used elsewhere (which mean above/below the child's own
   average) would misread here as fast=good, slow=bad. */
.rt-strip { display: flex; flex-direction: column; gap: 11px; }
.rt-row { display: flex; align-items: center; gap: 14px; }
.rt-label {
  flex: 0 0 190px;
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--navy-dark);
  min-width: 0;
}
.rt-label .domain-icon { width: 16px; height: 16px; margin: 0; vertical-align: 0; color: var(--navy); }
.rt-tag {
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border-radius: 999px;
  padding: 2px 7px;
  white-space: nowrap;
}
.rt-tag-fast { color: var(--navy); background: rgba(40, 41, 114, 0.10); }
.rt-tag-slow { color: var(--text-muted); background: rgba(91, 107, 118, 0.14); }
.rt-track {
  flex: 1;
  height: 10px;
  background: rgba(40, 41, 114, 0.07);
  border-radius: 999px;
  overflow: hidden;
}
.rt-fill {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--navy), #2c5a86);
}
.rt-value {
  flex: 0 0 44px;
  text-align: right;
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-size: 14px;
  font-weight: 700;
  color: var(--navy-dark);
  font-variant-numeric: tabular-nums;
}
.rt-note {
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--text-muted);
  margin: 16px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
@media (max-width: 620px) {
  .rt-row { flex-wrap: wrap; gap: 6px 10px; }
  .rt-label { flex: 1 1 100%; }
  .rt-value { flex: 0 0 auto; }
}


.report-stream-note {
  margin-top: 16px;
  padding: 14px 18px;
  background: rgba(15, 123, 138, 0.06);
  border-radius: 12px;
  font-size: 13.5px;
  color: var(--text-dark);
}

/* Retake comparison */
.report-compare-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.report-compare-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  background: var(--bg-light);
  border-radius: 10px;
  font-size: 14px;
}
.report-compare-label { display: flex; align-items: center; gap: 6px; font-weight: 600; color: var(--navy-dark); }
.report-compare-label .domain-icon { margin-right: 0; }

/* Visually separates the 2 overall metrics from the per-operation deltas
   below them — previously both used identical rows with only a plain-text
   "By operation:" line between them, so the two groups read as one
   undifferentiated list. */
.compare-group-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  margin: 0 0 8px;
  text-align: left;
}
.report-compare-list-sub .report-compare-row {
  background: transparent;
  border: 1px solid var(--border);
  padding: 8px 14px;
}
.report-compare-list-sub .report-compare-label { font-weight: 500; font-size: 13px; }

.report-teacher { background: rgba(40, 41, 114, 0.03); }
.report-teacher p { display: flex; align-items: flex-start; }
.report-teacher .domain-icon { margin-top: 3px; }
.report-compare-delta { font-weight: 700; font-variant-numeric: tabular-nums; }
.report-compare-up { color: var(--teal); }
.report-compare-down { color: var(--amber-dark); }
.report-compare-steady { color: var(--text-muted); }

.report-table-scroll { overflow-x: auto; }

.report-reliability-note {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  font-size: 12.5px;
  color: var(--text-muted);
}

/* SQ hero gauge (ring) */
.sq-gauge-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 24px;
  flex-wrap: wrap;
}
.sq-gauge-svg { flex-shrink: 0; }
/* The value now lives inside the SVG, positioned by the same geometry as
   the arc - so it cannot collide with the caption the way the old HTML
   .sq-gauge-num did at 42px. */
.sq-gauge-value {
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-weight: 700;
  font-size: 30px;
  fill: var(--navy-dark);
}
.sq-gauge-unit {
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-weight: 700;
  font-size: 10px;
  letter-spacing: 0.12em;
  fill: var(--text-muted);
}

/* Each tile carries its own verdict, so it is a small stack rather than a
   number over a caption. */
.sg-tile { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.sg-verdict {
  display: inline-block;
  margin-top: 5px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 700;
  line-height: 1.35;
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}
.sg-good  { background: rgba(15, 123, 138, 0.12); color: var(--teal); }
.sg-ok    { background: rgba(91, 107, 118, 0.12); color: var(--navy-dark); }
.sg-watch { background: rgba(243, 113, 48, 0.14); color: var(--amber-dark); }
.sg-foot { margin-top: 5px; font-size: 11px; line-height: 1.4; color: var(--text-muted); }
.sq-gauge-caption { font-size: 12.5px; color: var(--text-muted); margin-top: 4px; max-width: 22ch; }

/* Spelling report parity pass (2026-08-13) — replaces inline style
   attributes that were doing this work one element at a time. */
/* Compound selector so it also beats the shared .stat-row breakpoint in
   auth.css, which drops every stat row to two columns under 720. */
.stat-row.spelling-glance-tiles { grid-template-columns: repeat(3, 1fr); margin-top: 16px; }
/* "Compared to last time" now lives inside the momentum card. Two
   columns, because the Spelling list is eight rows (SQ plus seven
   skills) and stacking them made the card taller than the two sections
   it replaced. White rows rather than --bg-light, which sits too close
   to the card's own tint to read as separate. */
.momentum-hero .report-compare-list {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px 14px;
}
.momentum-hero .report-compare-row {
  padding: 8px 12px;
  font-size: 13px;
  background: #fff;
  border: 1px solid var(--border);
}
.momentum-hero .report-compare-empty { text-align: left; }
.momentum-hero .section-sub-tight { margin-top: 0; margin-bottom: 8px; }
/* The gauge caption sits beside the dial rather than under a giant
   number, so it needs room to be a sentence rather than a label. */
.report-at-a-glance .sq-gauge-caption { max-width: 42ch; margin-top: 0; font-size: 13px; line-height: 1.55; }
/* Spelling score detail (2026-08-13) — one row per skill, replacing a
   benchmark table stacked on top of an item list that repeated the same
   seven skills and the same seven percentages. Everything a row needs is
   on the row: accuracy as a bar with the benchmark notched into it, the
   two numbers, and the pace. */
.sdx-overall {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  margin-bottom: 16px;
}
.sdx-stat {
  background: var(--bg-soft, #f7f9fa);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
}
.sdx-stat-label {
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  margin: 0 0 4px;
}
.sdx-stat-val {
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-size: 22px;
  font-weight: 700;
  color: var(--navy-dark);
  line-height: 1.1;
  margin: 0;
  font-variant-numeric: tabular-nums;
}
.sdx-stat-vs { font-size: 12px; color: var(--text-muted); margin: 3px 0 0; }
.sdx-legend { font-size: 12.5px; color: var(--text-muted); margin: 0 0 10px; line-height: 1.5; }
.sdx-list { display: flex; flex-direction: column; gap: 6px; }
.sdx-group { border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }

/* Overrides .skill-group-head's flex/space-between — this row is a grid
   so the bars, percentages and times line up down the column instead of
   drifting with each skill name's length. */
.skill-group-head.sdx-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 116px 46px 66px 74px 14px;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 11px 14px;
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
}
.skill-group-head.sdx-row:hover { background: var(--bg-soft, #f7f9fa); }
.sdx-name {
  font-size: 13.5px;
  font-weight: 700;
  color: var(--navy-dark);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sdx-replay { margin-left: 5px; }
.sdx-bar {
  position: relative;
  display: block;
  height: 7px;
  border-radius: 999px;
  background: rgba(40, 41, 114, 0.09);
  overflow: visible;
}
.sdx-fill { position: absolute; inset: 0 auto 0 0; border-radius: 999px; }
.sdx-strength { background: var(--teal); }
.sdx-typical { background: var(--navy); }
.sdx-growth { background: var(--amber); }
/* The benchmark, notched through the bar rather than printed beside it —
   the whole point of the row is "did the bar reach the notch?". */
.sdx-mark {
  position: absolute;
  top: -3px;
  bottom: -3px;
  width: 2px;
  margin-left: -1px;
  background: var(--navy-dark);
  opacity: 0.55;
  border-radius: 1px;
}
.sdx-pct {
  font-size: 13.5px;
  font-weight: 700;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.sdx-t-strength { color: var(--teal); }
.sdx-t-typical { color: var(--navy); }
.sdx-t-growth { color: var(--amber-dark); }
.sdx-bench,
.sdx-time {
  font-size: 11.5px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.sdx-time { text-align: right; }
.sdx-group .skill-group-caret { transition: transform 0.15s ease; color: var(--text-muted); }
.sdx-group.open .skill-group-caret { transform: rotate(90deg); }

@media (max-width: 720px) {
  .sdx-overall { grid-template-columns: 1fr; }
  /* Six columns don't fit a phone. Dropping the bar and the pace still
     left the name on ~58px — enough to truncate "Double consonants" to
     nothing useful — so the row restacks instead: name over benchmark on
     the left, the percentage centred against both on the right. Nothing
     is lost but the bar, which is the one thing the numbers beside it
     already say. */
  .skill-group-head.sdx-row {
    grid-template-columns: minmax(0, 1fr) auto 14px;
    gap: 2px 10px;
  }
  .sdx-bar, .sdx-time { display: none; }
  .sdx-name { white-space: normal; grid-column: 1; grid-row: 1; }
  .sdx-bench { grid-column: 1; grid-row: 2; }
  .sdx-pct { grid-column: 2; grid-row: 1 / span 2; align-self: center; }
  .sdx-row .skill-group-caret { grid-column: 3; grid-row: 1 / span 2; align-self: center; }
}
/* Lifted out of inline style attributes (2026-08-13). What stays inline in
   this file is only ever a computed value — a bar width, a data-driven
   colour — which is the same line the cognitive report draws. */
.score-bar-pct {
  flex: 0 0 42px;
  text-align: right;
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.qks-confident { background: rgba(15, 123, 138, 0.16); }
.qks-fast { background: rgba(243, 113, 48, 0.14); }
.qks-slow { background: rgba(40, 41, 114, 0.07); }
.qks-support { background: rgba(243, 113, 48, 0.22); }
.section-sub-tight { margin-top: -8px; }
.level-badge-blank { flex-shrink: 0; }
.lbb-72 { width: 72px; height: 72px; }
.lbb-34 { width: 34px; height: 34px; }
.why-card-eyebrow { color: rgba(255, 255, 255, 0.75); }

/* THREE ACROSS FOR AS LONG AS THEY FIT. Dropping to one column at 720
   turned three short facts into three 576px bars that were nine tenths
   empty - and the report is often read at exactly that width, embedded in
   the profile page. They hold their shape down to 560, go two-and-one
   only on a phone, and the tiles are narrow enough there to be worth it. */
@media (max-width: 560px) {
  .stat-row.spelling-glance-tiles { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 380px) {
  .stat-row.spelling-glance-tiles { grid-template-columns: 1fr; }
}

/* Speed x accuracy quadrant chart */
.quadrant-svg { width: 100%; aspect-ratio: 600 / 240; display: block; }
.quadrant-legend { font-size: 11.5px; color: var(--text-muted); margin-top: 10px; }
/* The one sentence a parent takes away from the growth chart, sized to be
   read before the chart rather than after it. */
.trend-summary {
  margin: 12px 0 0;
  font-size: 14px;
  line-height: 1.55;
  color: var(--navy-dark);
}
.trend-summary strong { font-variant-numeric: tabular-nums; }
/* Legend keys drawn as real dots. They used to be a bare bullet character
   in the running text, which takes the text colour - so "navy = formal
   test" was written in grey, and the colour it named was nowhere on the
   line. */
.tl-dot {
  display: inline-block;
  width: 9px; height: 9px;
  border-radius: 50%;
  margin-right: 5px;
  vertical-align: 0;
}
.tl-dot-navy { background: var(--navy); }
.tl-dot-teal { background: var(--teal); }

/* Operation legend (numbered chips) + plain-English quadrant key — kept
   entirely outside the SVG's plot area on purpose, so no amount of data
   clustering can make this text overlap (unlike the old in-chart labels,
   which collided when two operations landed close together). */
.quadrant-legend-row { display: flex; flex-wrap: wrap; gap: 8px 16px; margin-top: 14px; }
.quadrant-legend-chip { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--navy-dark); font-weight: 600; }
.quadrant-legend-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  flex-shrink: 0;
}
.quadrant-key-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px 18px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  font-size: 12px;
  color: var(--text-muted);
}
.quadrant-key-swatch {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 3px;
  margin-right: 6px;
  vertical-align: -1px;
}

/* Growth/celeration trend chart (Maths fluency) */
.trend-chart-svg { width: 100%; height: 220px; display: block; }
.fact-list-empty { font-size: 12.5px; color: var(--text-muted); text-align: center; }

/* Strength / growth-focus narrative pair */
.pair-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.pair-card { border-radius: 12px; padding: 18px 20px; }
.pair-strength { background: rgba(15, 123, 138, 0.10); }
.pair-growth { background: rgba(243, 113, 48, 0.12); }
.pair-tag { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; margin: 0 0 8px; }
.pair-strength .pair-tag { color: var(--teal); }
.pair-growth .pair-tag { color: var(--amber-dark); }
.pair-card h3 { margin: 0 0 6px; font-size: 15px; color: var(--navy-dark); }
.pair-card p { margin: 0; font-size: 13.5px; color: var(--text-dark); line-height: 1.5; }
.pair-tip { margin-top: 10px; font-size: 12.5px; color: var(--text-muted); border-top: 1px dashed var(--border); padding-top: 10px; }

/* Words mastered / words to revisit */
.word-lists { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.word-list-card { border-radius: 12px; padding: 16px 18px; }
.word-list-card.mastered { background: rgba(15, 123, 138, 0.10); }
.word-list-card.revisit { background: rgba(243, 113, 48, 0.12); }
.word-list-title { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; margin: 0 0 10px; }
.word-list-card.mastered .word-list-title { color: var(--teal); }
.word-list-card.revisit .word-list-title { color: var(--amber-dark); }
.word-chip-row { display: flex; flex-wrap: wrap; gap: 6px; }
.word-list-card .word-chip { background: #fff; border: 1px solid var(--border); border-radius: 999px; padding: 4px 11px; font-size: 12.5px; font-weight: 600; color: var(--navy-dark); }
.word-list-empty { font-size: 12.5px; color: var(--text-muted); }

/* Item review, grouped by skill and collapsible */
.skill-group { margin-bottom: 6px; border-radius: 10px; overflow: hidden; }
.skill-group-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 12px 14px; background: var(--bg-light); cursor: pointer; user-select: none; border: none; width: 100%; text-align: left; font: inherit; }
.skill-group-head .name { font-weight: 600; font-size: 13.5px; color: var(--navy-dark); }
.skill-group-meta { font-size: 11px; color: var(--text-muted); margin-top: 1px; }
.skill-group-right { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.skill-group-badge { font-size: 11.5px; font-weight: 700; padding: 2px 9px; border-radius: 999px; font-variant-numeric: tabular-nums; }
.badge-strength { background: rgba(15, 123, 138, 0.14); color: var(--teal); }
.badge-typical { background: rgba(40, 41, 114, 0.10); color: var(--navy-dark); }
.badge-growth { background: rgba(243, 113, 48, 0.16); color: var(--amber-dark); }
.skill-group-caret { color: var(--text-muted); transition: transform 0.15s ease; }
.skill-group.open .skill-group-caret { transform: rotate(90deg); }
.skill-group-items { padding: 4px 0 10px; display: none; }
.skill-group.open .skill-group-items { display: block; }
.miss-tag { font-size: 10.5px; font-weight: 700; padding: 1px 7px; border-radius: 999px; margin-left: 8px; white-space: nowrap; }
.miss-close { background: rgba(243, 113, 48, 0.16); color: var(--amber-dark); }
.miss-far { background: rgba(178, 58, 36, 0.10); color: #B23A24; }

/* Compare-to-last-time honest placeholder */
.report-compare-empty { font-size: 13.5px; color: var(--text-muted); text-align: center; }
.report-compare-empty strong { color: var(--navy-dark); }

@media (max-width: 560px) {
  .score-bar-label { flex-basis: 100px; font-size: 12px; }
  .report-section { padding: 24px 20px; }
  .report-compare-row { flex-direction: column; align-items: flex-start; gap: 4px; }
  .pair-grid, .word-lists { grid-template-columns: 1fr; }
  .quadrant-key-grid { grid-template-columns: 1fr; }
}

/* Embedded mode (?embed=1): the report is shown inside profile.html's
   inline "Full report" collapsible iframe — the site header and back
   links belong to the outer page there, not this one. */
body.report-embedded .auth-header { display: none; }
body.report-embedded .profile-main { padding-top: 8px; }
body.report-embedded a[href^="profile.html"],
body.report-embedded a[href^="dashboard.html"] { display: none !important; }

/* Embedded chrome (2026-08-13). The masthead is a standalone document's
   identity block — right on its own page and in the PDF, which have to
   identify themselves. Inside profile.html it says nothing the
   surrounding section hasn't: you reached it from a row headed with the
   subject, score and date. Removed outright here.
   The report's own Mock/Practice tabs and Latest/All sub-tabs go too —
   the module tab already splits those into five independent sections, so
   in the embed they were a second navigation for the same content. What
   remains is exactly the panel the parent asked for. */
body.report-embedded .report-header { display: none; }
body.report-embedded .report-toplevel-tabs,
body.report-embedded .progress-subtabs { display: none; }

/* The two pieces that aren't redundant — the CHC credibility line and
   the never-ranks-your-child disclaimer — moved to the end and folded
   away rather than dropped. */
body.report-embedded .report-about {
  margin: 28px 0 8px;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}
body.report-embedded .report-about > summary {
  padding: 10px 14px;
  cursor: pointer;
  list-style: none;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--navy-dark);
  background: var(--bg-light);
}
body.report-embedded .report-about > summary::-webkit-details-marker { display: none; }
body.report-embedded .report-about > summary::after { content: ' \25BE'; color: var(--text-muted); }
body.report-embedded .report-about[open] > summary::after { content: ' \25B4'; }
body.report-embedded .report-about-body { padding: 14px; }
body.report-embedded .report-about-body .report-credibility-badge,
body.report-embedded .report-about-body .report-disclaimer { margin: 0 0 10px; }
body.report-embedded .report-about-body > :last-child { margin-bottom: 0; }

/* "Download PDF" just calls window.print() — the browser's own
   print-to-PDF is used instead of a client-side rendering library, since
   it produces sharp, selectable-text PDFs with zero extra dependencies. */
@media print {
  * {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }
  /* Keep the TopperLens Junior logo/wordmark in the printed PDF — only the
     "Back to profile" nav link (not useful on paper) gets hidden. This
     used to hide the whole header, which meant a downloaded report
     carried no TopperLens Junior branding at all. */
  .auth-header { position: static; backdrop-filter: none; }
  .auth-header .link-btn { display: none !important; }
  body { background: #fff; }
  main.profile-main { padding: 0; }
  .report-container { max-width: 100%; padding: 0; }
  /* break-inside: avoid used to sit here, on EVERY section (2026-08-20).
     It reads as harmless and is not: a section taller than the space left
     on the current page gets moved WHOLE to the next one, and whatever was
     left behind stays blank. Measured on the Cognitive sample, ten of the
     twenty sections were being shunted, wasting ~3,200px — more than three
     entire pages of white paper in a sixteen-page document.

     A long section is allowed to flow across a fold now. What is protected
     instead is the places where a fold actually hurts: a heading separated
     from what it introduces, a single line stranded, or one of the small
     units below split down the middle. */
  /* NO BORDER ON PAPER (2026-08-25). A bordered card and a page break are
     in direct conflict: allow the card to split and its border closes
     mid-page and reopens at the top of the next, which is what those stray
     rules across the middle of a page were. Forbid the split instead and a
     tall card that will not fit dumps most of a page of white to move whole.
     Neither is fixable while the box is drawn.

     Flat sections separated by a rule and some air have no such problem.
     They split invisibly wherever the page ends, so the only breaks left are
     the ones that matter - and those are handled by keeping the small units
     below atomic. */
  .report-section {
    box-shadow: none;
    border: 0;
    border-top: 1px solid #d8d8e0;
    border-radius: 0;
    background: none;
    padding: 16px 0 0;
    margin-bottom: 18px;
    break-inside: auto;
    page-break-inside: auto;
  }
  /* Deliberately NO first-section exception. :first-of-type matches once per
     PARENT, and the stepper spreads these sections across seven panels - so
     it would have stripped the rule from seven of them, scattered down the
     document, rather than from the one at the top. A rule above the first
     section is a smaller flaw than six missing ones in the middle. */
  .report-section h1,
  .report-section h2,
  .report-section h3,
  .pg-h3,
  .glance-bars-title,
  .m2d-title {
    break-after: avoid;
    page-break-after: avoid;
  }
  p, li, dd { orphans: 3; widows: 3; }
  /* PROTECT THE PARTS, NOT THE WHOLE CARD.
     Making the whole card unsplittable stopped the score ring being cut in
     half, and immediately caused the other failure: at 344px it lands near
     a page boundary often, moves whole, and leaves a third of a page blank
     behind it. Both are the same mistake at different scales - deciding
     atomicity by the container rather than by what actually must not be
     cut.
     The card splits again. The HEAD cannot: ring, role and name stay
     together, and break-after keeps them attached to at least the start of
     the prose rather than stranding a heading at the foot of a page. The
     action box cannot split either - it is four lines and the one thing a
     parent is meant to act on. Everything between is ordinary paragraphs,
     which break wherever the page ends without anyone noticing. */
  .pg-skill { break-inside: auto; page-break-inside: auto; }
  .pg-skill-head {
    break-inside: avoid;
    page-break-inside: avoid;
    break-after: avoid;
    page-break-after: avoid;
  }
  .pg-skill-do { break-inside: avoid; page-break-inside: avoid; }
  .pg-skill-head { break-after: avoid; page-break-after: avoid; }
  .pg-qa dt { break-after: avoid; page-break-after: avoid; }
  /* Atomic: splitting any of these mid-way loses the reading. */
  .pg-top,
  .pg-row,
  .pg-evidence,
  .pg-plan,
  .pg-check,
  .pg-caveat,
  .stat-tile,
  .glance-card,
  .report-badge,
  .report-compare-row,
  .score-bar,
  .trouble-fact-row,
  .spelling-review-row,
  .m2d,
  tr {
    break-inside: avoid;
    page-break-inside: avoid;
  }
  /* A LONG TABLE SPLITS, AND REPEATS ITS HEADER. Held whole it was 251px
     that had to find a home, and inside a 566px wrapper that also could
     not split it forced most of a blank page. Rows stay atomic (tr, above)
     and thead repeats on each page, which is what actually keeps a split
     table readable - the reason to hold it together in the first place. */
  /* Prose, not a unit: .pg-notmean and .pg-concern are several paragraphs
     each, 185px and 242px, and holding them whole bought nothing except
     another block that had to find a page. They break like the paragraphs
     they are, with the orphans/widows rule above keeping stray lines off. */
  .pg-notmean,
  .pg-concern { break-inside: auto; page-break-inside: auto; }
  .report-score-table { break-inside: auto; page-break-inside: auto; }
  .report-score-table thead { display: table-header-group; }
  .report-score-table tfoot { display: table-footer-group; }
  #maths-download-btn, #spelling-download-btn, #report-download-btn, .why-cta, a[href^="math-practice.html"], a[href^="spelling-test-demo.html"], a[href^="profile.html"] { display: none !important; }
}

.tag { display: inline-block; font-size: 10.5px; font-weight: 700; padding: 2px 8px; border-radius: 999px; }
.tag-growth { background: rgba(243, 113, 48, 0.16); color: var(--amber-dark); }
.tag-strength { background: rgba(15, 123, 138, 0.12); color: var(--teal); }

.digits-note { font-size: 10.5px; color: var(--text-muted); font-weight: 500; }

.personal-best-note {
  margin-top: 10px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--teal);
}

.projection-note { border-top: none; padding-top: 0; margin-top: 12px; font-style: normal; background: rgba(243, 113, 48, 0.10); border-radius: 8px; padding: 10px 14px; }

/* Grade history — small badge timeline, one per past attempt */
.grade-history-row { display: flex; gap: 14px; flex-wrap: wrap; align-items: flex-start; }
.grade-history-item { display: flex; flex-direction: column; align-items: center; gap: 4px; opacity: 0.55; }
.grade-history-item.grade-history-current { opacity: 1; }
.grade-history-date { font-size: 11px; color: var(--text-muted); font-variant-numeric: tabular-nums; }


}
}

/* Practice-module sell card — the site's brand gradient, so it reads as a
   distinct "call to action" moment rather than another neutral section. */
.why-card {
  background: var(--gradient-brand);
  border-radius: 16px;
  padding: 26px 24px;
  margin: 24px 0;
  color: #fff;
}
.why-card h2 { color: #fff; margin-top: 0; }
.why-card .section-sub { color: rgba(255, 255, 255, 0.85); }
.why-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin: 0 0 14px; }
.why-stat strong { display: block; font-family: 'Poppins', Arial, Helvetica, sans-serif; font-size: 20px; margin-bottom: 4px; }
.why-stat span { font-size: 11.5px; color: rgba(255, 255, 255, 0.85); line-height: 1.4; }
.why-cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--amber);
  color: var(--navy-dark);
  font-size: 13.5px;
  font-weight: 700;
  padding: 12px 20px;
  border-radius: 10px;
  text-decoration: none;
}

/* The concrete recommendation ("15 medium Division problems") — a lighter
   panel inside the dark why-card so it reads as the specific instruction,
   distinct from the surrounding sell copy and the stat row below it. */
.practice-recommend {
  background: rgba(255, 255, 255, 0.12);
  border-radius: 12px;
  padding: 16px 18px;
  margin: 18px 0;
}
.practice-recommend-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--amber);
  margin: 0 0 6px;
}
.practice-recommend-detail {
  font-size: 14.5px;
  color: #fff;
  margin: 0 0 8px;
  line-height: 1.5;
}
.practice-recommend-cadence {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.82);
  margin: 0 0 14px;
  line-height: 1.5;
}

/* Weekly goal progress — closes the loop on the cadence recommendation
   above by showing whether it's actually being followed. */
.practice-goal { margin: 0 0 16px; }
.practice-goal-label { font-size: 12.5px; color: rgba(255, 255, 255, 0.85); margin: 0 0 6px; }
.practice-goal-track { height: 8px; border-radius: 999px; background: rgba(255, 255, 255, 0.18); overflow: hidden; }
.practice-goal-fill { height: 100%; border-radius: 999px; background: var(--amber); }

.practice-recommend-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.why-cta-outline {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.5);
  color: #fff;
  font-size: 13.5px;
  font-weight: 700;
  padding: 11px 18px;
  border-radius: 10px;
  cursor: pointer;
}
.why-cta-outline:disabled { opacity: 0.7; cursor: default; }
.practice-assign-pending {
  width: 100%;
  font-size: 12.5px;
  color: rgba(255, 255, 255, 0.75);
  margin: 0 0 4px;
}
.practice-assign-confirm {
  width: 100%;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--amber);
  margin: 8px 0 0;
}

.why-stats-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.65);
  margin: 22px 0 12px;
  padding-top: 18px;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
}

@media (max-width: 560px) {
  .why-stats { grid-template-columns: 1fr; }
}

/* ============================================================
   Report v2 (2026-08-10) — Level/Summary hero + Mock/Practice
   split + Latest/Aggregated views. Shared shell across Maths,
   Spelling, and Cognitive; each subject fills it with its own
   real, derived diagnostics (no fabricated data). See HANDOFF.md
   for the design rationale.
   ============================================================ */

.age-note-banner {
  background: rgba(15, 123, 138, 0.10);
  border: 1px solid rgba(15, 123, 138, 0.3);
  color: var(--navy-dark);
  border-radius: 10px;
  padding: 12px 18px;
  font-size: 13px;
  margin-bottom: 20px;
}
.age-note-banner strong { color: var(--teal); }

.level-hero {
  background: linear-gradient(120deg, rgba(15, 123, 138, 0.08), rgba(243, 113, 48, 0.10));
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 30px 32px;
  margin-bottom: 24px;
}
.level-hero-top {
  display: flex;
  align-items: center;
  gap: 22px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}
.level-hero-badge { flex-shrink: 0; }
.level-hero-current-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--teal);
  margin: 0 0 4px;
}
.level-hero-name {
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-size: 26px;
  font-weight: 700;
  color: var(--navy-dark);
  margin: 0;
}
.level-hero-name span { color: var(--text-muted); font-size: 15px; font-weight: 600; margin-left: 4px; }
.level-hero-sq-explainer {
  font-size: 12.5px;
  color: var(--text-muted);
  margin: 4px 0 0;
}

/* Composite scale (2026-08-13) — replaced the bare "composite N of 100"
   in the hero headline. The child's own band is marked in the table
   rather than stated as a lone number, so the figure always arrives with
   the scale that gives it meaning. */
/* Level component (2026-08-13) — headline + a five-segment track,
   replacing a borrowed spelling gauge and five stacked full-width bars.
   Segments read left to right as a route: cleared, here, ahead. */
.clevel { margin: 0 0 18px; }
.clevel-head {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding-bottom: 16px;
}
.clevel-badge { flex-shrink: 0; line-height: 0; }
.clevel-headtext { flex: 1; min-width: 150px; }
.clevel-eyebrow {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--teal);
  margin: 0 0 2px;
}
.clevel-name {
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-size: 24px;
  font-weight: 700;
  color: var(--navy-dark);
  margin: 0;
  line-height: 1.15;
}
.clevel-score {
  flex-shrink: 0;
  text-align: right;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.1;
}
.clevel-score-num {
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-size: 30px;
  font-weight: 700;
  color: var(--navy-dark);
  font-variant-numeric: tabular-nums;
}
.clevel-score-of { font-size: 11.5px; color: var(--text-muted); margin-top: 2px; }

.clevel-track {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 10px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.clevel-step { position: relative; min-width: 0; }
.clevel-step-bar {
  display: block;
  height: 7px;
  border-radius: 999px;
  background: var(--border);
  margin-bottom: 8px;
}
.clevel-step.is-done .clevel-step-bar { background: var(--navy); }
.clevel-step.is-current .clevel-step-bar { background: var(--teal); }
.clevel-step-n {
  display: inline-block;
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-size: 12px;
  font-weight: 700;
  color: var(--text-muted);
  margin-right: 5px;
}
.clevel-step.is-done .clevel-step-n { color: var(--navy); }
.clevel-step.is-current .clevel-step-n { color: var(--teal); }
.clevel-step-label {
  font-size: 11.5px;
  line-height: 1.35;
  color: var(--text-muted);
}
.clevel-step.is-current .clevel-step-label { color: var(--navy-dark); font-weight: 700; }
.clevel-step-here {
  display: inline-block;
  margin-top: 5px;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #fff;
  background: var(--teal);
  border-radius: 999px;
  padding: 2px 8px;
  white-space: nowrap;
}
@media (max-width: 640px) {
  .clevel-track { grid-template-columns: repeat(2, 1fr); gap: 12px 10px; }
  .clevel-score { text-align: left; align-items: flex-start; }
}


.composite-scale {
  margin: 18px 0 0;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  background: var(--bg-light);
}
.composite-scale-summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 16px;
  cursor: pointer;
  list-style: none;
  transition: background 0.15s ease;
}
.composite-scale-summary::-webkit-details-marker { display: none; }
.composite-scale-summary:hover { background: rgba(15, 123, 138, 0.06); }
/* A small teal chevron disc leads the row, so the box reads as a control
   rather than a stray grey bar under the level. */
.composite-scale-summary::before {
  content: '\25BE';
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: rgba(15, 123, 138, 0.14);
  color: var(--teal);
  font-size: 10px;
  line-height: 1;
  transition: transform 0.15s ease;
}
.composite-scale[open] .composite-scale-summary::before { transform: rotate(180deg); }
.composite-scale-summary-title { font-size: 13.5px; font-weight: 700; color: var(--navy-dark); }
.composite-scale-summary-hint {
  margin-left: auto;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.composite-scale-body { padding: 14px 16px 16px; background: #fff; border-top: 1px solid var(--border); }
@media (prefers-reduced-motion: reduce) {
  .composite-scale-summary, .composite-scale-summary::before { transition: none; }
}
.composite-scale-note {
  font-size: 14px;
  line-height: 1.65;
  color: var(--text-muted);
  margin: 0 0 16px;
  max-width: 74ch;
}
.composite-scale-note strong, .composite-scale-foot strong { color: var(--navy-dark); }
.composite-scale-wrap { overflow-x: auto; }
.composite-scale-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13.5px;
  min-width: 520px;
}
.composite-scale-table th {
  text-align: left;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  padding: 0 12px 8px;
  border-bottom: 1px solid var(--border);
}
.composite-scale-table td {
  padding: 11px 12px;
  border-bottom: 1px solid var(--border);
  color: var(--text-muted);
  line-height: 1.55;
  vertical-align: top;
}
.composite-scale-table tr:last-child td { border-bottom: none; }
.csr-range { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--navy-dark); white-space: nowrap; }
.csr-level { font-weight: 600; color: var(--navy-dark); }
.composite-scale-table tr.is-current { background: rgba(15, 123, 138, 0.08); }
.composite-scale-table tr.is-current td { color: var(--navy-dark); }
.csr-here {
  display: inline-block;
  margin-left: 8px;
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  background: var(--teal);
  border-radius: 999px;
  padding: 2px 9px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.composite-scale-foot {
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--text-muted);
  margin: 12px 0 0;
  max-width: 74ch;
}

@media (max-width: 640px) {
  .composite-scale-table { font-size: 12.5px; min-width: 460px; }
  .csr-here { display: block; margin: 4px 0 0; }
}

@media print {
  /* THE BIGGEST UNSPLITTABLE BLOCK IN THE REPORT, at 566px once print
     opens it. More than half a page that has to land whole, so whenever
     less than that remained it jumped to the next page and left the rest
     blank - which is the large gap under "Where Level 1 sits on the
     scale". It splits now; the pieces inside it that must not be cut
     already say so themselves. */
  .composite-scale { break-inside: auto; page-break-inside: auto; }
  .composite-scale-wrap { overflow-x: visible; }
  .composite-scale-table { min-width: 0; }
  .composite-scale-table tr.is-current { background: #EDF6F8 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .csr-here { background: #0F7B8A !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}
.level-hero-delta {
  display: inline-flex;
  align-items: center;
  margin: 6px 8px 0 0;
  font-size: 12.5px;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: 999px;
}
.level-hero-delta-up { background: rgba(15, 123, 138, 0.12); color: var(--teal); }
.level-hero-delta-down { background: rgba(184, 76, 24, 0.14); color: var(--amber-dark); }
.level-hero-delta-steady { background: rgba(91, 107, 118, 0.12); color: var(--text-muted); }
@media print {
}
/* Per-section "How to read this" explainers (2026-08-11) */
/* The level headline as its own header band (2026-08-13) — the
   report title, separated from the summary card beneath it. */
/* THE HERO OF THIS STEP (2026-08-25). It was a bare row with a rule under
   it - the report's headline styled as a divider. Same navy-and-teal ground
   as the portal heroes and the 60-seconds block, so the top of a step looks
   like the top of a step everywhere in the product. */
.report-level-header {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 24px 26px;
  margin: 0 0 18px;
  border-bottom: 0;
  border-radius: 18px;
  color: #fff;
  background:
    radial-gradient(120% 150% at 100% 0%, rgba(15, 123, 138, 0.45), transparent 60%),
    linear-gradient(135deg, var(--navy) 0%, var(--navy-dark) 100%);
  box-shadow: 0 14px 34px rgba(27, 28, 80, 0.22);
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}
.report-level-header .level-hero-current-label { color: rgba(255, 255, 255, 0.72); }
.report-level-header .level-hero-name { color: #fff; }
.report-level-header .level-hero-name span { color: rgba(255, 255, 255, 0.7); }
.report-level-header .hero-info-btn {
  color: rgba(255, 255, 255, 0.8);
  border-color: rgba(255, 255, 255, 0.4);
}
/* The delta chip's light tints are near-invisible on navy - it is the most
   prominent up-or-down signal on the report and must stay legible. */
.report-level-header .level-hero-delta-up { background: rgba(111, 220, 232, 0.2); color: #8FE7F0; }
.report-level-header .level-hero-delta-down { background: rgba(243, 113, 48, 0.28); color: #FFC0A0; }
.report-level-header .level-hero-delta-steady { background: rgba(255, 255, 255, 0.16); color: rgba(255, 255, 255, 0.85); }
.report-level-header .level-hero-milestone {
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
}

/* Scoped to the card that FOLLOWS the header, so the Maths and Spelling
   reports - which still carry their level inside .level-hero itself - are
   untouched. Its teal-to-orange wash fought the navy above it; a plain
   surface lets the hero be the coloured thing. */
.report-level-header + .level-hero {
  background: var(--bg-light);
  border-color: var(--border);
}

@media print {
  .report-level-header {
    color: var(--text-dark);
    background: #fff;
    border-bottom: 2px solid var(--border);
    border-radius: 0;
    padding: 0 0 18px;
    box-shadow: none;
  }
  .report-level-header .level-hero-current-label { color: var(--text-muted); }
  .report-level-header .level-hero-name { color: var(--navy-dark); }
  .report-level-header .level-hero-delta-up { background: rgba(15, 123, 138, 0.12); color: var(--teal); }
  .report-level-header .level-hero-delta-down { background: rgba(184, 76, 24, 0.14); color: var(--amber-dark); }
}
.report-level-header-text { min-width: 0; }
.report-level-header .level-hero-badge { flex-shrink: 0; }
@media (max-width: 560px) { .report-level-header { gap: 12px; } }

.section-head-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.section-head-row h2 { margin-bottom: 0; }
.section-head-row + * { margin-top: 12px; }
/* The explainer is an "i" button + popup now (see attachSectionExplainer)
   — same control as every metric explainer, so it inherits .metric-info-btn
   and needs no pill/panel styling of its own. */
.hero-info-btn { position: absolute; top: 16px; right: 16px; }
.level-hero { position: relative; }
.report-level-header { position: relative; }
.report-level-header .hero-info-btn { top: 0; right: 0; }
@media print {
  .section-info-btn { display: none !important; }
  /* Printed from the profile embed, applyEmbeddedReportChrome() has
     already moved the credibility note and the disclaimer into this
     collapsible. beforeprint opens it and drops .report-embedded, so
     all that is left is the summary — a control nobody can click on
     paper. Hidden, the two paragraphs print as the plain run the
     standalone page shows. */
  .report-about > summary { display: none !important; }
  .report-about { border: none; }
  /* On screen the report is a place you act; on paper it is a record.
     The tab strips are controls nobody can press in a PDF, and the
     .print-hide momentum card (which now carries the day-to-day lines
     too) is advice the portal already owns and can keep current — a
     printed date to retest by goes stale on the page. */
  .report-toplevel-tabs,
  .progress-subtabs,
  .print-hide { display: none !important; }
}
@media (max-width: 720px) {
  .hero-info-btn { position: static; margin-top: 8px; }
  /* 32px of section padding either side is a large share of a phone —
     and larger still inside the profile embed, where the report already
     sits in a narrow column. It was squeezing the radar to ~110px. */
  .report-section { padding: 20px 16px; }
}

/* Keeping the momentum (2026-08-13) — the report's closing hero. Uses
   the same two-step shape as the Overview's "Our Recommendations"
   (practise the named area, then retest) so the report ends on the same
   advice the portal gives, not a differently-worded version of it. */
.momentum-hero {
  background: linear-gradient(120deg, rgba(15, 123, 138, 0.08), rgba(243, 113, 48, 0.09));
  border-left: 4px solid var(--teal);
}
.momentum-eyebrow {
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--teal);
  margin: 0 0 3px;
}
.momentum-title { margin-bottom: 10px !important; }
/* Side by side rather than stacked (2026-08-13) — two short steps in one
   row instead of two full-width bands halves the card's height, which is
   what let the day-to-day lines move in without the section growing. */
.momentum-steps {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  margin-top: 14px;
}
.momentum-step {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
}

/* The day-to-day lines, folded in as this card's lead. Two columns so
   the usual two growth areas sit on one row. */
.m2d { margin: 0 0 4px; }
.m2d-title {
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--navy);
  opacity: 0.75;
  margin: 0 0 7px;
}
.m2d-list {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 9px 22px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.m2d-item {
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--text-muted);
  margin: 0;
}
.m2d-item strong { color: var(--navy-dark); font-weight: 700; }
.m2d-where { color: var(--navy); opacity: 0.65; }

@media (max-width: 720px) {
  .momentum-steps,
  .m2d-list,
  .momentum-hero .report-compare-list { grid-template-columns: 1fr; }
}
.momentum-step-n {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--teal);
  color: #fff;
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-size: 13px;
  font-weight: 700;
}
.momentum-step-title {
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-size: 15px;
  font-weight: 700;
  color: var(--navy-dark);
  margin: 0 0 3px;
}
.momentum-step-text { font-size: 13px; line-height: 1.55; color: var(--text-muted); margin: 0; }
/* The Assign practice control, now living on step 1. .why-cta was sized
   for the dark sell card it used to sit in; on a white step it needs to
   read as a normal secondary button. */
.momentum-step .why-cta {
  margin-top: 9px;
  padding: 8px 14px;
  font-size: 12.5px;
  background: var(--teal);
  color: #fff;
}
.momentum-step .practice-assign-pending,
.momentum-step .practice-assign-confirm { font-size: 12px; margin: 8px 0 0; }


.report-roi-line { font-size: 14.5px; color: var(--navy-dark); }
.report-next-test {
  font-size: 14px;
  color: var(--navy-dark);
  background: rgba(243, 113, 48, 0.1);
  border: 1px solid rgba(243, 113, 48, 0.3);
  border-radius: 10px;
  padding: 10px 14px;
  margin: 10px 0 0;
}
.level-hero-milestone {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--amber-dark);
  background: rgba(243, 113, 48, 0.16);
  padding: 4px 10px;
  border-radius: 999px;
}
.level-hero-summary-line {
  background: #fff;
  border-radius: 12px;
  padding: 14px 18px;
  font-size: 14.5px;
  color: var(--text-dark);
  line-height: 1.6;
  margin-bottom: 18px;
}
.level-hero-summary-line strong { color: var(--navy-dark); }
.level-hero-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
.level-hero-stat {
  background: #fff;
  border-radius: 10px;
  padding: 12px 14px;
  text-align: center;
}
.level-hero-stat .num {
  font-family: 'Poppins', Arial, Helvetica, sans-serif;
  font-weight: 700;
  font-size: 19px;
  color: var(--navy-dark);
  font-variant-numeric: tabular-nums;
}
.level-hero-stat .label { font-size: 11px; color: var(--text-muted); margin-top: 2px; }

/* Mock / Practice top-level switch — the report's primary navigation. */
.report-toplevel-tabs {
  display: flex;
  gap: 10px;
  margin-bottom: 22px;
}
.report-toplevel-tab {
  flex: 1;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px 18px;
  font-family: inherit;
  cursor: pointer;
  text-align: left;
}
.report-toplevel-tab .rtt-title { font-size: 14.5px; font-weight: 700; color: var(--navy-dark); display: block; margin-bottom: 2px; }
.report-toplevel-tab .rtt-sub { font-size: 12px; color: var(--text-muted); }
.report-toplevel-tab.active { border-color: var(--teal); background: rgba(15, 123, 138, 0.07); box-shadow: 0 0 0 1px rgba(15, 123, 138, 0.18) inset; }
.report-toplevel-tab.active .rtt-title { color: var(--teal); }
.report-toplevel-panel { display: none; }
.report-toplevel-panel.active { display: block; }

/* Latest / Aggregated sub-switch reuses css/auth.css's .progress-subtab
   pill directly — only the panel show/hide needs a rule here. */
.report-subpanel { display: none; }
.report-subpanel.active { display: block; }

/* Times-table heatmap (Maths) — multiply/divide facts grouped by whichever
   operand is "the table"; 9 × 7 counts toward both table 9 and table 7,
   the same convention as a printed times-table chart. */
.table-heatmap-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
  gap: 10px;
  margin-top: 14px;
}
.table-heatmap-cell {
  border-radius: 10px;
  padding: 12px 10px;
  text-align: center;
  border: 1px solid transparent;
}
.table-heatmap-cell .thc-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; opacity: 0.75; }
.table-heatmap-cell .thc-pct { font-family: 'Poppins', Arial, Helvetica, sans-serif; font-size: 20px; font-weight: 700; margin: 4px 0 2px; }
.table-heatmap-cell .thc-time { font-size: 11px; opacity: 0.8; }
.table-heatmap-cell.thc-strong { background: rgba(15, 123, 138, 0.12); color: var(--teal); }
.table-heatmap-cell.thc-typical { background: rgba(40, 41, 114, 0.07); color: var(--navy-dark); }
.table-heatmap-cell.thc-growth { background: rgba(243, 113, 48, 0.18); color: var(--amber-dark); border-color: rgba(243, 113, 48, 0.4); }
.table-heatmap-note { font-size: 12px; color: var(--text-muted); margin-top: 12px; }
.table-heatmap-legend { display: flex; gap: 16px; margin-top: 10px; font-size: 11.5px; color: var(--text-muted); flex-wrap: wrap; }
.table-heatmap-legend span { display: inline-flex; align-items: center; gap: 5px; }
.table-heatmap-legend .swatch { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }

/* Carrying vs borrowing spotlight (Maths) — splits the existing combined
   "regrouping" concept by operation — two side-by-side cards. */
.regroup-split-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 14px; }
.regroup-card { border-radius: 12px; padding: 16px 18px; }
.regroup-card.rc-ok { background: rgba(15, 123, 138, 0.09); }
.regroup-card.rc-watch { background: rgba(243, 113, 48, 0.13); }
.regroup-card-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 6px; }
.regroup-card-title { font-size: 13.5px; font-weight: 700; color: var(--navy-dark); margin: 0; }
.regroup-card-pct { font-family: 'Poppins', Arial, Helvetica, sans-serif; font-size: 22px; font-weight: 700; }
.rc-ok .regroup-card-pct { color: var(--teal); }
.rc-watch .regroup-card-pct { color: var(--amber-dark); }
.regroup-card-sub { font-size: 12px; color: var(--text-muted); margin: 0 0 10px; }
.regroup-card .word-chip-row { margin-top: 6px; }
.regroup-card .word-chip { background: #fff; }

/* Fact/word-trouble list — sorted by how often something recurs (Maths'
   fluency lapses count, or a recurring-wrong-word tally for Spelling). */
.trouble-fact-list { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.trouble-fact-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: var(--bg-light);
  border-radius: 10px;
  padding: 10px 14px;
}
.trouble-fact-eq { font-family: 'Poppins', Arial, Helvetica, sans-serif; font-weight: 700; font-size: 14px; color: var(--navy-dark); min-width: 0; overflow-wrap: break-word; }
.trouble-fact-meta { font-size: 11.5px; color: var(--text-muted); min-width: 0; }
.trouble-fact-lapses {
  flex-shrink: 0;
  font-size: 11px;
  font-weight: 700;
  color: var(--amber-dark);
  background: rgba(243, 113, 48, 0.16);
  padding: 3px 10px;
  border-radius: 999px;
  white-space: nowrap;
}

/* Fact-mastery funnel (Maths) — Leitner box distribution, boxes 1-6 +
   retired. */
.mastery-funnel { display: flex; align-items: flex-end; gap: 8px; height: 130px; margin-top: 18px; }
.mastery-funnel-col { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; }
.mastery-funnel-bar { width: 100%; border-radius: 6px 6px 0 0; background: var(--navy); min-height: 4px; }
.mastery-funnel-col.mfc-retired .mastery-funnel-bar { background: var(--teal); }
.mastery-funnel-count { font-size: 12.5px; font-weight: 700; color: var(--navy-dark); margin-bottom: 4px; font-variant-numeric: tabular-nums; }
.mastery-funnel-label { font-size: 10.5px; color: var(--text-muted); margin-top: 6px; text-align: center; }

/* Practice session segment breakdown (any subject). */
.segment-row-list { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
.segment-row {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--bg-light);
  border-radius: 10px;
  padding: 10px 14px;
}
.segment-row-name { flex: 0 0 150px; font-size: 13px; font-weight: 600; color: var(--navy-dark); }
.segment-row-track { position: relative; flex: 1; height: 10px; background: rgba(40, 41, 114, 0.08); border-radius: 999px; overflow: hidden; }
.segment-row-fill { height: 100%; background: var(--teal); border-radius: 999px; }
.segment-row-fill.srf-growth { background: var(--amber); }
.segment-row-meta { flex: 0 0 96px; text-align: right; font-size: 12px; color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* Box-move ticker (Maths practice — this session's promotions/demotions). */
.box-move-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.box-move-chip { font-size: 12px; font-weight: 600; padding: 4px 11px; border-radius: 999px; display: inline-flex; align-items: center; gap: 5px; }
.box-move-chip.up { background: rgba(15, 123, 138, 0.12); color: var(--teal); }
.box-move-chip.down { background: rgba(178, 58, 36, 0.10); color: #B23A24; }

@media (max-width: 640px) {
  .level-hero-stats { grid-template-columns: repeat(2, 1fr); }
  .regroup-split-grid { grid-template-columns: 1fr; }
  .report-toplevel-tabs { flex-direction: column; }
}

/* Report tab styling lives in css/auth.css (2026-08-24): the report is
   EMBEDDED in profile.html, which loads style.css and auth.css but not this
   file. Styles here reached the standalone page and nothing else, so the
   tabs rendered as bare browser buttons in the place parents actually see
   them. auth.css is the sheet both pages share. */

/* Skill-block disclosure styles moved to auth.css on 2026-08-25. They lived
   here and this sheet is loaded by report.html but NOT by profile.html - so
   on the page a parent actually opens, the "More about ..." control had been
   rendering as an unstyled default disclosure triangle all along. */

/* ---- "What we found" opens on its promise (2026-08-25) -----------------
   A band carrying only the heading and the one sentence the step rests on.
   The findings sit under it in ordinary cards - a hero wrapped round the
   whole section would have turned several screens of evidence navy, which
   is not emphasis, it is just a lot of dark. */
.report-section.report-found-hero {
  border: 0;
  border-radius: 18px;
  color: #fff;
  background:
    radial-gradient(120% 150% at 100% 0%, rgba(15, 123, 138, 0.45), transparent 60%),
    linear-gradient(135deg, var(--navy) 0%, var(--navy-dark) 100%);
  box-shadow: 0 14px 34px rgba(27, 28, 80, 0.22);
  margin-bottom: 18px;
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}
/* Descendant, not child: attachSectionExplainer() wraps the h2 in a
   .section-head-row at runtime the moment this section gets an "i" button,
   which is what left two other hero headings navy-on-navy. */
.report-found-hero h2 { margin-bottom: 10px; }

/* ---- What we found, on the dark ground (2026-08-25) -------------------

   The .wf-* palette above was written for a light card: #7a4e08 amber on
   pale amber, #0d4f49 teal on pale teal. This section was later promoted
   to a navy hero and the palette came with it unchanged, so the text was
   landing at 1.4:1 to 2.6:1 against the background - AA wants 4.5, and at
   1.4 a sentence is a smudge. Every colour below clears 7:1 at the
   lightest end of the gradient and 8.9 at the darkest.

   THE TWO HERO CARDS ALSO HAD TO DIFFER FROM EACH OTHER. Their colour
   comes from the band - above, around, or below the age benchmark - so a
   child below it in every skill got the strongest and the trickiest in
   the same amber, which is the one comparison the pair exists to draw.
   The role now carries its own edge and label colour; the band keeps the
   score. */
/* INSIDE @media screen, ALL OF IT. This palette is only ever correct on
   the navy ground, and the navy ground only exists on screen - print puts
   the section back on white paper. Scoping it here means print inherits
   the light palette above for free, instead of needing a third copy that
   somebody has to remember to keep in step. That is the bug this replaces:
   the print block reset the section and the heading, and every one of
   these colours carried on regardless. */
@media screen {
  .report-found-hero .wf-hero,
  .report-found-hero .wf-block {
    --wf-tint: rgba(255, 255, 255, 0.08);
    --wf-name: #fff;
    --wf-body: #DDE1F2;
    --wf-track: rgba(255, 255, 255, 0.28);
    --wf-notch: #fff;
    --wf-halo: rgba(27, 28, 80, 0.65);
    --wf-note: #AEB4DA;
    border: 1px solid rgba(255, 255, 255, 0.14);
  }
  /* After the ground border, and one class more specific than it. Both
     ground rules use the `border` shorthand, which resets border-left-width
     and takes the role bracket with it - the edge is the only thing telling
     the best card from the hardest one when both land in the same band. */
  .report-found-hero .wf-hero.is-best,
  .report-found-hero .wf-hero.is-hardest { border-left: 3px solid var(--wf-role); }
  .report-found-hero .wf-strength { --wf-accent: #6FDCE8; }
  .report-found-hero .wf-growth { --wf-accent: #FFB183; }
  .report-found-hero .wf-typical { --wf-accent: #C3C9F0; }
  .report-found-hero .wf-hero.is-best { --wf-role: #6FDCE8; }
  .report-found-hero .wf-hero.is-hardest { --wf-role: #FFB183; }
  .report-found-hero .wf-rest-title { color: #AEB4DA; }
  .report-found-hero h2 { color: #fff; }
  .report-found-hero .report-found-lead { color: rgba(255, 255, 255, 0.9); }
}

/* The score against its benchmark, as a bar rather than two numbers and a
   middot between them. The notch is where the age benchmark sits.

   Three things were wrong here (2026-08-31). The fill was currentColor,
   which is the SECTION's colour, not the band's - so it drew white on the
   navy hero and black on paper, never teal or amber. The notch was #fff
   on a white fill, i.e. invisible in exactly the case the bar exists to
   show, "past the benchmark". And overflow:hidden clipped the overhang
   that was meant to make the notch findable, leaving 6px of white on
   white. Fill is the band colour, notch is haloed, overhang is visible. */
.wf-bar {
  position: relative;
  height: 9px;
  margin: 10px 0 9px;
  border-radius: 999px;
  background: var(--wf-track);
}
.wf-bar i { display: block; height: 100%; border-radius: 999px; background: var(--wf-accent); }
.wf-bar b {
  position: absolute;
  top: -4px;
  bottom: -4px;
  width: 3px;
  border-radius: 2px;
  background: var(--wf-notch);
  box-shadow: 0 0 0 1.5px var(--wf-halo);
  transform: translateX(-1.5px);
}
.wf-bar-note { font-size: 11px; margin: 0 0 8px; color: var(--wf-note); }
@media screen {
  .report-found-hero .metric-info-btn,
  .report-found-hero .section-info-btn {
    color: rgba(255, 255, 255, 0.8);
    border-color: rgba(255, 255, 255, 0.4);
  }
}
/* Not bolded. It was <strong> inside a takeaway box, which is how you shout
   a sentence nobody was going to skip anyway - at hero size it carries on
   its own. */
.report-found-lead {
  margin: 0;
  font-size: 16.5px;
  line-height: 1.6;
  color: var(--text-dark);
  max-width: 62ch;
}
@media (max-width: 640px) {
  .report-found-lead { font-size: 15px; }
}
/* Only the section's own chrome needs saying here now. Everything inside
   it already reads on paper, because the dark palette above never leaves
   @media screen. */
@media print {
  .report-section.report-found-hero {
    color: var(--text-dark);
    background: #fff;
    border: 1px solid var(--border);
    box-shadow: none;
  }
  .report-found-hero h2 { color: var(--navy-dark); }
  .report-found-hero .wf-hero,
  .report-found-hero .wf-block { border: 1px solid var(--border); }
  /* After the ground border, and one class more specific than it. Both
     ground rules use the `border` shorthand, which resets border-left-width
     and takes the role bracket with it - the edge is the only thing telling
     the best card from the hardest one when both land in the same band. */
  .report-found-hero .wf-hero.is-best,
  .report-found-hero .wf-hero.is-hardest { border-left: 3px solid var(--wf-role); }
}

/* ---- Personal bests, the hero of "Progress & charts" (2026-08-25) ------
   It opens that step, and a child's best-ever results are the one place in
   this report where celebrating is the correct tone. Navy ground so it
   carries weight; the tiles go WHITE rather than staying tinted, because a
   teal tint on navy is two dark colours arguing - the same mistake the
   first Level history attempt made. White tiles with teal numerals is the
   strongest contrast available in this palette, which is what a personal
   best deserves. */
.report-section.report-bests-hero {
  border: 0;
  border-radius: 18px;
  color: #fff;
  background:
    radial-gradient(120% 150% at 100% 0%, rgba(15, 123, 138, 0.45), transparent 60%),
    linear-gradient(135deg, var(--navy) 0%, var(--navy-dark) 100%);
  box-shadow: 0 14px 34px rgba(27, 28, 80, 0.22);
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}
/* Descendant, not "> h2": attachSectionExplainer() wraps the heading in a
   .section-head-row at runtime once this section gets an "i" button. */
.report-bests-hero h2 { color: #fff; }
.report-bests-hero > .section-sub { color: rgba(255, 255, 255, 0.78); }
.report-bests-hero .metric-info-btn,
.report-bests-hero .section-info-btn {
  color: rgba(255, 255, 255, 0.8);
  border-color: rgba(255, 255, 255, 0.4);
}
.report-bests-hero .stat-row { margin-bottom: 0; margin-top: 18px; }
.report-bests-hero .stat-tile {
  background: #fff;
  border-color: transparent;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.14);
}
.report-bests-hero .stat-tile .num { color: var(--teal); }
.report-bests-hero .stat-tile .label { color: var(--text-muted); }
/* The tile's own "i" sits on the white tile, not on the navy - it keeps the
   normal treatment rather than inheriting the hero's light one. */
.report-bests-hero .stat-tile .metric-info-btn {
  color: var(--teal);
  border-color: rgba(15, 123, 138, 0.4);
}
@media print {
  .report-section.report-bests-hero {
    color: var(--text-dark);
    background: #fff;
    border: 1px solid var(--border);
    box-shadow: none;
  }
  .report-bests-hero h2 { color: var(--navy-dark); }
  .report-bests-hero > .section-sub { color: var(--text-muted); }
  .report-bests-hero .stat-tile { box-shadow: none; border-color: rgba(15, 123, 138, 0.18); }
}

/* The level-history rail and the aggregated-comparison styles moved to
   auth.css on 2026-08-26. They lived here, and report.css is loaded by
   report.html but NOT by profile.html - so the portal's own "Aggregated mock
   tests" section, which is where a parent actually reaches these, had none of
   them at all. auth.css is the sheet both pages share. */

/* ---- The downloaded PDF is one test, not a history (2026-08-25) --------
   On screen the report earns its comparisons: a parent is exploring, and
   "how does this sit against last time" is half of what they came for. The
   PDF is a different object - a record of one sitting, filed away or handed
   to a teacher and read months later, by which point "last time" means
   something else entirely. Every cross-attempt section is dropped from it.

   Tagged where each section is BUILT rather than listed by selector here:
   the stepper moves these blocks by heading, so any list of positions would
   be wrong the first time a heading changed. */
@media print {
  .report-cross-test { display: none !important; }

  /* SPACING. Print was inheriting the on-screen stepper's layout - panels
     carrying their own margins, section padding sized for a scrolling page,
     and, once the cross-test sections are dropped, step panels holding
     nothing but their own margins. That is where the long blank runs came
     from. */
  .report-tabpanels,
  .report-tabpanel,
  .agg-group,
  .agg-panel {
    display: block !important;
    margin: 0 !important;
    padding: 0 !important;
  }
  .report-tabpanel > *,
  .agg-panel > * { margin-top: 0; }
  .report-section:last-child { margin-bottom: 0; }

  /* THE WHOLE STEPPER GOES. Every panel is revealed for print, so the label
     reading "STEP 1 OF 7 - Quick summary" sits at the top of a document that
     contains all seven - it names one step while the pages below ignore it,
     which is worse than no label at all. The dots, the hint and the Back and
     Next buttons are controls nobody can press on paper. Each section keeps
     its own heading, which is what actually orients a reader here. */
  .report-stepper { display: none !important; }
  .report-stepnav { display: none !important; }
}

/* ---- The printed page itself (2026-08-25) -----------------------------
   There was no @page rule at all, so every PDF used Chrome's defaults and
   the content sat tighter to the edge than anything else we control. A4
   with real margins, and a little more at the foot because that is where
   Chrome puts its own footer when the user leaves headers on. */
@page {
  size: A4;
  /* 17mm at the sides, not 14. The content measurably fits either way -
     nothing overflows the printable box - but a printer's own unprintable
     border, a dialog left on Scale: Custom, or a Letter/A4 mismatch all eat
     into the edge before the page ever gets a say. Three extra millimetres
     of slack costs a few words per page and removes the whole class of
     complaint. */
  margin: 15mm 17mm 17mm;
}

/* SURVIVES "BACKGROUND GRAPHICS" BEING OFF, which is Chrome's default and
   the single most common reason a print looks broken. Anything that says
   something with a coloured fill and white text on it disappears entirely
   when that box is unticked - white on white. These two carried the words
   "Veechi is here", which is the one label on the whole scale a parent
   needs, so they are rebuilt as dark text in an outlined pill: readable
   with backgrounds on OR off, and still obviously the marker. */
@media print {
  .clevel-step-here,
  .csr-here {
    background: transparent !important;
    color: var(--navy-dark) !important;
    border: 1.5px solid var(--teal);
    font-weight: 700;
  }
}

@media print {
  /* Belt and braces: no element may paint into the last 2mm of the content
     box, so a slight misregistration trims whitespace rather than a digit. */
  #report-app { padding-right: 2mm; }
}



/* ---- General Knowledge: the sections it gained in the 2026-08-27 pass ----
   Coverage history is a bar per sitting rather than a line, for the reason
   given above gkCoverageHistoryHtml: three points cannot carry a trajectory,
   and a line would draw one anyway. */
/* THE COVERAGE SCALE (2026-08-27). Same four-across ladder the Overview
   uses for levels, with one difference that matters: the current step is a
   SOLID fill, not a tint. A translucent tint over the card background came
   out at 3.83:1 behind its own label, which is a fail for body text - and a
   step that says "your child is here" is exactly the one that has to be
   readable. Navy on solid #4E9EA8 measures 5.9:1. */
.gkr-scale { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-top: 4px; }
.gkr-scale-step {
  display: flex; flex-direction: column; gap: 4px;
  padding: 12px 12px 13px; border-radius: 12px;
  background: var(--surface-alt, #F4F5FA); border: 1px solid var(--border, #E4E4EC);
}
.gkr-scale-step.is-current { background: #4E9EA8; border-color: #0F7B8A; }
.gkr-scale-range { font-size: 11.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--text-muted); }
.gkr-scale-name { font-family: 'Poppins', sans-serif; font-size: 14px; font-weight: 600; color: var(--navy, #1B1C50); line-height: 1.3; }
.gkr-scale-what { font-size: 12.5px; line-height: 1.45; color: var(--text-muted); }
.gkr-scale-step.is-current .gkr-scale-range,
.gkr-scale-step.is-current .gkr-scale-what { color: #10303A; }
.gkr-scale-you {
  margin-top: 2px; align-self: flex-start; padding: 2px 8px; border-radius: 999px;
  background: #10303A; color: #fff; font-size: 11.5px; font-weight: 600;
}
@media (max-width: 780px) { .gkr-scale { grid-template-columns: 1fr 1fr; } }
@media (max-width: 460px) { .gkr-scale { grid-template-columns: 1fr; } }

.gkr-hist { display: flex; flex-direction: column; gap: 9px; }
.gkr-hist-row { display: flex; align-items: center; gap: 12px; }
.gkr-hist-when { flex: 0 0 62px; font-size: 12.5px; color: var(--text-muted); }
.gkr-hist-bar { flex: 1; height: 12px; border-radius: 6px; background: var(--bg-light); overflow: hidden; }
.gkr-hist-bar > span { display: block; height: 100%; background: rgba(15, 123, 138, 0.45); }
.gkr-hist-pct {
  flex: 0 0 46px;
  text-align: right;
  font-family: 'Poppins', sans-serif;
  font-weight: 700;
  font-size: 13.5px;
  color: var(--navy-dark);
  font-variant-numeric: tabular-nums;
}
/* The sitting being read is the solid one; the rest are its context. */
.gkr-hist-row.is-current .gkr-hist-bar > span { background: var(--teal); }
.gkr-hist-row.is-current .gkr-hist-when { color: var(--navy-dark); font-weight: 600; }

.gkr-num { text-align: right; font-variant-numeric: tabular-nums; }
.gkr-delta { font-weight: 700; font-size: 12.5px; border-radius: 999px; padding: 2px 9px; }
.gkr-delta-up { color: #0A5C68; background: rgba(15, 123, 138, 0.12); }
.gkr-delta-down { color: var(--amber-dark); background: rgba(184, 76, 24, 0.12); }
.gkr-delta-flat { color: var(--text-muted); background: var(--bg-light); }

/* ---- The child's result card (2026-08-27) --------------------------------- */
.cres { max-width: 620px; margin: 22px auto 0; }
.cres-card {
  background: #fff; border: 1px solid var(--border, #E4E4EC); border-radius: 20px;
  padding: 32px 30px 28px; text-align: center;
  box-shadow: 0 16px 40px rgba(27, 28, 80, 0.08);
}
.cres-eyebrow {
  margin: 0; font-size: 12px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--teal, #0F7B8A);
}
.cres-title {
  margin: 6px 0 2px; font-family: 'Poppins', sans-serif;
  font-size: 26px; font-weight: 700; color: var(--navy, #1B1C50);
}
.cres-sub { margin: 0 0 20px; font-size: 14.5px; color: var(--text-muted, #5F5F75); }
.cres-counts { display: flex; gap: 12px; justify-content: center; margin-bottom: 22px; }
.cres-count { flex: 1 1 0; max-width: 170px; padding: 15px 10px 13px; border-radius: 14px; border: 1px solid var(--border, #E4E4EC); }
.cres-count .n { display: block; font-family: 'Poppins', sans-serif; font-size: 29px; font-weight: 700; line-height: 1.1; color: var(--navy, #1B1C50); }
.cres-count .l { display: block; margin-top: 3px; font-size: 12.5px; font-weight: 600; color: var(--text-muted, #5F5F75); }
/* Incorrect is slate, never red. Red is a teacher's mark on a page, and this
   screen is read by a nine-year-old sitting on their own. */
.cres-count.is-right { background: #EAF7F9; border-color: #9BD3DA; }
.cres-count.is-wrong { background: #F4F5FA; }
.cres-count.is-missed { background: #FFF7F0; border-color: #F2D3B6; }
.cres-level { padding: 19px 18px 17px; border-radius: 16px; background: #F7F7FB; margin-bottom: 20px; }
.cres-level-label { margin: 0 0 10px; font-size: 12px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--text-muted, #5F5F75); }
.cres-ladder { display: flex; gap: 7px; justify-content: center; margin-bottom: 10px; }
.cres-step { width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center; font-family: 'Poppins', sans-serif; font-weight: 700; font-size: 15px; background: #fff; border: 1px solid var(--border, #E4E4EC); color: #A9A9BC; }
.cres-step.is-done { background: #D8F0F3; border-color: #9BD3DA; color: #0B5A66; }
.cres-step.is-here { background: var(--teal, #0F7B8A); border-color: var(--teal, #0F7B8A); color: #fff; }
.cres-level-name { margin: 0; font-family: 'Poppins', sans-serif; font-size: 17px; font-weight: 700; color: var(--navy, #1B1C50); }
/* GK has no ladder on purpose - it reports how much of the syllabus has
   stuck, and inventing a rank for symmetry is the false precision that
   module refuses everywhere else. */
.cres-cov-num { font-family: 'Poppins', sans-serif; font-size: 40px; font-weight: 700; color: var(--navy, #1B1C50); line-height: 1; }
.cres-cov-bar { height: 10px; border-radius: 999px; background: #E4E4EC; overflow: hidden; margin: 12px auto 10px; max-width: 320px; }
.cres-cov-bar i { display: block; height: 100%; border-radius: 999px; background: var(--teal, #0F7B8A); }
.cres-msg {
  margin: 0 0 22px; padding: 15px 18px; border-radius: 14px;
  background: linear-gradient(135deg, #FFF4EC 0%, #FFEADC 100%);
  border: 1px solid #F2D3B6; font-size: 14.5px; line-height: 1.55; color: #7A3B0E;
}
.cres-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.cres-actions .btn { min-width: 150px; }
@media (max-width: 520px) {
  .cres-counts { flex-direction: column; }
  .cres-count { max-width: none; }
  .cres-actions .btn { width: 100%; }
}

/* The download button after a failed render. Not an error colour - the
   report is fine, only the PDF service was unreachable, and printing is
   still a perfectly good way to get one. */
.btn.is-fallback { border-color: var(--amber-dark, #B84C18); color: var(--amber-dark, #B84C18); }

/* The download confirmation. A browser cannot tell a page where it saved a
   file - there is no API for it - so this names the file and the Downloads
   folder rather than pretending to a path it cannot see. */
.download-toast {
  position: fixed; left: 50%; bottom: 26px; transform: translate(-50%, 16px);
  display: flex; align-items: flex-start; gap: 12px;
  max-width: min(460px, calc(100vw - 32px));
  padding: 14px 18px; border-radius: 14px;
  background: #10303A; color: #fff;
  font-size: 14px; line-height: 1.45;
  box-shadow: 0 14px 40px rgba(16, 48, 58, 0.34);
  opacity: 0; pointer-events: none; z-index: 1300;
  transition: opacity .18s ease, transform .18s ease;
}
.download-toast.is-up { opacity: 1; transform: translate(-50%, 0); }
.download-toast-tick {
  flex: 0 0 22px; width: 22px; height: 22px; border-radius: 50%;
  background: #7EE0E2; color: #10303A;
  display: grid; place-items: center; font-size: 13px; font-weight: 700;
}
.download-toast-file { color: #B8E9EC; word-break: break-all; }
@media (prefers-reduced-motion: reduce) { .download-toast { transition: none; } }

/* A quiet statement of fact, not a warning - a test taken over three
   evenings is a perfectly good test, the parent just needs to know when
   they are comparing it with one done in a single run. Deliberately not
   the amber .exam-early-banner treatment. */
.attempt-sittings-note {
  margin: 0 0 14px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-muted);
}
