/* ---------------------------------------------------------------------------
   Co-op app base stylesheet.

   Direction: a calm, modern web application. Soft desaturated colour on a
   near-white ground, one sans family, generous whitespace, hairline borders and
   shadows you notice only when they are gone. Nothing is skeuomorphic and
   nothing shouts; the content is the only thing with contrast.

   Colour still carries the one rule the whole app turns on (ADR-0002: exactly
   one school year is open, the rest are read-only history). A closed year
   retunes every token to warm stone, so history is legible as a different place
   at a glance rather than only in a banner. That is the single piece of
   meaning colour is asked to carry — everything else is quiet on purpose.

   Every later slice inherits from here, so this file defines the vocabulary
   (tokens, layout, forms, tables, calendar) rather than styling any one page.
   Built to read well on a phone in a church basement, which is where most of
   this app is actually used.
   --------------------------------------------------------------------------- */

/* --- Tokens: the live year ------------------------------------------------ */

:root {
  color-scheme: light dark;

  /* Ground and surfaces. The page is a hair cooler than the cards that sit on
     it, which is what gives a flat design its sense of depth without shadows. */
  --paper: #f6f7fa;
  --surface: #ffffff;
  --surface-sunk: #f1f3f8;
  --surface-hover: #f7f8fc;

  /* Never pure black: at these sizes it reads as harsh rather than crisp. */
  --ink: #1b2230;
  --ink-soft: #59637a;
  --ink-faint: #8b94a8;

  --rule: #e8eaf1;
  --rule-strong: #d6dae5;

  /* A soft indigo. Dark enough to pass contrast as body-sized link text, muted
     enough that a page full of links is not a page full of noise. */
  --accent: #5468b8;
  --accent-hover: #42549a;
  --accent-wash: #eef0fa;
  --accent-soft: #dde3f5;
  --accent-on: #ffffff;

  --warn: #8d6a1f;
  --warn-wash: #fbf3e3;
  --danger: #b0504a;
  --danger-wash: #fbeceb;
  --ok: #3d8268;
  --ok-wash: #e8f4ef;

  /* Event kinds. Soft tints for the chips on the month grid and the badges that
     echo them, so a glance at the calendar sorts field trips from meetings. */
  --ev-coop: #5468b8;
  --ev-trip: #3d8268;
  --ev-trip-wash: #e6f3ee;
  --ev-party: #a2568a;
  --ev-party-wash: #f8edf4;
  --ev-meeting: #8d6a1f;
  --ev-meeting-wash: #faf1de;
  --ev-other: #66718a;
  --ev-other-wash: #eef0f5;

  --radius-sm: 6px;
  --radius: 9px;
  --radius-lg: 14px;

  /* Two shadows only. The first is the border's soft edge, the second the lift.
     Both are tinted with the ink colour rather than black, which keeps them
     from going grey and muddy over a coloured ground. */
  --shadow-sm: 0 1px 2px rgba(27, 34, 48, 0.06);
  --shadow: 0 1px 2px rgba(27, 34, 48, 0.05), 0 6px 16px -10px rgba(27, 34, 48, 0.22);
  --shadow-lg: 0 2px 4px rgba(27, 34, 48, 0.05), 0 18px 36px -20px rgba(27, 34, 48, 0.3);

  --font-body: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  /* Headings are the same family, tuned tighter. One typeface, two voices. */
  --font-display: var(--font-body);

  --measure: 68ch;
  --gutter: 1.5rem;
}

/* --- Tokens: a closed year, which is warm stone --------------------------- */

:root[data-year="closed"] {
  --paper: #f7f5f1;
  --surface: #fffefb;
  --surface-sunk: #f2eee7;
  --surface-hover: #faf8f4;
  --ink: #292420;
  --ink-soft: #635b50;
  --ink-faint: #948b7d;
  --rule: #e9e3d9;
  --rule-strong: #d6cdbe;
  /* Muted on purpose: nothing in a closed year is yours to change. */
  --accent: #8a7145;
  --accent-hover: #6d5934;
  --accent-wash: #f3eee4;
  --accent-soft: #e8e0d0;
  --ev-coop: #8a7145;
  --ev-trip: #6b7a64;
  --ev-trip-wash: #edf0ea;
  --ev-party: #8d6b78;
  --ev-party-wash: #f3ecee;
  --ev-meeting: #8a6a3d;
  --ev-meeting-wash: #f3ebdd;
  --ev-other: #7d7566;
  --ev-other-wash: #f0ede6;
  --shadow-sm: 0 1px 2px rgba(41, 36, 32, 0.06);
  --shadow: 0 1px 2px rgba(41, 36, 32, 0.05), 0 6px 16px -10px rgba(41, 36, 32, 0.2);
  --shadow-lg: 0 2px 4px rgba(41, 36, 32, 0.05), 0 18px 36px -20px rgba(41, 36, 32, 0.28);
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #12151c;
    --surface: #1a1e27;
    --surface-sunk: #212632;
    --surface-hover: #232936;
    --ink: #e7eaf2;
    --ink-soft: #a6aebf;
    --ink-faint: #7e8798;
    --rule: #2a303d;
    --rule-strong: #3a4252;
    --accent: #93a5e8;
    --accent-hover: #b2c0f2;
    --accent-wash: #20263a;
    --accent-soft: #2b3350;
    --accent-on: #12151c;
    --warn: #d9b36a;
    --warn-wash: #2a2418;
    --danger: #e09a93;
    --danger-wash: #2d1f1e;
    --ok: #7cc0a5;
    --ok-wash: #17281f;
    --ev-coop: #93a5e8;
    --ev-trip: #7cc0a5;
    --ev-trip-wash: #1a2a25;
    --ev-party: #d79cc2;
    --ev-party-wash: #2c2029;
    --ev-meeting: #d9b36a;
    --ev-meeting-wash: #2a2418;
    --ev-other: #9aa4b8;
    --ev-other-wash: #232733;
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 6px 16px -10px rgba(0, 0, 0, 0.7);
    --shadow-lg: 0 2px 4px rgba(0, 0, 0, 0.4), 0 18px 36px -20px rgba(0, 0, 0, 0.8);
  }

  :root[data-year="closed"] {
    --paper: #16130f;
    --surface: #1e1a15;
    --surface-sunk: #262119;
    --surface-hover: #29241c;
    --ink: #ece5d9;
    --ink-soft: #bbb0a0;
    --ink-faint: #948a79;
    --rule: #322b22;
    --rule-strong: #453c2f;
    --accent: #d3b784;
    --accent-hover: #e5cda2;
    --accent-wash: #272016;
    --accent-soft: #362d1f;
    --accent-on: #16130f;
    --ev-coop: #d3b784;
    --ev-trip: #a8b79c;
    --ev-trip-wash: #1f241b;
    --ev-party: #c9a3ae;
    --ev-party-wash: #281f21;
    --ev-meeting: #d3b784;
    --ev-meeting-wash: #272016;
    --ev-other: #a79d8c;
    --ev-other-wash: #242018;
  }
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  background: var(--paper);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 0.9375rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* --- Type ----------------------------------------------------------------- */

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 650;
  line-height: 1.25;
  margin: 0 0 0.5em;
  letter-spacing: -0.018em;
  color: var(--ink);
}

h1 {
  font-size: clamp(1.5rem, 1.2rem + 1.3vw, 2rem);
  letter-spacing: -0.025em;
}
h2 {
  font-size: clamp(1.125rem, 1.02rem + 0.5vw, 1.3rem);
}
h3 {
  font-size: 1rem;
}

p {
  margin: 0 0 1rem;
  max-width: var(--measure);
}

a {
  color: var(--accent);
  text-decoration-color: color-mix(in srgb, var(--accent) 35%, transparent);
  text-underline-offset: 0.18em;
  text-decoration-thickness: 1px;
  transition: color 0.15s ease, text-decoration-color 0.15s ease;
}
a:hover {
  color: var(--accent-hover);
  text-decoration-color: currentColor;
}

strong {
  font-weight: 620;
}

/* The shared "small label" voice: table headers, legends, step names, meta
   labels. Stated once so every one of them agrees. */
.subform legend,
.year-switch__label,
.finder__field label,
.factlist dt,
.tally__label,
.agenda__weekday,
.agenda__monthname,
th {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  font-weight: 650;
  color: var(--ink-faint);
}

/* --- Layout --------------------------------------------------------------- */

.shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.container {
  width: 100%;
  max-width: 72rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

main {
  flex: 1;
  padding-block: 2.5rem 4rem;
}

/* --- Masthead and navigation ---------------------------------------------- */

.masthead {
  background: color-mix(in srgb, var(--surface) 85%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--rule);
  position: sticky;
  top: 0;
  z-index: 20;
}

.masthead__bar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: 3.5rem;
  flex-wrap: wrap;
}

.brand {
  font-size: 1.0625rem;
  font-weight: 680;
  letter-spacing: -0.025em;
  color: var(--ink);
  text-decoration: none;
  margin-right: auto;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  white-space: nowrap;
}

.brand:hover {
  color: var(--ink);
}

/* A rounded-square monogram — the one place the accent appears at full strength,
   so the eye has somewhere to land on an otherwise quiet bar. The letter is
   whatever the co-op is called (settings.COOP_NAME), so this has to centre any
   capital rather than one hand-kerned glyph.

   ``line-height: 1`` is the whole trick. Inherited, the body's 1.6 makes the grid
   centre the *line box* — half-leading and descender space included — which parks
   the capital visibly high in the square. At 1 the box is the glyph's own em box,
   which for Inter's capitals lands within half a pixel of optical centre at this
   size. Not chased further: the remainder is below the resolution of the screen
   it is drawn on. */
.brand__mark {
  width: 2rem;
  height: 2rem;
  border-radius: 9px;
  background: var(--accent);
  color: var(--accent-on);
  display: grid;
  place-items: center;
  line-height: 1;
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0;
  flex: none;
  box-shadow: var(--shadow-sm);
}

.nav {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex: 1 1 22rem;
  min-width: 0;
  gap: 0.1rem;
  flex-wrap: wrap;
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav a {
  display: block;
  padding: 0.35rem 0.65rem;
  border-radius: var(--radius-sm);
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.875rem;
  font-weight: 500;
  white-space: nowrap;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.nav a:hover {
  background: var(--surface-sunk);
  color: var(--ink);
}

.nav a[aria-current="page"] {
  background: var(--accent-wash);
  color: var(--accent-hover);
  font-weight: 600;
}

/* Who you are signed in as. A quiet chip, not a control. */
.nav__year {
  font-size: 0.78rem;
  color: var(--ink-faint);
  background: var(--surface-sunk);
  border-radius: 999px;
  padding: 0.2rem 0.7rem;
  white-space: nowrap;
}

.nav__signout {
  background: none;
  border: none;
  padding: 0.35rem 0.65rem;
  border-radius: var(--radius-sm);
  color: var(--ink-soft);
  font: inherit;
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.nav__signout:hover {
  background: var(--surface-sunk);
  color: var(--ink);
}

/* --- Cards and panels ----------------------------------------------------- */

.card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: 1.5rem;
  box-shadow: var(--shadow-sm);
}

.card + .card {
  margin-top: 1rem;
}

/* The grid does its own spacing; the stacking margin would push every card
   after the first out of line with its row. */
.grid .card + .card {
  margin-top: 0;
}

.card__title {
  margin-top: 0;
}

.stack > * + * {
  margin-top: 1rem;
}

.grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
}

.lede {
  font-size: 1.0625rem;
  line-height: 1.55;
  color: var(--ink-soft);
  margin-bottom: 1.5rem;
}

.muted {
  color: var(--ink-faint);
}

/* --- Buttons -------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.5rem 1rem;
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: var(--accent);
  color: var(--accent-on);
  font: inherit;
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.4;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: background-color 0.15s ease, border-color 0.15s ease,
    box-shadow 0.15s ease, transform 0.05s ease;
}

.btn:hover {
  background: var(--accent-hover);
  color: var(--accent-on);
  box-shadow: var(--shadow);
}

.btn:active {
  transform: translateY(1px);
  box-shadow: var(--shadow-sm);
}

.btn--quiet {
  background: var(--surface);
  border-color: var(--rule-strong);
  color: var(--ink);
}

.btn--quiet:hover {
  background: var(--surface-sunk);
  border-color: var(--rule-strong);
  color: var(--ink);
}

.btn--danger {
  background: var(--danger);
  color: #fff;
}

.btn--danger:hover {
  background: var(--danger);
  color: #fff;
  filter: brightness(0.93);
}

/* One focus ring for the whole app, drawn outside the element so it never
   changes anything's size. */
.btn:focus-visible,
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* --- Forms ---------------------------------------------------------------- */

label {
  display: block;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--ink-soft);
  margin-bottom: 0.35rem;
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="date"],
input[type="time"],
input[type="tel"],
input[type="search"],
input[type="url"],
select,
textarea {
  width: 100%;
  max-width: 28rem;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 0.9375rem;
  line-height: 1.5;
  min-height: 2.5rem;
  box-shadow: var(--shadow-sm);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

input:hover,
select:hover,
textarea:hover {
  border-color: var(--ink-faint);
}

/* A soft ring rather than a hard outline: the field grows a halo in its own
   colour instead of being boxed in. */
input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

textarea {
  min-height: 7rem;
  resize: vertical;
}

select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-faint) 50%),
    linear-gradient(135deg, var(--ink-faint) 50%, transparent 50%);
  background-position: calc(100% - 1.05rem) 55%, calc(100% - 0.8rem) 55%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 2.2rem;
}

input[type="checkbox"],
input[type="radio"] {
  accent-color: var(--accent);
  width: 1rem;
  height: 1rem;
  min-height: 0;
}

.field + .field {
  margin-top: 1rem;
}

.helptext {
  display: block;
  font-size: 0.8125rem;
  color: var(--ink-faint);
  margin-top: 0.3rem;
  max-width: var(--measure);
}

.errorlist {
  list-style: none;
  margin: 0.35rem 0 0;
  padding: 0;
  color: var(--danger);
  font-size: 0.8125rem;
  font-weight: 500;
}

/* --- Sub-forms (formset rows) --------------------------------------------- */

.subform {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 1.1rem 1.15rem;
  margin: 0 0 0.85rem;
  background: var(--surface-sunk);
}

.subform legend {
  padding-inline: 0.4rem;
}

/* --- Year switcher -------------------------------------------------------- */

.year-switch {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.year-switch__label {
  margin: 0;
}

.year-switch select {
  width: auto;
  max-width: none;
  min-height: 0;
  padding: 0.2rem 1.9rem 0.2rem 0.55rem;
  font-size: 0.82rem;
  background-position: calc(100% - 0.95rem) 55%, calc(100% - 0.7rem) 55%;
}

/* --- Guided-profile step indicator ---------------------------------------- */

.steps {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  list-style: none;
  margin: 0 0 2rem;
  padding: 0;
}

.steps__item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--ink-faint);
  font-size: 0.875rem;
}

.steps__marker {
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 0.75rem;
  font-weight: 650;
  border: 1px solid var(--rule-strong);
  background: var(--surface);
  flex: none;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.steps__item--done {
  color: var(--ok);
}

.steps__item--done .steps__marker {
  background: var(--ok);
  border-color: var(--ok);
  color: #fff;
}

.steps__item--current {
  color: var(--ink);
  font-weight: 600;
}

.steps__item--current .steps__marker {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-on);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* --- Banners, messages, badges -------------------------------------------- */

.banner {
  padding: 0.8rem 1rem;
  border-radius: var(--radius);
  border: 1px solid var(--rule);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  max-width: none;
  margin-bottom: 1.5rem;
  font-size: 0.9rem;
}

.banner--readonly {
  background: var(--accent-wash);
  border-color: var(--accent-soft);
  color: var(--ink);
}

.messages {
  list-style: none;
  margin: 0 0 1.5rem;
  padding: 0;
}

/* Tinted ground, saturated text, and a coloured bar down the leading edge —
   enough to tell success from failure without a wall of colour. */
.message {
  padding: 0.7rem 1rem;
  border-radius: var(--radius);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--ink-faint);
  background: var(--surface-sunk);
  color: var(--ink);
  margin-bottom: 0.5rem;
  font-size: 0.9rem;
  box-shadow: var(--shadow-sm);
}

.message--success {
  background: var(--ok-wash);
  border-color: color-mix(in srgb, var(--ok) 25%, transparent);
  border-left-color: var(--ok);
}
.message--warning {
  background: var(--warn-wash);
  border-color: color-mix(in srgb, var(--warn) 25%, transparent);
  border-left-color: var(--warn);
}
.message--error {
  background: var(--danger-wash);
  border-color: color-mix(in srgb, var(--danger) 25%, transparent);
  border-left-color: var(--danger);
}

.badge {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  background: var(--accent-wash);
  color: var(--accent-hover);
  white-space: nowrap;
  vertical-align: 0.05em;
}

.badge--admin {
  background: var(--warn-wash);
  color: var(--warn);
}

/* --- Tables --------------------------------------------------------------- */

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

th,
td {
  text-align: left;
  padding: 0.7rem 0.95rem;
  border-bottom: 1px solid var(--rule);
}

td {
  font-variant-numeric: tabular-nums;
}

th {
  background: var(--surface-sunk);
  border-bottom-color: var(--rule-strong);
  white-space: nowrap;
}

tbody tr {
  transition: background-color 0.12s ease;
}

tbody tr:hover {
  background: var(--surface-hover);
}

tbody tr:last-child td {
  border-bottom: none;
}

/* Per-row controls in an administrator's table. Small, right-aligned and never
   broken across lines, so they sit out of the way of the data they act on. */
.rowactions {
  white-space: nowrap;
  text-align: right;
  width: 1%;
}

.rowactions form {
  display: inline;
}

.rowactions .btn {
  padding: 0.3rem 0.7rem;
  font-size: 0.8125rem;
}

.rowactions .btn + .btn,
.rowactions form + .btn,
.rowactions .btn + form {
  margin-left: 0.35rem;
}

/* --- Footer --------------------------------------------------------------- */

.footer {
  border-top: 1px solid var(--rule);
  padding-block: 1.5rem;
  font-size: 0.82rem;
  color: var(--ink-faint);
  background: var(--surface);
}

/* --- Utilities ------------------------------------------------------------ */

.skip-link {
  position: absolute;
  left: -9999px;
}

.skip-link:focus {
  left: 1rem;
  top: 1rem;
  z-index: 100;
  background: var(--surface);
  padding: 0.6rem 1rem;
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
}

.empty {
  padding: 3rem 1.5rem;
  text-align: center;
  color: var(--ink-faint);
  background: var(--surface);
  border: 1px dashed var(--rule-strong);
  border-radius: var(--radius-lg);
  max-width: none;
}

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

/* --- Directory ------------------------------------------------------------ */

/* Search-and-sort bar. Wraps to stacked fields on a phone, which is where most
   parents will look somebody up. */
.finder {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.75rem;
  margin: 0 0 1.75rem;
  padding: 1rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

.finder__field {
  flex: 1 1 12rem;
}

.finder__field label {
  display: block;
  margin-bottom: 0.3rem;
}

.finder__field input,
.finder__field select {
  max-width: none;
}

.household__adults {
  list-style: none;
  margin: 0;
  padding: 0;
}

.household__adults > li + li {
  margin-top: 0.8rem;
}

.household__name {
  display: block;
  font-weight: 620;
}

.household__contact {
  display: block;
  font-size: 0.875rem;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
  word-break: break-word;
}

.household__children {
  margin: 1.1rem 0 0;
  padding-top: 0.9rem;
  border-top: 1px solid var(--rule);
  color: var(--ink-soft);
  font-size: 0.9rem;
}

.household__address {
  margin: 0.9rem 0 0;
  font-size: 0.875rem;
  color: var(--ink-soft);
}

.directory__note {
  margin-top: 2rem;
  font-size: 0.875rem;
}

/* --- Calendar: the shared chrome ------------------------------------------ */

.crumb {
  margin-bottom: 0.75rem;
  font-size: 0.875rem;
  color: var(--ink-faint);
}

/* Month / agenda / whole-year, plus the one action that belongs beside them. */
.viewswitch {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin: 0 0 1.5rem;
}

/* A segmented control: one sunk track, the selected view riding on a raised
   pill. Reads as a switch rather than as three links that happen to be near
   each other. */
.viewswitch__tabs {
  display: flex;
  gap: 0.15rem;
  padding: 0.2rem;
  background: var(--surface-sunk);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}

.viewswitch__tabs a {
  padding: 0.35rem 0.85rem;
  border-radius: var(--radius-sm);
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.875rem;
  font-weight: 500;
  white-space: nowrap;
  transition: background-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}

.viewswitch__tabs a:hover {
  color: var(--ink);
}

.viewswitch__tabs a[aria-current="page"] {
  background: var(--surface);
  color: var(--ink);
  font-weight: 600;
  box-shadow: var(--shadow-sm);
}

/* --- Calendar: the month grid --------------------------------------------- */

.monthbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 1rem;
}

.monthbar__title {
  margin: 0;
  text-align: center;
  font-size: 1.25rem;
  letter-spacing: -0.02em;
}

/* The grid keeps its seven columns at every width. Below 40rem it stops
   insisting on a minimum and switches to the compact treatment further down,
   so a phone gets the whole month on screen rather than a sideways drag. */
.cal-wrap {
  overflow-x: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}

.cal {
  min-width: 44rem;
}

.cal__weekdays,
.cal__week {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
}

.cal__weekdays {
  background: var(--surface-sunk);
  border-bottom: 1px solid var(--rule);
}

.cal__weekdays span {
  padding: 0.55rem 0.7rem;
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  font-weight: 650;
  color: var(--ink-faint);
  text-align: center;
}

.cal__week + .cal__week {
  border-top: 1px solid var(--rule);
}

.cal__day {
  position: relative;
  min-height: 7rem;
  padding: 0.4rem 0.4rem 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  transition: background-color 0.12s ease;
}

.cal__day + .cal__day {
  border-left: 1px solid var(--rule);
}

/* Three cell states, in cascade order: the ordinary day, a day spilling in from
   a neighbouring month, and today. Deliberately no weekend tint — it was a shade
   nobody could name, and its :first-child/:last-child specificity quietly beat
   both of the states below, which do carry meaning. Each :hover rule sits beside
   its own state so the two never fight. */
.cal__day:hover {
  background: var(--surface-hover);
}

.cal__day--outside {
  background: color-mix(in srgb, var(--surface-sunk) 55%, var(--surface));
}

.cal__day--outside:hover {
  background: var(--surface-sunk);
}

.cal__day--outside .cal__date {
  color: var(--ink-faint);
  opacity: 0.65;
}

.cal__date {
  display: inline-grid;
  place-items: center;
  width: 1.6rem;
  height: 1.6rem;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
  border-radius: 50%;
  flex: none;
}

/* Today is the only "you are here" mark on the grid. Last, so that a today which
   is also an outside day — August's grid running into September — still reads as
   today. */
.cal__day--today {
  background: var(--accent-wash);
}

.cal__day--today:hover {
  background: color-mix(in srgb, var(--accent-soft) 55%, var(--accent-wash));
}

.cal__day--today .cal__date,
.cal__day--today.cal__day--outside .cal__date {
  background: var(--accent);
  color: var(--accent-on);
  opacity: 1;
  box-shadow: var(--shadow-sm);
}

/* An event chip: tinted ground, a saturated bar down its leading edge, and a
   title that truncates rather than reflowing the cell. */
.cal__event {
  display: block;
  position: relative;
  padding: 0.22rem 0.4rem 0.22rem 0.5rem;
  border-radius: var(--radius-sm);
  border-left: 3px solid var(--ev-other);
  background: var(--ev-other-wash);
  color: var(--ink);
  text-decoration: none;
  font-size: 0.76rem;
  line-height: 1.35;
  transition: filter 0.12s ease, box-shadow 0.12s ease;
}

.cal__event:hover {
  color: var(--ink);
  box-shadow: var(--shadow-sm);
  filter: brightness(0.97);
}

.cal__event-title {
  display: block;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cal__event-time {
  display: block;
  font-size: 0.7rem;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}

/* Kinds, in their own soft hues. */
.cal__event--field_trip {
  border-left-color: var(--ev-trip);
  background: var(--ev-trip-wash);
}
.cal__event--party {
  border-left-color: var(--ev-party);
  background: var(--ev-party-wash);
}
.cal__event--meeting {
  border-left-color: var(--ev-meeting);
  background: var(--ev-meeting-wash);
}

/* Co-op days are the spine of the year, so they read as solid rather than
   tinted — the one thing on the grid you can find without reading it. */
.cal__event--spine,
.cal__event--co_op_day {
  background: var(--ev-coop);
  border-left-color: var(--accent-hover);
  color: var(--accent-on);
}

.cal__event--spine:hover,
.cal__event--co_op_day:hover {
  color: var(--accent-on);
}

.cal__event--spine .cal__event-time,
.cal__event--co_op_day .cal__event-time {
  color: inherit;
  opacity: 0.85;
}

/* Add-an-event. Hidden until the day is hovered, because seven-times-five of
   them showing at once is a grid of plus signs, not a calendar. */
.cal__add {
  position: absolute;
  right: 0.35rem;
  bottom: 0.35rem;
  width: 1.5rem;
  height: 1.5rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--rule-strong);
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 0.95rem;
  line-height: 1;
  opacity: 0;
  box-shadow: var(--shadow-sm);
  transition: opacity 0.15s ease, background-color 0.15s ease, color 0.15s ease;
}

.cal__day:hover .cal__add,
.cal__add:focus-visible {
  opacity: 1;
}

.cal__add:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-on);
}

/* --- Calendar: agenda ----------------------------------------------------- */

.agenda {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.6rem;
}

/* Each entry is its own card rather than a ruled row: on a phone this is the
   view people actually use, and a tappable block beats a line of text. */
.agenda__item {
  display: flex;
  gap: 1rem;
  padding: 1rem 1.15rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.agenda__item:hover {
  border-color: var(--rule-strong);
  box-shadow: var(--shadow);
}

/* The same kind-colour as the month grid, down the leading edge, so the two
   views agree about what a field trip looks like. */
.agenda__item {
  border-left: 3px solid var(--ev-other);
}

.agenda__item--co_op_day {
  border-left-color: var(--ev-coop);
}
.agenda__item--field_trip {
  border-left-color: var(--ev-trip);
}
.agenda__item--party {
  border-left-color: var(--ev-party);
}
.agenda__item--meeting {
  border-left-color: var(--ev-meeting);
}

/* The date block reads as a torn-off calendar leaf: month above, numeral big,
   weekday below. */
.agenda__date {
  flex: none;
  width: 3.25rem;
  text-align: center;
  padding: 0.35rem 0;
  border-radius: var(--radius);
  background: var(--surface-sunk);
  font-variant-numeric: tabular-nums;
  align-self: flex-start;
}

.agenda__day {
  display: block;
  font-size: 1.4rem;
  font-weight: 650;
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.agenda__body {
  min-width: 0;
  flex: 1;
}

.agenda__title {
  margin: 0 0 0.3rem;
  font-size: 1rem;
}

.agenda__title a {
  text-decoration: none;
  color: var(--ink);
}

.agenda__title a:hover {
  color: var(--accent);
}

.agenda__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem 0.75rem;
  margin: 0;
  max-width: none;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.agenda__note {
  margin: 0.5rem 0 0;
  color: var(--ink-soft);
  font-size: 0.9rem;
}

/* --- Whole-year list and event detail ------------------------------------- */

.yearlist__month {
  margin-top: 2.25rem;
  margin-bottom: 0.75rem;
}

.factlist {
  display: grid;
  grid-template-columns: minmax(6rem, auto) 1fr;
  gap: 0.6rem 1.5rem;
  margin: 0;
}

.factlist dt {
  padding-top: 0.2rem;
}

.factlist dd {
  margin: 0;
}

.factlist__note {
  margin-top: 1.25rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule);
  color: var(--ink-soft);
}

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

/* Headcounts read as numbers first, labels second — an organiser scanning for
   "how many chairs" should not have to read a sentence. */
.tally {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 1.5rem 0;
  padding: 0;
  list-style: none;
}

.tally__item {
  flex: 1 1 7rem;
  padding: 0.9rem 1rem;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

.tally__number {
  display: block;
  font-size: 1.75rem;
  font-weight: 650;
  line-height: 1.1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.tally__label {
  display: block;
  margin-top: 0.15rem;
}

.roster__section {
  margin-top: 2.25rem;
}

.namelist {
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  background: var(--surface);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}

.namelist li {
  padding: 0.6rem 0.95rem;
  border-bottom: 1px solid var(--rule);
  font-size: 0.9rem;
}

.namelist li:last-child {
  border-bottom: none;
}

/* Checkbox lists of children read better stacked and unpadded than as form rows. */
.field ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.field ul label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 400;
  color: var(--ink);
  margin: 0;
}

.field ul li + li {
  margin-top: 0.4rem;
}

/* --- Small screens -------------------------------------------------------- */

/* Below this width the nav sits on its own row under the brand and scrolls
   sideways rather than wrapping. Wrapped, eleven items stack into six rows and
   eat two thirds of a phone screen before any content appears; on one swipeable
   row the masthead costs two. It bleeds into the gutter on both edges so the
   half-cut item at the end reads as "there is more", and the scrollbar is hidden
   because it would be the only one on the page. */
@media (max-width: 48rem) {
  .masthead {
    position: static;
  }

  .nav {
    flex-wrap: nowrap;
    justify-content: flex-start;
    overflow-x: auto;
    overscroll-behavior-inline: contain;
    scrollbar-width: none;
    -ms-overflow-style: none;
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    /* Room for the focus ring, which would otherwise be clipped by the scroller. */
    padding-block: 0.2rem;
  }

  .nav::-webkit-scrollbar {
    display: none;
  }

  .nav > li {
    flex: none;
  }
}

/* The compact month grid. Event chips collapse to coloured dots and the whole
   month fits the screen; the agenda view remains the one built for reading
   detail on a phone. */
@media (max-width: 40rem) {
  .cal {
    min-width: 0;
  }

  .cal__weekdays span {
    padding: 0.45rem 0.15rem;
    font-size: 0.6rem;
    letter-spacing: 0.04em;
    overflow: hidden;
  }

  .cal__day {
    min-height: 3.9rem;
    padding: 0.25rem 0.15rem 0.3rem;
    align-items: center;
    gap: 0.15rem;
  }

  .cal__date {
    width: 1.45rem;
    height: 1.45rem;
    font-size: 0.75rem;
  }

  .cal__event {
    width: 0.4rem;
    height: 0.4rem;
    padding: 0;
    border-radius: 50%;
    border-left: none;
    background: var(--ev-other);
    display: inline-block;
  }

  .cal__event--field_trip {
    background: var(--ev-trip);
  }
  .cal__event--party {
    background: var(--ev-party);
  }
  .cal__event--meeting {
    background: var(--ev-meeting);
  }
  .cal__event--spine,
  .cal__event--co_op_day {
    background: var(--ev-coop);
  }

  .cal__event-title,
  .cal__event-time {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  /* Adding an event by tapping a 40px cell is a mis-tap waiting to happen; the
     "Add event" button above the grid is the way in on a phone. */
  .cal__add {
    display: none;
  }
}

@media (max-width: 30rem) {
  :root {
    --gutter: 1.1rem;
  }

  main {
    padding-block: 1.75rem 3rem;
  }

  .card {
    padding: 1.15rem;
  }

  .agenda__item {
    gap: 0.8rem;
    padding: 0.9rem 1rem;
  }

  .agenda__date {
    width: 2.75rem;
  }

  .monthbar__title {
    font-size: 1.05rem;
  }

  .monthbar .btn {
    padding-inline: 0.7rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
