:root {
  --bg:#0f1115; --panel:#171a21; --panel-2:#1e222b; --line:#2a2f3a;
  --ink:#e8e6e1; --ink-soft:#9aa0ad; --ink-faint:#6b7280;
  --accent:#6fa8dc; --gold:#d8ae57; --green:#6bbf7b; --red:#e0707f;
  color-scheme: dark;
}
:root {
  --amber:#e0a857;
  /* What reads on top of a filled button, and what a tinted pill sits on.
     Both flip with the theme, so nothing has to be hard-coded below. */
  --on-accent:#0f1115;
  --pill-green-bg:#16241a; --pill-green-line:#25402c;
  --pill-amber-bg:#241d12; --pill-amber-line:#3d3220;
  --pill-red-bg:#241419;   --pill-red-line:#40252c;
  --warn:#e0b07a; --danger:#e08a8a; --danger-line:#5a2a2a;
}

/* The book has had light and dark from the start; the panel used to be dark
   whatever you chose. Both now read the same stored preference, so crossing
   between them does not flip the lights. */
:root[data-theme="light"] {
  --bg:#f4f1ea; --panel:#fffdf8; --panel-2:#efebe1; --line:#ddd6c8;
  --ink:#231f1a; --ink-soft:#5d564c; --ink-faint:#8b8378;
  --accent:#2f5d8a; --gold:#9a7420; --green:#2f7a41; --red:#a6384a;
  --amber:#8a6420;
  --on-accent:#ffffff;
  --pill-green-bg:#e6f0e7; --pill-green-line:#b9d4be;
  --pill-amber-bg:#f6eedd; --pill-amber-line:#dfcda2;
  --pill-red-bg:#f7e4e7;   --pill-red-line:#e2bcc3;
  --warn:#8a5a12; --danger:#a6384a; --danger-line:#e2bcc3;
  color-scheme: light;
}
* { box-sizing:border-box; }
body { margin:0; background:var(--bg); color:var(--ink);
  font:15px/1.55 ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif; }
h1,h2,h3 { font-family:"Iowan Old Style",Palatino,Georgia,serif; margin:0 0 .4em; line-height:1.15; }
a { color:var(--accent); }
.wrap { max-width:1100px; margin:0 auto; padding:1.4rem 1.2rem 4rem; }

.bar { display:flex; align-items:center; gap:1rem; padding:.7rem 1.2rem;
  border-bottom:1px solid var(--line); background:var(--panel); position:sticky; top:0; z-index:20; }
.bar .brand { font-family:"Iowan Old Style",Georgia,serif; font-weight:600; }
.bar .who { margin-left:auto; color:var(--ink-soft); font-size:.86rem; }
.tabs { display:flex; gap:.2rem; }
.tabs button { background:none; border:0; color:var(--ink-soft); cursor:pointer;
  padding:.45rem .8rem; border-radius:8px; font-size:.9rem; }
.tabs button:hover { background:#ffffff0d; color:var(--ink); }
.tabs button.on { background:var(--panel-2); color:var(--ink); }

.card { background:var(--panel); border:1px solid var(--line); border-radius:12px; padding:1rem 1.1rem; margin-bottom:1rem; }
.row { display:flex; align-items:center; gap:.7rem; }
.grow { flex:1; min-width:0; }
.muted { color:var(--ink-soft); }
.tiny { font-size:.8rem; }
.btn { background:var(--panel-2); color:var(--ink); border:1px solid var(--line);
  border-radius:8px; padding:.45rem .8rem; cursor:pointer; font-size:.88rem; }
.btn:hover { border-color:var(--accent); }
.btn.primary { background:var(--accent); border-color:var(--accent); color:var(--on-accent); font-weight:600; }
.btn.good { background:var(--green); border-color:var(--green); color:var(--on-accent); font-weight:600; }
.btn.bad { color:var(--red); border-color:var(--pill-red-line); }
.btn:disabled { opacity:.45; cursor:not-allowed; }
.pill { font-size:.72rem; padding:.15rem .5rem; border-radius:99px; border:1px solid var(--line); color:var(--ink-soft); }
.pill.green { color:var(--green); border-color:var(--pill-green-line); background:var(--pill-green-bg); }
.pill.amber { color:var(--amber); border-color:var(--pill-amber-line); background:var(--pill-amber-bg); }
.pill.red { color:var(--red); border-color:var(--pill-red-line); background:var(--pill-red-bg); }
input, textarea, select { width:100%; background:var(--panel-2); color:var(--ink);
  border:1px solid var(--line); border-radius:8px; padding:.5rem .6rem; font:inherit; }
label.f { display:block; margin-bottom:.7rem; }
label.f > span { display:block; font-size:.7rem; letter-spacing:.12em; text-transform:uppercase;
  color:var(--ink-faint); margin-bottom:.25rem; }
table { width:100%; border-collapse:collapse; font-size:.88rem; }
th { text-align:left; font-size:.68rem; letter-spacing:.12em; text-transform:uppercase;
  color:var(--ink-faint); padding:.5rem .6rem; border-bottom:1px solid var(--line); }
td { padding:.55rem .6rem; border-bottom:1px solid var(--line); vertical-align:top; }
tr:last-child td { border-bottom:0; }
.empty { text-align:center; padding:3rem 1rem; color:var(--ink-faint);
  border:1.5px dashed var(--line); border-radius:12px; }

.signin { min-height:100vh; display:grid; place-items:center; padding:1rem; }
.signin .box { width:min(400px,92vw); background:var(--panel); border:1px solid var(--line);
  border-radius:16px; padding:2rem 1.8rem; text-align:center; }
.crest { width:56px;height:56px;border-radius:50%;margin:0 auto 1rem;display:grid;place-items:center;
  border:2px solid var(--gold); color:var(--gold); font-family:Georgia,serif; font-size:1.2rem; }
/* A failure that has just happened, said in red. The two hexes here used to be
   written out — #241419 and #40252c, the dark pill exactly — which meant that
   in light mode a sign-in error painted a near-black box across a cream page
   and then set red text on it. It predated the pill tokens rather than
   disagreeing with them, so it moves onto the same ones the .notice below uses
   and the dark rendering is unchanged to the byte. Measured both ways rather
   than eyeballed: 5.71:1 dark, 5.24:1 light, both past AA for body text. */
.err { background:var(--pill-red-bg); border:1px solid var(--pill-red-line); color:var(--red);
  border-radius:8px; padding:.55rem .7rem; font-size:.85rem; margin:.6rem 0; text-align:left; }

/* Something true that the editor has to act on, but has not gone wrong: no
   seats behind the invitations already sent, a receipt still under review.
   Distinct from .err, which is a failure that has just happened. Built on the
   amber pill tokens rather than fixed hexes so it is legible in both themes. */
.notice { background:var(--pill-amber-bg); border:1px solid var(--pill-amber-line);
  color:var(--ink-soft); border-radius:8px; padding:.6rem .75rem; font-size:.85rem;
  line-height:1.45; text-align:left; }
.notice strong { color:var(--amber); }
.google { display:flex; align-items:center; justify-content:center; gap:.6rem; width:100%;
  padding:.7rem; font-size:.95rem; }

/* the bookplate, sized by whatever box it is dropped into */
.crest { overflow: hidden; background: none; padding: 0; }
.crest-mark { display: block; width: 100%; height: 100%; }

/* Reveal the password you are typing. Not decoration: on a phone keyboard a
   long password typed blind is the usual reason somebody ends up resetting one
   they actually knew. Sits under the field it belongs to, never inside it, so
   it cannot be mistaken for part of the value. */
.pw-show {
  display: flex; align-items: center; gap: .45rem;
  margin: -.4rem 0 .9rem; cursor: pointer;
  font-size: .82rem; color: var(--muted, #8b8b8b);
  user-select: none;
}
.pw-show input { width: auto; margin: 0; cursor: pointer; }
.pw-show span { line-height: 1; }

/* How the whole thing goes, in the editor's workspace.
   The landing page used to carry this detail and is now deliberately thin —
   a visitor is deciding whether to bother, and the spreadsheet columns only
   mean anything to the person holding the class list. Numbered because the
   order is the content: portraits match against people already in the book,
   so importing the list before the pictures is not a preference. Stacks on a
   phone, which is where an organiser usually reads it. */
.howto { margin-top: .9rem; border-top: 1px solid var(--line); }
.howto-step { display: flex; gap: .9rem; padding: .9rem 0 0; }
.howto-n {
  flex: none; width: 2rem; font-size: .8rem; letter-spacing: .08em;
  color: var(--ink-faint); padding-top: .15rem;
}
.howto-step h4 { margin: 0 0 .25rem; font-size: .95rem; color: var(--ink); }
.howto-step p { margin: 0; font-size: .85rem; line-height: 1.6; color: var(--ink-soft); }
.howto-step em { font-style: italic; color: var(--ink); }
@media (max-width: 30rem) {
  .howto-step { gap: .6rem; }
  .howto-n { width: 1.5rem; }
}
