/* Palette taken from the logo: navy #2c4364 and warm grey #7c7670.
   No yellows or oranges anywhere — attention is carried by weight, a left
   rule and depth of blue rather than by hue. */
:root {
  --bg: #f6f8fb;
  --panel: #ffffff;
  --ink: #1b2434;
  --muted: #5d6b7e;
  --faint: #94a0b1;
  --line: #dfe5ed;
  --line-strong: #c4cedb;

  --accent: #2c4364;          /* the logo navy */
  --accent-deep: #1e3049;
  --accent-soft: #e7eef7;
  --accent-line: #bcd0e6;

  /* Advisory. Deeper blue plus a left rule, so it outranks plain info
     without reaching for amber. */
  --warn: #1f3c5f;
  --warn-soft: #dbe7f4;
  --warn-line: #9dbbd9;

  --stop: #a6342b;            /* genuine blocks only */
  --stop-soft: #fbeceb;

  --sky: #dbe8f6;             /* grid: special event / service project / POM */
  --sky-line: #b3cbe5;
  --sky-ink: #244667;

  --radius: 10px;
  --shadow: 0 1px 2px rgba(27, 36, 52, .06), 0 4px 14px rgba(27, 36, 52, .06);
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  padding-bottom: 96px;
}

a { color: var(--accent); }

.wrap { max-width: 960px; margin: 0 auto; padding: 0 16px; }
.wrap.wide { max-width: 1240px; }

header.top {
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  padding: 14px 0;
  margin-bottom: 22px;
}
header.top .wrap { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.brand { display: flex; align-items: center; gap: 11px; text-decoration: none; color: inherit; }
.brand img { width: 38px; height: auto; display: block; flex: none; }
.brandtext { display: flex; flex-direction: column; line-height: 1.25; }
.brandname { font-size: 17px; font-weight: 700; letter-spacing: -.01em; color: var(--accent); }
header.top .sub { color: var(--muted); font-size: 12.5px; }

footer.site {
  border-top: 1px solid var(--line);
  background: var(--panel);
  padding: 18px 0;
  margin-top: 40px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--muted);
}
footer.site strong { color: var(--ink); font-weight: 600; }
body.locked footer.site { display: none; }
header.top nav { margin-left: auto; display: flex; gap: 14px; font-size: 14px; align-items: center; flex-wrap: wrap; }
.navtag {
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  padding: 2px 8px; border-radius: 999px; background: var(--ink); color: #fff;
}
header.top nav a { text-decoration: none; }
header.top nav a:hover { text-decoration: underline; }

h2 { font-size: 22px; margin: 0 0 6px; letter-spacing: -.015em; }
h3 { font-size: 15px; margin: 0 0 10px; }
p.lede { color: var(--muted); margin: 0 0 22px; max-width: 62ch; }

.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px;
  margin-bottom: 16px;
  box-shadow: var(--shadow);
}
/* The current day in the week view. A left rule rather than a fill, so it
   reads as "you are here" without shouting over the other days. */
.card.today {
  border-color: var(--accent-line);
  background: var(--accent-soft);
  box-shadow: inset 3px 0 0 var(--accent);
}
.card.today h3 { color: var(--accent-deep); }

button, .btn {
  font: inherit;
  font-weight: 500;
  padding: 9px 15px;
  border-radius: 8px;
  border: 1px solid var(--line-strong);
  background: var(--panel);
  color: var(--ink);
  cursor: pointer;
  text-decoration: none;
  display: inline-block;
}
button:hover, .btn:hover { border-color: var(--faint); }
button.primary, .btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
button.primary:hover { filter: brightness(1.08); }
button:disabled { opacity: .45; cursor: not-allowed; }
button.ghost { border-color: transparent; background: transparent; color: var(--muted); }
button.small { padding: 5px 10px; font-size: 13px; }
button.danger { color: var(--stop); border-color: #e6c6c3; }

input[type=text], input[type=number], input[type=email], input[type=tel], select {
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--line-strong);
  border-radius: 7px;
  background: var(--panel);
  color: var(--ink);
  width: 100%;
}
label.field { display: block; margin-bottom: 12px; }
label.field > span { display: block; font-size: 13px; color: var(--muted); margin-bottom: 4px; }
label.check { display: flex; gap: 8px; align-items: flex-start; font-size: 14px; margin-bottom: 8px; }
label.check input { margin-top: 3px; }

.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 700px) { .grid2 { grid-template-columns: 1fr; } }

/* ---- family picker ---- */
.family-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; }
.family-tile {
  display: block; text-decoration: none; color: inherit;
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px; background: var(--panel); box-shadow: var(--shadow);
}
.family-tile:hover { border-color: var(--accent); }
.family-tile .name { font-size: 18px; font-weight: 600; }
.family-tile .meta { font-size: 13px; color: var(--muted); margin-top: 3px; }
.family-tile .meta.done { color: var(--accent); }

/* ---- stepper ---- */
.steps { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 20px; }
.steps .step {
  font-size: 13px; padding: 6px 11px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--panel); color: var(--muted);
  cursor: pointer;
}
.steps .step.active { background: var(--ink); border-color: var(--ink); color: #fff; }
/* :not(.active) matters — the step you are on is also a visited step, and this
   rule would otherwise repaint its label navy on a navy background. */
.steps .step.done:not(.active) { border-color: var(--accent); color: var(--accent); }

/* The same Back / Continue pair that sits in the fixed bar, repeated at the top
   so a long list never has to be scrolled back through to move on. */
.navrow {
  display: flex; gap: 8px; justify-content: flex-end;
  padding-bottom: 14px; margin-bottom: 4px;
  border-bottom: 1px solid var(--line);
}

/* Lead-or-assist preference, shown only on the three rows that carry both. */
.rolepref { display: flex; gap: 6px; align-items: center; margin-top: 6px; font-size: 12px; flex-wrap: wrap; }
.chipbtn {
  font: inherit; font-size: 12px; font-weight: 600; padding: 2px 10px;
  border-radius: 999px; border: 1px solid var(--line-strong);
  background: var(--panel); color: var(--muted); cursor: pointer;
}
.chipbtn:hover { border-color: var(--faint); }
.chipbtn.on { background: var(--ink); border-color: var(--ink); color: #fff; }

/* Round progress across the top of the draft board. */
/* A family who asked for the other role on this row — still assignable here,
   just not their stated preference. */
.mini.offrole { opacity: .5; }
.mini .rk.pref { background: var(--ink); color: #fff; border-color: var(--ink); }

.roundbar { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.roundstep {
  flex: 1; min-width: 150px; padding: 10px 13px; border-radius: var(--radius);
  border: 1px solid var(--line); background: var(--panel); font-size: 13px;
}
.roundstep .t { font-weight: 600; }
.roundstep .n { color: var(--muted); font-variant-numeric: tabular-nums; }
.roundstep.now { border-color: var(--accent); background: var(--accent-soft); }
.roundstep.now .t { color: var(--accent); }
.roundstep.done { opacity: .55; }
.roundstep.done .t::after { content: ' ✓'; color: var(--accent); }

.meter { height: 6px; background: var(--line); border-radius: 999px; overflow: hidden; margin: 10px 0 4px; }
.meter > i { display: block; height: 100%; background: var(--accent); transition: width .2s; }
.meter-label { font-size: 13px; color: var(--muted); }

/* ---- pick lists ---- */
.picklist { border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; background: var(--panel); }
.pickrow {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 12px; border-bottom: 1px solid var(--line);
  cursor: pointer; user-select: none;
}
.pickrow:last-child { border-bottom: none; }
.pickrow:hover { background: #f4f7fb; }
.pickrow .when { width: 116px; flex: none; font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.pickrow .what { flex: 1; min-width: 0; }
.pickrow .what b { font-weight: 500; }
.pickrow .tags { font-size: 12px; color: var(--faint); margin-top: 1px; }

/* What the day actually involves, under its title. */
.rowdesc {
  font-size: 12.5px; line-height: 1.45; color: var(--muted);
  font-style: italic; margin-top: 3px; max-width: 62ch;
}
.rowdesc.attire { color: var(--faint); font-style: normal; }
.rowdesc.attire::before { content: 'Wear: '; font-style: italic; }
.pickrow .mark {
  width: 22px; height: 22px; flex: none; border-radius: 6px;
  border: 1.5px solid var(--line-strong); display: grid; place-items: center;
  font-size: 12px; font-weight: 700; color: transparent;
}
.pickrow.on .mark { background: var(--accent); border-color: var(--accent); color: #fff; }
.pickrow.on { background: var(--accent-soft); }
.pickrow.on.stop .mark { background: var(--stop); border-color: var(--stop); }
.pickrow.on.stop { background: var(--stop-soft); }
.pickrow.ordered .mark { background: var(--accent); border-color: var(--accent); color: #fff; font-variant-numeric: tabular-nums; }
.pickrow.dim { opacity: .38; }
.pickrow.dim .what b { text-decoration: line-through; }

@media (max-width: 620px) {
  .pickrow { flex-wrap: wrap; gap: 4px 10px; }
  .pickrow .when { width: auto; order: 2; }
  .pickrow .what { order: 3; flex-basis: 100%; }
  .pickrow .mark { order: 1; }
}

.chip {
  display: inline-block; font-size: 11px; padding: 1px 7px; border-radius: 999px;
  border: 1px solid var(--line-strong); color: var(--muted); margin-right: 5px;
  vertical-align: 1px;
}
.chip.eday { background: #fff; }
.chip.serving, .chip.pom, .chip.service { background: var(--sky); border-color: var(--sky-line); color: var(--sky-ink); }
.chip.drive { background: #dcefea; border-color: #a9d2c7; color: #14584a; }
.chip.lead { background: var(--ink); border-color: var(--ink); color: #fff; }
.chip.assist { background: #e9edf3; }

/* ---- review sheet ---- */
table.sheet { width: 100%; border-collapse: collapse; font-size: 14px; background: var(--panel); }
table.sheet th {
  text-align: left; font-size: 12px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted); font-weight: 600; padding: 8px 10px; border-bottom: 1px solid var(--line-strong);
  background: #eef2f7; position: sticky; top: 0;
}
table.sheet td { padding: 7px 10px; border-bottom: 1px solid var(--line); vertical-align: top; }
table.sheet tr.dead td { color: var(--faint); }
table.sheet tr.dead .title { text-decoration: line-through; }
table.sheet tr.mine { background: var(--accent-soft); }
table.sheet .rank { font-variant-numeric: tabular-nums; font-weight: 600; width: 46px; }
table.sheet .when { white-space: nowrap; color: var(--muted); width: 118px; }
.scroll { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); }

/* ---- draft board ---- */
.turnbar {
  position: sticky; top: 0; z-index: 20;
  background: var(--ink); color: #fff; border-radius: var(--radius);
  padding: 14px 18px; margin-bottom: 16px;
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  box-shadow: var(--shadow);
}
.turnbar .who { font-size: 24px; font-weight: 600; letter-spacing: -.02em; }
.turnbar .pass { font-size: 13px; opacity: .75; }
.turnbar .spacer { margin-left: auto; }
.turnbar .count { font-size: 13px; opacity: .85; font-variant-numeric: tabular-nums; }

.slotgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 8px; }
.slot {
  border: 1px solid var(--line); border-radius: 9px; padding: 9px 11px;
  background: var(--panel); cursor: pointer; font-size: 13px;
}
.slot:hover { border-color: var(--accent); }
.slot .t { font-weight: 500; }
.slot .d { color: var(--muted); font-size: 12px; }
.slot.taken { background: #f2f0ea; color: var(--faint); cursor: default; border-style: dashed; }
.slot.taken .t { text-decoration: line-through; }
.slot.taken:hover { border-color: var(--line); }
.slot .by { color: var(--accent); font-size: 12px; font-weight: 500; }

/* ---- the draft grid: the school's printed sheet, made live ----
   white = Enrichment Day · light blue = special event / service project / POM
   green = driving required · grey "NO" = no slot in that cell            */
.gridwrap { overflow-x: auto; border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--panel); }
table.grid { border-collapse: collapse; width: 100%; font-size: 13px; }
table.grid th {
  position: sticky; top: 0; z-index: 5;
  background: #eef2f7; border: 1px solid var(--line-strong);
  padding: 7px 9px; text-align: center; font-size: 12px; font-weight: 700;
  letter-spacing: .01em; white-space: nowrap;
}
table.grid td { border: 1px solid var(--line-strong); padding: 4px 6px; vertical-align: top; }
table.grid td.topic { min-width: 190px; font-weight: 500; background: var(--panel); }
table.grid td.when { min-width: 118px; white-space: nowrap; color: var(--muted); background: var(--panel); }
table.grid tr:hover td.topic, table.grid tr:hover td.when { background: #f4f7fb; }

td.cell { min-width: 168px; }
td.cell.no { background: #8a8a86; text-align: center; color: #efeeea; font-size: 11px; font-weight: 600; letter-spacing: .08em; }
td.cell.white { background: #ffffff; }
td.cell.peach { background: var(--sky); }
td.cell.green { background: #d8ebe4; }
td.cell.filled { background: #e9edf3; }

.slotcell + .slotcell { margin-top: 5px; padding-top: 5px; border-top: 1px dashed rgba(0,0,0,.18); }
.slotcell .drivelabel { font-size: 10px; color: #14584a; font-weight: 700; letter-spacing: .04em; }

/* mini cards — one per family who wanted this row */
.mini {
  display: inline-flex; align-items: center; gap: 5px;
  background: rgba(255,255,255,.82); border: 1px solid rgba(0,0,0,.16);
  border-radius: 999px; padding: 2px 4px 2px 8px; margin: 2px 3px 0 0;
  font-size: 12px; line-height: 1.5; white-space: nowrap;
}
.mini .rk { color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; }
.mini button {
  border: none; background: transparent; padding: 0; margin: 0;
  width: 18px; height: 18px; border-radius: 50%; cursor: pointer;
  font-size: 13px; line-height: 1; display: grid; place-items: center; color: var(--muted);
}
.mini button:hover { background: rgba(0,0,0,.09); color: var(--ink); }
.mini.add button { color: var(--accent); font-weight: 700; }
.mini.onclock { border-color: var(--accent); box-shadow: 0 0 0 1.5px var(--accent); font-weight: 600; }
.mini.taken { background: var(--ink); border-color: var(--ink); color: #fff; }
.mini.taken .rk { color: rgba(255,255,255,.65); }
.mini.taken button { color: rgba(255,255,255,.75); }
.mini.taken button:hover { background: rgba(255,255,255,.2); color: #fff; }
.cellempty { color: var(--faint); font-size: 11px; font-style: italic; }

.viewtabs { display: flex; gap: 6px; margin-bottom: 12px; }
.viewtabs button.on { background: var(--ink); border-color: var(--ink); color: #fff; }

.legend { display: flex; gap: 14px; flex-wrap: wrap; font-size: 12px; color: var(--muted); margin: 10px 0 0; align-items: center; }
.legend i { display: inline-block; width: 13px; height: 13px; border: 1px solid var(--line-strong); vertical-align: -2px; margin-right: 5px; }
.legend i.white { background: #fff; } .legend i.peach { background: var(--sky); }
.legend i.green { background: #dcecd7; } .legend i.no { background: #8a8a86; }

.banner { border-radius: var(--radius); padding: 11px 14px; margin-bottom: 10px; font-size: 14px; }
.banner.warn {
  background: var(--warn-soft); border: 1px solid var(--warn-line);
  border-left: 4px solid var(--accent); color: var(--warn); font-weight: 500;
}
.banner.stop { background: var(--stop-soft); border: 1px solid #f0c8c5; color: var(--stop); }
.banner.info { background: var(--accent-soft); border: 1px solid #c4ded5; color: #16543f; }

.modal-back {
  position: fixed; inset: 0; background: rgba(28,27,24,.42);
  display: grid; place-items: center; padding: 16px; z-index: 100;
}
.modal { background: var(--panel); border-radius: 14px; padding: 22px; max-width: 520px; width: 100%; box-shadow: 0 12px 40px rgba(0,0,0,.2); }
.modal h3 { font-size: 18px; }

.rowlist { list-style: none; margin: 0; padding: 0; }
.rowlist li { display: flex; gap: 10px; align-items: center; padding: 7px 0; border-bottom: 1px solid var(--line); font-size: 14px; }
.rowlist li:last-child { border: none; }
.rowlist .n { font-variant-numeric: tabular-nums; color: var(--muted); width: 26px; }
.rowlist .grow { flex: 1; }

.sticky-actions {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  background: rgba(250,249,246,.95); backdrop-filter: blur(8px);
  border-top: 1px solid var(--line); padding: 11px 0;
}
.sticky-actions .wrap { display: flex; gap: 10px; align-items: center; }
.sticky-actions .status { font-size: 13px; color: var(--muted); margin-right: auto; }
.sticky-actions .status.failing { color: var(--stop); font-weight: 600; }

/* Nothing to navigate to until you are through the door. */
body.locked header.top nav { display: none; }

.muted { color: var(--muted); }
.small { font-size: 13px; }
.right { text-align: right; }
.mono { font-variant-numeric: tabular-nums; }
.stack > * + * { margin-top: 10px; }
.hidden { display: none !important; }

@media print {
  header.top nav, .sticky-actions, button { display: none !important; }
  body { background: #fff; padding: 0; }
  .card { box-shadow: none; break-inside: avoid; }
}




/* ---------------------------------------------------------------------------
   The family sheet: the paper form, filled in. Five columns, every row in
   grid order, sized so nothing is clipped and it prints on paper.
   --------------------------------------------------------------------------- */
.sheetdoc { max-width: 100%; }
.sheethead { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }
.sheethead h2 { margin: 0 0 2px; }
.sheethead .who { margin: 0; color: var(--muted); font-size: 14px; }

.tally {
  display: flex; flex-wrap: wrap; gap: 6px 18px;
  margin: 10px 0 16px; padding: 11px 15px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius);
  font-size: 14px; color: var(--muted);
}
.tally b { color: var(--ink); font-variant-numeric: tabular-nums; }
.tally .won, .tally .won b { color: var(--accent); }

table.sheet.filled td { padding: 6px 10px; vertical-align: top; }
/* Fixed widths for the first four columns; "Assigned to you" takes whatever is
   left, because it is the one with variable content (up to three slots). The
   rank column has to fit "Doesn't work" on a single line. */
table.sheet.filled .when { width: 118px; white-space: nowrap; }
table.sheet.filled .rank { width: 176px; }
table.sheet.filled .what { width: 366px; }
table.sheet.filled td.gone, table.sheet.filled th.gone { text-align: center; width: 132px; min-width: 132px; }
table.sheet.filled td.gone input { width: 17px; height: 17px; accent-color: var(--accent); cursor: pointer; }
table.sheet.filled td.gone input:disabled { cursor: default; opacity: .4; }
table.sheet.filled td.picks { width: auto; }

table.sheet.filled tr.mine { background: var(--accent-soft); }
table.sheet.filled tr.dead { color: var(--faint); }
table.sheet.filled tr.dead .title, table.sheet.filled tr.dead .when { text-decoration: line-through; }
table.sheet.filled tr.dead .pill { opacity: .55; }
table.sheet.filled tr.dead .rowdesc { display: none; }

.pickrow-h { display: flex; gap: 18px; flex-wrap: wrap; align-items: baseline; }
.slotpick { display: inline-flex; gap: 6px; align-items: baseline; font-size: 13.5px; white-space: nowrap; cursor: pointer; }
.slotpick input { margin: 0; accent-color: var(--accent); cursor: pointer; }
.slotpick.mine { color: var(--accent); font-weight: 700; }
.slotpick.gone { color: var(--faint); cursor: default; }
.slotpick.gone span { text-decoration: line-through; }
.slotpick.readonly, .slotpick.readonly input { cursor: default; }

.sheetfoot {
  margin: 16px 0 14px; padding: 13px 16px; border-radius: var(--radius);
  background: var(--accent-soft); border: 1px solid var(--accent-line);
  color: var(--accent-deep); font-size: 13.5px; line-height: 1.6;
}
.sheetfoot > div + div { margin-top: 3px; }
.sheetactions { display: flex; gap: 8px; flex-wrap: wrap; }

/* On a phone all five columns have to fit in ~340px, so the date moves inline
   under the title and everything else tightens. Nothing is hidden except the
   heading's parenthetical, which the footnote repeats anyway. */
.mobiledate { display: none; }

@media (max-width: 700px) {
  table.sheet.filled th:first-child,
  table.sheet.filled td:first-child { display: none; }
  .mobiledate {
    display: block; font-size: 10.5px; color: var(--muted);
    font-variant-numeric: tabular-nums; margin-bottom: 1px;
  }
  table.sheet.filled .rowdesc { display: none; }
  table.sheet.filled .rank { width: 84px; }
  table.sheet.filled .pill { white-space: normal; font-size: 10px; padding: 2px 7px; min-width: 0; line-height: 1.3; }
  table.sheet.filled .what { width: auto; }
  table.sheet.filled td.gone, table.sheet.filled th.gone { width: 42px; min-width: 42px; }
  table.sheet.filled td.gone input { width: 15px; height: 15px; }
  /* Outranks the base .thnote rule further down the file, which would
     otherwise win on equal specificity by coming later. */
  table.sheet.filled th .thnote { display: none; }
  table.sheet.filled td.picks { min-width: 0; }
  table.sheet.filled th, table.sheet.filled td { padding: 5px 4px; font-size: 12px; }
  table.sheet.filled th { font-size: 8.5px; letter-spacing: .01em; }
  .pickrow-h { flex-direction: column; gap: 4px; align-items: flex-start; }
  .slotpick { font-size: 11.5px; white-space: normal; }
}

@media print {
  .sheetactions, .sheethead a { display: none !important; }
  /* Nothing to tick on paper — the column and its instructions are for the
     live screen only. */
  table.sheet.filled th.gone, table.sheet.filled td.gone { display: none !important; }
  .sheetfoot { display: none !important; }
  .tally, .sheetfoot, .legendbox { background: #fff; }
  table.sheet.filled tr { break-inside: avoid; }
}

/* ---------------------------------------------------------------------------
   Per-row notes. Collapsed to a single quiet line until there is something in
   it, so 55 rows of them add almost no height to the page.
   --------------------------------------------------------------------------- */
.noterow { margin-top: 4px; }
.notesum {
  display: flex; align-items: baseline; gap: 6px; cursor: pointer;
  font-size: 11.5px; color: var(--muted); list-style: none;
  /* A 30px-tall target is the minimum that is comfortable with a thumb. */
  padding: 4px 0; min-height: 22px; user-select: none;
}
.notesum::-webkit-details-marker { display: none; }
.notesum::marker { content: ''; }
.notelabel {
  border-bottom: 1px dashed var(--line-strong); padding-bottom: 1px;
  white-space: nowrap;
}
.notesum:hover .notelabel { color: var(--accent); border-bottom-color: var(--accent); }
.noterow.has .notelabel { color: var(--accent-deep); font-weight: 600; }
/* The gist of a collapsed note, so a folded-away reason is never invisible.
   Takes whatever width is left rather than a fixed character count, which on a
   phone cut "Dreamforce in San Francisco" down to "Dreamforce S...". */
.notepeek {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-style: italic; color: var(--faint);
}
.noterow[open] .notepeek { display: none; }
.noteinput {
  display: block; width: 100%; margin: 2px 0 4px; padding: 7px 9px;
  border: 1px solid var(--line-strong); border-radius: 8px;
  background: var(--panel); color: var(--ink);
  font: inherit; font-size: 12.5px; line-height: 1.45;
  resize: vertical; min-height: 42px;
}
.noteinput:focus { outline: 2px solid var(--accent); outline-offset: -1px; border-color: var(--accent); }
.noteinput::placeholder { color: var(--faint); }

/* Phones: full width, and 16px so iOS does not zoom the page on focus. */
@media (max-width: 700px) {
  table.sheet.filled .noteinput { font-size: 16px; }
}

/* On screen the textarea is the note; the print copy stays out of the way. */
.noterow .noteprint { display: none; }

/* On paper a note is the point of the exercise, so it prints as plain text with
   no widget around it. An empty one prints as nothing at all. */
@media print {
  .noterow:not(.has) { display: none !important; }
  .notesum, .noteinput { display: none !important; }
  .noterow .noteprint { display: block; }
}
.noteprint {
  margin-top: 2px; font-size: 11px; font-style: italic;
  color: var(--muted); white-space: pre-wrap; overflow-wrap: anywhere;
}

/* The rank cell doubles as their answer: filled = really want, outline = maybe,
   grey = would rather not, dashed = doesn't work. Restored after an over-eager
   cleanup removed it and the numbers rendered as plain text. */
.pill {
  display: inline-block; min-width: 28px; text-align: center;
  padding: 2px 10px; border-radius: 999px; font-size: 11.5px;
  font-variant-numeric: tabular-nums; font-weight: 700; white-space: nowrap;
  border: 1px solid var(--line-strong); background: var(--panel); color: var(--ink);
}
.pill.want { background: var(--accent); border-color: var(--accent); color: #fff; }
.pill.maybe { background: var(--panel); color: var(--muted); font-weight: 500; }
.pill.no { background: #e6eaf0; border-color: #c0c9d6; color: #56637a; }
.pill.blocked {
  background: #e3e8ef; border: 1px dashed #93a1b5; color: #46536a;
  min-width: 0; font-weight: 600; white-space: nowrap;
}

.legendbox {
  margin-top: 14px; padding: 13px 16px; border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--panel);
}
.legendbox h3 { margin-bottom: 8px; }
.legend { display: flex; flex-wrap: wrap; gap: 8px 20px; font-size: 13px; color: var(--muted); align-items: center; }
.legend > span { display: inline-flex; align-items: center; gap: 7px; }

/* Printing has to produce the form itself — the whole sheet, on paper. */
@media print {
  @page { margin: 12mm; }
  header.top, footer.site, .sheetactions, .sheethead a, .lede, .banner { display: none !important; }
  body { padding: 0; background: #fff; }
  .scroll { border: none; overflow: visible !important; }
  table.sheet.filled { width: 100%; font-size: 10.5pt; }
  table.sheet.filled th { background: #f2f4f8 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  table.sheet.filled td, table.sheet.filled th { padding: 3px 6px; }
  .pill, .slotpick, .tally, .legendbox, .sheetfoot { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  thead { display: table-header-group; }
  tr { break-inside: avoid; }
}

/* The sheet carries five columns and needs the room the draft board gets. */
body.wide-page #root, body.wide-page header.top .wrap, body.wide-page footer.site .wrap,
body.wide-page .installwrap { max-width: 1240px; }

/* The second line under a column heading: quieter, sentence case, not shouted. */
.thnote {
  display: block; margin-top: 2px; font-size: 9.5px; font-weight: 500;
  letter-spacing: 0; text-transform: none; color: var(--faint);
}

/* ---------------------------------------------------------------------------
   All parent forms, one family per page, built to be saved as a single PDF.
   --------------------------------------------------------------------------- */
.famsheet { margin-bottom: 30px; }
.famhead { display: flex; justify-content: space-between; align-items: baseline; gap: 14px;
           flex-wrap: wrap; border-bottom: 2px solid var(--accent); padding-bottom: 6px; margin-bottom: 8px; }
.famhead h2 { margin: 0; font-size: 17px; }
.famhead .who { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.famtally { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.famwarn { font-size: 12px; color: var(--stop); margin: 0 0 8px; }
.prefnote { font-size: 11.5px; color: var(--muted); font-style: italic; }
.wonlabel { color: var(--accent); }

table.printsheet { width: 100%; }
table.printsheet .when { width: 118px; }
table.printsheet .rank { width: 176px; }
table.printsheet .what { width: auto; }
table.printsheet .need { width: 210px; font-size: 12.5px; color: var(--sky-ink); }
table.printsheet td { padding: 3.5px 8px; }
table.printsheet tr.mine { background: var(--accent-soft); }
table.printsheet tr.dead { color: var(--faint); }
table.printsheet tr.dead .title { text-decoration: line-through; }

@media print {
  @page { size: letter portrait; margin: 11mm 10mm; }
  .noprint { display: none !important; }
  .pagebreak { break-before: page; page-break-before: always; }
  .famsheet { margin-bottom: 0; }
  table.printsheet { font-size: 8.6pt; }
  table.printsheet td { padding: 2.4px 6px; }
  table.printsheet th { font-size: 7pt; padding: 3px 6px; }
  table.printsheet .rank { width: 150px; }
  table.printsheet .need { width: 175px; font-size: 8pt; }
  .famhead h2 { font-size: 13pt; }
  .pill { font-size: 8pt; padding: 1px 7px; }
}

/* On a phone the fixed bar ran the buttons into the right edge. Give the status
   its own centred line and centre the buttons underneath it. */
@media (max-width: 620px) {
  .sticky-actions .wrap { flex-wrap: wrap; justify-content: center; gap: 8px; padding: 0 14px; }
  .sticky-actions .status { flex: 1 0 100%; margin: 0 0 2px; text-align: center; font-size: 12px; }
  .sticky-actions button { flex: 0 1 auto; min-width: 108px; }
  .navrow { justify-content: center; }
  .navrow button { flex: 0 1 auto; min-width: 108px; }
  .steps { gap: 5px; }
  .steps .step { font-size: 12.5px; padding: 6px 10px; }
}

/* Which family this sheet belongs to, changeable in place. */
.famswitch { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.famswitch > span { font-size: 12px; color: var(--muted); white-space: nowrap; }
.famswitch select {
  width: auto; min-width: 132px; font-weight: 600; font-size: 14px;
  padding: 6px 10px; border-color: var(--accent-line); background: var(--accent-soft);
  color: var(--accent-deep); cursor: pointer;
}
@media (max-width: 620px) {
  .sheethead { flex-direction: column; align-items: stretch; }
  .famswitch { margin-left: 0; margin-top: 6px; }
  .famswitch select { flex: 1; }
}
@media print { .famswitch { display: none !important; } }

/* ---------------------------------------------------------------------------
   Cross-grade tracker (/tracker). Admin-only page, added after everything else
   so this block is the whole diff. Reuses card, banner, scroll, sheet, chip.
   --------------------------------------------------------------------------- */
.cards { display: flex; gap: 10px; flex-wrap: wrap; margin: 12px 0 14px; }
.tcard { flex: 1 1 210px; margin: 0; }
.tcard h3 { margin: 0 0 6px; font-size: 13px; }
.tbig { font-size: 23px; font-weight: 700; color: var(--accent); line-height: 1.1; }
.tbig .short { color: var(--stop); }
.tcard p { margin: 3px 0 0; }

table.sheet.tracker td.c, table.sheet.tracker th.c { text-align: center; }
table.sheet.tracker tr.lost td { background: var(--stop-soft); }
table.sheet.tracker tr.cant td { background: #f1f3f6; color: var(--faint); }
/* Only the 4th grade event strikes. The 1st grade side says its own piece
   through the "Doesn't work" pill next to it. */
table.sheet.tracker tr.cant .what.g4 .title { text-decoration: line-through; }
table.sheet.tracker tr.pre td { background: var(--bg); color: var(--faint); }

.tstatus { font-weight: 600; font-size: 12.5px; display: block; }
.tstatus.open { color: var(--accent); }
.tstatus.lost { color: var(--stop); }
.tstatus.cant, .tstatus.pre { color: var(--muted); font-weight: 500; }
/* The reason, and the 1st grade item that caused it. */
.twhy {
  display: block; font-weight: 400; font-size: 11.5px;
  color: var(--muted); margin-top: 1px;
}
.tstatus.lost .twhy { color: var(--stop); opacity: .85; }

@media (max-width: 700px) {
  .cards { gap: 8px; }
  .tcard { flex: 1 1 46%; }
  .tbig { font-size: 19px; }
  table.sheet.tracker th, table.sheet.tracker td { padding: 5px 6px; font-size: 12px; }
}

/* The tracker borrows .sheet.filled, which hides its first column on a phone
   because the family sheet repeats the date inline. There is no such repeat
   here and the date is the whole point, so put it back and drop the parents
   count instead — that one can wait for a wider screen. */
@media (max-width: 700px) {
  table.sheet.filled.tracker th:first-child,
  table.sheet.filled.tracker td:first-child { display: table-cell; width: 74px; }
  table.sheet.filled.tracker th:nth-child(3),
  table.sheet.filled.tracker td:nth-child(3) { display: none; }
  table.sheet.filled.tracker .when { font-size: 10.5px; line-height: 1.25; }
}

/* Seven columns now: date, both grades side by side, and our own working
   state. Widths are deliberate so "Where we stand" cannot squeeze the events. */
table.sheet.filled.tracker { table-layout: fixed; width: 100%; min-width: 1120px; }
table.sheet.filled.tracker .when { width: 104px; }
table.sheet.filled.tracker .what.g1 { width: 210px; }
table.sheet.filled.tracker .g1stat { width: 148px; }
table.sheet.filled.tracker .what.g4 { width: 210px; }
table.sheet.filled.tracker .g4stat { width: 210px; }
table.sheet.filled.tracker .g4note { width: 150px; }
table.sheet.filled.tracker td { vertical-align: top; }
table.sheet.filled.tracker .title { display: block; }

/* A 4th grade event 1st grade has already taken off the table. */
table.sheet.filled.tracker .what.g4.struck .title { text-decoration: line-through; color: var(--faint); }

.tstatus.won { color: var(--accent); }
/* The family's own reason, carried over from their sheet. */
.g1note {
  margin-top: 3px; font-size: 11px; font-style: italic; color: var(--muted);
  white-space: pre-wrap; overflow-wrap: anywhere;
}
/* Ticked and still available: the ones going on Friday's form. */
table.sheet.filled.tracker tr.taken td { background: var(--accent-soft); }
table.sheet.filled.tracker tr.taken .what.g4 .title { font-weight: 700; color: var(--accent-deep); }
table.sheet.filled.tracker td.c input[type=checkbox] { width: 17px; height: 17px; cursor: pointer; }

/* The table scrolls sideways inside its own box rather than the page. */
@media (max-width: 1180px) {
  .scroll { overflow-x: auto; }
}

/* ---------------------------------------------------------------------------
   Draft night: locked columns, flagged dates, instructions, final export.
   Appended last so this block is the whole diff.
   --------------------------------------------------------------------------- */

/* A locked grid column: visible, legible, inert. */
.grid td.cell.locked { background: #eef1f5; color: var(--muted); }
.grid td.cell.locked .mini.taken { background: #dfe5ed; border-color: var(--line-strong); color: var(--muted); }
.grid td.cell.locked .mini.empty { color: var(--faint); font-style: italic; }
.roundstep.locked { border-color: var(--line-strong); background: #eef1f5; opacity: .9; }
.roundstep.locked .t::after { content: ' ●'; color: var(--muted); }
.lockmark { font-size: 10px; font-weight: 600; color: var(--muted); white-space: nowrap; }

/* Flagging a date for follow-up. */
.grid th.flagcol, .grid td.flagcol { width: 30px; text-align: center; padding: 2px; }
.issueflag {
  border: 0; background: none; cursor: pointer; padding: 2px 4px;
  font-size: 15px; line-height: 1; color: var(--faint);
}
.issueflag:hover { color: var(--accent); }
.issueflag.on { color: var(--stop); }
.grid tr.flagged td { background: var(--stop-soft); }
.grid tr.flagged td.cell.filled { background: #f6e3e1; }
.issuenote {
  font-size: 11px; font-style: italic; color: var(--stop);
  margin-top: 2px; white-space: pre-wrap; overflow-wrap: anywhere;
}
.issuecard .issuenote { font-size: 12.5px; }

/* Instructions. Numbered, printable, readable at arm's length. */
.insteps { margin: 4px 0 18px; }
.instep {
  display: flex; gap: 14px; align-items: flex-start;
  padding: 16px 0; border-bottom: 1px solid var(--line);
  break-inside: avoid;
}
.inum {
  flex: none; width: 30px; height: 30px; border-radius: 999px;
  background: var(--accent); color: #fff; font-weight: 700;
  display: flex; align-items: center; justify-content: center; font-size: 15px;
}
.inbody { flex: 1; min-width: 0; }
.inbody h3 { margin: 3px 0 8px; }
.inbody ul { margin: 6px 0; padding-left: 20px; }
.inbody li { margin-bottom: 5px; }
.inbody .banner { margin: 10px 0 0; }
.inkey {
  display: inline-block; padding: 1px 7px; border-radius: 5px;
  background: var(--accent-soft); border: 1px solid var(--accent-line);
  color: var(--accent-deep); font-weight: 600; font-size: 13px; white-space: nowrap;
}

/* The hand-back document, in the coordinator's own column order. */
.exportdoc { background: var(--panel); padding: 18px; border-radius: var(--radius); border: 1px solid var(--line); }
.xtitle { font-size: 17px; margin: 0 0 12px; color: var(--accent); }
table.xgrid { width: 100%; border-collapse: collapse; font-size: 11px; }
table.xgrid th {
  background: var(--accent); color: #fff; text-align: left;
  padding: 5px 6px; font-size: 10.5px; font-weight: 600;
}
table.xgrid td { border: 1px solid var(--line-strong); padding: 3px 6px; vertical-align: top; }
table.xgrid td.xtopic { width: 24%; }
table.xgrid td.xdate { width: 13%; white-space: nowrap; color: var(--muted); }
table.xgrid td.xno { background: #d9d9d9; color: #6b6b6b; text-align: center; font-size: 10px; }
.xslot { min-height: 13px; }
.xslot + .xslot { margin-top: 3px; padding-top: 3px; border-top: 1px dotted var(--line-strong); }
.xslot.xempty { min-height: 15px; border-bottom: 1px solid var(--line); }
.xcar { color: var(--muted); font-size: 10px; }
.xissues { margin-top: 16px; break-inside: avoid; }
.xissues h3 { font-size: 13px; margin-bottom: 6px; }
.xissues li { margin-bottom: 5px; font-size: 11.5px; }

@media print {
  .noprint { display: none !important; }
  .exportdoc { border: 0; padding: 0; }
  table.xgrid { font-size: 8.5px; }
  table.xgrid th { font-size: 8px; padding: 3px 4px; }
  table.xgrid td { padding: 2px 4px; }
  table.xgrid tr { break-inside: avoid; }
  .instep { break-inside: avoid; }
  .issuecard { break-inside: avoid; }
}

@media (max-width: 700px) {
  .instep { gap: 10px; padding: 13px 0; }
  .inum { width: 26px; height: 26px; font-size: 13px; }
}

/* ---------------------------------------------------------------------------
   Family colours and the running tally.

   Seven hues, deliberately pale as a fill so the grid stays readable, with a
   saturated dot on the seat number doing the actual identifying. Colour is tied
   to the family, not the seat, so it means the same thing on every page.
   Yellow and orange are skipped to stay with the rest of the palette.
   --------------------------------------------------------------------------- */
.fam-0 { --fc: hsl(212 62% 42%); --fcs: hsl(212 62% 95%); }
.fam-1 { --fc: hsl(188 58% 34%); --fcs: hsl(188 58% 94%); }
.fam-2 { --fc: hsl(155 46% 33%); --fcs: hsl(155 46% 94%); }
.fam-3 { --fc: hsl(268 42% 48%); --fcs: hsl(268 42% 96%); }
.fam-4 { --fc: hsl(325 44% 45%); --fcs: hsl(325 44% 96%); }
.fam-5 { --fc: hsl(352 52% 46%); --fcs: hsl(352 52% 96%); }
.fam-6 { --fc: hsl(220 12% 40%); --fcs: hsl(220 12% 94%); }

/* A taken cell in the grid: faint wash, saturated left edge.
   The base .mini.taken paints white text for a near-black chip, so the text,
   the rank and the × all have to be repainted dark here or they vanish into
   the tint. Deliberately near-black rather than the family hue: it reads at a
   glance on all seven tints, and the left edge carries the identity. */
.grid .mini.taken[class*="fam-"] {
  background: var(--fcs);
  border-color: var(--line-strong);
  border-left: 3px solid var(--fc);
  color: var(--ink);
  font-weight: 600;
}
.grid .mini.taken[class*="fam-"] .rk { color: var(--muted); }
.grid .mini.taken[class*="fam-"] button { color: var(--muted); }
.grid .mini.taken[class*="fam-"] button:hover { background: rgba(0, 0, 0, .10); color: var(--ink); }

/* Seat chart. */
.seatchart li { align-items: center; }
.seatchart .seatnum {
  background: var(--fcs); border: 1px solid var(--fc); color: var(--fc);
  font-weight: 700;
}
.seatchart li.onclock { background: var(--accent-soft); border-radius: 8px; }
.seatchart li.onclock .grow { font-weight: 700; }
.clocktag {
  margin-left: 8px; font-size: 10px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; padding: 2px 7px; border-radius: 999px;
  background: var(--ink); color: #fff; white-space: nowrap;
}
/* Running count of everything that family holds. */
.seatchart .tally {
  min-width: 26px; text-align: center; padding: 2px 8px; border-radius: 999px;
  font-variant-numeric: tabular-nums; font-weight: 700; font-size: 13px;
  background: var(--bg); border: 1px solid var(--line); color: var(--faint);
}
.seatchart .tally.has { background: var(--fcs); border-color: var(--fc); color: var(--fc); }

/* Moving the room on is a deliberate press, never a side effect of assigning. */
.turnnav { display: flex; gap: 6px; align-items: center; }
.turnbar .nextperson { white-space: nowrap; }
.turnbar .turnnav button.ghost { color: #cdd6e2; border-color: transparent; }
.turnbar .turnnav button:disabled { opacity: .35; }

@media (max-width: 700px) {
  .turnnav { width: 100%; }
  .turnnav .nextperson { flex: 1; }
  .clocktag { display: none; }
}

/* ---------------------------------------------------------------------------
   One column at a time.

   The grid is worked Round 1 top to bottom, then Round 2, and so on, so the
   grid says which column is in play: finished columns go faint green, the
   live column keeps full strength, and the ones still to come are dimmed.
   Purely visual — a dimmed column is still clickable if you need to fill ahead.
   --------------------------------------------------------------------------- */
:root {
  --done-soft: #eef6f0;      /* finished: the only green in the app */
  --done-line: #bcd9c6;
  --done-ink:  #2f6b47;
}

/* Finished — locked, or every slot in it filled. */
.grid td.cell.col-done { background: var(--done-soft); }
.grid td.cell.col-done.no { background: #e4ece6; color: #93a89b; }
.grid th.col-done {
  background: var(--done-ink); color: #fff;
}
.grid th.col-done .lockmark { color: #cfe6d8; }
/* A finished column that is also locked keeps the green, not the grey. */
.grid td.cell.locked.col-done { background: var(--done-soft); }
.grid td.cell.locked.col-done .mini.taken { background: #dcebe1; border-color: var(--done-line); color: var(--done-ink); }

/* In play — full strength, with a clear edge either side of the column. */
.grid th.col-active { background: var(--accent); color: #fff; box-shadow: inset 0 -3px 0 var(--ink); }
.grid td.cell.col-active { border-left-color: var(--accent-line); border-right-color: var(--accent-line); }

/* Still to come — pushed back so the eye lands on the live column. */
.grid td.cell.col-pending { background: #fbfcfd; }
.grid td.cell.col-pending > * { opacity: .38; }
.grid td.cell.col-pending.no { background: #f2f4f7; color: #c3cad4; }
.grid th.col-pending { background: #93a1b3; color: #eef1f5; }
/* Hovering a pending column brings it back, so filling ahead stays easy. */
.grid td.cell.col-pending:hover > * { opacity: 1; }

/* The round bar mirrors exactly the same three states. */
.roundstep.col-done { border-color: var(--done-line); background: var(--done-soft); }
.roundstep.col-done .t { color: var(--done-ink); }
.roundstep.col-done .t::after { content: ' ✓'; }
.roundstep.col-active { border-color: var(--accent); background: var(--accent-soft); box-shadow: 0 0 0 2px var(--accent-line); }
.roundstep.col-active .t { color: var(--accent); font-weight: 700; }
.roundstep.col-pending { opacity: .55; }

@media print {
  .grid td.cell.col-pending > * { opacity: 1; }
}

/* ---------------------------------------------------------------------------
   How many people a cell needs.

   Six cells on the grid want two parents. Without a count they read as one
   cell showing the same suggestion twice, which is exactly how it was misread.
   --------------------------------------------------------------------------- */
.cellneed {
  display: block; margin: 0 0 4px;
  font-size: 9.5px; font-weight: 700; letter-spacing: .04em;
  padding: 2px 6px; border-radius: 4px; text-align: center;
  background: var(--panel); border: 1px solid var(--line-strong);
  color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Two-slot cells are the ones that get misread, so their badge is loud. */
.cellneed.multi { background: var(--stop); border-color: var(--stop); color: #fff; }
.cellneed.ok, .cellneed.multi.ok {
  background: var(--done-soft); border-color: var(--done-line); color: var(--done-ink);
}

/* Which of the two this block is. */
.slotwho {
  font-size: 9.5px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 2px;
}
/* A firmer divider, so two slots never blur into one. */
.slotcell + .slotcell { border-top: 1px solid rgba(0, 0, 0, .28); }
.grid td.cell.locked .mini.empty { font-style: italic; }

/* ---------------------------------------------------------------------------
   App + Printed — the merged grid.

   Six states, each with its own colour and a left rule so the state survives
   a black-and-white print. Nothing here is editable; it renders two records
   side by side.
   --------------------------------------------------------------------------- */
table.mgrid { font-size: 11.5px; }
table.mgrid td { vertical-align: top; padding: 4px 6px; }
table.mgrid td.mno {
  background: #e9edf3; color: var(--faint); text-align: center;
  font-size: 10px; font-weight: 600; letter-spacing: .06em;
}
table.mgrid td.mk { width: 76px; }
table.mgrid td.when { width: 118px; white-space: nowrap; }
table.mgrid td.what { width: 200px; }
table.mgrid tr.synthrow td { background: #faf7fe; }

.ment { line-height: 1.25; }
.ment + .ment { margin-top: 4px; }

/* The name carries the state as a solid pill — the grid should read like a
   chart of who is committed where, not like a table with coloured edges. */
.mname {
  display: inline-block; padding: 3px 10px; border-radius: 999px;
  font-weight: 600; font-size: 11px; line-height: 1.35;
  color: #fff; background: var(--ink);
  max-width: 100%; overflow-wrap: anywhere;
}
.p-agree   { background: #2f6b47; }
.p-doubled { background: #a6342b; }
.p-shifted { background: #8a5200; }
.p-norow   { background: #5a3596; }
.p-apponly { background: var(--accent); text-decoration: line-through; }
/* Our slot, whose paper counterpart lives in another column: outlined, not filled. */
.p-ghost {
  background: transparent; color: var(--muted); font-weight: 500; font-style: italic;
  border: 1px dashed var(--line-strong);
}
.mempty { color: var(--faint); }
.ment.dropped .mname { opacity: .38; text-decoration: line-through; }
.mtag {
  display: block; font-size: 8.5px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted); margin: 2px 0 0 2px;
}
.mraw { display: block; font-size: 9.5px; font-style: italic; color: var(--muted); }

.mmark {
  display: inline-block; font-size: 8px; font-weight: 700; text-transform: uppercase;
  padding: 1px 4px; border-radius: 3px; margin: 0 2px 2px 0; color: #fff;
}
.m-doubled  { background: var(--stop); }
.m-shifted  { background: #b26a00; }
.m-no-row   { background: #6b3fa0; }
.m-app-only { background: var(--accent); }

.issuebox h4 { margin: 0 0 6px; font-size: 12.5px; color: var(--muted); }
.sidebyside { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin: 10px 0; }
@media (max-width: 700px) { .sidebyside { grid-template-columns: 1fr; } }

.legend i.lg { display: inline-block; width: 12px; height: 12px; border-radius: 3px; margin-right: 5px; vertical-align: -2px; }
i.lg { border-radius: 999px; width: 22px; }
i.lg.agree   { background: #2f6b47; }
i.lg.doubled { background: #a6342b; }
i.lg.shifted { background: #8a5200; }
i.lg.norow   { background: #5a3596; }
i.lg.apponly { background: var(--accent); }
i.lg.ghost   { background: transparent; border: 1px dashed var(--line-strong); }

@media print {
  table.mgrid { font-size: 8.5px; }
  table.mgrid tr { break-inside: avoid; }
  .issuebox { break-inside: avoid; }
}

/* Scenario builder on the merged grid — the fixes, and what each costs. */
.fixrow { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.fixbtn {
  flex: 1 1 190px; text-align: left; padding: 10px 13px; border-radius: var(--radius);
  border: 1px solid var(--line-strong); background: var(--panel); cursor: pointer;
  font: inherit; line-height: 1.3;
}
.fixbtn b { display: block; font-size: 13px; color: var(--ink); }
.fixbtn span { display: block; font-size: 11.5px; color: var(--muted); margin-top: 2px; }
.fixbtn:hover { border-color: var(--accent); }
.fixbtn.on { background: var(--accent); border-color: var(--accent); }
.fixbtn.on b, .fixbtn.on span { color: #fff; }
.fixbtn.on span { opacity: .85; }
.fixsteps { margin: 0 0 12px; padding-left: 20px; font-size: 12.5px; color: var(--accent-deep); }
.fixsteps li { margin-bottom: 3px; }

table.famtable td, table.famtable th { padding: 6px 9px; }
table.famtable td.c, table.famtable th.c { text-align: center; }
table.famtable td.muted { color: var(--faint); }
table.famtable td.strong { font-weight: 700; font-size: 15px; color: var(--accent); }
table.famtable td.down { color: var(--stop); font-weight: 600; }
table.famtable td.up { color: var(--done-ink); font-weight: 600; }
table.famtable tfoot td { border-top: 2px solid var(--line-strong); font-weight: 600; }
.givenup { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
.givenup h4 { margin: 0 0 8px; font-size: 12.5px; color: var(--muted); }

/* The proposed grid — a printout correction, not a draft. Styled to look
   deliberately unlike the draft board so the two are never confused. */
.proposalcard { border-left: 4px solid var(--warn); }
table.proposal td.mno { background: var(--panel); color: var(--faint); }
table.proposal tr.handedback td { background: #f7f8fa; }
.p-final { background: var(--ink); }
.p-new   { background: var(--done-ink); }
.p-gone  { background: transparent; color: var(--faint); border: 1px dashed var(--line-strong);
           font-weight: 500; text-decoration: line-through; }

/* Adjusted grid — the callout for the two families that need a conversation. */
.callout {
  margin-top: 16px; padding: 14px 16px; border-radius: var(--radius);
  background: var(--accent-soft); border: 1px solid var(--accent-line);
}
.callout h4 { margin: 0 0 10px; font-size: 13.5px; color: var(--accent-deep); }
.calloutrow { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.calloutrow p { margin: 6px 0; font-size: 12.5px; line-height: 1.5; }
.calloutrow ul { margin: 6px 0 0; padding-left: 18px; font-size: 12.5px; }
.calloutrow li { margin-bottom: 4px; }
@media (max-width: 800px) { .calloutrow { grid-template-columns: 1fr; } }
i.lg.final { background: var(--ink); }
i.lg.gone  { background: transparent; border: 1px dashed var(--line-strong); }
i.lg.new   { background: var(--done-ink); }
/* Final grids: a cell this class does not fill reads the same on both sheets —
   grey, centred, saying plainly who covers it instead. */
table.xgrid td.xno {
  background: #d9d9d9; color: #5f5f5f; text-align: center;
  font-size: 9.5px; font-weight: 600; letter-spacing: .02em;
}

/* The adjusted-grid key shows the actual pill, not an abstract swatch — the
   three states differ by fill, strike and colour, which a 12px square cannot
   convey. */
.keylegend { display: flex; flex-direction: column; gap: 7px; margin-bottom: 12px; }
.keylegend span { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--muted); }
.keylegend .mname { flex: none; }

/* --- Admin drop-down in the header ---------------------------------------
   Native <details>, so it opens on touch and by keyboard with no script.
   The panel is absolutely positioned so it never reflows the header. */
.navmenu { position: relative; }
.navmenu > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: inline-flex; align-items: center; gap: 4px;
  color: var(--accent);
}
.navmenu > summary::-webkit-details-marker { display: none; }
.navmenu > summary::after {
  content: '▾'; font-size: 10px; line-height: 1; opacity: .7;
}
.navmenu > summary:hover { text-decoration: underline; }
.navmenu[open] > summary { text-decoration: underline; }
.navmenu-list {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 40;
  min-width: 148px; display: flex; flex-direction: column; gap: 2px;
  padding: 6px; border: 1px solid var(--line); border-radius: 10px;
  background: #fff; box-shadow: 0 8px 24px rgba(20,28,44,.14);
}
.navmenu-list a {
  padding: 6px 10px; border-radius: 7px; white-space: nowrap;
}
.navmenu-list a:hover { background: var(--accent-soft); text-decoration: none; }
@media (max-width: 640px) {
  /* No room to float on a phone — let it push the header open instead. */
  .navmenu { position: static; }
  .navmenu-list { position: static; box-shadow: none; margin-top: 6px; }
}

/* A retired row: kept on the sheet so it reads as dropped, not forgotten. */
tr.xstruck td { color: var(--faint); background: repeating-linear-gradient(
  135deg, transparent, transparent 6px, rgba(148,160,177,.09) 6px, rgba(148,160,177,.09) 12px); }
tr.xstruck td.xtopic { text-decoration: line-through; }
.xretired {
  display: block; margin-top: 2px; text-decoration: none;
  font-size: 11px; font-style: italic; color: var(--muted);
}
.callout.open { border-color: var(--warn-line); background: var(--warn-soft); }
.callout ul.settled { margin: 6px 0 12px; padding-left: 18px; }
.callout ul.settled li { margin-bottom: 7px; }
.resnote { margin-top: 3px; font-size: 11.5px; color: #16543f; }
.opennote { margin-top: 3px; font-size: 11.5px; color: var(--warn); font-weight: 600; }
tr.xstruck .what .title { text-decoration: line-through; }

/* An undecided role on the other class's sheet: still a writable box, but
   marked so it does not read as an ordinary blank. */
.xslot.xpending {
  border-style: dashed; border-color: var(--warn-line);
  background: var(--warn-soft); color: var(--warn);
  font-size: 11px; font-weight: 600; line-height: 1.25;
  display: flex; align-items: center; justify-content: center; text-align: center;
}

/* A 1st grade win in a locked column — settled, not merely claimed. */
.tstatus.won.locked { background: var(--ink); color: #fff; }
.tstatus.won.locked .twhy { color: #cdd6e2; }
/* Per-parent tallies on the 4th grade form card. */
.ptally { display: grid; grid-template-columns: 1fr auto auto; gap: 10px; font-size: 13px; padding: 1px 0; }
.ptally b { font-variant-numeric: tabular-nums; }

/* Live tick counts beside each parent's column. */
.hcount {
  display: inline-block; min-width: 18px; padding: 0 5px; margin-left: 2px;
  border-radius: 999px; background: var(--accent-soft); color: var(--accent);
  font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.ptallynums { display: flex; gap: 10px; }
/* The second shift of a split day — same date, its own job. */
tr.shift2 > td.when, tr.shift2 > td.g1, tr.shift2 > td.g1stat { border-top-color: transparent; }
.shift {
  display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent); font-size: 11px; font-weight: 700;
}
/* A row recorded against the family rather than one parent. */
.xgrid td.xfam { text-align: center; font-weight: 600; color: var(--ink); background: var(--accent-soft); }

/* --- Combined calendar ----------------------------------------------------
   A month grid with both grades on it. Corner badges carry the grade and the
   parent initials so a cell reads at a glance without opening anything. */
.cmonth { margin: 0 0 26px; break-inside: avoid; }
.cmonth h3 { font-size: 17px; margin: 0 0 8px; }
.cpom { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 8px; }
.pb {
  flex: 1 1 240px; padding: 5px 10px; border-radius: 7px;
  font-size: 12px; font-weight: 700; letter-spacing: .01em;
}
.pb.g1st { background: var(--accent); color: #fff; }
.pb.g4th { background: #2f6b47; color: #fff; }

.cgrid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
.cdow {
  text-align: center; font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--faint); padding: 2px 0;
}
.ccell {
  min-height: 76px; border: 1px solid var(--line); border-radius: 8px;
  padding: 4px 5px 5px; background: var(--panel); overflow: hidden;
}
.ccell.empty { border-color: transparent; background: transparent; }
.ccell.has { border-color: var(--line-strong); }
.chead { display: flex; align-items: center; gap: 4px; margin-bottom: 3px; }
.cday { margin-left: auto; margin-right: auto; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.cgrade, .cwho { display: flex; gap: 2px; }
.gb {
  padding: 0 4px; border-radius: 4px; font-size: 9px; font-weight: 800;
  line-height: 14px; letter-spacing: .02em;
}
.gb.g1st { background: var(--accent); color: #fff; }
.gb.g4th { background: #2f6b47; color: #fff; }
.wb {
  display: inline-block; min-width: 14px; text-align: center;
  border-radius: 4px; background: var(--ink); color: #fff;
  font-size: 9px; font-weight: 800; line-height: 14px;
}
.citem {
  margin-top: 3px; padding: 3px 5px; border-radius: 6px; border-left: 3px solid var(--accent);
  background: var(--accent-soft); font-size: 11px; line-height: 1.25;
}
.citem.g4th { border-left-color: #2f6b47; background: #e8f3ec; }
.citem b { display: block; font-size: 11px; }
.cwhoname { display: block; color: var(--muted); }
.ctags { display: block; color: var(--faint); font-size: 10px; }
.clegend {
  display: flex; flex-wrap: wrap; gap: 14px; align-items: center;
  margin: 0 0 12px; font-size: 12px; color: var(--muted);
}
@media (max-width: 780px) {
  .cgrid { grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 2px; }
  .ccell { min-height: 58px; padding: 3px; }
  .citem { font-size: 10px; }
}
@media print {
  .cmonth { break-inside: avoid; }
  .ccell { min-height: 66px; }
}

/* --- Combined calendar, as day cards -------------------------------------- */
.dmonth { margin: 22px 0 10px; }
.dmonth h3 { font-size: 17px; margin: 0 0 8px; }
.dday {
  display: grid; grid-template-columns: 116px minmax(0, 1fr); gap: 12px;
  padding: 10px 0; border-top: 1px solid var(--line); break-inside: avoid;
}
.dday.both { background: linear-gradient(90deg, var(--accent-soft) 0 4px, transparent 4px); }
.ddate { display: flex; flex-direction: column; gap: 2px; padding-left: 10px; }
.dnum { font-size: 26px; font-weight: 700; line-height: 1; color: var(--ink); }
.ddow { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--faint); }
.dgrades, .dwhos { display: flex; gap: 3px; }
.dcards { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.dcard {
  border: 1px solid var(--line); border-left: 4px solid var(--accent);
  border-radius: 9px; padding: 9px 12px; background: var(--panel);
}
.dcard.g4th { border-left-color: #2f6b47; }
.dcardhead { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.dtitle { font-size: 14px; }
.dwho { margin-left: auto; display: flex; align-items: center; gap: 5px; font-size: 12px; color: var(--muted); }
.ddesc { margin: 6px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--ink); }
.dnote { margin: 5px 0 0; font-size: 11px; font-style: italic; color: var(--faint); }
.dchips { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 7px; }
.dchips .chip {
  padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 600;
  background: var(--bg); color: var(--muted); border: 1px solid var(--line);
}
.dchips .chip.drive { background: #fff2cc; border-color: #d9a441; color: #6b4c00; }
.dchips .chip.dress { background: #f3e8fb; border-color: #c9a6e0; color: #5b2d7a; }
.dchips .chip.nodress { background: #e8f3ec; border-color: #9fd3b5; color: #16543f; }
.dchips .chip.span, .dchips .chip.time { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent); }
.dchips .chip.role { background: var(--ink); border-color: var(--ink); color: #fff; }
.allyear { margin-bottom: 16px; }
@media (max-width: 700px) {
  .dday { grid-template-columns: 1fr; gap: 6px; }
  .ddate { flex-direction: row; align-items: baseline; gap: 8px; padding-left: 0; }
  .dnum { font-size: 20px; }
}

/* Combined calendar in landscape: two columns of days across the sheet, and
   never split a day or a month heading across a page. */
@media print {
  .dday { break-inside: avoid; page-break-inside: avoid; }
  .dmonth { break-after: avoid; page-break-after: avoid; }
  .dcard { break-inside: avoid; page-break-inside: avoid; }
  .allyear { break-inside: avoid; }
  body.wide-page .exportdoc .dday { grid-template-columns: 130px minmax(0, 1fr); }
  .ddesc { font-size: 9.5pt; }
  .dchips .chip { font-size: 8.5pt; }
  .dtitle { font-size: 11pt; }
  .dnum { font-size: 18pt; }
}

/* --- Family calendars on a phone -----------------------------------------
   The parent columns are the point of these pages, and on a 375px screen they
   sit off the right edge behind a horizontal scroll. Below 700px each row
   becomes a stacked card instead, so the name is always visible. Scoped to
   .calsheet so the Final Grids, which need their full column shape, are
   untouched. */
@media (max-width: 700px) {
  .calsheet .scroll { border: none; overflow: visible; }
  .calsheet table.xgrid { display: block; font-size: 14px; }
  .calsheet table.xgrid thead { display: none; }
  .calsheet table.xgrid tbody { display: block; }
  .calsheet table.xgrid tr {
    display: block; border: 1px solid var(--line-strong);
    border-radius: 10px; padding: 10px 12px; margin-bottom: 8px;
    background: var(--panel);
  }
  .calsheet table.xgrid td { display: block; border: none; padding: 0; }
  /* An unassigned parent cell carries nothing worth a line of its own. */
  .calsheet table.xgrid td.xno { display: none; }
  .calsheet table.xgrid td.xtopic {
    width: auto; font-weight: 700; font-size: 15px; line-height: 1.3;
    color: var(--ink); margin-bottom: 3px;
  }
  .calsheet table.xgrid td.xdate {
    width: auto; display: inline-block; white-space: normal;
    font-size: 12.5px; color: var(--muted);
  }
  .calsheet table.xgrid td.xdate + td.xdate::before {
    content: '\00b7'; margin: 0 6px; color: var(--faint);
  }
  .calsheet table.xgrid td.xfam,
  .calsheet table.xgrid td:has(.xslot) { margin-top: 7px; }
  .calsheet .xslot, .calsheet td.xfam {
    display: inline-block; width: auto; min-height: 0;
    padding: 3px 12px; border-radius: 999px;
    background: var(--accent); color: #fff;
    font-size: 12.5px; font-weight: 700; text-align: left;
  }
  .calsheet td.xfam { background: var(--ink); }
  .calsheet .xslot.xempty { display: none; }
  .calsheet .xtitle { font-size: 17px; }
  .calsheet .xfoot { font-size: 12.5px; }
}

/* --- defence against third-party global resets -----------------------------
   The Stratis chat widget injects a Tailwind-style preflight into <head> at
   runtime, after this stylesheet. Its selectors are plain element selectors,
   so on equal specificity the later rules win and our headings flatten to
   16px/400 and our bullets disappear.

   Rather than chase it property by property, re-assert the handful of things
   a preflight resets, scoped to the three regions we own. The #id and .class
   prefixes outrank any bare element selector, so this holds regardless of
   load order or what the vendor ships next.

   Everything here restates a value already declared above; nothing new is
   designed in this block. If the widget is ever removed, deleting this block
   changes nothing visually. */
#root h1, header.top h1 { font-size: 26px; font-weight: 700; margin: 0 0 8px; }
#root h2, header.top h2 { font-size: 22px; font-weight: 700; margin: 0 0 6px; letter-spacing: -.015em; }
#root h3, header.top h3 { font-size: 15px; font-weight: 700; margin: 0 0 10px; }
#root h4 { font-size: 14px; font-weight: 700; margin: 0 0 8px; }
#root p, footer.site p { margin: 0 0 10px; }
#root ul, #root ol { list-style: revert; margin: 0 0 10px; padding-left: 24px; }
#root li { list-style: revert; }
#root b, #root strong, header.top strong, footer.site strong { font-weight: 700; }
#root table { border-collapse: collapse; }
#root img { display: initial; max-width: 100%; }

/* The chat widget floats over the bottom-right corner. Every calendar and grid
   page has a Print / Save as PDF button, and a chat bubble baked into a PDF
   that goes to Mary Beth or gets pinned to a fridge is not what anyone wants.
   It renders entirely inside #chatWidgetRoot, so one rule covers it. */
@media print { #chatWidgetRoot { display: none !important; } }

/* --- "view as parent" ------------------------------------------------------
   A room parent checking their own work. Client side only: the session is
   untouched and the server still enforces the real one. The striped bar exists
   so nobody spends ten minutes wondering why the Draft menu vanished. */
.viewswitch { white-space: nowrap; }
.viewswitch.on {
  background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600;
}
body.previewing { border-top: 3px solid var(--accent); }
body.previewing::before {
  content: 'Viewing as a family — the Draft and Baliles menus are hidden';
  display: block;
  background: repeating-linear-gradient(135deg,
    var(--accent-soft), var(--accent-soft) 10px, #dbe6f4 10px, #dbe6f4 20px);
  color: var(--accent-deep);
  font-size: 12.5px; font-weight: 600; text-align: center;
  padding: 5px 12px;
  border-bottom: 1px solid var(--accent-line);
}
@media print { body.previewing::before { display: none; } body.previewing { border-top: 0; } }

/* --- This Week ------------------------------------------------------------- */
.sources { background: var(--accent-soft); border-color: var(--accent-line); padding: 12px 16px; }
.sources.tight { margin-top: 16px; font-size: 13.5px; }
.sources p { margin: 0; font-size: 14px; line-height: 1.5; }
ul.daylist { margin: 0; padding-left: 18px; }
ul.daylist li { margin: 0 0 4px; }
ul.daylist li:last-child { margin-bottom: 0; }
table.xgrid tr.today td { background: var(--accent-soft); }
table.xgrid tr.today td.xtopic { font-weight: 700; color: var(--accent-deep); }
@media print { .sources { display: none; } }
table.xgrid td.xtime { white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--ink); }


/* --- class photo album ---------------------------------------------------- */
.uploadbar { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
/* The album's choose-and-download toolbar. Shares the upload row's shape on a
   wide screen but not its behaviour on a narrow one, so it has its own name. */
.albumbar { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.uploadbar select { min-width: 150px; }
.uploadbar input[type="text"] { flex: 1 1 220px; min-width: 160px; }

.shots {
  display: grid; gap: 12px; margin-top: 16px;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}
.shot {
  margin: 0; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow);
}
.shot img, .shot video {
  display: block; width: 100%; aspect-ratio: 4 / 3;
  object-fit: cover; background: #eef1f5;
}
.shot figcaption {
  display: flex; gap: 8px; align-items: center; justify-content: space-between;
  padding: 8px 10px; font-size: 13px;
}
.shot figcaption span:first-child { flex: 1; min-width: 0; overflow-wrap: anywhere; }
@media (max-width: 560px) {
  .shots { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
}

/* Album tiles are for choosing, so the whole tile is the target rather than a
   small checkbox that is hard to hit on a phone. */
.shot.pick { cursor: pointer; position: relative; user-select: none; }
.shot.pick:hover { border-color: var(--accent-line); }
.shot.pick.on { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent); }
.shot .tick {
  position: absolute; top: 8px; left: 8px; z-index: 1;
  width: 24px; height: 24px; border-radius: 50%;
  border: 1.5px solid rgba(255,255,255,.9); background: rgba(20,30,45,.45);
  color: #fff; font-size: 15px; line-height: 22px; text-align: center;
}
.shot.pick.on .tick { background: var(--accent); border-color: var(--accent); }
.shot.pick.on img, .shot.pick.on video { opacity: .82; }

/* ---------------------------------------------------------------------------
   Phones.
   The album is the part of this site most likely to be opened on a phone: it
   is where a parent goes straight after taking a photo. These rules were
   written against a 375px viewport with real content in the album, fixing what
   actually broke rather than what looked risky.
   --------------------------------------------------------------------------- */
@media (max-width: 620px) {
  /* .sheethead stacks to a column on a phone, which turns any button in it
     into a full-width block. Full width is right for a thumb; left-aligned
     text in a bordered full-width box is not, because it reads as an empty
     input field rather than something to tap. */
  .sheethead > a.btn, .sheethead > button { text-align: center; }
}

@media (max-width: 620px) {
  /* The buttons inherit desktop padding, which leaves them about 26px tall and
     the family select about 22px. Both are well under the ~44px that Apple and
     Google both put as the floor for something you hit with a thumb, and these
     are the controls the whole page exists for: print, download, add photos,
     choose your family. Given a real height rather than a bigger font, so the
     type stays the size it was. */
  .sheetactions button, .albumbar button, .uploadbar button, .uploadbar select,
  .uploadbar input[type="text"], .sheethead > a.btn, .sheethead > button {
    min-height: 44px;
  }

  /* Delete sits inside a small tile caption and already asks for confirmation.
     It gets a comfortable target without becoming the biggest thing on the
     tile, which would invite the mis-tap it is guarding against. */
  .shot figcaption button { min-height: 34px; }
}

@media (max-width: 560px) {
  /* Two tiles across at 375px leaves about 165px each. Caption, family and
     Delete on one row squeezed the caption into a column one character wide:
     "Art 2026" came out as "Art / 20 / 26". So the caption takes the full
     width and the rest sits underneath it. */
  .shot figcaption { flex-wrap: wrap; row-gap: 2px; padding: 8px; }
  .shot figcaption > span:first-child { flex: 1 1 100%; }
  .shot figcaption > .muted.small { flex: 1 1 auto; }

  /* Comfortably tappable without a mis-hit deleting a photo. */
  .shot figcaption button { padding: 4px 10px; }

  /* One clear column of controls beats four half-width buttons wrapping into
     each other. The count goes on its own line so it is readable while
     choosing. */
  .albumbar { flex-direction: column; align-items: stretch; }
  .albumbar button { width: 100%; }
  .albumbar > .muted.small {
    flex: none !important; width: 100%; display: block;
    text-align: center; padding: 2px 0;
  }

  /* Same reasoning for the upload row: family, caption and the button each
     get the full width rather than being crushed onto one line. */
  .uploadbar { flex-direction: column; align-items: stretch; }
  /* flex-grow on the caption field is meant to share out spare width in a row.
     Once this becomes a column that same grow applies to height, and the field
     stretched into a 430px block. Reset it: in a column each control is just
     its natural height. */
  .uploadbar select, .uploadbar input[type="text"], .uploadbar button {
    flex: 0 0 auto; width: 100%; min-width: 0;
  }

  /* The selection tick is the only hit target on an album tile that is not the
     tile itself, so it needs to be a finger, not a cursor. */
  .shot .tick { width: 28px; height: 28px; line-height: 26px; font-size: 16px; }

  /* The chat widget floats over the bottom-right corner. Without room to
     scroll past it, the last tile in the album can never be fully seen. */
  #root { padding-bottom: 72px; }
}

/* --- home screen install hint ---------------------------------------------- */
/* Inside its own .wrap, so width and centring come from there. */
.installbar {
  display: flex; align-items: center; gap: 12px;
  margin: 0 0 18px; padding: 12px 16px;
  background: var(--panel); border: 1px solid var(--accent-line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  font-size: 14px;
}
.installbar img { border-radius: 8px; flex: none; }
.installbar .installtext { flex: 1; min-width: 0; }
.installbar button { flex: none; }
@media (max-width: 620px) {
  /* Wraps to two rows on a phone. The crest stays beside the sentence it
     belongs to rather than being orphaned next to a button, and the buttons
     drop to their own row pushed right, where a thumb expects them. */
  .installbar { margin: 0 0 16px; flex-wrap: wrap; row-gap: 4px; }
  .installbar .installtext { flex: 1 1 0; min-width: 150px; }
  .installbar button { min-height: 40px; }
  .installbar button:first-of-type { margin-left: auto; }
}
@media print { .installbar { display: none !important; } }

/* --- eDays: the Friday Enrichment Day timetable ---------------------------- */
.edaypair {
  display: grid; grid-template-columns: 1fr 1fr; gap: 22px; align-items: start;
}
.edaypair h3 { margin: 0 0 2px; }
.edaypair .muted.small { margin: 0 0 10px; }
.edaygrid { width: 100%; }
.edaygrid td { padding: 7px 10px; }

/* The blocks no special has claimed. Shaded rather than left blank, because on
   an Enrichment Day this is the parent's teaching time and it is the one thing
   they are looking for. */
.edaygrid tr.openslot td { background: var(--accent-soft); }
.edaygrid .openlabel { color: var(--accent-deep); font-weight: 600; }

@media (max-width: 760px) {
  .edaypair { grid-template-columns: 1fr; gap: 26px; }
}
@media print {
  /* Both timetables side by side on one sheet, which is how it gets stuck to a
     fridge. */
  .edaypair { grid-template-columns: 1fr 1fr; gap: 14px; }
  .edaygrid tr.openslot td { background: #e7eef7 !important;
    -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* --- family calendar actions ----------------------------------------------- */
.calactions { display: flex; gap: 8px; align-items: center; flex: none; }
@media (max-width: 620px) {
  .calactions { width: 100%; }
  .calactions .btn { flex: 1; text-align: center; min-height: 44px; line-height: 26px; }
}
@media print { .calactions { display: none !important; } }

/* ---------------------------------------------------------------------------
   Directory. One card per family, each parent a name over a mailto and a tel.
   The links are laid out as rows rather than a table so a long gmail address
   wraps on a phone instead of forcing the page sideways. */
.dirgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 14px;
}
.dirgrid .card { margin-bottom: 0; }
.dirparent { padding: 8px 0; border-top: 1px solid var(--line); }
.dirparent:first-of-type { border-top: 0; padding-top: 0; }
.dirname { font-weight: 600; margin-bottom: 2px; }
/* Own line each, and break-anywhere so an address can never widen the card. */
.dirlink {
  display: block;
  font-size: 13px;
  line-height: 1.55;
  overflow-wrap: anywhere;
}
/* "Add to Contacts". An <a>, so it needs its own box: button.ghost is scoped
   to real buttons. Sits under the address and number as the third, quieter
   action on the row. */
a.vcard {
  display: inline-block;
  margin-top: 6px;
  padding: 5px 11px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.4;
  border: 1px solid var(--line-strong);
  border-radius: 7px;
  background: var(--panel);
  color: var(--muted);
  text-decoration: none;
}
a.vcard:hover { color: var(--ink); border-color: var(--accent-deep); }
@media (max-width: 700px) {
  .dirgrid { grid-template-columns: 1fr; gap: 12px; }
  /* Comfortable tap targets when the point of the page is tapping. */
  .dirlink { font-size: 14px; padding: 3px 0; }
  a.vcard { margin-top: 8px; padding: 8px 14px; font-size: 13px; }
}
@media print {
  .dirgrid { grid-template-columns: 1fr 1fr; gap: 10px; }
  .dirgrid .card { box-shadow: none; break-inside: avoid; }
}
