/* Wildmoot's one stylesheet. The rules for using it are in docs/design.md; read that first. */

/* ---------- tokens ---------- */
:root {
  /* colour: paper and ink, one warm accent (ember), and two quiet states (moss for done, night for closed) */
  --paper: #f4efe4; --card: #fffdf7; --ink: #2b2419; --muted: #685d50; --soft: #ece5d6;
  --line: #d9cfbd; --line-strong: #9c8e79;
  --ember: #c2531f; --ember-ink: #a84418; --ember-bg: #fbe6da; --on-ember: #fff;
  --moss: #4f6b3a; --moss-bg: #e4ecda; --on-moss: #fff;
  --night: #2c3550; --night-bg: #e1e4ee;
  --fill: var(--card);
  --shadow: 0 10px 30px rgba(0, 0, 0, .18);

  /* type: Alegreya for headings at 20px and up, Source Sans 3 for everything else */
  --display: "Alegreya", Georgia, "Times New Roman", serif;
  --text: "Source Sans 3", "Helvetica Neue", Arial, sans-serif;
  --fs-label: .8125rem;   /* 13px: overline labels only, never a sentence */
  --fs-sm: .9375rem;      /* 15px: hints, meta, table text; the floor for any sentence */
  --fs-body: 1.0625rem;   /* 17px */
  --fs-lead: 1.1875rem;   /* 19px */
  --fs-h3: 1.25rem;       /* 20px */
  --fs-h2: 1.375rem;      /* 22px */
  --fs-h1: 1.75rem;       /* 28px */
  --fs-hero: 2.25rem;     /* 36px */
  --fs-input: max(16px, var(--fs-body)); /* never under 16px, or iOS zooms the page */
  --lh-body: 1.5; --lh-tight: 1.2;

  /* space */
  --sp-1: .25rem; --sp-2: .5rem; --sp-3: .75rem; --sp-4: 1rem; --sp-5: 1.5rem; --sp-6: 2rem; --sp-7: 3rem;
  --gutter: 1rem; --card-pad: 1rem;

  /* shape and touch */
  --r-sm: 6px; --r-md: 10px; --r-lg: 14px; --r-pill: 999px;
  --tap: 44px; --tap-lg: 48px; --control-h: 48px;

  /* Optical centring. Source Sans 3's capitals sit about .05em above the middle of a 1.2 line box
     (its ascent rounds to 1.02em and its descent to .40em, and its cap height is .654em), so a
     label in a control looks as if it has more room under it than over it. A control whose words
     are centred in it sets line-height: var(--lh-control) and takes --nudge off its bottom
     padding and puts it on its top, which centres the capitals. text-box: trim-both cap
     alphabetic would do this, but it doesn't reach the anonymous box that holds the words of an
     inline-flex button, so it changes nothing here. */
  --lh-control: 1.2; --nudge: .05em;
}
@media (min-width: 40rem) {
  :root { --fs-h1: 2.125rem; --fs-h2: 1.5rem; --fs-hero: 2.75rem; --gutter: 1.5rem; --card-pad: 1.25rem; }
}
/* Dark. It follows the device unless the reader has held a theme from the personal menu, which
   the server puts on <html> as data-theme (src/web/html.ts): held dark is dark on any device,
   held light is never dark. The same tokens are written twice, once for each way in, because
   CSS has no way to share a block between a media query and a selector; test/theme.test.ts
   checks that each pair of blocks (marked dark:… below) stays word for word the same. */
/* dark:tokens */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #1c1a17; --card: #26221d; --ink: #efe6d4; --muted: #a2968a; --soft: #2f2a24;
    --line: #3d3730; --line-strong: #7a7064;
    --ember: #e0754a; --ember-ink: #e0754a; --ember-bg: #3d2418; --on-ember: #1c1a17;
    --moss: #8fb46f; --moss-bg: #26301e; --on-moss: #1c1a17;
    --night: #aab4d8; --night-bg: #232838;
    --fill: var(--card);
    --shadow: 0 10px 30px rgba(0, 0, 0, .5);
    --folk-atlas: var(--folk-atlas-night);
    color-scheme: dark;
  }
}
/* dark:tokens */
:root[data-theme="dark"] {
  --paper: #1c1a17; --card: #26221d; --ink: #efe6d4; --muted: #a2968a; --soft: #2f2a24;
  --line: #3d3730; --line-strong: #7a7064;
  --ember: #e0754a; --ember-ink: #e0754a; --ember-bg: #3d2418; --on-ember: #1c1a17;
  --moss: #8fb46f; --moss-bg: #26301e; --on-moss: #1c1a17;
  --night: #aab4d8; --night-bg: #232838;
  --fill: var(--card);
  --shadow: 0 10px 30px rgba(0, 0, 0, .5);
  --folk-atlas: var(--folk-atlas-night);
  color-scheme: dark;
}
:root[data-theme="light"] { color-scheme: light; }

/* ---------- base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { background: var(--paper); color: var(--ink); -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
  margin: 0; min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column;
  background: var(--paper); color: var(--ink);
  font-family: var(--text); font-size: var(--fs-body); line-height: var(--lh-body);
  font-variant-numeric: lining-nums tabular-nums; -webkit-tap-highlight-color: transparent;
}
a { color: inherit; text-underline-offset: 2px; }
a:focus-visible, button:focus-visible, summary:focus-visible, .btn:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }
h1, h2, h3 { font-family: var(--display); font-weight: 500; line-height: var(--lh-tight); margin: 0 0 var(--sp-2); overflow-wrap: anywhere; }
h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); }
p { margin: 0 0 var(--sp-3); }
small { font-size: var(--fs-sm); }
b, strong { font-weight: 700; }
code, kbd, samp { font-family: var(--text); font-size: inherit; }
.muted { color: var(--muted); }
.lead { font-size: var(--fs-lead); }
/* small uppercase labels: the kind of a notice, a role beside a name */
.overline { font-family: var(--text); font-weight: 700; font-size: var(--fs-label); letter-spacing: .07em; text-transform: uppercase; line-height: 1.3; }
.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; }
.warn { color: var(--ember-ink); }

main {
  flex: 1; width: 100%; max-width: 44rem; margin: 0 auto;
  padding: var(--sp-5) max(var(--gutter), env(safe-area-inset-right)) calc(var(--sp-7) + env(safe-area-inset-bottom)) max(var(--gutter), env(safe-area-inset-left));
}
main.wide { max-width: 72rem; }

/* ---------- icons ---------- */
.icon { width: 1.25em; height: 1.25em; flex: none; vertical-align: -.25em; }

/* ---------- header ---------- */
.top { background: var(--paper); border-bottom: 1px solid var(--line); padding-top: env(safe-area-inset-top); }
.top-bar { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); min-height: 60px;
  padding: var(--sp-2) max(var(--gutter), env(safe-area-inset-right)) var(--sp-2) max(var(--gutter), env(safe-area-inset-left)); }
.wordmark { font-family: var(--display); font-weight: 700; font-size: 1.5rem; line-height: 1; text-decoration: none; letter-spacing: .01em;
  display: inline-flex; align-items: center; min-height: var(--tap); }

/* the underline tab bar under the header: an event's Board, People, Event settings; the help pages */
.tabbar { padding: 0 max(var(--gutter), env(safe-area-inset-right)) 0 max(var(--gutter), env(safe-area-inset-left)); }
.tabbar-in { display: flex; gap: var(--sp-1); margin: 0 calc(-1 * var(--sp-3)); overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.tabbar-in::-webkit-scrollbar { display: none; }
.tabbar a { display: flex; align-items: center; min-height: var(--tap); padding: calc(2 * var(--nudge)) var(--sp-3) 0; white-space: nowrap; text-decoration: none;
  color: var(--muted); font-weight: 600; line-height: var(--lh-control); border-top: 3px solid transparent; border-bottom: 3px solid transparent; }
.tabbar a:hover { color: var(--ink); }
.tabbar a[aria-current="page"] { color: var(--ember-ink); border-bottom-color: var(--ember); }
.tabbar a:focus-visible { outline-offset: -2px; }
@media (max-width: 40rem) { .tabbar.no-phone { display: none; } }

/* ---------- menus: the personal menu in the header, and the More (⋯) menu on a row ---------- */
.menu, .more { position: relative; }
.menu > summary, .more > summary { list-style: none; cursor: pointer; user-select: none; -webkit-user-select: none; }
.menu > summary::-webkit-details-marker, .more > summary::-webkit-details-marker { display: none; }
.menu > summary { display: flex; align-items: center; gap: var(--sp-2); min-height: var(--tap); padding: calc(2 * var(--nudge)) var(--sp-3) 0 var(--sp-2); line-height: var(--lh-control);
  border: 1px solid var(--line-strong); border-radius: var(--r-pill); background: var(--card); font-size: var(--fs-sm); font-weight: 600; }
.menu > summary .menu-name { max-width: 9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.menu > summary .caret, .menu > summary .folk { margin-top: calc(-2 * var(--nudge)); }
.menu > summary .caret { width: 0; height: 0; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 6px solid var(--muted); transition: transform .15s; }
.menu[open] > summary { border-color: var(--ember); }
.menu[open] > summary .caret { transform: rotate(180deg); }
.more[open] > summary { background: var(--soft); }
.menu-panel { position: absolute; right: 0; top: calc(100% + 6px); z-index: 30; min-width: 14rem; max-width: calc(100vw - 2rem);
  background: var(--card); color: var(--ink); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--sp-1) 0; box-shadow: var(--shadow);
  text-align: left; font-size: var(--fs-body); font-style: normal; white-space: normal; }
.menu-panel form { margin: 0; }
.menu-panel a, .menu-panel button { display: flex; align-items: center; justify-content: flex-start; gap: var(--sp-3); width: 100%; min-height: var(--tap);
  padding: calc(var(--sp-2) + var(--nudge)) var(--sp-4) calc(var(--sp-2) - var(--nudge)); margin: 0; text-decoration: none; font: inherit; font-weight: 400; line-height: var(--lh-control); color: var(--ink); background: none;
  border: 0; border-radius: 0; text-align: left; cursor: pointer; white-space: nowrap; }
.menu-panel a:hover, .menu-panel button:hover, .menu-panel a:focus-visible, .menu-panel button:focus-visible { background: var(--soft); }
.menu-panel a:focus-visible, .menu-panel button:focus-visible { outline: 2px solid var(--ember); outline-offset: -2px; }
.menu-panel .icon { width: 20px; height: 20px; color: var(--muted); margin-top: calc(-2 * var(--nudge)); }
.menu-panel .danger, .menu-panel .danger .icon { color: var(--ember-ink); }
.menu-panel button[hidden] { display: none; }
.menu-panel button:disabled { color: var(--muted); cursor: default; background: none; opacity: 1; }
.menu-panel hr { border: 0; border-top: 1px solid var(--line); margin: var(--sp-1) 0; }
/* The theme switch: a small label over three buttons in a tray, the one in force raised, as
   the two views' switch on People (.seg). Device, Light, Dark; each a submit of its own. */
.theme-pick { padding: var(--sp-2) var(--sp-4) var(--sp-3); }
.theme-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-2); margin: 0 0 var(--sp-2); }
.theme-label { font-weight: 700; font-size: var(--fs-label); letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.theme-status { font-size: var(--fs-sm); color: var(--moss); font-weight: 600; }
.theme-seg { --tray-pad: 3px; display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--tray-pad); padding: var(--tray-pad);
  background: var(--soft); border-radius: var(--r-md); }
.menu-panel .theme-seg button { justify-content: center; min-height: var(--tap); padding: calc(2 * var(--nudge)) var(--sp-2) 0; font-size: var(--fs-sm); font-weight: 600;
  color: var(--muted); border: 1px solid transparent; border-radius: calc(var(--r-md) - var(--tray-pad)); background: none; }
.menu-panel .theme-seg button:hover { background: none; color: var(--ink); }
.menu-panel .theme-seg button[aria-pressed="true"] { background: var(--card); color: var(--ink); border-color: var(--line-strong); }
.menu-panel .theme-pick .flash { margin: var(--sp-2) 0 0; }

/* ---------- footer ---------- */
.foot { padding: var(--sp-4) var(--gutter) calc(var(--sp-4) + env(safe-area-inset-bottom)); border-top: 1px solid var(--line); color: var(--muted);
  font-size: var(--fs-sm); display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 0 var(--sp-3); text-align: center; }
.foot a { display: inline-flex; align-items: center; min-height: var(--tap); padding: 0 var(--sp-3); margin: 0 calc(-1 * var(--sp-3)); }

/* ---------- flash ---------- */
.flash { display: flex; align-items: flex-start; gap: var(--sp-2); margin: 0 0 var(--sp-4); padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md); background: var(--moss-bg); color: var(--moss); font-size: var(--fs-sm); font-weight: 600; text-align: left; overflow-wrap: anywhere; }
.flash .icon { width: 20px; height: 20px; margin-top: 1px; }
.flash.bad { background: var(--ember-bg); color: var(--ember-ink); }
/* A message about a card or a form is drawn inside it (flashAt in html.ts), above what it is about. */
.card > .flash, form > .flash { margin: var(--sp-3) 0; }
.flash:focus { outline: none; }
.flash:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }
/* An error under the field it is about (Back in fields.ts), the field itself outlined in ember. */
.field-err { display: flex; align-items: flex-start; gap: var(--sp-2); margin: var(--sp-1) 0 0; color: var(--ember-ink); font-size: var(--fs-sm); font-weight: 600; }
.field-err .icon { flex: none; width: 18px; height: 18px; margin-top: 2px; }
[aria-invalid="true"] { border-color: var(--ember) !important; box-shadow: 0 0 0 1px var(--ember); }
/* What app.js and a #card in the URL scroll to lands below the road's fixed pill, not under it. */
.card, form, [data-flash] { scroll-margin-top: calc(env(safe-area-inset-top) + 4.75rem); }

/* ---------- buttons ---------- */
button, .btn {
  font: inherit; font-size: var(--fs-body); font-weight: 600; line-height: var(--lh-control); letter-spacing: 0;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: var(--tap); padding: calc(var(--sp-2) + var(--nudge)) var(--sp-4) calc(var(--sp-2) - var(--nudge)); margin: 0;
  border: 1px solid var(--line-strong); border-radius: var(--r-md); background: var(--card); color: var(--ink);
  cursor: pointer; text-decoration: none; text-align: center; -webkit-appearance: none; appearance: none; touch-action: manipulation;
}
button .icon, .btn .icon { width: 20px; height: 20px; }
button:not(:disabled):hover, .btn:not(.is-disabled):hover { background: var(--soft); }
/* the icon beside the words stays in the middle of the button: it gives back the nudge its words take */
button > .icon, .btn > .icon { margin-top: calc(-2 * var(--nudge)); }
/* primary: one per screen, the thing the page is for */
button.ember, .btn.ember { background: var(--ember); border-color: var(--ember); color: var(--on-ember); min-height: var(--tap-lg); padding-inline: var(--sp-5); }
button.ember:not(:disabled):hover, .btn.ember:hover { background: color-mix(in srgb, var(--ember) 85%, var(--ink)); }
button.moss, .btn.moss { background: var(--moss); border-color: var(--moss); color: var(--on-moss); }
button.moss:not(:disabled):hover, .btn.moss:hover { background: color-mix(in srgb, var(--moss) 85%, var(--ink)); }
/* quiet: no border, still a full-size target */
button.quiet, .btn.quiet { background: transparent; border-color: transparent; color: var(--ink); }
/* danger: removing, taking down, turning away */
button.danger, .btn.danger { background: transparent; border-color: var(--ember); color: var(--ember-ink); }
button.danger:not(:disabled):hover, .btn.danger:hover { background: var(--ember-bg); }
button.quiet.danger, .btn.quiet.danger { border-color: transparent; }
button:disabled, .btn.is-disabled { opacity: .45; cursor: default; }
button[hidden], .btn[hidden] { display: none; }
/* icon-only: a square target, the words in aria-label */
.icon-btn { display: inline-flex; align-items: center; justify-content: center; flex: none; width: var(--tap); min-width: var(--tap); height: var(--tap);
  min-height: var(--tap); padding: 0; border: 1px solid transparent; border-radius: var(--r-md); color: var(--ink); cursor: pointer; }
.icon-btn .icon { width: 22px; height: 22px; margin-top: 0; }
summary.icon-btn:hover { background: var(--soft); }

.actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); margin-top: var(--sp-4); }
.actions > form { margin: 0; }
.actions > .hint { flex: 1 1 12rem; }
.board-actions { margin: 0 0 var(--sp-5); }
@media (max-width: 30rem) {
  /* on a phone a form's buttons stack, full width, primary first; a hint goes on its own line */
  form .actions, .actions.stack-phone { flex-direction: column; align-items: stretch; }
  form .actions > button, form .actions > .btn, .actions.stack-phone > button, .actions.stack-phone > .btn, .actions.stack-phone > form > button { width: 100%; }
  form .actions > .ember { order: -1; }
  form .actions > .hint, .actions.stack-phone > .hint { flex: none; }
  form.stack > button { width: 100%; }
}

/* ---------- form controls ---------- */
form.stack > label, form.stack label:not(.choice), .field { display: block; margin: 0 0 var(--sp-4); }
form.stack .choice label { margin: 0; }
label > span:first-child, .field > span:first-child { display: block; font-size: var(--fs-sm); font-weight: 600; color: var(--ink); margin-bottom: var(--sp-1); }
.hint { font-size: var(--fs-sm); color: var(--muted); }
.hint.warn { color: var(--ember-ink); }
label > .hint, .field .hint { display: block; margin: var(--sp-1) 0 0; }
input[type=text], input[type=email], input[type=tel], input[type=date], input[type=datetime-local], input[type=number], input[type=search], input[type=url], select, textarea {
  display: block; width: 100%; min-height: var(--control-h); margin: 0; padding: var(--sp-2) var(--sp-3);
  font: inherit; font-size: var(--fs-input); line-height: 1.3; color: var(--ink); background-color: var(--card);
  border: 1px solid var(--line-strong); border-radius: var(--r-md); -webkit-appearance: none; appearance: none;
}
input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 2px solid var(--ember); outline-offset: 1px; border-color: var(--ember); }
input::placeholder, textarea::placeholder { color: var(--muted); opacity: .8; }
input[readonly], textarea[readonly] { background-color: var(--soft); }
select {
  padding-right: 2.25rem; text-overflow: ellipsis;
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 1.15rem) 55%, calc(100% - .8rem) 55%; background-size: 6px 6px, 6px 6px; background-repeat: no-repeat;
}
textarea { min-height: 6rem; resize: vertical; }
input[type=radio], input[type=checkbox] { width: 22px; height: 22px; margin: 0; flex: none; accent-color: var(--ember); cursor: pointer; }
input[type=radio]:disabled, input[type=checkbox]:disabled { cursor: default; }
/* a choice is a whole row: the box and its words, at least one touch high */
.choice { display: flex; align-items: flex-start; gap: var(--sp-3); min-height: var(--tap); margin: 0; }
.choice > input { margin-top: 11px; }
.choice > label, label.choice > span { flex: 1; min-width: 0; min-height: var(--tap); padding: 10px 0; cursor: pointer; }
label.choice { cursor: pointer; }
.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--sp-4); }
@media (max-width: 30rem) { .row2 { grid-template-columns: 1fr; } .row2 > .choice { margin-top: 0 !important; } }
/* the number field: the country picker wide enough for its short label, "🇬🇧 +44", the number the rest */
.phone-row { display: grid; grid-template-columns: 8rem minmax(0, 1fr); gap: var(--sp-2); }
.phone-row select { min-width: 0; width: 100%; padding-left: var(--sp-2); }
.country-pick { position: relative; display: block; min-width: 0; }
.country-short { display: none; }
/* with script, the select's own words are hidden and the short label drawn over them; the
   border, the chevron, the focus ring and the open list stay the select's own */
.country-pick.short select { color: transparent; }
.country-pick.short select option { color: var(--ink); background: var(--paper); }
.country-pick.short .country-short { display: flex; align-items: center; position: absolute; inset: 0 2rem 0 0; padding-left: calc(var(--sp-2) + 1px);
  pointer-events: none; color: var(--ink); font-size: var(--fs-input); line-height: 1.3; white-space: nowrap; overflow: hidden; }
.phone .hint { margin: var(--sp-1) 0 0; }
.field[hidden] { display: none; }
/* the email box's words are its real <label>, laid out as if it weren't there */
.field.email > label.field-in { display: contents; }
fieldset { border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--sp-3) var(--sp-4) var(--sp-2); margin: 0 0 var(--sp-5); min-width: 0; }
legend { padding: 0 var(--sp-2); font-size: var(--fs-sm); font-weight: 700; color: var(--ink); }
fieldset > .hint:first-of-type { margin-top: 0; }
@media (max-width: 40rem) {
  /* inside a card a fieldset is already framed: it loses its own box, and its legend becomes a small heading */
  .card fieldset { border: 0; padding: 0; margin: 0 0 var(--sp-5); }
  .card legend { padding: 0; margin-bottom: var(--sp-2); font-size: var(--fs-body); }
}

/* ---------- cards and notices ---------- */
.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--card-pad); margin: 0 0 var(--sp-4); }
/* long words wrap rather than push the page sideways. In a table cell `anywhere` would also let the
   column shrink to one letter a line, so cells break only a word that can't fit, and a cell whose
   content is one long string (an address, a number) opts in with .wrap-anywhere */
.card p, .said .body, .flash, .wrap-anywhere { overflow-wrap: anywhere; }
td { overflow-wrap: break-word; }
.card > h2:first-child { margin-bottom: var(--sp-3); }
.notice { border-left: 5px solid var(--line); }
.notice.todo { border-left-color: var(--ember); background: color-mix(in srgb, var(--ember-bg) 45%, var(--card)); }
.notice.done, .notice.late { border-left-color: var(--moss); }
.notice.closed, .notice.sat_out { border-left-color: var(--night); }
.notice .kind { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-1); color: var(--muted); }
.notice.todo .kind { color: var(--ember-ink); }
.notice.done .kind, .notice.late .kind { color: var(--moss); }
.notice.closed .kind, .notice.sat_out .kind { color: var(--night); }
.notice .kind .tag { background: var(--soft); color: var(--muted); border-radius: var(--r-sm); padding: calc(2px + var(--nudge)) var(--sp-2) calc(2px - var(--nudge)); line-height: var(--lh-control); }
/* a notice's meta line and a taken-down stub: see "stage 2: member" at the foot */
.drafts { margin: 0 0 var(--sp-5); }
.drafts > .hint { display: block; margin-bottom: var(--sp-3); }
.notice.draft { border-left-color: var(--muted); background: var(--soft); }
.notice.draft .actions { margin-top: var(--sp-3); }
.danger-zone { margin-top: var(--sp-6); padding-top: var(--sp-4); border-top: 1px solid var(--line); }
.status { font-weight: 700; }
.status.good { color: var(--moss); } .status.warn { color: var(--ember-ink); } .status.cold { color: var(--night); }

/* the board's head: title, facts, and a pill that says what is waiting */
.board-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-3) var(--sp-4); flex-wrap: wrap; margin-bottom: var(--sp-4); }
.board-head h1 { margin-bottom: var(--sp-1); }
@media (max-width: 40rem) { .board-head { flex-direction: column; gap: var(--sp-2); } }
.facts { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4); color: var(--muted); font-size: var(--fs-sm); }
.facts li { display: inline-flex; align-items: center; gap: var(--sp-2); }
.facts .icon { width: 18px; height: 18px; }

/* pills: counts and states, never a button */
.pill { display: inline-flex; align-items: center; gap: var(--sp-1); min-height: 32px; padding: calc(var(--sp-1) + var(--nudge)) var(--sp-3) calc(var(--sp-1) - var(--nudge));
  border-radius: var(--r-pill); background: var(--soft); color: var(--ink); font-size: var(--fs-sm); font-weight: 700; line-height: var(--lh-control); white-space: nowrap; }
.pill > .icon { margin-top: calc(-2 * var(--nudge)); }
.pill.todo { background: var(--ember-bg); color: var(--ember-ink); }
/* the board's "N to deal with" is the one pill that goes somewhere: to the first card waiting on you */
a.pill.todo { min-height: var(--tap); text-decoration: none; }
a.pill.todo:hover { text-decoration: underline; text-underline-offset: 3px; }
.pill.done { background: var(--moss-bg); color: var(--moss); }
.pill.cold { background: var(--night-bg); color: var(--night); }
.pills { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin: 0 0 var(--sp-4); }
.head-row { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-3); }
.head-row > :first-child { flex: 1; min-width: 0; }
.yours { color: var(--muted); font-size: var(--fs-sm); margin: 0 0 var(--sp-4); }

/* a question's options: see "stage 2: member" at the foot */

/* ---------- lists of rows: a thing, a second line under it, its actions at the end ---------- */
ul.rows { list-style: none; padding: 0; margin: 0 0 var(--sp-4); }
ul.rows > li { display: flex; align-items: center; gap: var(--sp-2) var(--sp-3); min-height: 56px; padding: var(--sp-2) 0; border-top: 1px solid var(--line); }
ul.rows > li:first-child { border-top: 0; }
ul.rows .grow { flex: 1; min-width: 0; overflow-wrap: anywhere; }
ul.rows .sub { display: block; color: var(--muted); font-size: var(--fs-sm); }
.row-actions { display: flex; align-items: center; gap: var(--sp-1); flex: none; }
.row-actions > form { margin: 0; }
@media (max-width: 30rem) { ul.rows > li.wrap { flex-wrap: wrap; } ul.rows > li.wrap .row-actions { flex-basis: 100%; } }

/* ---------- chip grids: a set of chips in even columns ----------
   A set of chips never flows at their natural widths, which leaves a ragged right edge. It is a
   grid of equal columns, as many as fit at the set's minimum width, stretched to fill the row;
   a chip's words are cut short with an ellipsis rather than widen it, and the whole of them
   goes in its title. See "Chip grids" in docs/design.md. */
.chips { display: grid; grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); gap: var(--sp-2); margin: 0 0 var(--sp-4); }
.chip-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* ---------- chips: a person's events ---------- */
.chip { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; min-height: var(--tap);
  padding: calc(var(--sp-1) + var(--nudge)) var(--sp-3) calc(var(--sp-1) - var(--nudge)) var(--sp-4); border: 1px solid var(--line-strong);
  border-radius: var(--r-pill); background: var(--card); text-decoration: none; font-weight: 600; line-height: var(--lh-control); }
.chip:hover { background: var(--soft); }
.chip .badge { flex: none; margin-top: calc(-2 * var(--nudge)); }
.chip small { font-weight: 400; color: var(--muted); }
.chip.past { border-color: var(--line); font-weight: 400; color: var(--muted); }
.badge { display: inline-flex; align-items: center; justify-content: center; min-width: 1.5rem; min-height: 1.5rem; background: var(--ember); color: var(--on-ember);
  border-radius: var(--r-pill); padding: calc(2 * var(--nudge)) var(--sp-2) 0; font-size: var(--fs-label); font-weight: 700; line-height: var(--lh-control); }
.badge.zero { background: var(--moss); color: var(--on-moss); }
/* the second badge on an organiser's chip: how many people they are waiting on, said quietly */
.badge.waiting { background: transparent; color: var(--muted); border: 1px solid var(--line-strong); font-weight: 600; }
.section-label { color: var(--muted); margin: var(--sp-5) 0 var(--sp-2); }

/* ---------- the figure picker ---------- */
/* A figure is an <i> with the figures' atlas as its background (see figure() in html.ts). Pixel
   art is only crisp at a whole number of screen pixels to a sprite pixel, so a figure is never
   given a width: it is given a scale, --s, which must be a whole number, and its size and the
   atlas's size and position follow. 1 beside text, 2 for .big. Every figure is cropped to the
   same box (the head's variables, from the atlas's index), so they all stand on one line: in a
   flex row centre it with align-items: center; in running text vertical-align: middle does it.
   The sprites draw their own shadow under the feet. */
i.folk { --s: 1; display: inline-block; flex: none; vertical-align: middle;
  width: calc(var(--folk-w) * var(--s) * 1px); height: calc(var(--folk-h) * var(--s) * 1px);
  background: var(--folk-atlas) no-repeat;
  background-size: calc(var(--folk-aw) * var(--s) * 1px) calc(var(--folk-ah) * var(--s) * 1px);
  background-position: calc(var(--fx) * var(--s) * -1px) calc(var(--fy) * var(--s) * -1px);
  image-rendering: pixelated; }
.folk.big { --s: 2; }
.picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: var(--sp-2); margin-bottom: var(--sp-4); }
/* Each figure is a tile round a real radio button, all of them one group: one Tab stop, arrows
   to move. The radio itself is out of sight; the tile shows its focus and its state. */
.picker .tile { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: var(--sp-1);
  min-height: var(--tap); padding: var(--sp-2) var(--sp-1); border: 1px solid var(--line-strong); border-radius: var(--r-md); background: var(--card); color: var(--ink);
  font-size: .875rem; line-height: 1.2; text-align: center; min-width: 0; overflow-wrap: anywhere; cursor: pointer; }
.picker .tile > input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.picker .tile:hover { background: var(--soft); }
.picker .tile:has(input:checked) { border-color: var(--ember); box-shadow: inset 0 0 0 1px var(--ember); }
.picker .tile:has(input:focus-visible) { outline: 2px solid var(--ember); outline-offset: 2px; }
.picker .tile.current { border: 2px solid var(--moss); box-shadow: none; background: var(--moss-bg); font-weight: 700; }
.tile-saved { display: inline-flex; align-items: center; gap: 2px; color: var(--ink); font-size: .8125rem; }
.tile-saved .icon { width: 14px; height: 14px; }
.tile-saved:focus { outline: none; }
.picker-all { border: 0; margin: 0; padding: 0; min-width: 0; }
.picker-fold { border-bottom: 1px solid var(--line); }
.picker-fold > summary { display: flex; align-items: center; gap: var(--sp-3); min-height: var(--tap); padding: var(--sp-2) 0; cursor: pointer; }
.picker-fold > summary .picker-group { margin: 0; }
.picker-fold > summary .muted { margin-left: auto; }
.picker-peek { display: inline-flex; gap: 2px; }
.picker-fold[open] > summary .picker-peek { visibility: hidden; }
.picker-fold > .picker { margin-top: var(--sp-2); }
/* on a phone, four to a row: about 80px each, the labels at 14px */
@media (max-width: 30rem) {
  .picker { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-1); }
  .picker .tile { padding: var(--sp-2) 2px; }
}

/* ---------- Your settings: a title, the tabs, then the tab ---------- */
.tabs { margin: var(--sp-3) 0 var(--sp-5); }
.tabs-in { display: flex; flex-wrap: wrap; gap: 0 var(--sp-1); border-bottom: 1px solid var(--line); }
.tabs a { display: flex; align-items: center; min-height: var(--tap); padding: calc(2 * var(--nudge)) var(--sp-3) 0; white-space: nowrap; text-decoration: none; color: var(--muted);
  font-weight: 600; line-height: var(--lh-control); border-top: 3px solid transparent; border-bottom: 3px solid transparent; margin-bottom: -1px; }
.tabs a:hover { color: var(--ink); }
.tabs a[aria-current="page"] { color: var(--ember-ink); border-bottom-color: var(--ember); }
.tabs a:focus-visible { outline-offset: -2px; }
@media (max-width: 40rem) {
  /* on a phone the five tabs wrap onto two rows of pills, every one in sight, the current one filled */
  .tabs-in { gap: var(--sp-2); border-bottom: 0; }
  .tabs a { flex: 1 1 auto; justify-content: center; padding: calc(2 * var(--nudge)) var(--sp-4) 0; margin: 0; border: 1px solid var(--line-strong); border-radius: var(--r-pill);
    color: var(--ink); font-size: var(--fs-sm); }
  .tabs a[aria-current="page"] { background: var(--ink); border-color: var(--ink); color: var(--paper); }
}
.tab-body > .muted:first-child { margin-bottom: var(--sp-4); }

/* ---------- the people table ---------- */
table.people { border-collapse: collapse; width: 100%; font-size: var(--fs-sm); }
table.people th, table.people td { border-bottom: 1px solid var(--line); padding: var(--sp-2); text-align: left; vertical-align: top; }
table.people th { font-weight: 600; color: var(--muted); }
table.people th.col { min-width: 10rem; }
table.people th.col .col-head { display: flex; align-items: flex-start; gap: var(--sp-1); }
table.people th.col .col-head > div { flex: 1; min-width: 0; }
table.people th.col b { display: block; color: var(--ink); font-family: var(--text); font-size: var(--fs-body); font-weight: 700; overflow-wrap: anywhere; }
table.people th.col small { display: block; font-weight: 400; }
table.people td.who { min-width: 9rem; }
table.people td.who .name { display: flex; align-items: center; gap: var(--sp-1); font-weight: 600; }
/* the person's ⋯ sits beside their name, in the sticky column, so it never scrolls away */
table.people td.who .name > span { flex: 1; min-width: 0; overflow-wrap: anywhere; }
table.people td.who .name > .more { flex: none; margin: calc(-1 * var(--sp-1)) 0; }
table.people td.who .row-actions { margin-top: var(--sp-2); }
table.people td.who .seen { display: block; margin-top: var(--sp-1); }
table.people td.who .tags { display: flex; flex-wrap: wrap; gap: var(--sp-1); margin-top: var(--sp-1); }
table.people td.who .tags .overline { background: var(--soft); color: var(--muted); border-radius: var(--r-sm); padding: calc(2px + var(--nudge)) var(--sp-2) calc(2px - var(--nudge)); line-height: var(--lh-control); }
table.people .cell { display: inline-block; padding: calc(.1rem + var(--nudge)) var(--sp-2) calc(.1rem - var(--nudge)); border-radius: var(--r-sm); white-space: nowrap; font-weight: 600; }
table.people tr.sum td { color: var(--muted); border-bottom: 0; }
table.people tr.sum td span { display: block; white-space: nowrap; }
.chan { display: inline-block; margin: 0 var(--sp-1) var(--sp-1) 0; padding: 0 var(--sp-2); border-radius: var(--r-sm); background: var(--soft); white-space: nowrap; font-size: var(--fs-sm); }
table.people td small { white-space: nowrap; }
.cell.done, .cell.late { background: var(--moss-bg); color: var(--moss); }
.cell.late::after { content: "late"; display: block; font-weight: 400; }
.cell.sent, .cell.queued { background: var(--soft); color: var(--muted); }
.cell.silent, .cell.failed, .cell.unreached { background: var(--ember-bg); color: var(--ember-ink); }
.cell.sat_out { background: var(--night-bg); color: var(--night); }
.cell .nudges { display: block; font-weight: 400; font-size: var(--fs-sm); }
.scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ---------- pages with a hero ---------- */
.hero { padding: var(--sp-6) 0 var(--sp-4); }
.hero h1 { font-size: var(--fs-hero); }
/* The front page's figures and what Wildmoot is, under "Get it again" and over "Start an event". */
.hero.front-about { padding: 0; margin-top: var(--sp-5); }
.party { display: flex; align-items: flex-end; gap: 2px; margin: var(--sp-4) 0; color: var(--ink); overflow: hidden; }
/* eight at 2x is wider than a phone, but each has clear pixels either side: they stand closer */
.party .folk { --s: 2; margin-inline: -5px; }
.party .folk:first-child { margin-left: 0; }
.fanout { background: var(--soft); border-radius: var(--r-md); padding: var(--sp-3) var(--sp-4); font-size: var(--fs-sm); margin-bottom: var(--sp-4); }
.fanout .hint { margin-top: var(--sp-2); }
.empty { color: var(--muted); font-style: italic; padding: var(--sp-5) 0; text-align: center; }
dl.kv { display: grid; grid-template-columns: auto 1fr; gap: var(--sp-1) var(--sp-4); }
dl.kv dt { color: var(--muted); } dl.kv dd { margin: 0; }
.quiet-banner { display: flex; align-items: center; gap: var(--sp-2) var(--sp-3); flex-wrap: wrap; background: var(--night-bg); color: var(--night);
  padding: var(--sp-2) var(--sp-4); border-radius: var(--r-md); margin-bottom: var(--sp-4); }
.quiet-banner > span { flex: 1 1 12rem; }
.quiet-banner form { margin: 0; }
.quiet-banner > .icon { width: 20px; height: 20px; }

/* the road */
.road { position: relative; overflow-x: auto; overflow-y: hidden; border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--card); -webkit-overflow-scrolling: touch; margin: 0 0 var(--sp-5); scrollbar-width: thin;
  overscroll-behavior-x: contain; --road-scale: .5; }
.road::-webkit-scrollbar { height: 6px; }
.road::-webkit-scrollbar-thumb { background: var(--line); border-radius: 3px; }
/* Drawn at a fixed scale rather than a fixed height, so a label is the same size on every road:
   the viewBox's height is on the svg as --vbh. The scenery and the figures are pixel art on one
   grid, PX (4, in road-art.ts) units to a sprite pixel, so --road-scale times 4 must be a whole
   number of device pixels or they blur: .5 makes a sprite pixel 2 CSS px (2 device px at 1x);
   at 2x, .375 makes it 1.5 (3 device px); at 3x, 1/3 makes it 4/3 (4 device px). The labels
   stay the same size on the screen at every scale; src/web/road.ts lays them out for the
   smallest scale (MIN_SCALE there). */
@media (min-resolution: 2dppx), (-webkit-min-device-pixel-ratio: 2) { .road { --road-scale: .375; } }
@media (min-resolution: 3dppx), (-webkit-min-device-pixel-ratio: 3) { .road { --road-scale: calc(1 / 3); } }
.road svg { position: relative; display: block; height: calc(var(--vbh, 500) * var(--road-scale) * 1px); width: auto; max-width: none; color: var(--ink); }
/* The scenery: a strip of panels behind the svg, in the same road units at the same scale, so
   they land on the same whole CSS pixels. Each is a <picture>, which fetches only the theme's art. */
.road-art { position: absolute; top: 0; left: 0; height: calc(var(--art-h) * var(--road-scale) * 1px); }
.road-art img { position: absolute; top: 0; left: calc(var(--x) * var(--road-scale) * 1px); width: calc(var(--w) * var(--road-scale) * 1px);
  height: 100%; max-width: none; image-rendering: pixelated; }
/* The boards come as day and night art; the theme shows one. */
.road-svg .night { display: none; }
/* The figures on the road (and the walk-on's pill, a copy of one) come as day and night atlases,
   both in the drawing while the page follows the device; the theme shows one (road.ts, sprite). */
svg .folk-night { display: none; }
/* dark:figures */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) svg .folk-day { display: none; }
  :root:not([data-theme="light"]) svg .folk-night { display: inline; }
}
/* dark:figures */
:root[data-theme="dark"] svg .folk-day { display: none; }
:root[data-theme="dark"] svg .folk-night { display: inline; }
/* dark:boards */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .road-svg .day { display: none; }
  :root:not([data-theme="light"]) .road-svg .night { display: inline; }
}
/* dark:boards */
:root[data-theme="dark"] .road-svg .day { display: none; }
:root[data-theme="dark"] .road-svg .night { display: inline; }
.road-svg .asleep { opacity: .7; }
.road-svg text { stroke: none; font-family: var(--text); text-anchor: middle; }
.road-svg a { text-decoration: none; cursor: pointer; }
/* Sizes are CSS px on the screen, over the scale to make them road units: a name is 16px at
   every scale. src/web/road.ts keeps a copy of each (CSS_SIZE), to lay labels out with. */
.road-svg .t-name { font-size: calc(16px / var(--road-scale)); font-weight: 600; }
.road-svg .t-name.back { font-size: calc(15px / var(--road-scale)); }
.road-svg .t-title { font-size: calc(18px / var(--road-scale)); font-weight: 600; }
.road-svg .t-close { font-size: calc(15px / var(--road-scale)); }
.road-svg .t-banner { font-size: calc(18px / var(--road-scale)); font-weight: 600; }
.road-svg .t-sp { font-size: calc(14px / var(--road-scale)); font-weight: 600; }
.road-svg .t-fp { font-size: calc(16px / var(--road-scale)); font-weight: 600; }
.road-svg .t-more { font-weight: 700; font-size: calc(15px / var(--road-scale)); }
/* The drawn marks (the YOU arrow and its word, the z's, the ticks) are drawn at their size at .5
   and scaled about a point road.ts gives each (transform-origin) to stay that size on the screen. */
.road-svg .mark { transform: scale(calc(.5 / var(--road-scale))); }
.road-svg .t-you { font-weight: 700; font-size: 34px; letter-spacing: .1em; }
/* Everything drawn over the art is light with a dark outline, the same in both themes: it has
   to read on grass, dirt and cobbles, by day and by night. */
.road-svg .t-name, .road-svg .t-sp, .road-svg .t-fp, .road-svg .t-more, .road-svg .t-you {
  fill: #fff6e4; stroke: #1b1712; stroke-width: calc(3.5px / var(--road-scale)); stroke-linejoin: round; paint-order: stroke; }
.road-svg .t-you { stroke-width: 7px; }
.road-svg .t-you { fill: #ffb48c; }
.road-svg .zzz-o, .road-svg .tick-o, .road-svg .youmark-o { stroke: #1b1712; fill: none; }
.road-svg .zzz-o { stroke-width: 6.5; }
.road-svg .zzz { stroke: #fff6e4; stroke-width: 2.5; fill: none; }
.road-svg .tick-o { stroke-width: 10; }
.road-svg .tick { stroke: #a8dc78; stroke-width: 4.5; fill: none; }
.road-svg .youmark { stroke: #f08a5a; stroke-width: 5; fill: none; }
.road-svg .youmark-o { stroke-width: 11; }
/* The plates (a milestone's title, under the road beneath its landmark's feature) and the
   castle's banner (the event's name, under its gate) are pixel art drawn in the svg, once for
   each scale so that every edge is on the sprite-pixel grid and each fits its words at that
   scale: s2, s3 and s4 are the scales at which a sprite pixel is 2, 3 and 4 device px, shown in
   the same queries as --road-scale above. src/web/road.ts draws them (PLATE_SCALES). */
.road-svg .s3, .road-svg .s4 { display: none; }
@media (min-resolution: 2dppx), (-webkit-min-device-pixel-ratio: 2) { .road-svg .s2 { display: none; } .road-svg .s3 { display: inline; } }
@media (min-resolution: 3dppx), (-webkit-min-device-pixel-ratio: 3) { .road-svg .s3 { display: none; } .road-svg .s4 { display: inline; } }
.road-svg .plate path, .road-svg .plate rect, .road-svg .banner path { stroke: none; shape-rendering: crispEdges; }
.road-svg .pl-sh { fill: #14100c; fill-opacity: .2; }
/* parchment; a closed question's plate is the night blue the board gives it */
.road-svg .pl-o { fill: #3a2c22; } .road-svg .pl-f { fill: #f1dfb0; } .road-svg .pl-hi { fill: #fff3cf; } .road-svg .pl-lo { fill: #c9a86a; }
.road-svg .plate .t-title { fill: #3a2c22; } .road-svg .plate .t-close { fill: #6b5233; }
.road-svg .closed .pl-o { fill: #2c3550; } .road-svg .closed .pl-f { fill: #dde2ee; } .road-svg .closed .pl-hi { fill: #f3f5fa; } .road-svg .closed .pl-lo { fill: #a9b2ca; }
.road-svg .closed .t-title { fill: #2c3550; } .road-svg .closed .t-close { fill: #4c5779; }
/* the banner: red cloth, cream words */
.road-svg .bn-o { fill: #3a1a14; } .road-svg .bn-f { fill: #b5432f; } .road-svg .bn-hi { fill: #d9654c; } .road-svg .bn-lo { fill: #7e2a1d; }
.road-svg .t-banner { fill: #fff3dc; }
/* by night the parchment and the cloth are darker, the words still dark on light and light on dark */
/* dark:plates */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .road-svg .pl-sh { fill-opacity: .3; }
  :root:not([data-theme="light"]) .road-svg .pl-o { fill: #17120d; }
  :root:not([data-theme="light"]) .road-svg .pl-f { fill: #b39a6a; }
  :root:not([data-theme="light"]) .road-svg .pl-hi { fill: #c9b285; }
  :root:not([data-theme="light"]) .road-svg .pl-lo { fill: #866e45; }
  :root:not([data-theme="light"]) .road-svg .plate .t-title { fill: #21180f; }
  :root:not([data-theme="light"]) .road-svg .plate .t-close { fill: #3b2c1b; }
  :root:not([data-theme="light"]) .road-svg .closed .pl-o { fill: #12172a; }
  :root:not([data-theme="light"]) .road-svg .closed .pl-f { fill: #8b95b4; }
  :root:not([data-theme="light"]) .road-svg .closed .pl-hi { fill: #a3acc8; }
  :root:not([data-theme="light"]) .road-svg .closed .pl-lo { fill: #646e90; }
  :root:not([data-theme="light"]) .road-svg .closed .t-title { fill: #131a30; }
  :root:not([data-theme="light"]) .road-svg .closed .t-close { fill: #222b47; }
  :root:not([data-theme="light"]) .road-svg .bn-o { fill: #1b0d09; }
  :root:not([data-theme="light"]) .road-svg .bn-f { fill: #80301f; }
  :root:not([data-theme="light"]) .road-svg .bn-hi { fill: #9b4331; }
  :root:not([data-theme="light"]) .road-svg .bn-lo { fill: #561c13; }
}
/* dark:plates */
:root[data-theme="dark"] .road-svg .pl-sh { fill-opacity: .3; }
:root[data-theme="dark"] .road-svg .pl-o { fill: #17120d; }
:root[data-theme="dark"] .road-svg .pl-f { fill: #b39a6a; }
:root[data-theme="dark"] .road-svg .pl-hi { fill: #c9b285; }
:root[data-theme="dark"] .road-svg .pl-lo { fill: #866e45; }
:root[data-theme="dark"] .road-svg .plate .t-title { fill: #21180f; }
:root[data-theme="dark"] .road-svg .plate .t-close { fill: #3b2c1b; }
:root[data-theme="dark"] .road-svg .closed .pl-o { fill: #12172a; }
:root[data-theme="dark"] .road-svg .closed .pl-f { fill: #8b95b4; }
:root[data-theme="dark"] .road-svg .closed .pl-hi { fill: #a3acc8; }
:root[data-theme="dark"] .road-svg .closed .pl-lo { fill: #646e90; }
:root[data-theme="dark"] .road-svg .closed .t-title { fill: #131a30; }
:root[data-theme="dark"] .road-svg .closed .t-close { fill: #222b47; }
:root[data-theme="dark"] .road-svg .bn-o { fill: #1b0d09; }
:root[data-theme="dark"] .road-svg .bn-f { fill: #80301f; }
:root[data-theme="dark"] .road-svg .bn-hi { fill: #9b4331; }
:root[data-theme="dark"] .road-svg .bn-lo { fill: #561c13; }
}
@media (max-width: 40rem) {
  /* edge to edge on a phone: the drawing is wider than any phone, so give it every pixel */
  .road { margin-inline: calc(-1 * var(--gutter)); border-inline: 0; border-radius: 0; }
}

/* ---------- the shared link page ---------- */
.sheet { border-color: var(--ember); box-shadow: 0 8px 30px rgba(0, 0, 0, .12); }
.sheet .privacy { margin: var(--sp-3) 0 0; }
.lookbar[hidden], .sheet[hidden] { display: none; }
/* "Just looking": a bar fixed to the foot of the screen, clear of the home indicator */
.lookbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 20; display: flex; gap: var(--sp-4); align-items: center; justify-content: center;
  background: var(--card); border-top: 1px solid var(--line); box-shadow: var(--shadow); font-weight: 600;
  padding: var(--sp-3) max(var(--gutter), env(safe-area-inset-right)) calc(var(--sp-3) + env(safe-area-inset-bottom)) max(var(--gutter), env(safe-area-inset-left)); }
body.has-lookbar { padding-bottom: calc(var(--tap-lg) + var(--sp-5) + env(safe-area-inset-bottom)); }
.doorlink { display: block; padding: var(--sp-3) var(--sp-4); background: var(--soft); border-radius: var(--r-md); overflow-wrap: anywhere; font-size: var(--fs-sm); margin: 0 0 var(--sp-3); }

/* ---------- the chat ---------- */
.chat { margin: var(--sp-6) 0 0; padding-top: var(--sp-3); border-top: 1px solid var(--line); }
.chat > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: var(--sp-2); min-height: var(--tap-lg); font-family: var(--display); font-size: var(--fs-h3); }
.chat > summary::-webkit-details-marker { display: none; }
.chat > summary b { font-weight: 500; }
.chat > summary .muted { font-family: var(--text); font-size: var(--fs-sm); }
.chat > summary::after { content: ""; margin-left: auto; width: 8px; height: 8px; border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted); transform: rotate(45deg); transition: transform .15s; }
.chat[open] > summary::after { transform: rotate(225deg); }
.flame { color: var(--ember); flex: none; }
.flame .core { fill: var(--ember-bg); }
.flame.cold { color: var(--muted); opacity: .55; }
.flame.cold .core { fill: var(--soft); }
.chat .promise { margin: var(--sp-3) 0 var(--sp-4); padding: var(--sp-2) var(--sp-3); background: var(--soft); border-radius: var(--r-md); color: var(--muted); font-size: var(--fs-sm); }
.said-list { list-style: none; margin: 0; padding: 0; }
.said { padding: var(--sp-3) 0 var(--sp-1); border-top: 1px solid var(--line); }
.said-list > li:first-child > .said { border-top: 0; }
.said .who { display: flex; align-items: center; gap: var(--sp-2); margin: 0; font-family: var(--text); font-size: var(--fs-body, 1rem); font-weight: 400; line-height: inherit; }
.said .who b { font-weight: 600; }
.said .body { margin: var(--sp-1) 0 0 calc(var(--folk-w) * 1px + var(--sp-2)); }
.said .body p { margin: 0 0 var(--sp-1); }
.mention { color: var(--ember-ink); font-weight: 700; }
.said .tools { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--sp-1); margin: 0 0 0 calc(18px + var(--sp-2) - var(--sp-3)); }
.said .tools > form { margin: 0; }
.said .tools .icon-btn { color: var(--muted); }
.said .tools .btn.pinned { color: var(--moss); }
.said .tools .btn.quiet { color: var(--muted); padding-inline: var(--sp-3); }
/* pinning, decided on the message: a small sheet that folds out under it */
.pinsheet > summary { list-style: none; }
.pinsheet > summary::-webkit-details-marker { display: none; }
.pinsheet[open] { flex: 1 0 100%; }
.pinsheet[open] > summary { color: var(--ink); }
.pinsheet .sheet-in { margin: var(--sp-1) 0 var(--sp-2) var(--sp-3); padding: var(--sp-3) var(--sp-4); background: var(--card); border: 1px solid var(--line); border-left: 3px solid var(--ember); border-radius: var(--r-md); }
.pinsheet .sheet-in p { margin: 0; }
.pinsheet .sheet-in .actions { margin-top: var(--sp-3); }
.pinsheet .sheet-in .fanout { margin: var(--sp-2) 0 0; }
.said.gone { color: var(--muted); font-style: italic; font-size: var(--fs-sm); }
.chat .say { margin-top: var(--sp-4); }
.chat .say textarea { min-height: 4.5rem; }

/* ---------- Your settings ---------- */
/* the contacts and "Add another": see "stage 2: member" at the foot */
#push p { margin: 0 0 var(--sp-2); }
#push p:last-child { margin-bottom: 0; }

/* ---------- the help pages: prose, in the same two themes as everything else ---------- */
.help { max-width: 34rem; }
.help > :first-child { margin-top: 0; }
.help h1 { margin: 0 0 var(--sp-3); }
.help h2 { margin: var(--sp-6) 0 var(--sp-2); }
.help h3 { margin: var(--sp-5) 0 var(--sp-1); }
.help p { margin: 0 0 var(--sp-3); }
.help ul, .help ol { margin: 0 0 var(--sp-4); padding-left: 1.4rem; }
.help li { margin: 0 0 var(--sp-2); }
.help li > p { margin: 0; }
.help a { color: var(--ember-ink); text-decoration: underline; }
.help code { font-size: .92em; background: var(--soft); border-radius: 4px; padding: .06em .32em; overflow-wrap: anywhere; }
/* Screenshots: never wider than the column, in a hairline frame that reads in both themes. A
   phone's is drawn at about a phone's width rather than stretched across the column. */
.help figure { margin: var(--sp-4) 0 var(--sp-5); }
.help img { display: block; max-width: 100%; height: auto; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--card); }
.help img[src*="-phone"] { width: 320px; }
.help figcaption { margin-top: var(--sp-2); font-size: var(--fs-sm); color: var(--muted); }

/* stage 2: road */
/* The line under the road that says how far along you are, for reading and for screen readers. */
.road.has-caption { margin-bottom: var(--sp-2); }
.road-caption { font-size: var(--fs-sm); font-weight: 600; color: var(--ink); margin: 0 0 var(--sp-5); }
/* Soft edges say the road carries on sideways, since iOS hides the scrollbar; the script sets
   data-edge as you scroll, and the fade goes from whichever end you have reached. */
.road { --fade: 1.75rem;
  -webkit-mask-image: linear-gradient(to right, transparent, black var(--fade), black calc(100% - var(--fade)), transparent);
  mask-image: linear-gradient(to right, transparent, black var(--fade), black calc(100% - var(--fade)), transparent); }
.road[data-edge="start"] { -webkit-mask-image: linear-gradient(to left, transparent, black var(--fade));
  mask-image: linear-gradient(to left, transparent, black var(--fade)); }
.road[data-edge="end"] { -webkit-mask-image: linear-gradient(to right, transparent, black var(--fade));
  mask-image: linear-gradient(to right, transparent, black var(--fade)); }
.road[data-edge="both"] { -webkit-mask-image: none; mask-image: none; }
.road-svg .you-ground { fill: #f08a5a; stroke: none; opacity: .45; }
/* The walk-on (road.js): the figures are out of sight for the moment before the script has put
   the movers back where they were last seen, and a crowd's names, ticks and z's wait for the
   people walking to it, then fade in. */
.road.walk-wait .people { visibility: hidden; }
.road-svg .spot { transition: opacity .4s; }
.road-svg .spot.hush { opacity: 0; transition: none; }
/* The pill (road.js): you have moved, and the road is out of sight. Fixed at the top left, over
   the page (nothing on a member's board is sticky at the top), a plate in the road's pixel manner:
   square-ish, a hard outline and a hard shadow one step down and right. Your own figure walks on
   the spot in it, drawn from the atlas at 1 CSS px to a sprite pixel, so it stays crisp. */
.road-pill-wrap { position: fixed; z-index: 25; top: calc(env(safe-area-inset-top) + var(--sp-3)); left: max(var(--sp-3), env(safe-area-inset-left));
  max-width: calc(100vw - 2 * var(--sp-3)); pointer-events: none; }
.road-pill { pointer-events: auto; display: inline-flex; align-items: center; gap: var(--sp-2); max-width: 100%; min-height: var(--tap-lg);
  padding: var(--sp-1) var(--sp-4) var(--sp-1) var(--sp-2); border: 2px solid var(--ink); border-radius: 3px; background: var(--card); color: var(--ink);
  box-shadow: 3px 3px 0 color-mix(in srgb, var(--ink) 30%, transparent); font: inherit; font-size: var(--fs-sm); font-weight: 700; line-height: var(--lh-control);
  text-align: left; cursor: pointer; animation: road-pill-in .25s ease-out; }
.road-pill:hover { border-color: var(--ember); }
.road-pill-fig { flex: none; display: block; width: 26px; height: 36px; image-rendering: pixelated; }
.road-pill-text { display: block; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  padding-top: calc(2 * var(--nudge)); }
.road-pill-text .icon { width: 1.1em; height: 1.1em; margin-right: var(--sp-1); vertical-align: -.2em; }
.road-pill.done .road-pill-text { color: var(--moss); }
@keyframes road-pill-in { from { transform: translateY(-8px); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .road-pill { animation: none; } }
/* On a wide screen the road runs wider than the text column, centred on it. */
@media (min-width: 40rem) {
  .road { --road-w: min(100vw - 3rem, 72rem); width: var(--road-w); margin-left: calc(50% - var(--road-w) / 2); }
}

/* stage 2: organiser */

/* ---------- People: the wide grid, and the two phone views that replace it under 40rem ---------- */
.people-wide { display: none; }
@media (min-width: 40rem) {
  .people-phone { display: none; }
  .people-wide { display: block; }
  /* the grid scrolls inside its own box, so its header row and Person column can stay put */
  .people-scroll { max-height: calc(100dvh - 9rem); overflow: auto; border: 1px solid var(--line); border-radius: var(--r-md); background: var(--card); margin: 0 0 var(--sp-5); }
  table.people thead th { position: sticky; top: 0; z-index: 2; background: var(--card); box-shadow: inset 0 -1px var(--line); }
  table.people th.who, table.people td.who { position: sticky; left: 0; z-index: 1; background: var(--card); box-shadow: inset -1px 0 var(--line); }
  table.people thead th.who { z-index: 3; box-shadow: inset -1px -1px var(--line); }
  /* an open ⋯ in a header cell must sit above the next header cell along */
  table.people thead th:has(.more[open]) { z-index: 4; }
  /* and an open ⋯ in a person's cell above the rows below it and the sticky header row */
  table.people td.who:has(.more[open]) { z-index: 5; }
}

/* the two views' switch: a segmented control, two links, the current one raised */
/* A tray hugs its buttons: the same small inset on every side, and the buttons' corners are the
   tray's less that inset, so the two curves run parallel. */
.seg { --tray-pad: 3px; display: grid; grid-template-columns: 1fr 1fr; gap: var(--tray-pad); padding: var(--tray-pad); margin: 0 0 var(--sp-4);
  background: var(--soft); border-radius: var(--r-md); }
.seg a { display: flex; align-items: center; justify-content: center; min-height: var(--tap); padding: calc(2 * var(--nudge)) var(--sp-2) 0;
  border: 1px solid transparent; border-radius: calc(var(--r-md) - var(--tray-pad)); text-decoration: none; font-weight: 600; line-height: var(--lh-control); color: var(--muted); }
.seg a[aria-current="page"] { background: var(--card); color: var(--ink); border-color: var(--line-strong); }
.seg a:focus-visible { outline-offset: -2px; }

/* Asking to join: the one thing on the page waiting on the organiser, so it leads */
.card.asking { border-color: var(--ember); background: color-mix(in srgb, var(--ember-bg) 45%, var(--card)); }
.card.asking ul.rows { margin: 0; }
.card.asking .row-actions { gap: var(--sp-2); }
.card.asking .sub .chan { background: var(--card); }

/* By notice: a card per notice, a bar, then who hasn't dealt with it */
.notice.pn.todo { background: var(--card); }
.pn h2 { margin-bottom: var(--sp-2); }
.pn-when { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-3); margin: 0 0 var(--sp-3); font-size: var(--fs-sm); }
.prog { position: relative; height: 10px; margin: var(--sp-3) 0 var(--sp-2); background: var(--soft); border-radius: var(--r-pill); overflow: hidden; }
.prog span { position: absolute; left: 0; top: 0; bottom: 0; border-radius: var(--r-pill); }
.prog .prog-reached { background: var(--line-strong); }
.prog .prog-done { background: var(--moss); }
.pn .pills { margin-bottom: var(--sp-2); }
.grp { margin: var(--sp-4) 0 0; }
.grp h3, .grp-done h3 { display: flex; align-items: center; gap: var(--sp-2); margin: 0 0 var(--sp-2); color: var(--muted); }
.grp h3 .n, .grp-done h3 .n { min-width: 1.5rem; padding: calc(2px + var(--nudge)) var(--sp-2) calc(2px - var(--nudge)); border-radius: var(--r-pill); background: var(--soft); color: var(--ink);
  text-align: center; letter-spacing: 0; line-height: var(--lh-control); }
.grp-silent h3, .grp-failed h3, .grp-unreached h3 { color: var(--ember-ink); }
.grp-stopped h3 { color: var(--night); }
/* a chip grid (see .chips): two to a row on a phone. The name, and under it the note (how long
   silent, what failed), each cut short with an ellipsis; the chip's title has them whole */
ul.pchips { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); gap: var(--sp-2); }
ul.pchips > li { display: flex; min-width: 0; }
.pchip { flex: 1; display: flex; align-items: center; gap: var(--sp-2); min-width: 0; min-height: var(--tap);
  padding: calc(6px + var(--nudge)) var(--sp-3) calc(6px - var(--nudge));
  border: 1px solid var(--line-strong); border-radius: var(--r-pill); background: var(--card); color: var(--ink); text-decoration: none;
  font-size: var(--fs-sm); font-weight: 600; line-height: var(--lh-control); }
.pchip .folk { margin-top: calc(-2 * var(--nudge)); }
.pchip-text { display: flex; flex-direction: column; min-width: 0; }
.pchip-name, .pchip small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pchip small { font-weight: 400; color: var(--muted); }
.pchip:hover { background: var(--soft); }
.pchip.silent { background: var(--ember-bg); border-color: var(--ember); color: var(--ember-ink); }
.pchip.silent small, .pchip.failed small, .pchip.unreached small { color: var(--ember-ink); }
.pchip.failed, .pchip.unreached { border-color: var(--ember); border-style: dashed; color: var(--ember-ink); }
.pchip.waiting { background: var(--soft); border-color: var(--line); }
.pchip.stopped, .pchip.sat_out { background: var(--night-bg); border-color: var(--night-bg); color: var(--night); }
.pchip.stopped small, .pchip.sat_out small { color: var(--night); }
.pchip.done { background: var(--moss-bg); border-color: var(--moss-bg); color: var(--moss); }
.pchip.done small { color: var(--moss); }
.grp-done { margin-top: var(--sp-4); padding-top: var(--sp-1); border-top: 1px solid var(--line); }
.grp-done > summary { list-style: none; display: flex; align-items: center; gap: var(--sp-2); min-height: var(--tap); padding-top: calc(2 * var(--nudge)); cursor: pointer; font-weight: 700; line-height: var(--lh-control); }
.grp-done > summary::-webkit-details-marker { display: none; }
.grp-done > summary::after { content: ""; margin-left: auto; width: 8px; height: 8px; border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted); transform: rotate(45deg); transition: transform .15s; }
.grp-done[open] > summary::after { transform: rotate(225deg); }
.grp-done > summary .pill { min-height: 26px; }
.grp-done h3 { margin-top: var(--sp-3); }
.grp-done h3:first-of-type { margin-top: var(--sp-1); }
.pn-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); margin-top: var(--sp-4); padding-top: var(--sp-3); border-top: 1px solid var(--line); }
.card.pins ul.rows { margin: 0; }

/* By person: a row per person that opens to what they have and haven't done */
ul.plist { list-style: none; margin: 0 0 var(--sp-5); padding: 0; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-md); }
ul.plist > li + li { border-top: 1px solid var(--line); }
.prow > summary { list-style: none; display: flex; align-items: flex-start; gap: var(--sp-3); min-height: 56px; padding: var(--sp-2) var(--sp-3); cursor: pointer; }
.prow > summary::-webkit-details-marker { display: none; }
.prow > summary:hover, .prow[open] > summary { background: var(--soft); }
.prow > summary:focus-visible { outline-offset: -2px; }
ul.plist > li:first-child .prow > summary { border-radius: var(--r-md) var(--r-md) 0 0; }
/* The figure lines up with the name, not with the whole block: its box and the name's line are
   the same height (--prow-line), both at the top of the row, and the name is centred in its line.
   Lines under the name ("Never opened", the dots) then hang below without moving the figure. */
.prow { --prow-line: calc(var(--folk-h) * 1px); }
.prow .folk-gap { width: calc(var(--folk-w) * 1px); height: var(--prow-line); flex: none; }
.prow-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--sp-1); }
.prow-name { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-2); min-height: var(--prow-line); overflow-wrap: anywhere; }
.prow-name b { font-weight: 600; }
.prow-name .tag, .pick-name .tag { background: var(--soft); color: var(--muted); border-radius: var(--r-sm); padding: calc(2px + var(--nudge)) var(--sp-2) calc(2px - var(--nudge)); line-height: var(--lh-control); }
.prow[open] .prow-name .tag { background: var(--card); }
.prow-status { flex: none; align-self: center; }
/* The name's line is as tall as the figure; pull what hangs under it back up so it reads as one block. */
.prow-main > .prow-name + * { margin-top: calc(-1 * var(--sp-2)); }
.pill.outline { background: transparent; border: 1px solid var(--ember); color: var(--ember-ink); }
.pill.quiet-pill { color: var(--muted); }
.dots { display: flex; flex-wrap: wrap; gap: 5px; }
.dot { display: block; width: 10px; height: 10px; border-radius: 50%; background: var(--line-strong); }
.dot.done, .dot.late { background: var(--moss); }
.dot.silent { background: var(--ember); }
.dot.failed, .dot.unreached { background: transparent; box-shadow: inset 0 0 0 2px var(--ember); }
.dot.sat_out, .dot.muted { background: var(--night); }
.prow-body { padding: var(--sp-3) var(--sp-3) var(--sp-4) calc(var(--sp-3) * 2 + 22px); }
.prow-body .chans { margin: 0 0 var(--sp-2); }
ul.pnotes { list-style: none; margin: 0 0 var(--sp-3); padding: 0; }
ul.pnotes > li { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3); padding: var(--sp-2) 0; border-top: 1px solid var(--line); font-size: var(--fs-sm); }
ul.pnotes > li:first-child { border-top: 0; }
.pnote-title { flex: 1; min-width: 0; overflow-wrap: anywhere; font-weight: 600; }
.pnotes .cell { flex: none; max-width: 60%; padding: calc(.1rem + var(--nudge)) var(--sp-2) calc(.1rem - var(--nudge)); border-radius: var(--r-sm); font-weight: 600; text-align: right; }
/* a person's Can pin / Can notify: the same switch rows as Your settings (see "a switch" below) */
.switches { margin: 0 0 var(--sp-3); border-bottom: 1px solid var(--line); }
.switches form { margin: 0; }
.prow-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.prow-actions > form { margin: 0; }

/* ---------- Post a notice and Edit: option cards, and nothing loud while the choice is quiet ---------- */
.notice-form fieldset.loud, .notice-form fieldset.renotify { border: 0; padding: 0; margin: 0 0 var(--sp-4); }
.notice-form fieldset.loud > legend, .notice-form fieldset.renotify > legend { padding: 0; margin-bottom: var(--sp-2); }
form.stack label.opt-card { display: flex; align-items: flex-start; gap: var(--sp-3); min-height: 56px; margin: 0 0 var(--sp-2); padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--line-strong); border-radius: var(--r-md); background: var(--card); cursor: pointer; }
.opt-card > input { margin-top: 1px; }
.opt-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.opt-body b { font-weight: 700; }
.opt-detail { font-size: var(--fs-sm); }
.opt-cost { font-size: var(--fs-sm); font-weight: 600; color: var(--muted); }
form.stack label.opt-card:has(input:checked) { border-color: var(--ember); background: var(--ember-bg); box-shadow: inset 0 0 0 1px var(--ember); }
form.stack label.opt-card:has(input:checked) .opt-cost { color: var(--ember-ink); }
.opt-card:has(input:focus-visible) { outline: 2px solid var(--ember); outline-offset: 2px; }
/* under the cards: only what they don't already say (who can't be reached, the month's cap) */
.notice-form .reach-note { margin: var(--sp-2) 0 0; }
.notice-form:has(input[name=kind][value=pin]:checked) .loud-only,
.notice-form:has(input[name=renotify][value=small]:checked) .loud-only { display: none; }
/* the question's fields show while Ask a question is chosen, with or without app.js */
.notice-form:has(input[name=kind][value=question]:checked) #qbits[hidden] { display: block; }
.notice-form textarea[name=consequence] { min-height: 0; }
/* a whole-row checkbox, boxed so it reads as one target */
form.stack label.choice.boxed { display: flex; margin: 0 0 var(--sp-4); padding: 0 var(--sp-3); border: 1px solid var(--line); border-radius: var(--r-md); background: var(--card); }
.choice .sub { display: block; font-size: var(--fs-sm); font-weight: 400; color: var(--muted); }
.hint.locked { display: flex; align-items: flex-start; gap: var(--sp-2); }
.hint.locked .icon { width: 16px; height: 16px; margin-top: 3px; }
.edit-status { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); margin: 0 0 var(--sp-5); font-size: var(--fs-sm); }
.reopen { margin: 0 0 var(--sp-4); padding: var(--sp-3) var(--sp-4) var(--sp-1); background: var(--ember-bg); border-radius: var(--r-md); }
.danger-zone h2 { font-size: var(--fs-h3); margin-bottom: var(--sp-1); }
.danger-zone .actions { margin-top: var(--sp-3); }

/* ---------- Event settings: sections, and Save kept in reach on a phone ---------- */
.set-sec > h2 { margin-bottom: var(--sp-4); }
.set-sec > :last-child, .set-sec fieldset:last-child { margin-bottom: 0; }
@media (max-width: 40rem) {
  form .actions.savebar { position: sticky; bottom: 0; z-index: 5; flex-direction: row; align-items: center;
    margin: var(--sp-4) calc(-1 * var(--gutter)) 0; padding: var(--sp-3) var(--gutter) calc(var(--sp-3) + env(safe-area-inset-bottom));
    background: var(--paper); border-top: 1px solid var(--line); }
  form .actions.savebar > button { flex: 1; width: auto; }
  form .actions.savebar > .btn { width: auto; }
}

/* ---------- New event from this one ---------- */
.subtitle { color: var(--muted); margin: 0 0 var(--sp-3); }
.tick-all { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin: 0 0 var(--sp-2); }
.tick-all[hidden] { display: none; }
button.small { padding: calc(var(--sp-1) + var(--nudge)) var(--sp-3) calc(var(--sp-1) - var(--nudge)); font-size: var(--fs-sm); }
form.stack label.choice.person-pick { align-items: center; margin: 0; border-top: 1px solid var(--line); }
form.stack label.choice.person-pick:first-of-type { border-top: 0; }
label.person-pick > input { margin-top: 0; }
.pick-name { display: flex; flex-direction: column; justify-content: center; gap: 2px; }
.pick-name > span { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); font-weight: 600; }
.pick-name .hint { display: block; font-weight: 400; }

/* ---------- a person's Edit page ---------- */
.back-row { margin: 0 0 var(--sp-2); }
.back-row .btn { margin-left: calc(-1 * var(--sp-3)); padding-left: var(--sp-3); }
h1.with-folk { display: flex; align-items: center; gap: var(--sp-3); }
ul.contact-cards { list-style: none; margin: 0 0 var(--sp-5); padding: 0; display: grid; gap: var(--sp-2); }
ul.contact-cards > li { display: flex; align-items: center; gap: var(--sp-3); min-height: 56px; padding: var(--sp-2) var(--sp-1) var(--sp-2) var(--sp-4);
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--paper); }
ul.contact-cards .grow { flex: 1; min-width: 0; }
ul.contact-cards form { margin: 0; }
.contact-kind { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.contact-kind .pill { min-height: 24px; padding: calc(2 * var(--nudge)) var(--sp-2) 0; }
ul.contact-cards .sub { display: block; color: var(--muted); font-size: var(--fs-sm); }
.add-contact { padding-top: var(--sp-4); border-top: 1px solid var(--line); }

/* ---------- Preview as ---------- */
.preview-bar { gap: var(--sp-3); }
.preview-bar > .preview-words { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; line-height: 1.3; }
.preview-words .sub { font-size: var(--fs-sm); }
.preview-bar .btn { background: var(--card); }
@media (max-width: 40rem) {
  .preview-bar { position: sticky; top: 0; z-index: 20; flex-wrap: nowrap; margin: 0 calc(-1 * var(--gutter)) var(--sp-4); padding: var(--sp-1) var(--gutter); border-radius: 0; }
  .preview-words .sub { display: none; }
}
.previewing input:disabled, .previewing textarea:disabled, .previewing select:disabled { opacity: .5; cursor: not-allowed; }
.previewing input:disabled + label, .previewing .options label { cursor: default; }
.previewing input:disabled + label { color: var(--muted); }
.previewing .btn.is-disabled, .previewing button:disabled { cursor: not-allowed; }

/* stage 2: member */

/* a folding row's chevron: Add another, Help topics */
.add-option > summary::after, .help-topics > summary::after {
  content: ""; flex: none; width: 8px; height: 8px; margin-left: auto; border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted);
  transform: rotate(45deg); transition: transform .15s; }
.add-option[open] > summary::after, .help-topics[open] > summary::after { transform: rotate(225deg); }
.add-option > summary, .help-topics > summary, .answer-late > summary, .tz-pick > summary { list-style: none; cursor: pointer; }
.add-option > summary::-webkit-details-marker, .help-topics > summary::-webkit-details-marker,
.answer-late > summary::-webkit-details-marker, .tz-pick > summary::-webkit-details-marker { display: none; }
button.block, .btn.block { width: 100%; }

/* a switch: a checkbox drawn as a track and a knob, on the right of a whole-row label */
input.switch { -webkit-appearance: none; appearance: none; position: relative; flex: none; width: 52px; height: 32px; margin: 0;
  border-radius: var(--r-pill); background: var(--line-strong); cursor: pointer; transition: background .15s; }
input.switch::before, .switch-btn .track::before { content: ""; position: absolute; top: 3px; left: 3px; width: 26px; height: 26px; border-radius: 50%;
  background: var(--card); transition: transform .15s; }
input.switch:checked { background: var(--moss); }
input.switch:checked::before { transform: translateX(20px); }
input.switch:disabled { opacity: .45; cursor: default; }
input.switch:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }
.switch-row { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); min-height: var(--tap-lg); margin: 0;
  padding: var(--sp-1) 0; border-top: 1px solid var(--line); cursor: pointer; }
.switch-row > span:first-child { flex: 1; min-width: 0; margin: 0; font-size: var(--fs-body); font-weight: 400; color: var(--ink); }
.card > h2 + .switch-row { border-top: 0; }
/* the same look on a button that posts its own little form (Pause an event) */
.switch-btn { gap: var(--sp-3); min-height: var(--tap-lg); padding: calc(var(--sp-1) + var(--nudge)) 0 calc(var(--sp-1) - var(--nudge)) var(--sp-2); border-color: transparent; background: transparent; font-weight: 600; }
.switch-btn:not(:disabled):hover { background: transparent; }
.switch-btn .track { position: relative; flex: none; margin-top: calc(-2 * var(--nudge)); width: 52px; height: 32px; border-radius: var(--r-pill); background: var(--line-strong); transition: background .15s; }
.switch-btn[aria-checked="true"] .track { background: var(--moss); }
.switch-btn[aria-checked="true"] .track::before { transform: translateX(20px); }

/* ---------- the board: notice cards ---------- */
/* a question's options: whole rows to tap, the share of answers a quiet fill behind each */
.options { list-style: none; padding: 0; margin: var(--sp-3) 0 0; display: flex; flex-direction: column; gap: var(--sp-2); }
.options .opt { display: flex; align-items: center; gap: var(--sp-3); min-height: 52px; margin: 0; padding: calc(var(--sp-2) + var(--nudge)) var(--sp-4) calc(var(--sp-2) - var(--nudge));
  border: 1px solid var(--line-strong); border-radius: var(--r-md); font-size: var(--fs-body); line-height: 1.3;
  background: linear-gradient(to right, var(--moss-bg) var(--share, 0%), var(--card) var(--share, 0%)); }
label.opt { cursor: pointer; }
label.opt:has(input:checked) { border-color: var(--ember); box-shadow: inset 0 0 0 1px var(--ember); }
.options .opt-text { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.options .n { flex: none; min-width: 1.5rem; text-align: right; color: var(--muted); font-size: var(--fs-sm); font-weight: 700; }
.options .tick { display: inline-flex; flex: none; width: 22px; color: var(--moss); margin-top: calc(-2 * var(--nudge)); }
.options .opt > input { margin-top: calc(-2 * var(--nudge)); }
.options .tick .icon { width: 22px; height: 22px; }
.options .opt.picked { border-color: var(--moss); font-weight: 600; }
@media (max-width: 30rem) { .notice form.actions { flex-direction: column; align-items: stretch; } }
.answer-late { margin-top: var(--sp-3); }
.answer-late[open] > summary { background: var(--soft); }
.answer-late form > .hint { margin: var(--sp-3) 0 0; }
/* a deadline still to meet is something to read, not a hint */
.notice .deadline { margin: var(--sp-3) 0; font-size: var(--fs-body); color: var(--ink); }
.notice .deadline b { color: var(--ember-ink); }
/* where you stand with it, on its own line; then who posted it, small, with their figure */
.notice p.status { display: flex; align-items: center; gap: var(--sp-2); margin: var(--sp-3) 0 0; font-size: var(--fs-body); }
.notice p.status .icon { width: 20px; height: 20px; }
.notice .meta { display: flex; align-items: center; gap: var(--sp-2); min-height: var(--tap); margin-top: var(--sp-2); color: var(--muted); font-size: var(--fs-sm); line-height: 1.3; }
.notice .meta .by { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--sp-2); flex: 1; min-width: 0; }
.notice .meta .by b { color: var(--ink); font-weight: 600; }
.notice .meta .edit { margin: 0 calc(-1 * var(--sp-2)) 0 auto; }
.notice .meta .edit .icon-btn { color: var(--muted); }
.notice.stub { border: 1px dashed var(--line-strong); background: transparent; color: var(--muted); font-size: var(--fs-sm); font-style: normal; padding: var(--sp-3) var(--card-pad); }
.notice.stub b { color: var(--ink); font-weight: 600; }
/* the foot of the board: the other events, clear of the chat */
.board-foot { margin-top: var(--sp-6); padding-top: var(--sp-2); border-top: 1px solid var(--line); }
.board-foot .section-label:first-child { margin-top: var(--sp-3); }

/* ---------- Your events ---------- */
.event-cards { list-style: none; padding: 0; margin: var(--sp-4) 0 var(--sp-5); display: flex; flex-direction: column; gap: var(--sp-3); }
.event-card { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-2); margin: 0; border-left: 5px solid var(--moss); color: inherit; text-decoration: none; }
.event-card.todo { border-left-color: var(--ember); }
.event-card:hover { background: var(--soft); }
.event-card .event-name { font-family: var(--display); font-size: var(--fs-h3); font-weight: 700; line-height: var(--lh-tight); overflow-wrap: anywhere; }
.event-card .pills { margin: 0; }
.event-card .waiting { color: var(--ink); font-size: var(--fs-sm); }
.past-list a.grow { display: flex; flex-direction: column; justify-content: center; min-height: var(--tap); color: var(--muted); text-decoration: none; }
.past-list a.grow:hover { color: var(--ink); }

/* ---------- the chat ---------- */
.chat > summary { width: 100%; min-height: var(--tap-lg); padding: var(--sp-2) 0; }
.said .body { min-width: 0; overflow-wrap: anywhere; }
.said .tools { gap: var(--sp-1); }
.said .tools .icon-btn { color: var(--muted); }
.pin-preview { display: flex; flex-direction: column; gap: 2px; margin: var(--sp-2) 0 0; padding: var(--sp-3) var(--sp-4);
  background: var(--paper); border: 1px solid var(--line); border-left: 4px solid var(--line-strong); border-radius: var(--r-md); }
.pin-preview .overline { color: var(--muted); }
.pin-preview b { font-weight: 700; overflow-wrap: anywhere; }
.pin-preview .pin-detail { color: var(--muted); font-size: var(--fs-sm); overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow-wrap: anywhere; }
/* the composer: one row, stuck to the foot of the screen while the chat is open */
.chat .say { position: sticky; bottom: 0; z-index: 5; margin: var(--sp-4) calc(-1 * var(--gutter)) 0;
  padding: var(--sp-2) var(--gutter) calc(var(--sp-2) + env(safe-area-inset-bottom)); background: var(--paper); border-top: 1px solid var(--line); }
.say-row { display: flex; align-items: flex-end; gap: var(--sp-2); }
/* one line of words sits in the middle of the box, as in an input, until it grows */
.chat .say textarea { flex: 1; min-width: 0; min-height: var(--control-h); height: var(--control-h); max-height: 40vh; resize: none; overflow-y: auto;
  --pad: calc((var(--control-h) - 2px - 1.3em) / 2); padding-top: calc(var(--pad) + var(--nudge)); padding-bottom: calc(var(--pad) - var(--nudge)); }
.say-row > button { flex: none; }
/* the names to mention: they wrap inside the bar, two rows at most, and scroll within it past that */
.mention-chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin: 0 0 var(--sp-2); min-width: 0;
  max-height: calc(2 * var(--tap) + var(--sp-2)); overflow-y: auto; overscroll-behavior: contain; }
.mention-chips .chip { flex: none; max-width: 12rem; min-height: var(--tap); padding: calc(2 * var(--nudge)) var(--sp-3) 0; font-size: var(--fs-sm); color: var(--ember-ink); }
.mention-chips .chip[hidden] { display: none; }
.mention-chips .chip-name { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* while the chat is open, whatever takes the focus is kept clear of the bar stuck over it */
html:has(#chat[open]) { scroll-padding-bottom: calc(var(--say-h, 7.5rem) + var(--sp-3)); }
/* a short screen (a phone on its side, or zoomed in): the names only while an @word is typed, one row */
@media (max-height: 32rem) {
  .mention-chips { max-height: var(--tap); }
  .mention-chips:not(.filtering) { display: none; }
  .chat .say > .hint { display: none; }
}
.chat .say > .hint { margin: 0 0 var(--sp-2); }

/* ---------- Your settings ---------- */
.tab-body > h2:first-child { margin-top: 0; }
/* How you're reached: each way a card of its own */
.rule { margin: 0 0 var(--sp-3); }
.contacts { list-style: none; padding: 0; margin: 0 0 var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-3); }
.contact { padding: var(--sp-3) var(--sp-4) var(--sp-2); background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-md); }
.contact-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); }
.contact-head .icon { width: 20px; height: 20px; color: var(--muted); }
.contact-head b { font-weight: 700; }
.contact-head .pill { margin-left: auto; }
.contact-value { margin: var(--sp-1) 0 var(--sp-2); }
.contact-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); padding-top: var(--sp-2); border-top: 1px solid var(--line); }
.contact-actions > .icon-btn { margin-left: auto; }
/* Add another: one large row per way, each folding out its own panel */
.add-head { margin: var(--sp-6) 0 var(--sp-3); }
.add-options { display: flex; flex-direction: column; gap: var(--sp-2); }
.add-option { background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--r-md); }
.add-option > summary { display: flex; align-items: center; gap: var(--sp-3); min-height: 56px; padding: calc(var(--sp-2) + var(--nudge)) var(--sp-4) calc(var(--sp-2) - var(--nudge)); font-weight: 600; line-height: var(--lh-control); }
.add-option > summary .icon { width: 22px; height: 22px; color: var(--muted); margin-top: calc(-2 * var(--nudge)); }
.add-option[open] > summary { border-bottom: 1px solid var(--line); }
.add-panel { padding: var(--sp-4); }
.add-panel form.stack > button { width: 100%; }
.add-panel form.stack > .hint { margin: var(--sp-2) 0 0; }
ol.steps { margin: var(--sp-2) 0 0; padding-left: 1.5rem; font-size: var(--fs-body); }
ol.steps li { margin: 0 0 var(--sp-2); padding-left: var(--sp-1); }
/* Your figure */
.you-now { display: flex; align-items: center; gap: var(--sp-4); }
.you-now .folk.big { flex: none; }
.you-now .overline { display: block; color: var(--muted); }
.you-now b { display: block; font-family: var(--display); font-size: var(--fs-h2); font-weight: 500; line-height: var(--lh-tight); }
.you-now p { margin: var(--sp-1) 0 0; }
.picker-group { font-size: var(--fs-h3); font-weight: 600; margin: var(--sp-5) 0 var(--sp-2); }
/* Pause an event */
.pause-list .grow > a { font-weight: 600; }
.pause-list .pill { margin-top: var(--sp-1); }
.pause-list .row-actions { justify-content: flex-end; }
/* Privacy: Delete me in an area of its own */
.delete-me { padding: var(--card-pad); border: 1px solid var(--ember); border-radius: var(--r-md); background: var(--ember-bg); }
.delete-me label.sure-row { align-items: center; min-height: var(--tap-lg); margin: var(--sp-3) 0 0; padding: 0 var(--sp-4);
  background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--r-md); }
.delete-me label.sure-row > input { margin-top: 0; }
.delete-me label.sure-row > span { min-height: 0; padding: var(--sp-2) 0; font-weight: 600; }

/* ---------- the shared link page: the claim sheet ---------- */
.sheet .sheet-head { font-size: var(--fs-h3); margin: var(--sp-4) 0 var(--sp-2); }
.pick-list { display: flex; flex-direction: column; gap: var(--sp-2); margin: 0 0 var(--sp-4); }
.sheet form.stack label.pick-row { display: flex; align-items: center; gap: var(--sp-3); min-height: 56px; margin: 0; padding: var(--sp-1) var(--sp-4);
  background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--r-md); cursor: pointer; }
.sheet form.stack label.pick-row:has(input:checked) { border-color: var(--ember); box-shadow: inset 0 0 0 1px var(--ember); }
.pick-row > span.pick-figure { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 28px; margin: 0; color: var(--ink); }
.pick-row .pick-figure .icon { width: 22px; height: 22px; color: var(--muted); }
.pick-row .name { flex: 1; min-width: 0; font-weight: 600; overflow-wrap: anywhere; }
.sheet .privacy a { color: inherit; }

/* ---------- the front page ---------- */
.tz-pick { margin: 0 0 var(--sp-4); }
.tz-pick > summary { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-1) var(--sp-3); }
.tz-pick > summary .btn { padding-left: 0; padding-right: 0; color: var(--ember-ink); }
.tz-pick[open] > summary .btn { display: none; }
form.stack .tz-pick label { margin: var(--sp-2) 0 0; }

/* ---------- the help: on a phone, the topics fold into one row ---------- */
.help-topics { display: none; }
@media (max-width: 40rem) {
  .help-nav .tabbar { display: none; }
  .help-topics { display: block; padding: 0 max(var(--gutter), env(safe-area-inset-right)) 0 max(var(--gutter), env(safe-area-inset-left)); }
  .help-topics > summary { display: flex; align-items: center; gap: var(--sp-3); min-height: 56px; padding: var(--sp-2) 0; }
  .help-topics > summary .overline { color: var(--muted); }
  .help-topics > summary b { font-weight: 600; }
  .help-topics ul { list-style: none; margin: 0; padding: 0 0 var(--sp-3); }
  .help-topics a { display: flex; align-items: center; min-height: var(--tap); padding: 0 var(--sp-3); border-radius: var(--r-sm); text-decoration: none; }
  .help-topics a[aria-current="page"] { background: var(--soft); color: var(--ember-ink); font-weight: 700; }
}

/* ---------- bigger hit areas ----------
   Small things to tap, for a hand that isn't steady: padding round them to hit, taken back by an
   equal negative margin so nothing moves. A link in a line of text grows above and below into the
   line's own leading; a checkbox in a table cell gets a whole tap-sized square of its cell. */
.yours a, .hint a:not(.btn) { padding: 10px 4px; margin: -10px -4px; }
.cell-check { display: inline-flex; align-items: center; justify-content: center; min-width: var(--tap); min-height: var(--tap); margin: calc((22px - var(--tap)) / 2); cursor: pointer; }
.road:focus-visible { outline: 2px solid var(--ember); outline-offset: -2px; }
