/* Termbook.
 *
 * Hand-written, no build step (ADR 0010). Tokens and idioms ported from
 * termbook-pricing.html, which is the design the product is sold on.
 *
 * The metaphor is an exercise book: paper ground, pen ink, a red margin rule, a
 * well-done stamp in green. Teacher input is set on feint rules in a handwriting face;
 * generated prose is set clean. That contrast is the product's argument made visible -
 * rough notes in, parent-ready prose out - so it is load-bearing, not decoration.
 */

:root {
  --ink: #16233F;          /* pen ink */
  --ink-soft: #4A5670;
  --ink-faint: #8B94A8;
  --paper: #FBFCFE;        /* exercise book paper */
  --paper-warm: #F4F1E9;
  --rule: #CBD9EE;         /* feint rule */
  --margin-red: #D8323F;   /* the red margin line */
  --stamp: #1F6B4D;        /* well done stamp green */
  --manila: #E9DEC4;
  --line: #DDE3EC;
  --danger: #B3261E;
  --danger-bg: #FDF3F2;
  --shadow: 0 1px 2px rgba(22, 35, 63, .06), 0 8px 24px -12px rgba(22, 35, 63, .18);
  --radius: 10px;
  --radius-sm: 6px;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: "Literata", Georgia, serif;
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* Hold the footer to the bottom on a short page. Half the app's pages are one card
     and a sentence - a footer floating in the middle of the window looks like the page
     failed to load the rest of itself. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

h1, h2, h3, h4 {
  font-family: "Familjen Grotesk", system-ui, sans-serif;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -.015em;
  margin: 0;
}

a { color: inherit; }
button { font: inherit; cursor: pointer; }

/* Red, thick, offset. Keyboard users get the same signature as the margin rule. */
:focus-visible {
  outline: 3px solid var(--margin-red);
  outline-offset: 3px;
  border-radius: 4px;
}

.mono {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
}

/* The signature: the red margin line down the left of the page. */
.page-rule {
  position: fixed;
  inset: 0 auto 0 0;
  width: 64px;
  border-right: 1px solid var(--margin-red);
  opacity: .3;
  pointer-events: none;
  z-index: 0;
}
@media (max-width: 1180px) { .page-rule { display: none; } }

.wrap { max-width: 1080px; margin: 0 auto; padding: 0 24px; }
.wrap-narrow { max-width: 620px; margin: 0 auto; padding: 0 24px; }

/* ---------- header ---------- */

header.site {
  position: relative;
  z-index: 2;
  border-bottom: 1px solid var(--line);
  background: var(--paper);
}
.hdr {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 24px;
  max-width: 1080px;
  margin: 0 auto;
}
.logo {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: "Familjen Grotesk", system-ui, sans-serif;
  font-weight: 700;
  font-size: 20px;
  letter-spacing: -.02em;
  text-decoration: none;
}
/* The spine of a small red exercise book. */
.logo i {
  display: block;
  width: 19px;
  height: 25px;
  border-radius: 2px 3px 3px 2px;
  background: var(--margin-red);
  box-shadow: inset 4px 0 0 rgba(0, 0, 0, .22);
}
.hdr nav { display: flex; align-items: center; gap: 22px; font-size: 15px; }
.hdr nav a { text-decoration: none; color: var(--ink-soft); }
.hdr nav a:hover, .hdr nav a[aria-current="page"] { color: var(--ink); }

.whoami {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 12.5px;
  color: var(--ink-faint);
  /* An email address is long and the least important thing in the header. Truncate
     rather than push the sign-out button off the edge, and drop it entirely on a
     phone - a teacher knows who they are signed in as. */
  max-width: 22ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Below 700px the email goes first - a teacher knows who they are signed in as. Below
   560px the nav wraps to its own line rather than pushing Sign out off the edge, which
   is what a phone or a narrow tablet split-screen actually does. */
@media (max-width: 700px) {
  .whoami { display: none; }
  .hdr { gap: 10px; padding: 14px 18px; }
  .hdr nav { gap: 14px; font-size: 14px; }
  .logo { font-size: 18px; }
}
@media (max-width: 560px) {
  .hdr { flex-wrap: wrap; }
  .hdr nav { width: 100%; justify-content: flex-start; gap: 16px; }
}

/* ---------- page furniture ---------- */

main { position: relative; z-index: 1; padding: 40px 0 72px; flex: 1 0 auto; }

.eyebrow {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 12.5px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--margin-red);
  margin-bottom: 14px;
}
.page-head { margin-bottom: 32px; }
.page-head h1 { font-size: clamp(28px, 4.5vw, 40px); }
.page-head p { color: var(--ink-soft); margin: 12px 0 0; max-width: 58ch; }

.card {
  border: 1px solid var(--line);
  border-radius: 14px;
  background: #fff;
  padding: 26px;
  box-shadow: var(--shadow);
}
.card + .card { margin-top: 18px; }
.card-manila { background: var(--manila); border-color: #D3C4A2; }

.stack > * + * { margin-top: 18px; }
.row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.row-between { display: flex; gap: 16px; align-items: center; justify-content: space-between; flex-wrap: wrap; }
/* Card headers keep the title and its status on one line and let the title shrink,
   rather than wrapping unpredictably depending on how long the metadata happens to be.
   Two cards side by side with the status in different places reads as a bug. */
.card-head { display: flex; gap: 16px; align-items: baseline; justify-content: space-between; }
.card-head > :first-child { min-width: 0; }
.card-status { flex: none; }
.grow { flex: 1 1 auto; }

/* ---------- forms ---------- */

label.field-label {
  display: block;
  font-family: "Familjen Grotesk", system-ui, sans-serif;
  font-weight: 600;
  font-size: 15px;
  margin-bottom: 6px;
}
.field-hint {
  font-size: 14px;
  color: var(--ink-faint);
  margin: -2px 0 8px;
}
input[type="text"], input[type="email"], input[type="number"],
input[type="password"], select, textarea {
  width: 100%;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: #fff;
  font-family: inherit;
  font-size: 16px;
  color: var(--ink);
  line-height: 1.5;
}
input:focus, select:focus, textarea:focus { border-color: var(--ink-faint); }

/* Word targets are three digits. A full-width box invites someone to type an essay into
   it, and the spinners add nothing when the range is already bounded. */
input[type="number"] { max-width: 9ch; -moz-appearance: textfield; appearance: textfield; }
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
textarea { resize: vertical; min-height: 76px; }

/* Teacher input sits on feint rules in a handwriting face. Rough notes should look
 * like rough notes; that is what makes the generated prose feel like a step forward. */
textarea.scrawl {
  font-family: "Caveat", "Bradley Hand", cursive;
  font-size: 22px;
  line-height: 34px;
  color: #2A3E6B;
  background-image: repeating-linear-gradient(
    to bottom, transparent 0 33px, var(--rule) 33px 34px
  );
  background-attachment: local;
  padding-top: 6px;
  min-height: 108px;
}

fieldset { border: 0; margin: 0; padding: 0; }
legend { padding: 0; }

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  font-family: "Familjen Grotesk", system-ui, sans-serif;
  font-weight: 600;
  font-size: 16px;
  padding: 12px 20px;
  border-radius: 8px;
  border: 1px solid transparent;
  text-decoration: none;
  transition: .15s;
  background: none;
  color: var(--ink);
}
.btn-primary { background: var(--ink); color: #fff; }
.btn-primary:hover:not(:disabled) { background: #0D1830; }
.btn-ghost { border-color: var(--line); }
.btn-ghost:hover:not(:disabled) { border-color: var(--ink-faint); }
.btn-danger { color: var(--danger); border-color: var(--line); }
.btn-danger:hover:not(:disabled) { border-color: var(--danger); background: var(--danger-bg); }
.btn-sm { font-size: 14px; padding: 8px 14px; }

/* Approve sits beside decline-with-a-reason, so two forms share one table cell. Without
   this they stack and the reason box takes the full column width. */
.row-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.row-actions form { display: flex; gap: 6px; align-items: center; margin: 0; }
.row-actions input[type="text"] { width: auto; max-width: 16ch; padding: 7px 10px; font-size: 14px; }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn-block { width: 100%; }

/* Segmented control, for tone and length. */
.segmented {
  display: inline-flex;
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
  background: #fff;
}
.segmented button {
  border: 0;
  border-right: 1px solid var(--line);
  background: transparent;
  padding: 9px 16px;
  font-family: "Familjen Grotesk", system-ui, sans-serif;
  font-size: 15px;
  color: var(--ink-soft);
}
.segmented button:last-child { border-right: 0; }
.segmented button:hover { background: var(--paper-warm); }
.segmented button[aria-pressed="true"] {
  background: var(--ink);
  color: #fff;
  font-weight: 600;
}

/* ---------- the well-done stamp ---------- */

.stamp {
  display: inline-block;
  background: var(--stamp);
  color: #fff;
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  padding: 5px 11px;
  border-radius: 4px;
  transform: rotate(-2deg);
}
/* Waiting on a decision from us. The same stamp without the congratulation, because a
   request that has not been approved yet must not look like a licence that has. */
.stamp-wait { background: var(--ink-faint); }

.pill {
  display: inline-block;
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 11.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 100px;
  border: 1px solid var(--line);
  color: var(--ink-faint);
}
.pill-done { border-color: var(--stamp); color: var(--stamp); }
.pill-drafted { border-color: var(--margin-red); color: var(--margin-red); }

/* ---------- messages ---------- */

.notice {
  border-left: 3px solid var(--ink-faint);
  background: #fff;
  padding: 12px 16px;
  border-radius: var(--radius-sm);
  font-size: 15.5px;
}
.notice-error { border-left-color: var(--danger); background: var(--danger-bg); color: var(--danger); }
.notice-ok { border-left-color: var(--stamp); }

/* ---------- roster ---------- */

.roster { list-style: none; padding: 0; margin: 0; }
.roster li + li { border-top: 1px solid var(--line); }
.roster a {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 13px 4px;
  text-decoration: none;
}
.roster a:hover { background: var(--paper-warm); }
.roster .name { font-family: "Familjen Grotesk", system-ui, sans-serif; font-weight: 600; }
.roster .idx {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 12px;
  color: var(--ink-faint);
  min-width: 2.5ch;
}

/* Progress through a class. The point of the roster is the pile going down. */
.progress {
  height: 6px;
  border-radius: 100px;
  background: var(--line);
  overflow: hidden;
}
.progress > span { display: block; height: 100%; background: var(--stamp); }

/* ---------- generated draft ---------- */

.draft {
  font-size: 17px;
  line-height: 1.75;
  width: 100%;
  border: 0;
  background: transparent;
  padding: 0;
  min-height: 220px;
  color: var(--ink);
  font-family: inherit;
  resize: vertical;
}
.draft:focus { outline: none; }
.draft-meta {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 12px;
  color: var(--ink-faint);
}

.muted { color: var(--ink-soft); }
.faint { color: var(--ink-faint); }
.small { font-size: 14px; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- pupil workspace ---------- */

.workspace { display: grid; grid-template-columns: 1fr; gap: 22px; }
@media (min-width: 980px) {
  .workspace { grid-template-columns: minmax(0, 1fr) 440px; align-items: start; }
  /* The draft stays in view while the teacher scrolls their notes. Reading the two
     against each other is the actual task. */
  .workspace-draft { position: sticky; top: 24px; }
}

.qnum {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  margin-right: 9px;
  border-radius: 50%;
  background: var(--ink);
  color: #fff;
  font-size: 11px;
  vertical-align: 1px;
}

.draft-empty { min-height: 220px; display: flex; flex-direction: column; justify-content: center; }

/* htmx toggles this while a request is in flight. */
.htmx-indicator { opacity: 0; transition: opacity .15s; }
.htmx-request .htmx-indicator, .htmx-indicator.htmx-request { opacity: 1; }

/* Question labels arrive mixed-case from the prompt module - a capitalised heading
   followed by a lowercase gloss. Setting them at a smaller size lets both halves read
   naturally without transforming the string. */
.question-label {
  font-size: 14.5px;
  letter-spacing: .01em;
  line-height: 1.4;
}

/* ---------- settings ---------- */

.length-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
@media (max-width: 600px) { .length-grid { grid-template-columns: 1fr; } }

.preview-block + .preview-block { margin-top: 22px; }
.preview-table { width: 100%; border-collapse: collapse; }
.preview-table td { padding: 7px 12px 7px 0; border-top: 1px solid var(--line); }
.preview-table tr:first-child td { border-top: 0; }

/* The two states worth interrupting for: getting tight, and too tight to work. */
.flag-warn { color: var(--margin-red); }
/* The roll-mismatch note in the approval queue (ADR 0025). Wide enough that
   "says 230, DfE 459" stays on one line - the two numbers only mean anything
   read together, and wrapping between them is how you misread it. */
.roll-flag { min-width: 148px; margin-top: 4px; }
.flag-block { color: #fff; background: var(--margin-red); padding: 2px 8px; border-radius: 4px; }

/* ---------- recent drafts ---------- */

.recent-list { list-style: none; padding: 0; margin: 0; }
.recent-list li + li { border-top: 1px solid var(--line); }
.recent-item {
  display: flex;
  align-items: baseline;
  gap: 10px;
  width: 100%;
  padding: 9px 4px;
  background: none;
  border: 0;
  text-align: left;
}
.recent-item:hover { background: var(--paper-warm); }
.recent-name {
  font-family: "Familjen Grotesk", system-ui, sans-serif;
  font-weight: 600;
  flex: 1 1 auto;
}
.recent-meta { font-size: 12px; color: var(--ink-faint); }
/* Marks an entry whose care notes are gone, so the flag is visible before restoring
   rather than only in the warning afterwards. */
.recent-flag {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 10.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--margin-red);
}

/* ---------- pricing ---------- */

.plans { display: grid; grid-template-columns: 1fr 1.15fr; gap: 22px; align-items: start; }
@media (max-width: 820px) { .plans { grid-template-columns: 1fr; } }

.price { display: flex; align-items: baseline; gap: 9px; margin: 14px 0 4px; }
.price b {
  font-family: "Familjen Grotesk", system-ui, sans-serif;
  font-size: 44px;
  font-weight: 700;
  letter-spacing: -.03em;
}
.price span { font-size: 13px; color: var(--ink-soft); }

.feat { list-style: none; padding: 0; margin: 18px 0 22px; font-size: 15.5px; }
.feat li { display: flex; gap: 11px; padding: 6px 0; color: var(--ink-soft); }
.feat li::before {
  content: "";
  flex: none;
  width: 7px;
  height: 7px;
  margin-top: 9px;
  border-radius: 2px;
  background: var(--margin-red);
  opacity: .55;
}
.card-manila .feat li::before { background: var(--ink); opacity: .4; }

/* ---------- skip link ---------- */

/* The workspace has a lot of header above the notes field. A keyboard user should not
   have to tab the whole nav to reach it. */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 8px;
  z-index: 5;
  background: var(--ink);
  color: #fff;
  padding: 10px 16px;
  border-radius: var(--radius-sm);
  text-decoration: none;
  font-size: 15px;
}
.skip-link:focus { left: 24px; }

/* Staff only, and the one item in the header that is not about your own account. Red
   pen, the same red as the margin rule: this is the marking view. */
/* On a phone the nav wraps to its own line and the buttons get narrow. "Sign out"
   breaking across two lines makes the header taller than the page head below it. */
.hdr nav .btn { white-space: nowrap; }

.hdr nav a.nav-admin { color: var(--margin-red); }
.hdr nav a.nav-admin:hover,
.hdr nav a.nav-admin[aria-current="page"] { color: #A8232E; }

/* ---------- landing ---------- */

.hero { padding: 26px 0 8px; max-width: 40rem; }
.hero h1 {
  font-size: clamp(34px, 5.6vw, 54px);
  letter-spacing: -.025em;
}
.hero p.lede {
  font-size: clamp(18px, 2.2vw, 21px);
  color: var(--ink-soft);
  margin: 18px 0 0;
}

/* The product's argument, made visible rather than described: rough notes on one side,
   parent-ready prose on the other. The CSS at the top of this file calls that contrast
   load-bearing, and until now the landing page only asserted it in words. */
.demo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  gap: 20px;
  align-items: stretch;
  margin-top: 40px;
}
@media (max-width: 860px) {
  .demo { grid-template-columns: minmax(0, 1fr); }
  /* Rotated a quarter turn so it still reads as "this becomes that" when stacked. */
  .demo-arrow { transform: rotate(90deg); justify-self: center; }
}
.demo-panel { display: flex; flex-direction: column; }
.demo-label {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 11.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 10px;
}
.demo-panel .card { flex: 1 1 auto; margin: 0; }
.demo-arrow {
  align-self: center;
  color: var(--margin-red);
  font-size: 26px;
  line-height: 1;
}

/* The static twin of textarea.scrawl. Same hand, same feint rules; not a form control,
   because there is nothing here to type into. */
.scrawl-sample {
  font-family: "Caveat", "Bradley Hand", cursive;
  font-size: 22px;
  line-height: 34px;
  color: #2A3E6B;
  background-image: repeating-linear-gradient(
    to bottom, transparent 0 33px, var(--rule) 33px 34px
  );
  /* No top padding here, unlike the textarea. The rules repeat every 34px from the top
     of the box, so any offset walks the text off its own line. */
  padding: 0;
  margin: 0;
  min-height: 34px;
}
.scrawl-q {
  font-family: "Familjen Grotesk", system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-faint);
  line-height: 1.4;
  margin: 0 0 2px;
}
/* The feint rule sits on the very bottom edge of a sample, so the next question label
   needs air under it or the rule reads as an underline on the label instead. */
.scrawl-sample + .scrawl-q { margin-top: 20px; }
.demo-prose { font-size: 16.5px; line-height: 1.75; margin: 0; }

/* ---------- how it works ---------- */

.steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 26px;
  margin-top: 18px;
}
@media (max-width: 760px) { .steps { grid-template-columns: minmax(0, 1fr); gap: 20px; } }
.step h3 { font-size: 18px; margin-bottom: 6px; }
.step p { margin: 0; color: var(--ink-soft); font-size: 15.5px; }
/* Numbered in red pen, in the margin, where a teacher would number them. */
.step-n {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 12px;
  color: var(--margin-red);
  display: block;
  margin-bottom: 8px;
}

.section { margin-top: 64px; }
.section > h2 { font-size: clamp(22px, 3vw, 28px); }
.section > p.section-lede { color: var(--ink-soft); margin: 10px 0 0; max-width: 56ch; }

/* ---------- footer ---------- */

.site-footer {
  border-top: 1px solid var(--line);
  background: var(--paper);
  position: relative;
  z-index: 1;
  padding: 34px 0 44px;
  margin-top: 72px;
  flex: none;
}
.footer-inner {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) auto;
  gap: 30px;
  align-items: start;
}
@media (max-width: 760px) {
  .footer-inner { grid-template-columns: minmax(0, 1fr); gap: 22px; }
}
.logo-sm { font-size: 17px; }
.logo-sm i { width: 15px; height: 20px; }
.footer-promises {
  list-style: none;
  padding: 0;
  margin: 0;
  color: var(--ink-soft);
}
.footer-promises li { padding-left: 18px; position: relative; }
.footer-promises li + li { margin-top: 6px; }
/* A tick in the margin, in marking green. */
.footer-promises li::before {
  content: "\2713";
  position: absolute;
  left: 0;
  color: var(--stamp);
}
.footer-nav { display: flex; flex-direction: column; gap: 8px; }
.footer-nav a { color: var(--ink-soft); text-decoration: none; }
.footer-nav a:hover { color: var(--ink); text-decoration: underline; }
@media (max-width: 760px) {
  .footer-nav { flex-direction: row; gap: 20px; flex-wrap: wrap; }
}

/* ---------- dashboard ---------- */

/* Two across on a desktop: a teacher with one class should not get a card stretched to
   the width of the window, and one with four should see them all without scrolling. */
.board {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: 18px;
}
.board-class { margin: 0; }
.board-class .progress { margin-top: 2px; }

/* Groups a list of classes by academic year. Only appears when there is more than one
   year to tell apart, so it has to read as a divider rather than a page heading. */
.year-head {
  font-size: 15px;
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 34px 0 14px;
}
.year-head:first-of-type { margin-top: 0; }

/* ---------- editing a register ---------- */

.edit-roster { list-style: none; padding: 0; margin: 18px 0 0; }
.edit-roster li {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 9px 0;
}
.edit-roster li + li { border-top: 1px solid var(--line); }
.edit-roster input[type="text"] { width: auto; flex: 1 1 12ch; min-width: 12ch; }
/* Checkbox and label as one target: the labels are short and the boxes are small, and a
   teacher doing this on a laptop trackpad at 9pm should not have to aim. */
.edit-flag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--ink-soft);
  white-space: nowrap;
  cursor: pointer;
}
.edit-flag input { width: auto; margin: 0; }
.edit-note { flex-basis: 100%; padding-left: 3.4ch; }
/* The year group sits beside the name on a mixed-age register. Narrow enough that the
   row still fits on a laptop, and it wraps below the name on a phone. */
.edit-year { width: auto; max-width: 15ch; padding: 7px 10px; font-size: 14px; }

/* ---------- the pre-launch gate ---------- */

/* No header on this page, so the content needs its own air at the top - and the whole
   thing wants to sit a little above centre rather than clinging to the fold. */
.gate { padding-top: 30px; }
.gate .logo { pointer-events: none; }

/* ---------- admin statistics ---------- */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: 16px;
}
.stat {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px 20px;
  box-shadow: var(--shadow);
}
/* The number is the point of the card, so it is the size of a heading rather than of
   body text - a percentage set at 17px is a percentage nobody reads. */
.stat-value {
  font-family: "Familjen Grotesk", system-ui, sans-serif;
  font-weight: 600;
  font-size: 34px;
  line-height: 1.05;
  letter-spacing: -.02em;
}
.stat-label { color: var(--ink-soft); font-size: 14.5px; margin-top: 6px; }
/* The referral code is read aloud in a staffroom and typed by someone else, so it is
   set large and monospaced. Upright, unlike the well-done stamp: this is a reference,
   not a flourish. */
.stamp-code {
  font-size: 17px;
  letter-spacing: .16em;
  padding: 9px 16px;
  transform: none;
  background: var(--ink);
}

/* ---------- school admin ---------- */

.subnav {
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
  font-size: 15px;
  padding-bottom: 14px;
  margin-bottom: 22px;
  border-bottom: 1px solid var(--line);
}
.subnav a { text-decoration: none; color: var(--ink-soft); }
.subnav a:hover { color: var(--ink); }
/* The current page gets the red margin rule under it, echoing the page edge. */
.subnav a[aria-current="page"] {
  color: var(--ink);
  box-shadow: 0 14px 0 -12px var(--margin-red);
}

.usage-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: 18px;
  align-items: start;
}
.usage { list-style: none; padding: 0; margin: 16px 0 0; }
.usage li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 90px 4ch;
  gap: 10px;
  align-items: center;
  padding: 5px 0;
  font-size: 14.5px;
}
.usage-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Bars rather than a chart library: three lists of counts do not need a build step
   (ADR 0010), and a head reading this wants the shape, not the axis labels. */
.usage-bar { background: var(--line); border-radius: 100px; height: 8px; overflow: hidden; }
.usage-bar > span { display: block; height: 100%; background: var(--stamp); }
.usage-count { text-align: right; color: var(--ink-soft); font-size: 13px; }

.audit-entry + .audit-entry { margin-top: 14px; }
.audit-text { margin: 14px 0 0; line-height: 1.7; }
/* Someone invited but not yet arrived. Present in the list, clearly not yet a member. */
.faded td { opacity: .62; }

/* ---------- marketing page ---------- */

.plans { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); gap: 20px; }
.price { margin: 18px 0 4px; display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.price b {
  font-family: "Familjen Grotesk", system-ui, sans-serif;
  font-size: 44px;
  font-weight: 700;
  letter-spacing: -.03em;
  line-height: 1;
}
.price span { font-size: 13px; color: var(--ink-soft); }
.feat { list-style: none; padding: 0; margin: 18px 0 22px; font-size: 15.5px; }
.feat li { padding-left: 18px; position: relative; color: var(--ink-soft); }
.feat li + li { margin-top: 9px; }
.feat li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .62em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--margin-red);
}

/* The refund is the growth mechanism, so it gets the price set large enough to be the
   thing you read rather than a line of small print. */
.refer { display: flex; gap: 22px; align-items: center; margin-top: 22px; }
.refer-mark {
  font-family: "Familjen Grotesk", system-ui, sans-serif;
  font-weight: 700;
  font-size: 40px;
  letter-spacing: -.03em;
  color: var(--margin-red);
  flex: none;
}
@media (max-width: 560px) { .refer { flex-direction: column; align-items: flex-start; gap: 12px; } }

.case { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); gap: 20px; align-items: start; }
/* A textarea rather than a rendered block: readable, selectable and copyable with no
   JavaScript, which is the state this page has to work in. */
.case-out {
  font-size: 13.5px;
  line-height: 1.65;
  min-height: 380px;
  background: var(--paper-warm);
  resize: vertical;
}
.price-from { font-size: 13px; color: var(--ink-soft); align-self: center; }
/* The three bands, shown rather than summarised: a head wants to know which one they are
   in before they decide anything else. */
.bands { list-style: none; padding: 0; margin: 6px 0 0; font-size: 14px; }
.bands li { display: flex; justify-content: space-between; gap: 12px; padding: 5px 0; }
.bands li + li { border-top: 1px solid rgba(22, 35, 63, .08); }
.bands span { color: var(--ink-soft); }

/* ---------------------------------------------------------------------------
   The school picker (ADR 0025)

   A search over the DfE's own list. Styled as a short stack rather than a
   dropdown: the results are three lines each - name, authority, roll - and
   squeezing that into an autocomplete would hide the roll, which is the number
   the price depends on and the thing they should be reading.
   --------------------------------------------------------------------------- */

.picker > * + * { margin-top: 18px; }
.picker-manual > * + * { margin-top: 18px; }

input[type="search"] {
  width: 100%;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: #fff;
  font-family: inherit;
  font-size: 16px;
  color: var(--ink);
  line-height: 1.5;
}
input[type="search"]:focus { border-color: var(--ink-faint); }

.picker-results {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: #fff;
  /* Twelve results at three lines each is longer than the form. Scrolls rather
     than pushing the billing fields off the screen. */
  max-height: 320px;
  overflow-y: auto;
}
.picker-results li + li { border-top: 1px solid var(--line); }

.picker-choice {
  display: block;
  width: 100%;
  text-align: left;
  padding: 11px 13px;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: 15px;
  color: var(--ink);
  cursor: pointer;
}
.picker-choice:hover, .picker-choice:focus-visible {
  background: var(--paper-warm);
  outline: none;
}

.picker-name {
  display: block;
  font-weight: 600;
  margin: 0;
}
.picker-meta {
  display: block;
  font-size: 13px;
  color: var(--ink-faint);
  margin-top: 2px;
}

.picker-chosen {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 13px 15px;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--stamp);
  border-radius: var(--radius-sm);
  background: var(--paper);
}
.picker-chosen p { margin: 2px 0 0; }
.picker-hint { margin: 8px 0 0; }

/* A button that reads as a link. The picker's escape hatches are actions, not
   navigation, so they are buttons - but making them look like buttons would
   give a form with three of them the weight of a toolbar. */
.linky {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  color: var(--ink);
  text-decoration: underline;
  cursor: pointer;
}
.linky:hover { color: var(--margin-red); }

.btn-small { font-size: 13px; padding: 6px 11px; }
