/* ==========================================================================
   LSSC Manager

   Two accents, each with one job:

     copper  — do something. Sign up, save, add.
     green   — done. You're on the bar, batch on tap, saved.

   Keeping those apart is what makes a card readable at a glance in a dim
   room: amber-ish means the shift wants something from you, green means it
   doesn't. Neutrals are biased very slightly green rather than blue-grey, so
   they sit with the accents instead of fighting them.
   ========================================================================== */

:root {
  --bg:          #f2f5f1;
  --card:        #ffffff;
  --surface-2:   #f7f9f6;
  --ink:         #16211a;
  --muted:       #55635b;
  --faint:       #7c8981;
  --line:        #dce4dc;
  --line-firm:   #c3cec3;

  /* done / confirmed */
  --accent:      #2c6640;
  --accent-ink:  #ffffff;
  --accent-bg:   #e8f2ea;
  --accent-line: #b6d3be;

  /* act now */
  --copper:      #a85419;
  --copper-ink:  #ffffff;
  --copper-bg:   #fbefe6;

  /* needs attention, but not wrong */
  --warn:        #7e4a0e;
  --warn-bg:     #fbf0dc;

  --danger:      #a3322a;
  --danger-bg:   #f7e4e2;
  --danger-line: #e6c3c0;

  --focus:       #1d6fd6;
  --shadow-sm:   0 1px 2px rgba(22, 33, 26, .05);
  --shadow-card: 0 1px 2px rgba(22, 33, 26, .05), 0 6px 16px -12px rgba(22, 33, 26, .3);

  --serif: Georgia, "Iowan Old Style", "Times New Roman", serif;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* The club is open at night and the bar is dim. Follow the phone's setting. */
@media (prefers-color-scheme: dark) {
  :root {
    --bg:          #101410;
    --card:        #1a201b;
    --surface-2:   #212822;
    --ink:         #ecf1eb;
    --muted:       #a6b2a8;
    --faint:       #8a968c;
    --line:        #2c342e;
    --line-firm:   #3b453d;

    --accent:      #6dbe84;
    --accent-ink:  #0c1a10;
    --accent-bg:   #18261c;
    --accent-line: #2f4a37;

    --copper:      #e08641;
    --copper-ink:  #1a1005;
    --copper-bg:   #2e2015;

    --warn:        #e7b267;
    --warn-bg:     #2a2115;

    --danger:      #e88c84;
    --danger-bg:   #33201e;
    --danger-line: #5a3230;

    --focus:       #7fb2ff;
    --shadow-sm:   0 1px 2px rgba(0, 0, 0, .4);
    --shadow-card: 0 1px 2px rgba(0, 0, 0, .4), 0 8px 20px -12px rgba(0, 0, 0, .7);
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font: 15px/1.45 var(--sans);
  background: var(--bg);
  color: var(--ink);
  -webkit-text-size-adjust: 100%;
}

a { color: var(--copper); text-decoration: none; }
a:hover { text-decoration: underline; }

:where(a, button, summary, input, select, textarea):focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: 6px;
}

/* Staff and staff managers only ever see one or two links, so their nav stays
   a slim bar. Committee and above get the sidebar below. */
.topbar {
  display: flex; align-items: center; gap: 1.2rem;
  background: var(--card); border-bottom: 1px solid var(--line);
  padding: 0 1.2rem; height: 52px; position: sticky; top: 0; z-index: 5;
}
.topbar .brand { font-family: var(--serif); font-weight: 700; font-size: 1.05rem; color: var(--ink); }
.topbar nav { display: flex; gap: 1rem; flex: 1; }
.topbar nav a { color: var(--ink); }
.logout { display: flex; align-items: center; gap: .6rem; margin: 0; }
.logout .who, .topbar .who { color: var(--muted); font-size: .85rem; text-decoration: none; }
.topbar .who:hover { text-decoration: underline; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 20;
  background: var(--card); color: var(--ink);
  padding: .6rem .9rem; border: 1px solid var(--line-firm); border-radius: 0 0 6px 0;
}
.skip:focus { left: 0; }

/* The admin sidebar. Ten links fit vertically with room for group headings,
   which is the whole reason it isn't a row of tabs with a "more" menu. */
.sidebar {
  position: fixed; top: 0; bottom: 0; left: 0; width: 208px; z-index: 5;
  display: flex; flex-direction: column; gap: .9rem;
  padding: 1rem .9rem;
  background: var(--card); border-right: 1px solid var(--line);
  overflow-y: auto;
}
.sidebar .brand {
  font-family: var(--serif); font-weight: 700; font-size: 1.05rem; color: var(--ink);
  padding: 0 .4rem;
}
.navdrop { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.navdrop-body { display: flex; flex-direction: column; flex: 1; gap: .9rem; }
.navdrop nav { display: flex; flex-direction: column; flex: 1; }
.navdrop nav a {
  display: block; color: var(--ink); padding: .42rem .55rem; border-radius: 6px;
  border-left: 3px solid transparent;
}
.navdrop nav a:hover { background: var(--surface-2); text-decoration: none; }
.navdrop nav a.active {
  background: var(--accent-bg); border-left-color: var(--accent);
  color: var(--accent); font-weight: 600;
}
.navgroup {
  margin: .9rem 0 .25rem; padding: 0 .55rem;
  font-size: .72rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--faint); font-weight: 600;
}
.navgroup:first-child { margin-top: 0; }
.navfoot {
  display: flex; flex-direction: column; align-items: flex-start; gap: .5rem;
  margin: 0; padding-top: .9rem; border-top: 1px solid var(--line);
}
.navfoot .who {
  color: var(--muted); font-size: .85rem; text-decoration: none;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.navfoot .who:hover { text-decoration: underline; }

/* Wide enough for the sidebar: the summary goes away and the panel is shown
   regardless of the [open] state, so the disclosure stops existing. Two rules
   because browsers hide the panel two different ways. */
@media (min-width: 861px) {
  .navdrop > summary { display: none; }
  .navdrop:not([open]) > .navdrop-body { display: flex; }
  .navdrop::details-content { content-visibility: visible; }
  body.with-sidebar { padding-left: 208px; }
}

.content { max-width: 1000px; margin: 1.6rem auto; padding: 0 1.2rem; }

h1 { font-size: 1.5rem; margin: 0 0 1rem; }
h2 { font-size: 1.05rem; margin: 1.6rem 0 .6rem; }

.page-head { display: flex; align-items: center; justify-content: space-between; }

table {
  width: 100%; border-collapse: collapse; background: var(--card);
  border: 1px solid var(--line); border-radius: 8px; overflow: hidden;
}
th, td { text-align: left; padding: .55rem .7rem; border-bottom: 1px solid var(--line); }
th {
  background: var(--surface-2); font-size: .8rem; text-transform: uppercase;
  letter-spacing: .03em; color: var(--muted);
}
tr:last-child td { border-bottom: 0; }

/* The products table is one <tbody> per drink, so the row group is the unit
   the eye should pick out: a heading row carrying the name and the shared
   flags, then its measures indented under it. */
.items tbody.item + tbody.item { border-top: 2px solid var(--line-firm); }
.items .item-head th {
  background: transparent; text-transform: none; letter-spacing: 0;
  font-size: 1rem; font-weight: 650; color: var(--ink);
}
.items .item-head th .muted { font-weight: 400; font-size: .82rem; margin-left: .5rem; }
.items .item-head td { vertical-align: middle; }
.items tr.measure td { border-bottom: 0; color: var(--ink); }
.items tr.measure .measure-name { padding-left: 1.8rem; color: var(--muted); }
/* A retired drink stays legible — it is still the row you click to bring back. */
.items tbody.retired .item-head th, .items tbody.retired > tr > td:first-child { opacity: .65; }
.items .flag form { margin: 0; }
.items .flag .check { gap: .35rem; }

.muted { color: var(--muted); }
/* One "key: value" of an audit row, kept whole: a pair split across a line
   break reads as two facts. */
.detail { white-space: nowrap; }
.neg { color: var(--danger); font-weight: 600; }

/* Ordinary buttons are actions, so they take the copper. */
button, .btn {
  background: var(--copper); color: var(--copper-ink); border: 0;
  padding: .45rem .8rem; border-radius: 6px; cursor: pointer; font-size: .9rem;
}
button:hover, .btn:hover { filter: brightness(1.06); text-decoration: none; }
button.primary { background: var(--copper); color: var(--copper-ink); font-weight: 600; }
button.secondary { background: var(--surface-2); color: var(--ink); border: 1px solid var(--line-firm); }
button.danger {
  background: var(--danger-bg); color: var(--danger); border: 1px solid var(--danger-line);
}

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 1rem; margin-bottom: 1rem; }
.card {
  background: var(--card); border: 1px solid var(--line); border-radius: 10px;
  padding: 1rem; display: flex; flex-direction: column;
}
.card .num { font-size: 1.6rem; font-weight: 700; }
.card .lbl { color: var(--muted); font-size: .85rem; }
.card.warn { border-color: var(--warn); }

.pill { font-size: .72rem; padding: .12rem .5rem; border-radius: 999px; background: var(--surface-2); color: var(--ink); }
.pill.on_tap { background: var(--accent-bg); color: var(--accent); }
.pill.in_hand { background: var(--warn-bg); color: var(--warn); }
.pill.closed { background: var(--surface-2); color: var(--muted); }

form.stacked {
  display: flex; flex-direction: column; gap: .8rem; max-width: 560px;
  background: var(--card); padding: 1.2rem; border: 1px solid var(--line); border-radius: 10px;
}
/* Wrap, don't overflow. A date input or a long select won't shrink below its
   own contents, so an unwrapped row of four pushes the last one straight out
   through the panel border — and the same happens to a row of two on a phone.
   The basis is the narrowest a field stays usable at; below that they stack. */
/* Bottom-aligned, so a label that runs to two lines ("To (included)") doesn't
   leave its own field sitting lower than the one beside it. */
form.stacked .row { display: flex; gap: 1rem; flex-wrap: wrap; align-items: end; }
form.stacked .row label { flex: 1 1 11rem; min-width: 0; }
/* For a filter bar: four controls that belong on one line where there's room. */
form.stacked.wide { max-width: 820px; }
label { display: flex; flex-direction: column; gap: .25rem; font-size: .85rem; color: var(--muted); }
label.check { flex-direction: row; align-items: center; gap: .5rem; color: var(--ink); }
/* A box with a line of explanation under its label: the box lines up with
   the label, not with the middle of the pair. */
label.check.top { align-items: flex-start; }
label.check.top input { margin-top: .2rem; }
input, select, textarea {
  padding: .45rem .55rem; border: 1px solid var(--line-firm); border-radius: 6px;
  font: inherit; background: var(--card); color: var(--ink);
}
fieldset { border: 1px solid var(--line); border-radius: 8px; }
legend { color: var(--muted); font-size: .8rem; padding: 0 .4rem; }
.actions { display: flex; gap: .8rem; align-items: center; }
.row-actions { display: flex; gap: .4rem; flex-wrap: wrap; }
.row-actions form { margin: 0; }
form.inline { display: inline-flex; gap: .3rem; align-items: center; }

.login-card {
  max-width: 340px; margin: 8vh auto; background: var(--card);
  border: 1px solid var(--line); border-radius: 12px; padding: 1.6rem;
  box-shadow: var(--shadow-card);
}
.login-card h1 { text-align: center; font-family: var(--serif); }
.login-card form { display: flex; flex-direction: column; gap: .9rem; margin-bottom: .4rem; }
.login-card button { width: 100%; padding: .6rem; }
.login-card .pw-details { margin-top: 1.1rem; border-top: 1px solid var(--line); padding-top: .9rem; }
.login-card .pw-details summary { cursor: pointer; color: var(--muted); font-size: .85rem; text-align: center; }
.login-card .pw-details form { margin-top: .9rem; }

.error { background: var(--danger-bg); color: var(--danger); padding: .5rem .7rem; border-radius: 6px; font-size: .85rem; }
.flash {
  background: var(--accent-bg); border: 1px solid var(--accent-line); color: var(--accent);
  padding: .6rem .8rem; border-radius: 8px; margin-bottom: 1rem; font-size: .9rem;
}
.notice { background: var(--accent-bg); border: 1px solid var(--accent-line); color: var(--accent); padding: .6rem .8rem; border-radius: 8px; font-size: .9rem; }
.hint { color: var(--muted); font-size: .85rem; text-align: center; }
.hint a { color: var(--muted); }
.head-actions { display: flex; gap: .6rem; align-items: center; }
.head-actions form { margin: 0; }
code { background: var(--surface-2); padding: .05rem .35rem; border-radius: 4px; font-size: .85em; }

/* The less-common half of a form, folded away until it's wanted. Keeps the
   one-tap path a dropdown and a button without hiding the other one. */
details.more { border-top: 1px solid var(--line); padding-top: .8rem; }
details.more summary { cursor: pointer; color: var(--muted); font-size: .9rem; }
details.more > .row, details.more > .actions { margin-top: .8rem; }

/* A sync's own log. Wide lines scroll inside the box rather than stretching
   the page, and the text wraps on a phone instead of disappearing. */
.runlog {
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 8px;
  padding: .8rem; font-size: .8rem; line-height: 1.5; overflow-x: auto;
  white-space: pre-wrap; word-break: break-word; max-height: 32rem; overflow-y: auto;
}

/* ==========================================================================
   The rota — a volunteer holding a phone, often in a dim room.
   Bigger type, bigger targets, and state carried by words as well as colour.
   ========================================================================== */

.rota { max-width: 640px; margin: 0 auto; font-size: 17px; }
.rota-title { font-family: var(--serif); font-size: 1.6rem; margin: .2rem 0 1rem; }
.rota .back { display: inline-block; margin-bottom: .8rem; font-size: 1rem; color: var(--muted); }

.rota-manage { display: flex; flex-wrap: wrap; gap: .6rem; margin-bottom: 1.4rem; }
.rota-manage form { margin: 0; }

.rota-group { margin-bottom: 1.8rem; }
.rota-heading {
  font-size: .78rem; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--faint); margin: 0 0 .7rem;
}

.shift {
  background: var(--card); border: 1px solid var(--line); border-radius: 14px;
  padding: 1rem 1rem 1.1rem; margin-bottom: .9rem;
  display: flex; flex-direction: column; gap: .8rem;
  box-shadow: var(--shadow-card);
  transition: background-color .25s ease, border-color .25s ease;
}
/* Tinting the whole card is the fastest possible read of "you're on this one". */
.shift[data-state="on"] { background: var(--accent-bg); border-color: var(--accent-line); }
.shift[data-state="off"] { opacity: .7; }

.shift-top { display: flex; align-items: flex-start; justify-content: space-between; gap: .7rem; }
/* The date is the headline of the card, so it gets the serif. */
.shift-date { font-family: var(--serif); margin: 0; font-size: 1.32rem; line-height: 1.2; font-weight: 700; }
.shift-time { margin: .15rem 0 0; font-size: 1.05rem; color: var(--ink); }
.shift-away { margin: .25rem 0 0; font-size: .9rem; color: var(--faint); }
.shift-name { margin: 0; font-size: 1.02rem; font-weight: 650; }
.shift-desc { margin: .2rem 0 0; color: var(--muted); font-size: .96rem; }
.shift-who { margin: 0; padding-top: .8rem; border-top: 1px solid var(--line); font-size: 1rem; }
.shift[data-state="on"] .shift-who { border-top-color: var(--accent-line); }
.shift-more { display: inline-block; font-size: .92rem; }

.shift-action { display: flex; flex-direction: column; gap: .6rem; }

/* 56px: comfortably past the 44px minimum, so a mistap on the next shift
   is unlikely on a phone held one-handed. */
.btn {
  display: flex; align-items: center; justify-content: center;
  width: 100%; min-height: 56px; padding: .7rem 1rem;
  border-radius: 12px; border: 2px solid transparent;
  font: inherit; font-size: 1.05rem; font-weight: 600;
  cursor: pointer; text-align: center; text-decoration: none;
}
.btn:hover { text-decoration: none; }
.btn-go { background: var(--copper); color: var(--copper-ink); }
.btn-wait { background: transparent; color: var(--copper); border-color: var(--copper); }
.btn-quiet {
  background: var(--card); color: var(--ink); border-color: var(--line-firm);
  min-height: 50px; font-size: 1rem;
}
.btn-add { background: var(--copper); color: var(--copper-ink); width: auto; padding: .7rem 1.2rem; }
.rota-manage .btn-quiet { width: auto; padding: .7rem 1.2rem; }
.btn-link {
  background: none; border: none; color: var(--danger);
  font: inherit; cursor: pointer; padding: .4rem; min-height: 44px;
}

/* Green, not copper: this one is a statement, not a button. */
.onbar {
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: 56px; border-radius: 12px;
  background: var(--accent); color: var(--accent-ink); font-size: 1.08rem; font-weight: 700;
}

.pill[data-tone] {
  flex: none; font-size: .78rem; font-weight: 700; padding: .3rem .6rem;
  border-radius: 999px; white-space: nowrap;
}
.pill[data-tone="on"]    { background: var(--accent); color: var(--accent-ink); }
.pill[data-tone="needs"] { background: var(--warn-bg); color: var(--warn); }
.pill[data-tone="full"]  { background: var(--surface-2); color: var(--muted); border: 1px solid var(--line-firm); }
.pill[data-tone="wait"]  { background: var(--copper-bg); color: var(--copper); }
.pill[data-tone="off"]   { background: var(--danger-bg); color: var(--danger); }

/* Withdrawing asks first. <details> keeps it working without JavaScript. */
.drop summary {
  cursor: pointer; text-align: center; color: var(--muted);
  font-size: .95rem; padding: .7rem; min-height: 44px;
}
.drop-confirm {
  border: 2px solid var(--line-firm); border-radius: 12px; padding: .9rem;
  display: flex; flex-direction: column; gap: .6rem; background: var(--card);
}
.drop-confirm p { margin: 0; }
.drop-confirm form { margin: 0; }

.panel {
  background: var(--card); border: 1px solid var(--line); border-radius: 14px;
  padding: 1rem; margin-bottom: .9rem;
}
.panel h2 { font-size: 1.05rem; margin: 0 0 .6rem; }
.people { list-style: none; margin: 0; padding: 0; }
.people li {
  display: flex; align-items: center; justify-content: space-between; gap: .6rem;
  padding: .5rem 0; border-bottom: 1px solid var(--line);
}
.people li:last-child { border-bottom: none; }
.people form { margin: 0; }
.add-person { display: flex; flex-direction: column; gap: .6rem; margin-bottom: .9rem; }
.add-person select { min-height: 48px; }
.manage-actions { display: flex; flex-direction: column; gap: .6rem; }
.manage-actions form { margin: 0; }

.rota-form { max-width: 100%; }
.rota-form input, .rota-form textarea, .rota-form select { min-height: 48px; font-size: 1rem; }
.rota-form textarea { min-height: 80px; }

.empty {
  background: var(--card); border: 1px dashed var(--line-firm); border-radius: 14px;
  padding: 1.4rem; text-align: center;
}
.empty p { margin: .3rem 0; }
.rota-foot { text-align: center; color: var(--faint); font-size: .88rem; margin-top: 2rem; }

/* ==========================================================================
   Categories — sixty mappings, so a page of sixty input boxes would read as a
   raw table edit. Each row is a sentence instead: "this name books here". The
   fields only exist once a row is open, which is also what lets each one hold
   a real form rather than inputs wired to a form elsewhere.
   ========================================================================== */

.subhead {
  margin: 1.2rem 0 .4rem;
  font-size: .74rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--faint);
}

.maplist {
  background: var(--card); border: 1px solid var(--line); border-radius: 10px;
  overflow: hidden;
}
.mapempty { margin: 0; padding: .8rem .85rem; }

.maprow { border-bottom: 1px solid var(--line); }
.maprow:last-child { border-bottom: 0; }
.maprow > summary {
  display: flex; align-items: center; gap: .8rem;
  padding: .5rem .85rem; cursor: pointer; list-style: none;
}
.maprow > summary::-webkit-details-marker { display: none; }
.maprow > summary:hover { background: var(--surface-2); }
.maprow[open] > summary { background: var(--surface-2); }
/* The affordance is a word, not an icon: this page is only ever read by
   someone who came here to change something. */
.maprow > summary::after {
  content: "Edit"; color: var(--copper); font-size: .8rem; flex: none;
}
.maprow[open] > summary::after { content: "Close"; color: var(--muted); }

.mapname {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: .45rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mapto { color: var(--muted); font-size: .85rem; flex: none; }

.mapedit {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: .7rem;
  padding: .85rem; border-top: 1px solid var(--line); background: var(--surface-2);
}
.mapedit > form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: .7rem; margin: 0; }
.mapedit > form:first-child { flex: 1; min-width: 15rem; }
.mapedit label { flex: 1 1 11rem; }
.mapedit .mapnote { margin: 0 0 .4rem; font-size: .82rem; }

/* Adding is the rare case — it sits folded away so the mapping itself is what
   the page is. */
.adder { margin-top: 1rem; }
.adder > summary {
  display: inline-flex; align-items: center; cursor: pointer; list-style: none;
  padding: .45rem .8rem; border-radius: 6px; font-size: .9rem;
  background: var(--surface-2); border: 1px solid var(--line-firm); color: var(--ink);
}
.adder > summary::-webkit-details-marker { display: none; }
.adder > summary::before { content: "+ "; color: var(--copper); font-weight: 700; }
.adder[open] > summary { margin-bottom: .8rem; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* ==========================================================================
   Price list. The two sheets are the only pages here meant to leave the
   screen, so they are laid out for A4 first and shown on screen second:
   clean sans type, tight rows, and prices in a column your eye can run down.
   In print the customer list flows its sections into two columns so the
   whole list fits on one sheet of paper.
   ========================================================================== */

/* Money reads down a column, so it aligns right and holds its digit widths.
   Scoped to tables to leave the dashboard's big .card .num alone. */
table th.num, table td.num { text-align: right; font-variant-numeric: tabular-nums; }

.sheet-body { max-width: 46rem; margin: 0 auto; font-family: var(--sans); }
.sheet-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  flex-wrap: wrap; margin-bottom: 1.1rem; padding-bottom: .5rem;
  border-bottom: 2px solid var(--ink);
}
.sheet-head h1 {
  font-family: var(--sans); font-size: 1.6rem; font-weight: 700;
  letter-spacing: -.01em; margin: 0;
}
.sheet-note { color: var(--muted); margin: 0; font-size: .85rem; }

.pricesection { margin-bottom: 1rem; break-inside: avoid; }
.pricesection h2 {
  font-family: var(--sans); font-size: .78rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em; color: var(--accent);
  margin: 0 0 .2rem; padding-bottom: .2rem; border-bottom: 1px solid var(--line-firm);
}

.pricetable { border: 0; border-radius: 0; background: transparent; font-size: .9rem; }
.pricetable th, .pricetable td { padding: .2rem .4rem; border-bottom: 1px solid var(--line); }
.pricetable th:first-child, .pricetable td:first-child { padding-left: 0; }
.pricetable th:last-child, .pricetable td:last-child { padding-right: 0; }
.pricetable thead th {
  background: transparent; border-bottom: 1px solid var(--line-firm);
  font-size: .68rem; font-weight: 600; letter-spacing: .06em; color: var(--faint);
  padding-top: 0;
}
.pricetable tbody th {
  background: transparent; text-transform: none; letter-spacing: 0;
  font-size: .9rem; font-weight: 600; color: var(--ink);
}
.pricetable tbody th .muted { font-weight: 400; font-size: .8rem; }
.pricetable td { color: var(--muted); }
.pricetable td.num { color: var(--ink); white-space: nowrap; }
.pricetable td.num:last-child { color: var(--accent); }
.pricetable tbody tr:last-child td, .pricetable tbody tr:last-child th { border-bottom: 0; }

/* Bar sheet: the members' price rides under the list price rather than
   doubling the number of columns, which is what keeps five prices per drink
   on one sheet of paper. */
.bartable td.num:last-child { color: var(--ink); }
.bartable .price { display: block; font-weight: 600; }
.bartable .price-member { display: block; font-size: .75rem; color: var(--accent); }

.sheet-rule {
  margin-top: 1rem; padding: .6rem .8rem;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 6px;
  font-size: .85rem;
}

/* The print pages show the sheet as the paper it will be: an A4 page at
   print sizes, so what you see is what comes out of the printer. */
body.sheet { background: var(--bg); padding: 1.5rem 1rem 3rem; }
body.sheet > .sheet-body {
  width: 210mm; max-width: 100%; min-height: 297mm; margin: 0 auto;
  padding: 12mm 12mm 10mm; background: #fff; color: var(--ink);
  /* Paper is white in dark mode too, so the sheet keeps the light palette. */
  --ink: #16211a; --muted: #55635b; --faint: #7c8981; --card: #fff;
  --surface-2: #f7f9f6; --line: #dce4dc; --line-firm: #c3cec3; --accent: #2c6640;
  box-shadow: 0 1px 3px rgba(0,0,0,.12), 0 6px 24px rgba(0,0,0,.08);
}
body.sheet { font-size: 9pt; }
body.sheet .sheet-head { margin-bottom: 4mm; }
body.sheet .sheet-head h1 { font-size: 18pt; }
body.sheet .sheet-note { font-size: 8.5pt; }
body.sheet .sheet-body:has(.pricesection) { column-count: 2; column-gap: 8mm; }
body.sheet .sheet-body:has(.pricesection) .sheet-head { column-span: all; }
body.sheet .pricesection { margin-bottom: 3.5mm; }
body.sheet .pricesection h2 { font-size: 7.5pt; }
body.sheet .pricetable { font-size: 8.5pt; }
body.sheet .pricetable th, body.sheet .pricetable td { padding: .6mm 1.2mm; }
body.sheet .pricetable :is(th, td):first-child { padding-left: 0; }
body.sheet .pricetable :is(th, td):last-child { padding-right: 0; }
body.sheet .pricetable tbody th { font-size: 8.5pt; }
body.sheet .pricetable thead th { font-size: 6.5pt; }
body.sheet .bartable { font-size: 10pt; }
body.sheet .bartable tbody th { font-size: 10pt; }
body.sheet .bartable th, body.sheet .bartable td { padding: 1.2mm 1.5mm; }
/* A phone is narrower than the paper: one column there, two on the page. */
@media screen and (max-width: 640px) {
  body.sheet { padding: .75rem 0 2rem; }
  body.sheet > .sheet-body { padding: 6mm 16px; min-height: 0; }
  body.sheet .sheet-body:has(.pricesection) { column-count: 1; }
  .sheet-tools { padding: 0 16px; }
}
.sheet-tools {
  display: flex; align-items: center; justify-content: space-between; gap: .8rem;
  width: 210mm; max-width: 100%; margin: 0 auto 1rem;
}

/* On the working screen each sheet is shown as what it will be, boxed so it
   reads as a preview and not as another admin table. */
.sheet-preview {
  background: var(--card); border: 1px solid var(--line); border-radius: 14px;
  padding: 1.4rem 1.2rem; margin-bottom: 1.4rem;
}
.sheet-preview .sheet-head h1 { font-size: 1.35rem; }

/* ==========================================================================
   Membership

   Two audiences on one page. Committee get the usual admin density; staff get
   a row they can read at a glance across a bar. Status is a word before it is
   a colour — "is she a member?" has to be answerable in a dim room by someone
   who can't tell the amber from the green.
   ========================================================================== */

.filters { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; margin-bottom: 1rem; }
.filters .grow { flex: 1 1 16rem; }
.filters label { display: flex; flex-direction: column; margin: 0; }
.filters input, .filters select { padding: .45rem .6rem; }

.linkbtn {
  display: inline-block; background: var(--surface-2); color: var(--ink);
  border: 1px solid var(--line-firm); border-radius: 6px;
  padding: .45rem .8rem; font-size: .9rem; text-decoration: none;
}
.linkbtn:hover { text-decoration: none; filter: brightness(.98); }

.lead { font-size: 1.05rem; font-weight: 600; margin: .2rem 0 1rem; }

.badge {
  display: inline-block; background: var(--surface-2); color: var(--muted);
  border: 1px solid var(--line); border-radius: 999px;
  padding: .05rem .5rem; font-size: .75rem; font-weight: 600;
  vertical-align: middle; margin-left: .3rem;
}
.badge.warn { background: var(--warn-bg); color: var(--warn); border-color: var(--warn); }

/* The words carry it; the colour only agrees with them. */
.status-current { color: var(--accent); font-weight: 600; }
.status-due     { color: var(--warn); font-weight: 600; }
.status-lapsed  { color: var(--danger); font-weight: 600; }
.status-ended   { color: var(--muted); }

.notice.warn { background: var(--warn-bg); border-color: var(--warn); color: var(--warn); }

/* The import preview. Same rule as the statuses above: the words say what
   happens and the colour only agrees with them. */
.import-create    { color: var(--accent); font-weight: 600; }
.import-update    { color: var(--warn); font-weight: 600; }
.import-unchanged { color: var(--muted); }
.import-rejected  { color: var(--danger); font-weight: 600; }

/* A spreadsheet is as wide as somebody made it, and the preview of it must
   not take the page sideways with it. */
.scroll-x { overflow-x: auto; }
ul.spaced li { margin-bottom: .4rem; }

.member-people { list-style: none; margin: 0 0 1rem; padding: 0; }
.member-people li { padding: .5rem 0; border-bottom: 1px solid var(--line); }
.member-people li:last-child { border-bottom: none; }

/* One person per block: three fields on a line, consent on its own.
   ``minmax(0, …)`` and the ``min-width: 0`` below are what keep the row inside
   the fieldset — a grid column's default minimum is its content, and three
   text inputs won't shrink below their own intrinsic width, so without these
   the row grows straight out through the panel border. */
.person-fields {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: .6rem .8rem; align-items: end;
}
.person-fields > * { min-width: 0; }
.person-row {
  padding: .7rem 0; border-bottom: 1px dashed var(--line);
}
.person-row:last-of-type { border-bottom: none; }
.person-row label { margin: 0; }
.person-row input { width: 100%; }
/* Its own line, so the label reads as a sentence rather than as one word per
   line in a column an inch wide — and so it's a target worth tapping. */
.person-row .check { margin-top: .5rem; }

/* Sized to its words, not to the panel: it adds a box, it doesn't save. */
.addperson { display: inline-block; width: auto; margin-top: .8rem; }

.since { margin-top: .8rem; max-width: 20rem; }
.since .muted { font-size: .8rem; }

fieldset.radios { border: 0; padding: 0; margin: .4rem 0; }
fieldset.radios legend { font-size: .85rem; color: var(--muted); padding: 0; }

.notes { list-style: none; margin: 0 0 1.2rem; padding: 0; }
.note {
  background: var(--card); border: 1px solid var(--line); border-left: 3px solid var(--line-firm);
  border-radius: 8px; padding: .7rem .9rem; margin-bottom: .6rem;
}
.note.deleted { opacity: .6; border-left-color: var(--danger); }
.note-body { white-space: pre-wrap; margin-bottom: .3rem; }
.note-edit summary { cursor: pointer; color: var(--muted); font-size: .85rem; margin-top: .4rem; }
.note-edit form { margin-top: .6rem; }

@media screen and (max-width: 860px) {
  /* One field per line: the household form is the one screen a committee
     member is most likely to fill in on a phone at the AGM. */
  .person-fields { grid-template-columns: 1fr; align-items: stretch; }
}

/* ==========================================================================
   The handbook. The only page here that is read rather than worked in, so it
   is set as prose: a measure narrow enough to read down, headings with air
   above them, and lists that breathe. Everything else on this stylesheet is
   laid out to fit data on a screen; this one is laid out to be read.
   ========================================================================== */

.guide { max-width: 44rem; }
.guide h2 {
  font-family: var(--serif); font-size: 1.3rem;
  margin: 2.2rem 0 .5rem; padding-top: .6rem; border-top: 1px solid var(--line);
  /* An in-page link must not land its heading under the sticky mobile bar. */
  scroll-margin-top: 4rem;
}
.guide h3 { font-size: 1rem; margin: 1.4rem 0 .4rem; }
/* Somebody reading a section usually wants the page it describes, and hunting
   the sidebar for it is a worse ending than a link right there. */
.guide-open {
  font-family: var(--sans); font-size: .78rem; font-weight: 400;
  color: var(--muted); margin-left: .5rem; white-space: nowrap;
}
.guide-open:hover { color: var(--copper); }
.guide p { margin: 0 0 .8rem; }
.guide ul, .guide ol { margin: 0 0 1rem; padding-left: 1.3rem; }
.guide li { margin-bottom: .5rem; }
.guide .subhead { margin-top: 2.4rem; }
.guide table { margin: .4rem 0 1.2rem; }
.guide .notice p:last-child { margin-bottom: 0; }

/* The contents list is a signpost, not content: two columns of small type,
   folded into the page rather than boxed like a panel. */
.guide-toc { margin: 1.6rem 0 .4rem; }
.guide-toc .subhead { margin-top: 0; }
.guide-toc ul {
  columns: 2; column-gap: 2rem; list-style: none;
  margin: 0; padding: 0; font-size: .92rem;
}
.guide-toc li { margin-bottom: .25rem; break-inside: avoid; }

/* Two lines of arithmetic, which read as arithmetic or not at all. */
.calc {
  background: var(--surface-2); border: 1px solid var(--line); border-radius: 8px;
  padding: .7rem .9rem; margin: 0 0 1rem;
  font-size: .88rem; line-height: 1.6; overflow-x: auto;
}

.guide-foot {
  margin-top: 2.4rem; padding-top: .9rem; border-top: 1px solid var(--line);
  color: var(--muted); font-size: .9rem;
}

@media screen and (max-width: 700px) {
  .guide-toc ul { columns: 1; }
  /* These tables hold sentences, not figures, so they wrap rather than
     scrolling sideways the way the data tables do. */
  .guide table { display: table; white-space: normal; }
}

@media print {
  /* A printer has no dark mode, and a phone set to one would otherwise send
     white text to the page. Pin the palette to ink on paper. */
  :root, body.sheet > .sheet-body {
    --bg: #fff; --card: #fff; --surface-2: #fff;
    --ink: #000; --muted: #444; --faint: #555;
    --line: #bbb; --line-firm: #666;
  }
  .sheet-tools, .sidebar, .topbar, .flash, .skip { display: none !important; }
  body, body.sheet { background: #fff; padding: 0; margin: 0; }
  .sheet-body { max-width: none; }
  .sheet-preview { border: 0; padding: 0; }
  .pricesection h2 { color: var(--ink); }
  .pricetable td.num:last-child, .bartable .price-member { color: var(--ink); }
  @page { size: A4; margin: 12mm 12mm 10mm; }
  body.sheet > .sheet-body { width: auto; min-height: 0; padding: 0; box-shadow: none; }

  a { color: inherit; text-decoration: none; }
  table { break-inside: auto; }
  thead { display: table-header-group; }
  tr { break-inside: avoid; }
}

/* ==========================================================================
   Mobile. The admin panel was built for a desktop; the rota was not, and
   staff only ever see the rota.
   ========================================================================== */

/* Too narrow for a sidebar: it lies down as a bar, and the links fold into a
   disclosure so ten of them don't push the page down three rows. */
@media screen and (max-width: 860px) {
  .sidebar {
    position: sticky; top: 0; bottom: auto; width: auto;
    flex-direction: row; align-items: center; justify-content: space-between;
    gap: .9rem; padding: .6rem .9rem;
    border-right: 0; border-bottom: 1px solid var(--line);
    overflow: visible;
  }
  .sidebar .brand { font-size: 1rem; padding: 0; }
  .navdrop { flex: 0 0 auto; }
  .navdrop > summary {
    list-style: none; cursor: pointer;
    display: inline-flex; align-items: center; min-height: 44px; padding: 0 .8rem;
    background: var(--surface-2); border: 1px solid var(--line-firm); border-radius: 6px;
    font-size: .9rem;
  }
  .navdrop > summary::-webkit-details-marker { display: none; }
  .navdrop[open] > summary { background: var(--accent-bg); border-color: var(--accent-line); }
  .navdrop-body {
    position: absolute; left: 0; right: 0; top: 100%;
    padding: .6rem .9rem 1rem;
    background: var(--card); border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow-sm);
  }
  .navdrop nav a { padding: .6rem .55rem; }
  .navfoot { flex-direction: row; align-items: center; justify-content: space-between; }
}

@media screen and (max-width: 700px) {
  .topbar { height: auto; flex-wrap: wrap; gap: .5rem .9rem; padding: .6rem .9rem; }
  .topbar nav { flex-wrap: wrap; gap: .5rem .9rem; order: 3; width: 100%; }
  .topbar .brand { font-size: 1rem; }
  .logout { margin-left: auto; }
  .logout .who { display: none; }

  .content { margin: 1rem auto; padding: 0 .9rem; }
  .shift-date { font-size: 1.24rem; }

  /* Wide admin tables scroll inside their own box rather than pushing the
     whole page sideways. */
  table { display: block; overflow-x: auto; white-space: nowrap; }

  form.stacked { padding: .9rem; }
  form.stacked .row { flex-direction: column; gap: .8rem; }

  /* The mapping rows are not a table, so they don't scroll sideways — they
     just get narrower, and the edit fields stack. */
  .people li { flex-wrap: wrap; }
  .people li form.inline { flex: 1 1 100%; }
  .people li form.inline select { flex: 1; min-width: 0; }
  .mapedit > form:first-child { min-width: 100%; }
}

@media screen and (max-width: 420px) {
  .rota-manage { flex-direction: column; }
  .rota-manage .btn, .rota-manage .btn-add { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: .01ms !important; }
}
