/* Zonnekring theme — warm paper/clay design system (RU primary / NL secondary). */
:root {
  --masthead-h: 68px; /* measured at runtime; keeps the sticky rail clear of the header */
  --paper: #F5F7FA;
  --card: #FFFFFF;
  --ink: #16233A;
  --muted: #5C6B82;
  --faint: #8B97A8;
  --clay: #C9714B;
  --clay-deep: #A9552F;
  --clay-soft: #F8ECE5;
  /* A whole-row tint for the roster. --clay-soft is an accent for small badges
     and focus rings; behind every flagged row it reads as a block of colour, so
     the roster gets its own, paler wash. */
  --flag-soft: #FDF5F0;
  --green: #1E8E5A;
  --green-soft: #E7F4EE;
  --line: #E4E9F0;
  --navy: #24466E;
  --amber: #C99A2E;
  --red: #C2352B;
  --red-soft: #FCF0EF;
  --mono: "IBM Plex Mono", ui-monospace, monospace;
  --body: "Inter", system-ui, sans-serif;
  --display: "Sora", var(--body);
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 13px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
/* Any author `display` rule (.grid, .field.two, .lrow …) outranks the UA
   [hidden] rule, so element.hidden alone would not hide those nodes. */
[hidden] { display: none !important; }

/* Honeypot. Deliberately NOT display:none or [hidden] — a bot that respects
   those would skip the field and defeat the trap. It stays in the layout,
   pushed off-screen, out of the tab order and hidden from screen readers. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.wrap { max-width: 1180px; margin: 0 auto; padding: 0 22px 40px; }
.muted { color: var(--muted); }
.right { text-align: right; }
.mono { font-family: var(--mono); font-size: 11px; }

/* ---------- header ---------- */
/* The masthead stays on top while the page scrolls; --masthead-h is measured
   at runtime (src/views/layout.js) so the sticky rail can clear it. */
.masthead {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 14px 0 12px; border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
  position: sticky; top: 0; z-index: 30; background: var(--paper);
}
.brand { display: flex; align-items: center; gap: 10px; min-width: 0; }
.brand img { width: 40px; height: 40px; display: block; flex: none; }
.brand .who { line-height: 1.2; }
.brand .who strong { font-family: var(--display); font-size: 16px; }
.brand .who span { display: block; color: var(--muted); font-size: 11px; }
.mast-meta { display: flex; gap: 7px; flex-wrap: wrap; align-items: center; }
.chip {
  font-size: 11px; color: var(--muted); background: var(--card);
  border: 1px solid var(--line); border-radius: 999px; padding: 4px 11px;
  white-space: nowrap; text-decoration: none;
}
.chip b { color: var(--ink); font-weight: 600; }

.strap { padding: 14px 0 0; }
.strap h1 { font-family: var(--display); font-weight: 700; margin: 0; font-size: 20px; letter-spacing: -.01em; }
.strap h1 .for { color: var(--clay); }
.strap p { margin: 4px 0 0; color: var(--muted); font-size: 12px; }

/* ---------- layout ---------- */
.grid { display: grid; gap: 14px; margin-top: 14px; align-items: start; }
.form-grid { grid-template-columns: minmax(0, 1fr) 368px; }
.admin-grid { grid-template-columns: 340px minmax(0, 1fr); }
@media (max-width: 980px) {
  .form-grid, .admin-grid { grid-template-columns: 1fr; }
  .rail { position: static !important; }
}
.maincol { display: flex; flex-direction: column; gap: 14px; min-width: 0; }

.panel {
  background: var(--card); border: 1px solid var(--line);
  border-radius: 14px; padding: 14px 17px 15px; min-width: 0;
}
.colhead { display: flex; align-items: center; gap: 9px; margin-bottom: 11px; padding-bottom: 9px; border-bottom: 1px solid var(--line); }
.colhead .no {
  font-family: var(--mono); font-size: 10px; color: var(--clay-deep);
  border: 1px solid var(--clay); border-radius: 6px; padding: 2px 6px; background: var(--clay-soft);
}
.colhead h2 { font-family: var(--display); font-size: 14.5px; margin: 0; letter-spacing: -.01em; }
.colhead .art { font-family: var(--mono); font-size: 9.5px; color: var(--faint); margin-left: auto; }

.subhead {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--faint); font-weight: 500; margin: 12px 0 5px; padding-top: 10px; border-top: 1px solid var(--line);
  display: flex; justify-content: space-between;
}

.nl { color: var(--muted); font-weight: 500; font-size: .93em; }
.nl-inline { font-weight: 500; opacity: .85; }
.req { color: var(--clay-deep); font-weight: 700; }
.hint { color: var(--faint); font-size: 10.5px; font-weight: 400; }

/* ---------- fields ---------- */
.field { margin-bottom: 11px; }
.field.two { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
@media (max-width: 560px) { .field.two { grid-template-columns: 1fr; } }
/* Field captions carry .flabel. Never style bare `.field label`: that selector
   (0,1,1) outranks the component classes .plan / .chk (0,1,0) and forced their
   labels back to display:block, which collapsed the plan tick and un-aligned
   the price column. Any new label inside .field styles itself. */
.flabel { display: block; font-weight: 600; font-size: 11.5px; margin-bottom: 4px; }
.eyebrow-lbl { font-family: var(--mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase; color: var(--clay-deep); }
input[type=text], input[type=email], input[type=tel], input[type=date], input[type=number], select, textarea {
  width: 100%; border: 1.5px solid var(--line); border-radius: 9px; padding: 8px 11px;
  font: inherit; color: var(--ink); background: #fff;
}
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: none; border-color: var(--clay); box-shadow: 0 0 0 3px var(--clay-soft);
}
textarea { resize: vertical; }
.invalid { border-color: var(--red) !important; box-shadow: 0 0 0 3px var(--red-soft) !important; }

/* A field the parent still has to fill in: the label turns red and the whole
   block is marked, so radio/checkbox groups (which have no border of their own)
   are as obvious as a text input. Set on submit, cleared as soon as it is fixed. */
.missing > .flabel, .missing .flabel { color: var(--red); }
.missing > .flabel .req, .missing .flabel .req { color: var(--red); }
.missing .flabel .hint { color: var(--faint); }
.missing .flabel .subj-counter { color: inherit; }
.chkgroup.missing { border-color: var(--red); box-shadow: 0 0 0 3px var(--red-soft); }
.chk.consent.missing { border-color: var(--red); box-shadow: 0 0 0 3px var(--red-soft); }
.field.missing .plan { border-color: #e5b3ae; }
.errlist { margin: 6px 0 0; padding-left: 18px; }
.errlist li { margin: 2px 0; }

/* ---------- checkbox / radio rows ---------- */
.chk { display: flex; gap: 9px; align-items: flex-start; padding: 5px 0; font-size: 12px; cursor: pointer; }
.chk input { margin-top: 2px; accent-color: var(--clay); width: 15px; height: 15px; flex: none; }
.chk.consent { border: 1.5px solid var(--line); border-radius: 10px; padding: 10px 12px; margin-top: 8px; }
.chk.consent:hover { border-color: #cdb6a8; }
.chkgroup { border: 1.5px solid var(--line); border-radius: 10px; padding: 4px 12px; }
.chkgroup.invalid { border-color: var(--red); }

/* ---------- subjects gating (count = lessons per week) ---------- */
/* Inactive until a lessons option is chosen; boxes over the limit gray out. */
.chkgroup.inactive { background: var(--paper); }
.chk.disabled { opacity: .5; color: var(--muted); cursor: not-allowed; }
.chk input:disabled { cursor: not-allowed; }
.subj-counter {
  font-family: var(--mono); font-size: 10px; font-weight: 500; white-space: nowrap;
  color: var(--clay-deep); background: var(--clay-soft);
  border: 1px solid var(--clay); border-radius: 999px; padding: 1px 8px; margin-left: 5px;
}
.subj-counter.done { color: #17603E; background: var(--green-soft); border-color: #CBE7D9; }

/* ---------- plan rows (lessons per week) ---------- */
.plan {
  position: relative; cursor: pointer; border: 1.5px solid var(--line);
  border-radius: 10px; background: var(--card); padding: 9px 12px;
  display: flex; align-items: center; gap: 10px;
  transition: border-color .15s, box-shadow .15s; margin-bottom: 8px;
}
.plan:hover { border-color: #cdb6a8; }
.plan.sel { border-color: var(--clay); box-shadow: 0 0 0 3px var(--clay-soft); }
.plan input { position: absolute; opacity: 0; pointer-events: none; }
.plan .tick {
  width: 16px; height: 16px; flex: none;
  border-radius: 50%; border: 1.5px solid var(--line); background: #fff;
}
.plan.sel .tick { border-color: var(--clay); background: var(--clay); box-shadow: inset 0 0 0 3.5px #fff; }
/* The radio itself is opacity:0, so focus has to show on the drawn .tick. */
.plan input:focus-visible + .tick { outline: 2px solid var(--navy); outline-offset: 2px; }
.plan .pbody { flex: 1; min-width: 0; }
.plan h3 { font-family: var(--display); font-size: 12.5px; margin: 0; }
.plan .tag { font-size: 10.5px; color: var(--muted); }
.plan .pprice { text-align: right; flex: none; }
.plan .pprice .now { font-family: var(--mono); font-size: 13px; font-weight: 600; }

/* ---------- child cards ---------- */
.childcard {
  border: 1.5px solid var(--line); border-radius: 12px;
  padding: 12px 14px; margin-bottom: 12px; background: #FDFCFB;
}
.childcard .colhead { margin-bottom: 9px; }
.mini-remove {
  margin-left: auto; border: 1px solid var(--line); background: var(--card); border-radius: 8px;
  width: 26px; height: 26px; cursor: pointer; font-size: 12px; color: var(--muted);
}
.mini-remove:hover { background: var(--red-soft); color: var(--red); border-color: var(--red); }

/* ---------- buttons ---------- */
.btn {
  font-family: var(--body); font-size: 12.5px; font-weight: 600; cursor: pointer;
  border-radius: 999px; padding: 8px 16px; border: 1px solid var(--clay);
  background: var(--clay); color: #fff;
}
.btn:hover { background: var(--clay-deep); }
.btn:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.btn.ghost { background: var(--card); color: var(--clay-deep); }
.btn.ghost:hover { background: var(--clay-soft); }
.btn.small { padding: 4px 10px; font-size: 11px; }
.btn.big { width: 100%; padding: 12px 16px; font-size: 14px; margin-top: 12px; }
.btn.danger { border-color: var(--red); color: var(--red); }
.btn.danger:hover { background: var(--red-soft); }
.btn:disabled { opacity: .55; cursor: wait; }

/* ---------- notice boxes ---------- */
.included {
  display: flex; gap: 7px; align-items: flex-start;
  background: var(--green-soft); border: 1px solid #CBE7D9; border-radius: 8px;
  padding: 7px 10px; margin-bottom: 6px; font-size: 11px; color: #17603E; line-height: 1.4;
}
.included .mark { font-weight: 700; }
.errbox {
  background: var(--red-soft); border: 1px solid #F0CFCA; color: var(--red);
  border-radius: 8px; padding: 8px 12px; font-size: 12px; margin-top: 10px;
}

/* ---------- invoice rail ---------- */
.rail { position: sticky; top: calc(var(--masthead-h) + 10px); }
.invoice { background: var(--card); border: 1px solid var(--line); border-radius: 14px; overflow: hidden; box-shadow: 0 10px 30px -18px rgba(22,35,58,.25); }
.inv-head { padding: 12px 15px 10px; background: linear-gradient(180deg, #FDFBFA, #fff); border-bottom: 1px solid var(--line); }
.eyebrow {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--faint);
}
.permin { display: flex; align-items: baseline; gap: 7px; margin-top: 2px; }
.permin .val { font-family: var(--display); font-weight: 700; font-size: 27px; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.pmsplit { font-size: 11px; color: var(--muted); margin-top: 3px; }
.pmsplit b { font-family: var(--mono); font-weight: 600; color: var(--ink); }

.ledger { padding: 4px 15px 8px; }
.ledger h4 { font-family: var(--mono); font-size: 9.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--faint); margin: 8px 0 2px; font-weight: 500; }
.lrow { display: grid; grid-template-columns: minmax(0,1fr) auto auto; gap: 2px 8px; padding: 3.5px 0; border-top: 1px dashed #EDF0F4; font-size: 11.5px; align-items: baseline; }
.lrow:first-of-type { border-top: 0; }
.lrow .lbl { color: var(--ink); }
.lrow .sub { grid-column: 1 / -1; color: var(--faint); font-size: 10px; margin-top: -2px; }
/* the child's own name, sitting under the "Child N" line */
.lrow .sub.kidname { color: var(--ink); font-size: 11px; font-weight: 600; overflow-wrap: anywhere; }
.lrow .eur { font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }
.lrow .pm { color: var(--faint); font-size: 10px; }
.lrow.red .lbl, .lrow.red .eur { color: var(--red); font-style: italic; }
.lrow.green .lbl, .lrow.green .eur { color: var(--green); }
.totals { border-top: 2px solid var(--ink); margin-top: 4px; padding: 5px 0 2px; }
.totals .lrow { border-top: 0; font-weight: 600; font-size: 12px; }
.totals .lrow .eur { font-size: 12.5px; }
.vatnote { padding: 7px 15px 10px; font-size: 9.5px; color: var(--faint); line-height: 1.45; border-top: 1px solid var(--line); }

/* ---------- success / notice pages ---------- */
.center-card { display: flex; justify-content: center; padding: 44px 0; }
.center-card .notice { max-width: 520px; text-align: center; padding: 28px 30px; }
.bigsun { font-size: 40px; margin-bottom: 6px; }
.notice h1 { font-family: var(--display); font-size: 19px; margin: 0 0 6px; }
.notice .nl-h { font-family: var(--display); font-size: 15px; color: var(--muted); margin: 0 0 4px; }
.notice p { color: var(--ink); font-size: 12.5px; }
hr.soft { border: 0; border-top: 1px solid var(--line); margin: 14px 0; }

.success-panel { max-width: 640px; margin: 20px auto; }
.success-panel .paybox {
  background: var(--clay-soft); border: 1px solid #EAD3C6; border-radius: 10px;
  padding: 10px 14px; margin-top: 10px; font-size: 12.5px;
}
.success-panel .paybox .mono { font-size: 12px; }

/* ---------- success summary (everything that was stored) ---------- */
.summary { margin: 12px 0 4px; }
.sumtitle {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--faint); font-weight: 500; margin: 0 0 8px;
}
.sumsec > h4 { font-size: 12.5px; margin: 0 0 6px; }
/* Label column tracks the longest label but never eats the value column;
   `minmax(0,1fr)` lets a long address wrap instead of widening the grid. */
.sumgrid {
  display: grid; grid-template-columns: minmax(110px, 33%) minmax(0, 1fr);
  gap: 3px 12px; margin: 0 0 10px;
}
.sumgrid dt {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--faint); align-self: baseline;
}
/* Health notes come from textareas — keep the parent's own line breaks, and
   let a long e-mail or address break rather than push the panel sideways. */
.sumgrid dd { margin: 0; font-size: 12.5px; white-space: pre-line; overflow-wrap: anywhere; }
.sumkid { border-top: 1px solid var(--line); padding-top: 10px; margin-top: 10px; }
/* Deliberately NOT .colhead: that component is a full-bleed panel-top bar with
   negative margins and rounded top corners, which reads as broken mid-panel. */
.sumhead { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.sumhead h4 { font-family: var(--display); font-size: 13.5px; margin: 0; }
.sumhead .kidno {
  font-family: var(--mono); font-size: 10px; font-weight: 600; color: var(--faint);
  border: 1px solid var(--line); border-radius: 999px;
  min-width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center;
}
.kidprice {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  font-size: 12px; padding-top: 2px;
}
.kidprice .lbl { color: var(--faint); }
.kidprice .cut { color: var(--red); }
.kidprice .eur { margin-left: auto; font-size: 13.5px; }

@media (max-width: 520px) {
  /* One column: a 110px label beside a value leaves too little room to read. */
  .sumgrid { grid-template-columns: minmax(0, 1fr); gap: 1px 0; }
  .sumgrid dd { margin-bottom: 6px; }
}

/* ---------- admin ---------- */
.adminnav { display: flex; gap: 8px; margin-top: 14px; flex-wrap: wrap; }
.navchip.on { border-color: var(--clay); color: var(--clay-deep); background: var(--clay-soft); font-weight: 600; }
.navchip.dl { color: var(--green); border-color: #CBE7D9; }
.navchip:hover { border-color: var(--clay); }
/* Sign out is a POST, so it needs a form — but the form must not become a
   second layout box inside the flex nav. `display:contents` puts the button
   itself in the flex flow, so it lines up with the <a> chips beside it. */
.navform { display: contents; }
/* A <button> does not inherit the page font the way an <a> does. */
.navform .navchip { font: inherit; font-size: 11px; cursor: pointer; margin-left: auto; }
.adminnav + .panel, .adminnav + .included, .adminnav + .errbox, .adminnav + .grid { margin-top: 12px; }

.tablewrap { overflow-x: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: 12px; }
.data th {
  text-align: left; font-family: var(--mono); font-size: 9px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--faint); font-weight: 500;
  padding: 6px 8px; border-bottom: 1px solid var(--line); white-space: nowrap;
}
.data td { padding: 8px; border-top: 1px solid #EEF1F5; vertical-align: top; }
.data tr:first-child td { border-top: 0; }

.badge { font-family: var(--mono); font-size: 10px; border-radius: 6px; padding: 2px 7px; white-space: nowrap; }
.badge.ok { background: var(--green-soft); color: #17603E; border: 1px solid #CBE7D9; }
.badge.warn { background: #FBF3E1; color: #8A6A1B; border: 1px solid #EBD9AC; }
.badge.bad { background: var(--red-soft); color: var(--red); border: 1px solid #F0CFCA; }

.linkline { display: flex; gap: 6px; align-items: center; }
.linkinput {
  font-family: var(--mono); font-size: 10.5px; color: var(--muted);
  border: 1px solid var(--line); border-radius: 7px; padding: 4px 8px; min-width: 210px; background: var(--paper);
}

/* ---------- registration edit ---------- */
/* The row's "Edit" and the screen's "Cancel" are links, not buttons. .btn is
   written for a <button>, so an <a> wearing it still carries the UA underline
   and an inline box the padding leaks out of. */
a.btn { display: inline-block; text-decoration: none; }
/* .panel carries no margin of its own — everywhere else it is the only card or
   sits in a gapped grid. The edit screen stacks three, like .rostergroup. */
.editpanel { margin-top: 14px; }
/* Save, Cancel and the "prices are recalculated" line read as one row: the
   note belongs beside the button it explains, not under it. */
.editactions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-top: 14px; }

/* ---------- school-day roster ---------- */
/* Screen rules only. The sheet this page exists for is built in the @media
   print block at the foot of this file. */

/* .panel carries no margin of its own — on every other screen it is the only
   card, or it sits in a gapped grid. Here the group panels stack. */
.rostergroup { margin-top: 14px; }
.rostersummary .chiprow { display: flex; flex-wrap: wrap; gap: 6px; margin: 2px 0 10px; }
/* the headcount, not the class name, is what staff read off this row */
.chiprow .chip b { font-family: var(--mono); font-variant-numeric: tabular-nums; margin-left: 2px; }
.rostersummary p.hint { margin: 0 0 10px; }

/* The group name repeated inside <thead> so it travels with the header onto
   every printed page. On screen the panel .colhead directly above already names
   the class, so showing it here would read as the same heading twice. */
.roster tr.grouphead { display: none; }

/* Seven columns of prose do not fit a narrow screen. Percentages so the table
   still fills a wide one; min-width so the narrow case goes to .tablewrap's
   horizontal scroll instead of squeezing every note column to one word wide.
   The widths hang off thead's LAST row: the first row is now .grouphead, one
   cell spanning all seven, and nth-child there would size the wrong thing. */
table.data.roster { min-width: 880px; }
.roster th { white-space: normal; }
/* Nothing here is an unbreakable token, so a long note wraps instead of forcing
   its column wider than the share below. This is what keeps the percentages
   honest under the browser's automatic table layout. */
.roster th, .roster td { overflow-wrap: anywhere; }
.roster thead tr:last-child th:nth-child(1) { width: 17%; }  /* child + date of birth */
.roster thead tr:last-child th:nth-child(2) { width: 15%; }  /* allergies */
.roster thead tr:last-child th:nth-child(3) { width: 15%; }  /* medical */
.roster thead tr:last-child th:nth-child(4) { width: 14%; }  /* medication */
.roster thead tr:last-child th:nth-child(5) { width: 16%; }  /* parent + phone */
.roster thead tr:last-child th:nth-child(6) { width: 14%; }  /* emergency contact */
.roster thead tr:last-child th:nth-child(7) { width: 9%; }   /* reg. no. + payment */

/* An empty note is an em dash, and it stays at --muted rather than the lighter
   --faint: a mark you can barely see reads as "nobody checked this", which is
   the one thing an allergy column must never say. */
.roster .muted { color: var(--muted); }

/* A child with an allergy, a medical note or medication.
   This is printed in black and white, so colour is the LAST of three cues:
   a bar down the left edge, a glyph before the name, and the three note
   columns set in bold. Any one of them alone identifies the row. */
.roster td:first-child { border-left: 3px solid transparent; }
.roster tr.flagged { background: var(--flag-soft); }
.roster tr.flagged td:first-child { border-left-color: var(--clay); }
.roster tr.flagged td:first-child::before {
  content: "\26A0\FE0E"; /* U+FE0E forces text presentation — never a colour emoji */
  color: var(--clay-deep); font-weight: 700; margin-right: 4px;
}
.roster tr.flagged td:nth-child(2),
.roster tr.flagged td:nth-child(3),
.roster tr.flagged td:nth-child(4) { font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
  .plan { transition: none; }
}
/* ---------- print ---------- */
/* The school-day roster is the reason this block exists: one A4 portrait sheet,
   printed in black and white, carried around a hall. Every rule below is here
   for legibility on paper or to stop toner going on chrome nobody can click. */
@media print {
  /* A4 because that is what the school's printer has; portrait because seven
     narrow columns down a tall page is the shape of the sheet. */
  @page { size: A4 portrait; margin: 12mm 10mm 14mm; }

  body { background: #fff; }
  .rail { position: static; }     /* a sticky rail would print on page 1 only */
  .masthead { position: static; }
  .btn { display: none; }         /* nothing on paper is clickable */

  /* The one utility the markup uses to opt out of the sheet: the "rows are
     marked" hint and the print button. !important for the same reason [hidden]
     at the top of this file carries it — a single class must outrank any author
     `display` rule that a future component puts on the node it is added to. */
  .noprint { display: none !important; }
  .adminnav { display: none; }    /* navigation chips are dead ink */

  /* Admin chrome and card styling, scoped to the admin skin so that printing a
     parent-facing page (the blocks skin) keeps its letterhead and its cards
     exactly as they are today. */
  [data-theme="classic"] .masthead { display: none; }
  /* The 1180px column and its 22px gutters are screen furniture; on paper the
     margin comes from @page and the table needs every millimetre. */
  [data-theme="classic"] .wrap { max-width: none; padding: 0; }
  /* A card is a screen affordance: the shadow prints as a grey smear, the
     radius is invisible, and the border plus padding only steal width. */
  [data-theme="classic"] .panel {
    background: #fff; border: 0; border-radius: 0; box-shadow: none; padding: 0;
  }
  /* The panel heading is the divider between classes, so it needs a rule that
     actually prints — var(--line) is near-white on paper. It is KEPT alongside
     the .grouphead row inside thead, on purpose: this one carries the headcount
     (.art, "12 children") and prints once, while .grouphead carries only the
     name and repeats on every sheet. So the class name does appear twice at the
     top of page 1 — accepted, because losing the headcount to avoid it is the
     worse trade for someone counting children in a hall. The two are set at
     different sizes below so the repeat reads as a running head. */
  [data-theme="classic"] .colhead {
    border-bottom: 1px solid #000; margin-bottom: 5px; padding-bottom: 4px;
    break-after: avoid;           /* a heading alone at the foot of a page names nothing */
  }
  [data-theme="classic"] .colhead h2 { font-size: 12pt; }
  [data-theme="classic"] .colhead .no { display: none; }        /* the ☀ badge is a filled decoration */
  [data-theme="classic"] .colhead .art { color: #000; font-size: 8pt; }

  /* Keep a class on one sheet where it fits. `avoid-page` is a request, not a
     guarantee: a group longer than a page still breaks, and the repeating
     header plus the per-row rule below make that break land cleanly. */
  .rostergroup { break-inside: avoid-page; margin-top: 8mm; }

  /* The headcount summary is worth the ink; the pill fill is not. */
  .chiprow .chip { background: none; border: 1px solid #666; color: #000; padding: 2px 8px; }

  /* There is no scrolling on paper — a clipping wrapper would silently cut off
     the last columns. */
  .tablewrap { overflow: visible; }
  /* min-width undoes the screen rule that forces horizontal scroll; width:100%
     plus the tighter type and padding is what makes seven text columns fit A4
     portrait. Deliberately NOT `table-layout: fixed`: fixed layout takes its
     column widths from the FIRST row only, and that row is now .grouphead — one
     cell spanning all seven — which would flatten the sheet to seven equal
     columns. Automatic layout reads the real header row, and the
     `overflow-wrap: anywhere` above stops any note dragging its column wide. */
  table.data.roster { width: 100%; min-width: 0; font-size: 8.5pt; }
  .roster th, .roster td { padding: 2.5px 4px; }
  .roster th { color: #000; font-size: 7pt; border-bottom: 1px solid #000; }
  .roster td { border-top: 1px solid #BBB; }
  /* --faint and --muted are tuned for a backlit screen; on paper they fade. */
  .roster .hint, .roster .mono { font-size: 7.5pt; color: #444; }
  .roster .muted { color: #444; }   /* the em dash has to be visibly there */

  /* Page 2 of a class is unreadable without the column names. */
  .roster thead { display: table-header-group; }
  /* And the column names alone do not say whose class they belong to, so the
     group name rides along inside thead. Undoing the screen `display: none`. */
  .roster tr.grouphead { display: table-row; }
  /* `.data th` would make this a 7pt uppercase mono column label — it is a
     running class title, so every one of those is reset. Two classes and two
     elements outrank both `.data th` and the `.roster th` rule above. 10.5pt is
     well clear of the 7pt column labels but a step below the panel's 12pt h2,
     so on page 1 it reads as a running head rather than a second title. */
  .roster tr.grouphead th {
    font-family: var(--display); font-size: 10.5pt; font-weight: 700;
    text-transform: none; letter-spacing: -.01em; text-align: left; color: #000;
    padding: 5px 4px 1px; border-bottom: 0;
  }
  /* A child's allergies must never be on a different sheet from their name. */
  .roster tr { break-inside: avoid; page-break-inside: avoid; }

  /* The flag loses its colour here: the bar goes black, and the glyph and the
     bold note columns carry the rest. The row tint is dropped — a fill behind
     every flagged row is the single biggest toner cost on the sheet. */
  .roster tr.flagged { background: none; }
  .roster tr.flagged td:first-child { border-left-color: #000; }
  .roster tr.flagged td:first-child::before { color: #000; }

  /* The payment status is spelled out in words inside the badge, so nothing is
     lost by dropping the fill that distinguished ok from warn on screen. The
     modifiers are listed because .badge.ok would otherwise out-rank a bare
     .badge and keep its green wash. */
  .badge, .badge.ok, .badge.warn, .badge.bad {
    background: none; border: 1px solid #666; color: #000; font-size: 7.5pt;
  }
}
