/*
 * FCC Family Hub — application stylesheet
 * ----------------------------------------------------------------------------
 * Brand refresh built on the Fauntleroy Children's Center identity:
 *   • azure  #0091C7  — the "circle of people" logo color (friendly, primary mark)
 *   • navy   #0A3D7C  — the wordmark color (trust, anchoring)
 * plus a warm sun accent and accessible semantic colors.
 *
 * Design system reference: docs/DESIGN_GUIDELINES.md
 * Fonts (Nunito / Nunito Sans) are loaded via <link> in layouts/application.html.erb.
 *
 * Conventions:
 *   - Everything is token-driven (see :root). Don't hard-code hex in views.
 *   - State is never color-alone: icons (via ::before) + labels accompany color.
 *   - Class names, IDs, data-targets, and the [hidden] rule below are part of
 *     the JS/test contract — restyle them, don't rename them.
 * ========================================================================== */

/* ===========================================================================
   1. DESIGN TOKENS
   =========================================================================== */
:root {
  /* Brand */
  --navy: #0B3D7B;
  --navy-strong: #082F60;
  --azure: #0095CA;
  --azure-ink: #0A6E9C;           /* AA on white — use for link/azure text */
  --sky-50: #EEF7FB;
  --sky-100: #DDEFF8;
  --sky-200: #C4E3F2;

  /* Warm accent */
  --sun: #F6A609;
  --sun-soft: #FFF3DC;
  --sun-ink: #8A5A00;

  /* Primary call-to-action (buttons) — deliberately off the navy/azure chrome so
     the key actions pop against a calmer page. AA with white text. */
  --cta: #157A4A;

  /* Semantic */
  --success: #1E8E5A;
  --success-strong: #157A4A;      /* white text stays AA */
  --success-soft: #E4F5EC;
  --success-ink: #136441;
  --warning: #C77700;
  --warning-soft: #FFF1DA;
  --warning-ink: #8A5300;
  --danger: #CE3B2E;
  --danger-strong: #B5281D;
  --danger-soft: #FBEAE8;
  --danger-ink: #92271E;

  /* Neutrals */
  --ink: #16263D;
  --ink-muted: #51637B;
  --ink-subtle: #6E7E94;
  --surface: #FFFFFF;
  --surface-alt: #F7FAFD;
  --border: #D8E3EE;
  --border-strong: #BFD2E3;

  /* Type */
  --font-display: "Nunito", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-body: "Nunito Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --text-xs: 0.8125rem;
  --text-sm: 0.9375rem;
  --text-base: 1.0625rem;
  --text-lg: 1.25rem;
  --text-xl: 1.5rem;
  --text-2xl: 1.875rem;
  --text-3xl: clamp(1.9rem, 1.4rem + 1.8vw, 2.5rem);

  /* Space (4px scale) */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 2.5rem;
  --space-8: 3rem;

  /* Radius */
  --radius-sm: 8px;
  --radius: 12px;
  --radius-lg: 16px;
  --radius-xl: 22px;
  --radius-pill: 999px;

  /* Shadow (navy-tinted, restrained) */
  --shadow-sm: 0 1px 2px rgba(11, 61, 123, 0.06), 0 1px 3px rgba(11, 61, 123, 0.08);
  --shadow: 0 4px 14px rgba(11, 61, 123, 0.10);
  --shadow-md: 0 10px 28px rgba(11, 61, 123, 0.12);
  --shadow-lg: 0 22px 48px rgba(8, 37, 76, 0.28);

  /* Focus ring */
  --ring: 0 0 0 3px rgba(0, 149, 202, 0.40);

  --content-width: 760px;
  --content-width-wide: 1200px;
}

/* ===========================================================================
   2. BASE / RESET
   =========================================================================== */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.6;
  color: var(--ink);
  margin: 0;
  padding: 0;
  min-height: 100vh;
  background:
    radial-gradient(1200px 480px at 50% -8%, var(--sky-100) 0%, rgba(221, 239, 248, 0) 60%),
    linear-gradient(180deg, #EFF5FA 0%, #FBFDFE 38%) no-repeat;
  background-color: #FBFDFE;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* The HTML `hidden` attribute must beat explicit `display:flex/grid` on
 * components like .bulk-action-bar / modal steps. (Relied on by JS + tests.) */
[hidden] { display: none !important; }

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  color: var(--navy);
  margin: 0 0 var(--space-4);
  line-height: 1.2;
  font-weight: 800;
  letter-spacing: -0.01em;
}
h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-2xl); }
h3 { font-size: var(--text-xl); }
h4 { font-size: var(--text-lg); }

p { margin: 0 0 var(--space-4); }
p:last-child { margin-bottom: 0; }

strong, b { font-weight: 700; }

a {
  color: var(--azure-ink);
  text-decoration: none;
  font-weight: 600;
  transition: color 0.15s ease;
}
a:hover { color: var(--navy); text-decoration: underline; }

/* Universal, consistent focus indicator (WCAG 2.4.7) */
:focus-visible {
  outline: 3px solid var(--azure);
  outline-offset: 2px;
  border-radius: 4px;
}
/* Components that draw their own ring suppress the default outline. */
.btn:focus-visible { outline-offset: 3px; }

img { max-width: 100%; }

/* Skip link (WCAG 2.4.1) */
.skip-link {
  position: absolute;
  left: var(--space-4);
  top: -100px;
  z-index: 1000;
  background: var(--surface);
  color: var(--navy);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  font-weight: 700;
  transition: top 0.15s ease;
}
.skip-link:focus { top: var(--space-4); text-decoration: none; }

/* Visually hidden, still available to screen readers */
.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;
}

/* ===========================================================================
   3. LAYOUT — masthead, main, footer
   =========================================================================== */
.main-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  background: linear-gradient(115deg, var(--navy-strong) 0%, var(--navy) 45%, var(--azure) 130%);
  padding: var(--space-4) var(--space-6);
  color: #fff;
  box-shadow: var(--shadow);
}

.left-header { display: flex; align-items: center; gap: var(--space-4); }

.logo-img {
  height: 52px;
  width: 52px;
  object-fit: contain;
  background: #fff;
  border-radius: var(--radius-pill);
  padding: 5px;
  box-shadow: 0 4px 10px rgba(8, 37, 76, 0.25);
}

.daycare-title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: 800;
  color: #fff;
  letter-spacing: -0.01em;
  line-height: 1.1;
}

.admin-badge {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--navy);
  background: rgba(255, 255, 255, 0.9);
  border-radius: var(--radius-pill);
  padding: 2px 8px;
  line-height: 1.6;
}

.right-header {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-1);
}

.right-header a,
.logout-link {
  color: #EAF4FB;
  font-weight: 700;
  font-size: var(--text-base);
  text-decoration: none;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-pill);
  transition: background-color 0.15s ease, color 0.15s ease;
}
.right-header a:hover,
.logout-link:hover {
  background-color: rgba(255, 255, 255, 0.16);
  color: #fff;
  text-decoration: none;
}
.right-header a[aria-current="page"] {
  background-color: rgba(255, 255, 255, 0.22);
  color: #fff;
}

.main-content {
  max-width: var(--content-width);
  margin: var(--space-6) auto var(--space-8);
  padding: var(--space-7);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
}
.main-content--wide { max-width: var(--content-width-wide); }

.site-footer {
  max-width: var(--content-width-wide);
  margin: 0 auto;
  padding: var(--space-5) var(--space-6) var(--space-8);
  color: var(--ink-muted);
  font-size: var(--text-sm);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  align-items: center;
  justify-content: space-between;
}
.site-footer a { font-weight: 700; }
.site-footer__brand { font-weight: 800; color: var(--navy); font-family: var(--font-display); }

/* ===========================================================================
   4. FLASH / ALERTS  (role=status|alert; icon + color, never color alone)
   =========================================================================== */
.alert {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin: 0 0 var(--space-5);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-left-width: 5px;
  border-radius: var(--radius);
  font-weight: 600;
  background: var(--surface-alt);
  color: var(--ink);
}
.alert::before {
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1.5;
  flex: none;
}
.alert--success { background: var(--success-soft); border-color: var(--success); color: var(--success-ink); }
.alert--success::before { content: "✓"; color: var(--success); }
.alert--danger  { background: var(--danger-soft);  border-color: var(--danger);  color: var(--danger-ink); }
.alert--danger::before  { content: "!"; color: var(--danger); }
.alert--warning { background: var(--warning-soft); border-color: var(--warning); color: var(--warning-ink); }
.alert--warning::before { content: "!"; color: var(--warning); }
.alert--info    { background: var(--sky-100);      border-color: var(--azure);   color: var(--navy); }
.alert--info::before    { content: "i"; color: var(--azure-ink); }

/* ===========================================================================
   5. BUTTONS
   Base `.btn` + modifiers, plus the legacy button classes (kept for JS/tests).
   =========================================================================== */
/* Primary buttons. Note: this intentionally does NOT blanket-style `form button`,
 * because button_to renders row actions (e.g. Archive) as a <button> inside a <form>
 * and they must keep their own small/secondary styling. In-form <button>s all carry
 * their own classes (.btn-primary, .add-family-toggle, token chips, etc.). */
.btn,
form input[type="submit"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: 700;
  line-height: 1.1;
  padding: 0.7rem 1.5rem;
  min-height: 44px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: var(--cta);
  color: #fff;
  cursor: pointer;
  text-decoration: none;
  box-shadow: var(--shadow-sm);
  transition: transform 0.12s ease, box-shadow 0.15s ease, background-color 0.15s ease, filter 0.15s ease;
}
.btn:hover,
form input[type="submit"]:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow);
  color: #fff;
  filter: saturate(1.05);
}
/* Tactile press "squish" — gives mobile taps the feedback the hover-lift can't. */
.btn:active,
form input[type="submit"]:active { transform: scale(0.97); }

.btn--secondary {
  background: var(--surface);
  color: var(--navy);
  border-color: var(--border-strong);
  box-shadow: none;
}
.btn--secondary:hover { background: var(--sky-50); color: var(--navy); filter: none; }

.btn--ghost {
  background: transparent;
  color: var(--azure-ink);
  border-color: transparent;
  box-shadow: none;
}
.btn--ghost:hover { background: var(--sky-100); color: var(--navy); filter: none; }

.btn--success { background: var(--success-strong); }
.btn--danger  { background: var(--danger); color: #fff; }
.btn--block   { width: 100%; }

/* ===========================================================================
   6. FORMS
   Base form is layout-only (no card chrome); the page surface is the card.
   =========================================================================== */
form {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  max-width: 100%;
}
form > div { display: flex; flex-direction: column; gap: var(--space-2); }

label { font-weight: 700; color: var(--ink); font-size: var(--text-sm); }
form label { margin-bottom: var(--space-1); }

input[type="text"],
input[type="password"],
input[type="number"],
input[type="email"],
textarea,
select {
  font-family: inherit;
  font-size: var(--text-base);
  color: var(--ink);
  padding: 0.65rem 0.8rem;
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  width: 100%;
  box-sizing: border-box;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
input[type="text"]:focus,
input[type="password"]:focus,
input[type="number"]:focus,
input[type="email"]:focus,
textarea:focus,
select:focus {
  outline: none;
  border-color: var(--azure);
  box-shadow: var(--ring);
}
::placeholder { color: var(--ink-subtle); opacity: 1; }

input[disabled] {
  background-color: var(--sky-50);
  cursor: not-allowed;
  color: rgba(22, 38, 61, 0.6);
}

.small-help {
  font-size: var(--text-sm);
  color: var(--ink-muted);
  margin: var(--space-1) 0 var(--space-2);
  line-height: 1.45;
  display: block;
}

/* Donation grid (new hours form) — two fields side by side, stack on mobile */
.donation-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-5);
  align-items: start;
}
.donation-field { display: flex; flex-direction: column; gap: var(--space-2); transition: opacity 0.15s ease; }

/* Form-level error summary */
.form-errors {
  margin: 0 0 var(--space-5);
  padding: var(--space-3) var(--space-4);
  background: var(--danger-soft);
  border: 1px solid var(--danger);
  border-left-width: 5px;
  border-radius: var(--radius);
  color: var(--danger-ink);
}
.form-errors ul { margin: var(--space-2) 0 0; padding-left: 1.25rem; }
.form-errors li { font-size: var(--text-sm); }

.inline-form {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
  background: transparent;
  border: none;
  box-shadow: none;
  padding: 0;
  width: 100%;
}
.inline-input { width: 5rem; }

.decline-reason-field { display: flex; flex-direction: column; gap: var(--space-2); width: 100%; }
.decline-reason-label { font-size: var(--text-sm); color: var(--ink-muted); }
.decline-reason-input {
  width: 100%;
  padding: 0.55rem 0.8rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  font-family: inherit;
  font-size: var(--text-sm);
  background: var(--surface);
}
.decline-reason-input:focus { outline: none; border-color: var(--azure); box-shadow: var(--ring); }

.hours-money-wrapper { display: flex; gap: var(--space-6); align-items: flex-start; flex-wrap: wrap; }

/* ===========================================================================
   7. BADGES (status)  — keeps text label intact; icon via ::before
   =========================================================================== */
.status-text {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.25rem 0.7rem;
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 700;
  line-height: 1.3;
  white-space: nowrap;
  border: 1px solid transparent;
}
.status-text::before {
  font-weight: 800;
  line-height: 1;
}
/* Pending */
.status-text--pending {
  background: var(--sky-100); color: var(--navy); border-color: var(--sky-200);
}
.status-text--pending::before { content: "•"; color: var(--azure); font-size: 1.2em; }
/* Verified / approved / success */
.status-text--approved {
  background: var(--success-soft); color: var(--success-ink); border-color: rgba(30, 142, 90, 0.35);
}
.status-text--approved::before { content: "✓"; color: var(--success); }
/* Declined / rejected / danger */
.status-text--rejected {
  background: var(--danger-soft); color: var(--danger-ink); border-color: rgba(206, 59, 46, 0.35);
}
.status-text--rejected::before { content: "✕"; color: var(--danger); }

/* ===========================================================================
   8. CARDS, STAT CARDS, PROGRESS
   =========================================================================== */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-5);
}

.stat-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4);
  margin: var(--space-5) 0;
}
/* Metrics are reference info, not actions — kept quiet (flat, no shadow, no hover)
   so the CTAs carry the visual weight. But they must still read as info cards, not
   disabled buttons: a brand-tinted surface (not grey), a defined border, a semantic
   top accent per metric, and a dark, readable number give them clear identity. */
.stat-card {
  background: var(--sky-50);
  border: 1px solid var(--border-strong);
  border-top: 3px solid var(--border-strong);
  border-radius: var(--radius-lg);
  box-shadow: none;
  padding: var(--space-4) var(--space-5);
  text-align: center;
}
.stat-card--needed   { border-top-color: var(--azure); }
.stat-card--verified { border-top-color: var(--success); }
.stat-card--due      { border-top-color: var(--warning); }
.stat-card__label {
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 var(--space-1);
}
.stat-card__value {
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 1.3rem + 1.4vw, 2.1rem);
  font-weight: 700;
  color: var(--ink);
  line-height: 1.1;
}
.stat-card__hint { font-size: var(--text-xs); color: var(--ink-subtle); margin-top: var(--space-1); }

.progress-block { margin: var(--space-5) 0; }
.progress-block__meta {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
  flex-wrap: wrap;
}
.progress-block__meta strong { font-family: var(--font-display); color: var(--navy); }
.progress {
  height: 16px;
  background: var(--sky-100);
  border-radius: var(--radius-pill);
  overflow: hidden;
  border: 1px solid var(--border);
}
.progress__bar {
  height: 100%;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--azure) 0%, var(--navy) 100%);
  transition: width 0.4s ease;
  min-width: 0.5rem;
}
.progress__bar--complete { background: linear-gradient(90deg, var(--success) 0%, var(--success-strong) 100%); }
.progress__bar--early { background: linear-gradient(90deg, var(--sun) 0%, #E8890B 100%); }

/* Involvement-hours "hero" — the most prominent block on the family page. A
   floating, brand-accented card that anchors the family's status. Stat cards
   (sky-tinted) nest cleanly on its white surface. */
.hours-hero {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-top: 4px solid var(--azure);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  padding: var(--space-6);
  /* Separate the card from the "Your completed hours and contributions" bar below it. */
  margin-bottom: var(--space-5);
}
.hours-hero .progress-block { margin-top: 0; }
.hours-hero .stat-grid { margin-bottom: 0; }
/* Small "work or pay" fine print, shown only while hours are still owed. */
.hours-hero__fee { margin: var(--space-4) 0 0; font-size: var(--text-xs); color: var(--ink-subtle); }
.hours-hero__fee strong { color: var(--ink-muted); font-family: var(--font-display); }

/* "Requirement complete" note in place of the "hours left" line once a family is done. */
.progress-block__done {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  color: var(--success-ink);
  font-family: var(--font-display);
  font-weight: 800;
}
.progress-block__done::before { content: "✓"; }

/* ===========================================================================
   9. TABLES  (unified navy header, soft zebra, accessible)
   =========================================================================== */
table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  margin-top: var(--space-5);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  font-size: var(--text-base);
  box-shadow: var(--shadow-sm);
}

th {
  background: var(--navy);
  color: #fff;
  text-align: left;
  padding: 0.9rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-sm);
  letter-spacing: 0.01em;
  vertical-align: bottom;
}
td {
  padding: 0.85rem 0.9rem;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
tbody tr:last-child td { border-bottom: none; }
tbody tr:nth-child(even) { background-color: var(--sky-50); }
tbody tr:hover { background-color: var(--sky-100); transition: background 0.15s ease; }

td a { color: var(--azure-ink); font-weight: 700; }
td a:hover { color: var(--navy); text-decoration: underline; }

/* Quiet header + flat surface for the family contributions table, so it recedes
   behind the page's actions. (Admin tables keep their navy headers; the thead is
   hidden on mobile, so this only affects the desktop layout.) */
.hours-table { box-shadow: none; }
.hours-table th {
  background: var(--surface-alt);
  color: var(--ink-muted);
  border-bottom: 1px solid var(--border);
}

.hours-table tbody tr { vertical-align: top; }
.hours-table__date { white-space: nowrap; color: var(--ink-muted); }
.hours-table__detail { word-break: break-word; }
.hours-table__hours { font-weight: 800; text-align: center; font-family: var(--font-display); color: var(--navy); }
.hours-table__status { text-align: left; }

.status-wrapper { display: flex; flex-direction: column; gap: var(--space-2); align-items: flex-start; }

/* The pending-entry Delete sits below the status badge — give it clear separation
   and a light outline so a destructive control doesn't crowd/obscure the status. */
.hours-table .status-wrapper { gap: var(--space-3); }
.hours-table .status-wrapper .btn--danger {
  background: var(--surface);
  color: var(--danger-ink);
  border: 1px solid var(--danger);
}
.hours-table .status-wrapper .btn--danger:hover { background: var(--danger-soft); color: var(--danger-ink); filter: none; }
.status-reason {
  font-size: var(--text-sm);
  color: var(--ink-muted);
  background: var(--surface-alt);
  border: 1px solid var(--border);
  padding: 0.35rem 0.6rem;
  border-radius: var(--radius-sm);
  white-space: normal;
  font-weight: 500;
}

.contribution-hours-row {
  display: flex; flex-direction: row !important; align-items: center;
  gap: var(--space-2); white-space: nowrap; width: 100%; font-weight: 600;
}
.action-buttons-row { display: flex; flex-direction: row !important; gap: var(--space-2); align-items: center; }

/* The families "Hours DUE" column intentionally keeps stakeholder-required workflow
 * colors (red = not started, purple = commitment met). They are applied INLINE in
 * app/views/family_summaries/index.html.erb so they override row zebra/hover. This is a
 * deliberate exception to the "no color-only state" rule — staff scan by these colors. */

/* Compact tables (e.g. pending approvals) */
table.small-table, table.small-table td, table.small-table th { font-size: var(--text-sm); }
.small-table th:last-child, .small-table td:last-child { min-width: 260px; }

/* Inline approve/decline action buttons in the pending table */
.hours-table .action-buttons,
.small-table .action-buttons {
  min-height: 0;
  padding: 0.4rem 1rem;
  font-size: var(--text-sm);
  border-radius: var(--radius-pill);
  box-shadow: none;
}
/* Decline submit reads as a cautious action without being alarmist */
.action-buttons-row input[type="submit"][formaction] {
  background: var(--surface);
  color: var(--danger-ink);
  border: 1px solid var(--danger);
}
.action-buttons-row input[type="submit"][formaction]:hover {
  background: var(--danger-soft); color: var(--danger-ink); filter: none;
}

/* ===========================================================================
   10. FAMILIES DASHBOARD — metrics panel, toolbar, filters, bulk bar, inline edit
   =========================================================================== */

/* Page header row: title on the left, primary action (Add New Family) on the right. */
.page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-5);
}
.page-head h1 { margin: 0; }

/* Reporting dashboard (metrics panel, from PR #48) — restyled to the design
 * system. Left-accent variants map to semantic tokens; mirrors .stat-card. */
.metrics-panel { margin-bottom: var(--space-5); }
.metrics-grid {
  display: grid;
  /* Six metrics on one row; minmax(0, 1fr) lets equal columns shrink to fit. */
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--space-3);
}
.metric-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid var(--azure);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.metric-card--positive { border-left-color: var(--success); }
.metric-card--warning  { border-left-color: var(--sun); }
.metric-card--danger   { border-left-color: var(--danger); }
.metric-card__value {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 1.2rem + 1vw, 2rem);
  font-weight: 800;
  line-height: 1.05;
  color: var(--navy);
}
.metric-card--positive .metric-card__value { color: var(--success-ink); }
.metric-card--warning  .metric-card__value { color: var(--sun-ink); }
.metric-card--danger   .metric-card__value { color: var(--danger-ink); }
.metric-card__label { font-size: var(--text-sm); font-weight: 700; color: var(--ink); }
.metric-card__sub { font-size: var(--text-xs); font-weight: 600; color: var(--ink-muted); }
.metrics-panel__note { margin: var(--space-3) 0 0; font-size: var(--text-sm); color: var(--ink-muted); }

/* Below the wide layout the six columns get too cramped — let them wrap. */
@media (max-width: 960px) {
  .metrics-grid { grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); }
}

/* Tabbed metrics panel: Summary cards <-> "hours logged over time" trend chart. */
.metrics-tabs {
  display: flex;
  gap: var(--space-1);
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--space-4);
}
.metrics-tab {
  appearance: none;
  border: 0;
  background: none;
  margin-bottom: -1px;
  padding: var(--space-3) var(--space-4);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--ink-muted);
  cursor: pointer;
  border-bottom: 3px solid transparent;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
}
.metrics-tab:hover { color: var(--ink); background: var(--surface-alt); }
.metrics-tab.is-active { color: var(--navy); border-bottom-color: var(--azure); }
.metrics-tab:focus-visible { outline: 2px solid var(--azure); outline-offset: 2px; }

/* Day / Week / Month segmented control */
.trend-controls {
  display: inline-flex;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  overflow: hidden;
  margin-bottom: var(--space-4);
}
.trend-range-btn {
  appearance: none;
  border: 0;
  background: var(--surface);
  padding: var(--space-2) var(--space-4);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--ink-muted);
  cursor: pointer;
}
.trend-range-btn + .trend-range-btn { border-left: 1px solid var(--border); }
.trend-range-btn:hover { background: var(--surface-alt); color: var(--ink); }
.trend-range-btn.is-active { background: var(--azure); color: #fff; }
.trend-range-btn:focus-visible { outline: 2px solid var(--navy); outline-offset: -2px; }

.trend-caption { margin: 0 0 var(--space-3); font-size: var(--text-sm); color: var(--ink-muted); }
.trend-caption strong { color: var(--navy); font-family: var(--font-display); font-size: var(--text-lg); }

.trend-chart { width: 100%; overflow-x: auto; }
.trend-chart__svg { display: block; width: 100%; min-width: 520px; height: auto; }
.trend-chart__bar { fill: var(--azure); transition: fill 0.12s ease; }
.trend-chart__bar:hover { fill: var(--navy); }
.trend-chart__grid { stroke: var(--border); stroke-width: 1; }
.trend-chart__axis { stroke: var(--border-strong); stroke-width: 1; }
.trend-chart__ylabel,
.trend-chart__xlabel { fill: var(--ink-subtle); font-family: var(--font-body); font-size: 11px; }
.trend-chart__annotation { stroke: var(--warning); stroke-width: 1.5; stroke-dasharray: 3 3; }
.trend-chart__annotation-dot { fill: var(--warning); }

/* Burndown: dual-axis line chart of equivalent value outstanding and the number
   of families still owing hours, over time. */
.burndown-chart { position: relative; }
.burndown-chart__svg { display: block; width: 100%; height: auto; }
.burndown-chart__grid { stroke: var(--border); stroke-width: 1; }
.burndown-chart__axis { stroke: var(--border-strong); stroke-width: 1; }
.burndown-chart__ylabel,
.burndown-chart__xlabel { fill: var(--ink-subtle); font-family: var(--font-body); font-size: 11px; }
.burndown-chart__axis-title { fill: var(--ink-muted); font-family: var(--font-body); font-size: 12px; font-weight: 700; }
.burndown-chart__line { fill: none; stroke: var(--azure); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.burndown-chart__area { fill: var(--azure); opacity: 0.12; stroke: none; }
.burndown-chart__dot { fill: var(--azure); }
.burndown-chart__dot--last { fill: var(--navy); }

/* Secondary series: families still with outstanding hours (right y-axis). */
.burndown-chart__line--families { stroke: var(--sun); stroke-dasharray: 5 4; }
.burndown-chart__dot--families { fill: var(--sun-ink); }
.burndown-chart__ylabel--families { fill: var(--sun-ink); }
.burndown-chart__axis-title--families { fill: var(--sun-ink); }
.burndown-chart__focus--families { fill: var(--sun-ink); }

/* Legend for the two burndown series. */
.burndown-chart__legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
  margin-bottom: var(--space-2);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  color: var(--ink-muted);
}
.burndown-chart__legend-item { display: inline-flex; align-items: center; gap: var(--space-1); }
.burndown-chart__swatch { display: inline-block; width: 16px; height: 3px; border-radius: 2px; }
.burndown-chart__swatch--value { background: var(--azure); }
.burndown-chart__swatch--families { background: var(--sun); }

/* Instant day-granularity hover readout (see burndown_chart_controller.js) */
.burndown-chart__hitbox { fill: transparent; pointer-events: all; cursor: crosshair; }
.burndown-chart__guide { stroke: var(--navy); stroke-width: 1; stroke-dasharray: 3 3; pointer-events: none; }
.burndown-chart__focus { fill: var(--navy); stroke: #fff; stroke-width: 1.5; pointer-events: none; }
.burndown-chart__tooltip {
  position: absolute;
  transform: translate(-50%, calc(-100% - 10px));
  padding: var(--space-1) var(--space-2);
  background: var(--navy);
  color: #fff;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 600;
  white-space: nowrap;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  pointer-events: none;
  z-index: 5;
}

.trend-empty {
  padding: var(--space-6);
  text-align: center;
  color: var(--ink-muted);
  background: var(--surface-alt);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
}

/* Activity Log "activity over time" chart: a card wrapping the reused trend chart. */
.activity-chart {
  margin: var(--space-4) 0 var(--space-5);
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
}
.activity-chart__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}
.activity-chart__head .trend-controls { margin-bottom: 0; }
.activity-chart__title { margin: 0; font-size: var(--text-lg); color: var(--navy); }

.family-toolbar { display: flex; flex-direction: column; gap: var(--space-4); margin-bottom: var(--space-4); }

.filters-bar {
  display: flex; flex-direction: row; flex-wrap: wrap; align-items: flex-end;
  gap: var(--space-3) var(--space-4);
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.filter-field { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.filter-field label {
  font-size: var(--text-xs); font-weight: 800; color: var(--navy);
  letter-spacing: 0.05em; text-transform: uppercase; margin: 0;
}
.filter-field input[type="text"], .filter-field select { width: auto; }
.filter-field input[type="text"] { min-width: 16rem; }
.filter-field select { min-width: 12rem; }
/* No top label, so it sits on the control baseline: a 44px box (matching the
   input / slider / button height) with the checkbox vertically centered. */
.filter-field--check { flex-direction: row; align-items: center; gap: var(--space-2); min-height: 44px; }
.filter-field--check input[type="checkbox"] { width: 1.1rem; height: 1.1rem; margin: 0; cursor: pointer; accent-color: var(--azure); }
.filter-field--check label { text-transform: none; letter-spacing: normal; font-size: var(--text-base); font-weight: 600; color: var(--ink); cursor: pointer; }

/* Actions float to the right edge, separating them from the filter inputs. */
.filters-bar__submit { margin: 0 0 0 auto !important; align-self: flex-end; }
.filters-bar__clear {
  align-self: flex-end;
  display: inline-flex; align-items: center;
  min-height: 44px;
  padding: 0.55rem 1rem;
  font-size: var(--text-sm); font-weight: 700;
  color: var(--azure-ink);
  background: transparent;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  text-decoration: none; cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.filters-bar__clear:hover, .filters-bar__clear:focus { background: var(--sky-50); border-color: var(--azure); color: var(--navy); text-decoration: none; }
/* Result count gets its own full-width line under the controls, right-aligned. */
.filters-count { flex-basis: 100%; text-align: right; margin: var(--space-1) 0 0; font-size: var(--text-sm); font-weight: 700; color: var(--ink-muted); }

/* "Hours remaining" dual-handle range filter. Two overlaid range inputs share a
   single visual track; the JS (range_slider_controller.js) keeps the handles
   from crossing and paints the fill between them. */
.filter-field--range { min-width: 16rem; }
/* Label + live value share one row so the field is the same height as the
   others (readout below the slider used to make this field taller and throw
   the whole bar's alignment off). */
.filter-field__labelrow { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); }
.filter-field__label {
  font-size: var(--text-xs); font-weight: 800; color: var(--navy);
  letter-spacing: 0.05em; text-transform: uppercase; margin: 0;
}
/* Slider lives in a 44px band (like the search input and buttons) with its
   6px track + handles centered, so it aligns on the same control baseline. */
.range-slider { position: relative; height: 44px; }
.range-slider__track, .range-slider__fill {
  position: absolute; top: 50%; transform: translateY(-50%);
  height: 6px; border-radius: 999px;
}
.range-slider__track { left: 0; right: 0; background: var(--border-strong); }
.range-slider__fill { background: var(--azure); }

.range-slider__input {
  position: absolute; top: 50%; transform: translateY(-50%); left: 0; width: 100%; height: 24px; margin: 0;
  -webkit-appearance: none; appearance: none; background: transparent;
  pointer-events: none; /* only the thumbs are grabbable, so both tracks stack */
}
.range-slider__input:focus { outline: none; }
.range-slider__input::-webkit-slider-runnable-track { -webkit-appearance: none; height: 24px; background: transparent; }
.range-slider__input::-moz-range-track { height: 24px; background: transparent; }
.range-slider__input::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 18px; height: 18px; margin-top: 3px; /* center 18px thumb on 24px track */
  border-radius: 50%; background: var(--surface); border: 3px solid var(--azure);
  box-shadow: var(--shadow-sm); cursor: pointer; pointer-events: auto;
}
.range-slider__input::-moz-range-thumb {
  width: 18px; height: 18px;
  border-radius: 50%; background: var(--surface); border: 3px solid var(--azure);
  box-shadow: var(--shadow-sm); cursor: pointer; pointer-events: auto;
}
.range-slider__input:focus-visible::-webkit-slider-thumb { outline: 2px solid var(--navy); outline-offset: 2px; }
.range-slider__input:focus-visible::-moz-range-thumb { outline: 2px solid var(--navy); outline-offset: 2px; }
.range-slider__readout { font-size: var(--text-sm); font-weight: 800; color: var(--navy); white-space: nowrap; letter-spacing: normal; text-transform: none; }
.range-slider__readout-unit { font-weight: 600; color: var(--ink-muted); }

/* Sortable column headers on the All Families table. The link inherits the
   header's text color (white on the navy / KPI-colored <th>s); inline-block so
   the two-line KPI labels keep their <br> break while staying a click target. */
.sort-link { display: inline-block; color: inherit; text-decoration: none; cursor: pointer; }
.sort-link:hover, .sort-link:focus-visible { text-decoration: underline; }
.sort-link__arrow { margin-left: 0.35rem; font-size: 0.85em; opacity: 0.6; white-space: nowrap; }
.sort-link--active .sort-link__arrow { opacity: 1; }

.add-family-dropdown { position: relative; }
.add-family-toggle {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: 0.6rem 1.25rem; min-height: 44px;
  font-family: var(--font-display); font-size: var(--text-base); font-weight: 700;
  color: var(--navy);
  background: var(--sky-100);
  border: 1px solid var(--sky-200);
  border-radius: var(--radius);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.add-family-toggle:hover { background: var(--sky-200); border-color: var(--azure); }
.add-family-toggle-arrow { display: inline-block; transition: transform 0.2s ease; font-size: 0.8rem; }
.add-family-dropdown.open .add-family-toggle-arrow { transform: rotate(180deg); }
.add-family-panel {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  z-index: 50;
  width: min(360px, 92vw);
  opacity: 0;
  transform: translateY(-6px) scale(0.99);
  transform-origin: top right;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s;
}
.add-family-dropdown.open .add-family-panel {
  opacity: 1;
  transform: translateY(0) scale(1);
  visibility: visible;
  pointer-events: auto;
}
@media (max-width: 600px) {
  .add-family-panel { right: auto; left: 0; transform-origin: top left; }
}
.add-family-panel .add-family-form {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-5);
}

.bulk-action-bar {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-4);
  margin: var(--space-4) 0 0;
  padding: var(--space-3) var(--space-5);
  background: linear-gradient(115deg, var(--navy-strong), var(--navy) 60%, var(--azure) 150%);
  color: #fff;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.bulk-action-bar__count { font-size: var(--text-base); font-weight: 600; color: #fff; }
.bulk-action-bar__count strong { font-size: var(--text-lg); margin-right: 0.15rem; font-family: var(--font-display); }
/* Shared pill-button base for the toolbar/modal action buttons. Each button's
   own block (below / in section 11) keeps just its colors, padding and hover. */
.bulk-action-bar__send,
.bulk-email-modal__footer .btn-primary,
.bulk-email-modal__footer .btn-secondary,
.bulk-email-modal__footer input[type="submit"],
.btn-danger {
  appearance: none; border: none; cursor: pointer; min-height: 44px;
  border-radius: var(--radius-pill); margin: 0;
  font-family: var(--font-display); font-weight: 800; font-size: var(--text-sm);
  transition: transform 0.12s ease, box-shadow 0.15s ease, background 0.15s ease;
}

.bulk-action-bar__send {
  background: #fff; color: var(--navy);
  padding: 0.55rem 1.2rem;
  box-shadow: var(--shadow-sm);
}
.bulk-action-bar__send:hover { transform: translateY(-1px); box-shadow: var(--shadow); }

/* Sticky controls */
.sticky-controls { position: sticky; top: 0; z-index: 10; background: var(--surface); padding-bottom: var(--space-2); }
.sticky-controls--stuck { box-shadow: 0 6px 16px rgba(11, 61, 123, 0.10); }

#family_summaries { margin-top: var(--space-2); }
#family_summaries table { border-collapse: separate; border-spacing: 0; overflow: clip; margin-top: 0; }
#family_summaries tbody tr:last-child td { border-bottom: none; }
#family_summaries thead th { position: sticky; top: var(--sticky-controls-height, 0px); z-index: 5; }
#family_summaries td:last-child { white-space: nowrap; }

.bulk-checkbox-cell { width: 1px; white-space: nowrap; padding-right: var(--space-2); }
.bulk-checkbox-cell input[type="checkbox"] { width: 1.15rem; height: 1.15rem; cursor: pointer; margin: 0; accent-color: var(--azure); }

/* Family name is a link to that family's page (kept as the inline-edit "display" target).
 * display:block so the whole name cell is a click target (names wrap to 2 lines). */
#family_summaries .family-link { display: block; color: var(--navy); font-weight: 700; text-decoration: none; }
#family_summaries .family-link:hover,
#family_summaries .family-link:focus-visible { color: var(--azure-ink); text-decoration: underline; }

.archived-row { opacity: 0.62; }
.archived-row td:first-child { font-style: italic; }

/* Row-level admin action buttons (Show / Archive / Edit / Delete / Save / Cancel) */
.row-actions { white-space: nowrap; }
.row-actions form.row-hidden-form { display: none; }
td form:has(.archive-button), td form.button_to { display: inline-block; padding: 0; border: none; box-shadow: none; gap: 0; margin: 0; }

.show-button, .archive-button, .edit-button, .delete-button, .save-button, .cancel-button {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 0;
  padding: 0.35rem 0.85rem;
  font-family: var(--font-display);
  font-size: var(--text-xs); font-weight: 700; line-height: 1.2;
  border-radius: var(--radius-pill);
  color: #fff; border: 1px solid transparent; cursor: pointer;
  margin-left: var(--space-2); margin-top: 0;
  text-decoration: none; white-space: nowrap;
  box-shadow: none;
  transition: transform 0.12s ease, box-shadow 0.15s ease, background 0.15s ease;
}
.show-button:hover, .archive-button:hover, .edit-button:hover, .delete-button:hover, .save-button:hover, .cancel-button:hover {
  transform: translateY(-1px); box-shadow: var(--shadow-sm); text-decoration: none; color: #fff;
}
.show-button { background: var(--navy); color: #fff !important; }
.show-button:hover { background: var(--navy-strong); color: #fff !important; }
.edit-button { background: var(--azure-ink); }
.edit-button:hover { background: var(--navy); }
.delete-button { background: var(--danger); }
.delete-button:hover { background: var(--danger-strong); }
.save-button { background: var(--success-strong); }
.cancel-button { background: var(--surface); color: var(--ink-muted); border-color: var(--border-strong); }
.cancel-button:hover { background: var(--surface-alt); color: var(--ink); }
/* Archive is a secondary (outline) action — lower emphasis than the solid Show/Edit/Delete. */
.archive-button { background: var(--surface); color: var(--ink-muted); border-color: var(--border-strong); }
.archive-button:hover { background: var(--surface-alt); color: var(--ink); border-color: var(--ink-subtle); }
.archive-button.unarchive { background: var(--surface); color: var(--success-ink); border-color: var(--success); }
.archive-button.unarchive:hover { background: var(--success-soft); color: var(--success-ink); border-color: var(--success); }

/* Inline edit inputs */
.inline-edit-input {
  padding: 0.4rem 0.6rem; border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  font-family: inherit; font-size: var(--text-base); background: var(--surface); margin: 0; box-sizing: border-box;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.inline-edit-input:focus { outline: none; border-color: var(--azure); box-shadow: var(--ring); }
.inline-edit-input:invalid { border-color: var(--danger); box-shadow: 0 0 0 2px rgba(206, 59, 46, 0.15); }
.inline-edit-input--name { width: 100%; min-width: 12rem; }
.inline-edit-input--hours { width: 6rem; }
tr.inline-editing { background: var(--sky-50); }

/* Reveal inline edit form on row hover/focus (admin convenience tables) */
.small-table tbody tr .inline-form { opacity: 0; max-height: 0; overflow: hidden; pointer-events: none; transition: opacity 0.2s ease, max-height 0.2s ease; }
.small-table tbody tr:hover .inline-form, .small-table tbody tr:focus-within .inline-form { opacity: 1; max-height: 520px; pointer-events: auto; }

/* ===========================================================================
   11. MODALS (bulk email + delete family) — <dialog>
   =========================================================================== */
.bulk-email-modal, .delete-family-modal {
  padding: 0; border: none; border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg); background: var(--surface); color: var(--ink); overflow: hidden;
}
.bulk-email-modal { width: min(720px, 92vw); max-height: 90vh; }
.delete-family-modal { width: min(480px, 92vw); }
.bulk-email-modal::backdrop, .delete-family-modal::backdrop { background: rgba(8, 30, 60, 0.55); backdrop-filter: blur(2px); }

.bulk-email-form { display: block; padding: 0; margin: 0; border: none; box-shadow: none; background: transparent; border-radius: 0; gap: 0; max-height: 90vh; overflow-y: auto; }
.bulk-email-form > div { padding: var(--space-5) var(--space-6); }

.bulk-email-modal__header, .delete-family-modal .bulk-email-modal__header {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--space-4) var(--space-6);
  background: linear-gradient(115deg, var(--navy-strong), var(--navy) 70%, var(--azure) 160%);
  color: #fff;
}
.bulk-email-modal__header h2 { margin: 0; font-size: var(--text-xl); color: #fff; }
.bulk-email-modal__close {
  appearance: none; background: transparent; border: none; color: #fff; font-size: 1.6rem; line-height: 1;
  cursor: pointer; padding: 0.2rem 0.5rem; border-radius: var(--radius-sm);
}
.bulk-email-modal__close:hover { background: rgba(255, 255, 255, 0.18); }

.bulk-email-field { margin-bottom: var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); }
.bulk-email-field label { font-size: var(--text-xs); font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase; color: var(--navy); }
.bulk-email-field--check { flex-direction: row; align-items: center; gap: var(--space-2); }
.bulk-email-field--check input[type="checkbox"] { width: 1.1rem; height: 1.1rem; margin: 0; accent-color: var(--azure); }
.bulk-email-field--check label { text-transform: none; letter-spacing: normal; font-weight: 600; font-size: var(--text-sm); color: var(--ink); }

.bulk-email-field__hint { margin: 0.15rem 0 0; font-size: var(--text-sm); color: var(--ink-muted); }
.bulk-email-field__hint code { background: var(--sky-100); border: 1px solid var(--sky-200); border-radius: var(--radius-sm); padding: 0.05rem 0.3rem; font-size: 0.85em; color: var(--navy); }

.bulk-email-tokens { margin: var(--space-2) 0 0; font-size: var(--text-sm); color: var(--ink-muted); display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.bulk-email-tokens__label { font-weight: 700; color: var(--navy); margin-right: 0.15rem; }
.bulk-email-tokens__chip {
  appearance: none; display: inline-flex; align-items: baseline; gap: 0.35rem;
  padding: 0.3rem 0.65rem; border-radius: var(--radius-pill);
  background: var(--sky-100); color: var(--navy); border: 1px solid var(--sky-200);
  font: inherit; cursor: pointer; margin: 0;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.1s ease;
}
.bulk-email-tokens__chip:hover { background: var(--sky-200); border-color: var(--azure); transform: translateY(-1px); }
.bulk-email-tokens__chip:active { transform: translateY(0); }
.bulk-email-tokens__chip-token { font-family: "SF Mono", Menlo, Consolas, monospace; font-size: 0.82rem; font-weight: 700; }
.bulk-email-tokens__chip-label { font-size: var(--text-xs); color: var(--ink-muted); }

.bulk-email-preview { background: var(--surface-alt); border: 1px solid var(--border); border-radius: var(--radius); padding: var(--space-4); margin-top: var(--space-2); }
.bulk-email-preview__header { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-3); flex-wrap: wrap; }
.bulk-email-preview__header h3 { margin: 0; font-size: var(--text-base); color: var(--navy); }
.bulk-email-preview__header label { font-size: var(--text-xs); font-weight: 700; color: var(--ink-muted); margin-right: 0.4rem; }
.bulk-email-preview__header select { width: auto; padding: 0.35rem 0.5rem; font-size: var(--text-sm); }
.bulk-email-preview__email { background: var(--surface); border-radius: var(--radius-sm); padding: var(--space-3) var(--space-4); border: 1px solid var(--border); }
.bulk-email-preview__subject { font-size: var(--text-sm); padding-bottom: var(--space-2); margin-bottom: var(--space-2); border-bottom: 1px solid var(--border); word-break: break-word; }
.bulk-email-preview__label { font-weight: 700; color: var(--ink-muted); margin-right: 0.35rem; }
.bulk-email-preview__body { white-space: pre-wrap; font-size: var(--text-sm); line-height: 1.5; color: var(--ink); min-height: 4rem; }

.bulk-email-modal__footer { display: flex; justify-content: flex-end; gap: var(--space-3); padding: var(--space-4) var(--space-6); background: var(--surface-alt); border-top: 1px solid var(--border); }
/* Pill base comes from the shared rule in section 10 (see .bulk-action-bar__send). */
.bulk-email-modal__footer .btn-primary, .bulk-email-modal__footer .btn-secondary, .bulk-email-modal__footer input[type="submit"] {
  padding: 0.6rem 1.3rem;
}
.bulk-email-modal__footer .btn-primary, .bulk-email-modal__footer input[type="submit"] {
  background: linear-gradient(135deg, var(--navy), var(--azure) 150%); color: #fff; box-shadow: var(--shadow-sm);
}
.bulk-email-modal__footer .btn-primary:hover, .bulk-email-modal__footer input[type="submit"]:hover { transform: translateY(-1px); box-shadow: var(--shadow); }
.bulk-email-modal__footer .btn-secondary { background: var(--surface); color: var(--navy); border: 1px solid var(--border-strong); }
.bulk-email-modal__footer .btn-secondary:hover { background: var(--sky-50); }

.bulk-email-skipped { margin: var(--space-2) 0 var(--space-4); color: var(--warning-ink); background: var(--warning-soft); border-radius: var(--radius-sm); padding: 0.6rem 0.85rem 0.6rem 2rem; list-style: disc; }
.bulk-email-skipped li { font-size: var(--text-sm); }

.delete-family-modal__body { padding: var(--space-4) var(--space-6); }
.delete-family-modal__body p { margin: 0 0 var(--space-3); }
.delete-family-modal__warning { color: var(--danger-ink); background: var(--danger-soft); padding: 0.65rem 0.85rem; border-radius: var(--radius-sm); border-left: 4px solid var(--danger); font-weight: 600; }

.btn-danger {
  background: var(--danger); color: #fff;
  padding: 0.6rem 1.3rem;
  box-shadow: var(--shadow-sm);
}
.btn-danger:hover { transform: translateY(-1px); box-shadow: var(--shadow); background: var(--danger-strong); }

/* ===========================================================================
   12. PAGE: LOGIN
   =========================================================================== */
.auth-lead { font-size: var(--text-lg); color: var(--ink-muted); }
.auth-form {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm); padding: var(--space-5); gap: var(--space-3); margin: var(--space-5) 0;
}
.auth-form input[type="email"] { font-size: var(--text-lg); }
.auth-magic { background: var(--sky-50); border: 1px dashed var(--azure); border-radius: var(--radius); padding: var(--space-4); }
.auth-help { color: var(--ink-muted); font-size: var(--text-sm); }

/* ===========================================================================
   13. PAGE: FAMILY SUMMARY
   =========================================================================== */
.summary-section { margin-top: var(--space-7); }
.summary-section:first-child { margin-top: 0; }

.section-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; margin-bottom: var(--space-4); }

/* Useful Links page — link cards with a description + URL. */
.useful-links { list-style: none; margin: var(--space-5) 0 0; padding: 0; display: grid; gap: var(--space-3); max-width: 62ch; }
.useful-links li {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: var(--space-4) var(--space-5);
}
.useful-links a { font-family: var(--font-display); font-weight: 800; font-size: var(--text-lg); }
.useful-links__desc { display: block; color: var(--ink-muted); margin-top: var(--space-1); }
.useful-links__url { display: block; font-size: var(--text-sm); color: var(--ink-subtle); margin-top: var(--space-1); }
.section-head .btn { margin: 0; }

.email-list { list-style: none; margin: 0 0 var(--space-4); padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2); }
.email-list li { background: var(--sky-50); border: 1px solid var(--sky-200); border-radius: var(--radius-pill); padding: 0.35rem 0.85rem; font-size: var(--text-sm); color: var(--navy); font-weight: 600; }
.add-email-form { flex-direction: row; align-items: center; gap: var(--space-2); max-width: 480px; }
.add-email-form input[type="email"] { flex: 1; }
.add-email-form input[type="submit"] { width: auto; flex: none; }

/* ===========================================================================
   14. PAGE: FAQ
   =========================================================================== */
.faq h3 { margin-top: var(--space-6); padding-top: var(--space-5); border-top: 1px solid var(--border); }
.faq h3:first-of-type { border-top: none; padding-top: 0; }
.faq h3 a { color: inherit; text-decoration: none; font-weight: inherit; }
.faq h3 a:hover { color: var(--azure-ink); text-decoration: underline; }
.faq h4 { color: var(--azure-ink); margin-top: var(--space-5); }
.faq ol { padding-left: 1.3rem; display: grid; gap: var(--space-2); }
.faq ol li { padding-left: var(--space-1); }
.faq__ideas { background: var(--surface-alt); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: var(--space-5) var(--space-6); margin-top: var(--space-4); }

/* ===========================================================================
   15. PAGE: AVAILABLE TASKS
   =========================================================================== */
.tasks-intro {
  font-size: var(--text-lg);
  color: var(--ink-muted);
  max-width: 62ch;
  margin-bottom: var(--space-6);
}

.task-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  /* min(18rem, 100%) keeps a single card from overflowing narrow viewports */
  grid-template-columns: repeat(auto-fill, minmax(min(18rem, 100%), 1fr));
  gap: var(--space-4);
}

.task-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-top: 4px solid var(--azure);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-5);
}

.task-card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
}
.task-card__title { margin: 0; font-size: var(--text-lg); }

/* Estimate chip — hours tasks read sky/navy, money tasks read green, each with
   its own icon, so the type is clear by more than color alone. */
.task-card__estimate {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.25rem 0.7rem;
  border-radius: var(--radius-pill);
  background: var(--sky-100);
  color: var(--navy);
  border: 1px solid var(--sky-200);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 700;
  white-space: nowrap;
}
.task-card__estimate--hours::before { content: "\23F1"; } /* stopwatch */
.task-card__estimate--money {
  background: var(--success-soft);
  color: var(--success-ink);
  border-color: rgba(30, 142, 90, 0.35);
}
.task-card__estimate--money::before { content: "\1F4B5"; } /* banknote */

.task-card__desc { margin: 0; color: var(--ink-muted); }

.task-card__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: auto;
  padding-top: var(--space-2);
}

.task-card__due {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--ink-muted);
}
.task-card__due::before { content: "\1F4C5"; } /* calendar */
.task-card__due--overdue { color: var(--danger-ink); }
.task-card__due--overdue::before { content: "\26A0"; } /* warning */
.task-card__due--none { color: var(--ink-subtle); font-weight: 600; }
.task-card__due--none::before { content: ""; }

/* Admin Edit + Delete actions, right-aligned in the card footer */
.task-card__actions { display: inline-flex; align-items: center; gap: var(--space-2); }
/* button_to renders a <form>; keep the inline Delete action compact */
.task-card form.button_to {
  display: inline-block;
  margin: 0;
  padding: 0;
  border: none;
  box-shadow: none;
  background: transparent;
}
.task-card__actions .edit-button,
.task-card__actions .delete-button { margin: 0; }

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

/* Two Add controls (Task + Event) sit together in the page head */
.page-head__actions { display: inline-flex; gap: var(--space-2); flex-wrap: wrap; }
.page-head__actions .btn { margin: 0; }

/* Each listing section (independent tasks, then events) */
.tasks-section { margin-bottom: var(--space-8); }
.tasks-section__title { font-size: var(--text-xl); margin: 0 0 var(--space-1); }

/* Event cards reuse the task-card shell but read navy (a scheduled happening)
   rather than the azure of pick-up-anytime tasks. Past events dim down. */
.task-card--event { border-top-color: var(--navy); }
.task-card--past { opacity: 0.6; }

/* Stacked when / where / capacity metadata on an event card */
.event-meta {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.event-meta li {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--ink-muted);
}
.event-meta__when::before { content: "\1F4C5"; }     /* calendar */
.event-meta__when--past { color: var(--ink-subtle); }
.event-meta__where::before { content: "\1F4CD"; }    /* round pushpin */
.event-meta__capacity::before { content: "\1F465"; } /* volunteers */
.event-meta--center { align-items: center; text-align: center; margin: var(--space-3) 0; }

/* "✓ You're registered" chip on an event card the family has signed up for. */
.task-card__registered {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-weight: 800;
  font-size: var(--text-sm);
  color: var(--success-ink);
}

/* Admin event roster wrapper. */
.roster { margin-top: var(--space-4); }

/* ---------------------------------------------------------------------------
   Task pickup: nav badge, held/active cards, sign-up confirmation
   --------------------------------------------------------------------------- */
.nav-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.35rem;
  height: 1.35rem;
  padding: 0 0.4rem;
  border-radius: var(--radius-pill);
  background: var(--sun);
  color: var(--navy-strong);
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 800;
  line-height: 1;
}

/* Countdown pill — icon + words, never color alone (WCAG 1.4.1). */
.task-deadline {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.7rem;
  border-radius: var(--radius-pill);
  background: var(--sky-100);
  color: var(--navy);
  border: 1px solid var(--sky-200);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 700;
  white-space: nowrap;
}
.task-deadline::before { content: "\23F1"; }            /* stopwatch */
.task-deadline--urgent {
  background: var(--danger-soft);
  color: var(--danger-ink);
  border-color: rgba(206, 59, 46, 0.35);
}
.task-deadline--urgent::before { content: "\26A0"; }    /* warning */

/* On-card state chip for the "Your Tasks" section — replaces the old grouping
   subheaders (WCAG 1.4.1: each carries a text label, not color alone). */
.task-state {
  flex: none;
  display: inline-flex;
  align-items: center;
  padding: 0.2rem 0.7rem;
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-xs);
  white-space: nowrap;
}
.task-state--progress   { background: var(--success-soft); color: var(--success-ink); border: 1px solid rgba(30, 142, 90, 0.30); }
.task-state--log        { background: var(--warning-soft); color: var(--warning-ink); border: 1px solid rgba(199, 119, 0, 0.30); }
.task-state--registered { background: var(--sky-100);      color: var(--azure-ink);   border: 1px solid var(--sky-200); }

.task-card--active { border-top-color: var(--success); }
.task-card--urgent { border-top-color: var(--danger); }
.task-card--done   { border-top-color: var(--ink-subtle); }

.task-card__meta { margin: 0; color: var(--ink-muted); font-size: var(--text-sm); }
.task-card__hold-note { margin: 0; color: var(--ink-muted); font-size: var(--text-sm); }

/* Instructions — shown to a family only after they sign up. */
.task-instructions {
  background: var(--sun-soft);
  border: 1px solid rgba(246, 166, 9, 0.35);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
}
.task-instructions p { margin: 0 0 var(--space-2); color: var(--ink); }
.task-instructions p:last-child { margin-bottom: 0; }
.task-instructions__label {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-xs);
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sun-ink);
  margin-bottom: var(--space-1);
}
.task-instructions--lg { margin: var(--space-4) 0; text-align: left; }

.task-card__cta { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: auto; }
.task-card__cta .btn { margin: 0; }
.task-card__cta form.button_to { margin: 0; }

/* Full-screen "you've signed up" confirmation. */
.task-confirm { max-width: 30rem; margin: var(--space-6) auto; text-align: center; }
.task-confirm__badge {
  width: 3.5rem;
  height: 3.5rem;
  margin: 0 auto var(--space-3);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--success-soft);
  color: var(--success);
  font-size: 2rem;
  font-weight: 800;
}
.task-confirm__heading { margin-bottom: var(--space-2); }
.task-confirm__task { font-size: var(--text-lg); margin-bottom: var(--space-4); }
.task-confirm__deadline {
  background: var(--sky-50);
  border: 1px solid var(--sky-200);
  border-radius: var(--radius);
  padding: var(--space-4);
  margin: var(--space-4) 0;
  text-align: left;
}
.task-confirm__deadline--due { background: var(--warning-soft); border-color: rgba(199, 119, 0, 0.35); }
.task-confirm__actions { margin-top: var(--space-5); }

/* Compact, clickable "Your Tasks" card → opens the task detail page. */
.task-list--active { grid-template-columns: 1fr; gap: var(--space-3); }
.task-card--compact { padding: 0; gap: 0; overflow: hidden; }
.task-summary {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  text-decoration: none;
  color: var(--ink);
  font-weight: 400;
}
.task-summary:hover { background: var(--sky-50); text-decoration: none; }
.task-summary__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.task-summary__title { font-family: var(--font-display); font-weight: 800; color: var(--navy); font-size: var(--text-base); }
.task-summary__hint { font-size: var(--text-xs); color: var(--ink-muted); }
.task-summary__chevron { flex: none; color: var(--ink-subtle); font-size: 1.6rem; line-height: 1; }
.task-summary--static { cursor: default; }

/* The green "log hours / contribution" action at the top of the Hours &
   Contributions section. */
/* Primary "log hours" action, anchored at the bottom of the metrics card. Spans the
   card's inner width (matching the progress bar + stat grid) so it reads as the card's
   action, not an orphaned button between the full-width blocks. */
.hours-hero__cta { margin-top: var(--space-5); }
.hours-hero__cta .btn { width: 100%; margin: 0; padding-top: 0.85rem; padding-bottom: 0.85rem; }
/* Framing note under the primary action — this is the main way to earn hours. */
.hours-hero__cta-note { margin: var(--space-3) auto 0; max-width: 56ch; font-size: var(--text-xs); color: var(--ink-subtle); text-align: center; line-height: 1.5; }
.hours-hero__cta-note strong { color: var(--ink-muted); }

/* "More Ways to Earn Hours" — open tasks / upcoming events surfaced on the family
   page while hours are still owed. Grouped in a tinted block so opportunities read
   as distinct from the held-task cards above them. */
.earn {
  margin-top: var(--space-5);
  background: var(--sky-50);
  border: 1px solid var(--sky-200);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-5) var(--space-5);
}
.earn__title { margin: 0; font-family: var(--font-display); font-weight: 700; font-size: var(--text-base); color: var(--navy); }
.earn__cap { margin: var(--space-1) 0 var(--space-3); font-size: var(--text-sm); color: var(--ink-muted); }
.earn .task-list--active { margin-top: 0; }
/* Offers read azure (opportunity), distinct from the green of a held/active task. */
.earn .task-card--offer { border-top-color: var(--azure); }
.earn .task-card--offer .task-summary:hover { background: var(--sky-100); }
.earn__browse { margin: var(--space-4) 0 0; }

/* Collapsible hours & contributions history — the detail behind the Verified stat,
   kept next to it. Always collapsed by default; the summary is styled as an obvious
   toggle (a "Show ▾ / Hide ▴" pill on the right, plus a hover state). */
.contributions > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-3);
  list-style: none;
  cursor: pointer;
  padding: var(--space-4) var(--space-5);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition: background 0.15s ease, border-color 0.15s ease;
}
.contributions > summary::-webkit-details-marker { display: none; }
.contributions > summary:hover { background: var(--sky-50); border-color: var(--azure); }
.contributions__label { font-family: var(--font-display); font-weight: 700; color: var(--navy); font-size: var(--text-base); }
.contributions__meta { display: inline-flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; justify-content: flex-end; }
.contributions__count { color: var(--ink-muted); font-size: var(--text-sm); white-space: nowrap; }
/* The obvious toggle: azure pill whose label + chevron swap between open/closed. */
.contributions__toggle {
  flex: none;
  display: inline-flex;
  align-items: center;
  padding: 0.3rem 0.85rem;
  border-radius: var(--radius-pill);
  background: var(--sky-100);
  border: 1px solid var(--sky-200);
  color: var(--azure-ink);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--text-sm);
  white-space: nowrap;
}
.contributions__toggle::before { content: "Show \25BE"; }
.contributions[open] .contributions__toggle::before { content: "Hide \25B4"; }
.contributions > summary:hover .contributions__toggle { background: var(--azure); border-color: var(--azure); color: #fff; }
.contributions[open] .hours-table { margin-top: var(--space-4); }

/* Task detail page (opened from a compact card). */
.back-link { margin-bottom: var(--space-3); }
.back-link a { font-weight: 700; }
.task-detail__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; }
.task-detail__title { margin: 0; }
.task-detail__desc { color: var(--ink-muted); margin-top: var(--space-2); }
.task-detail__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-5); }
.task-detail__actions .btn { margin: 0; }
.task-detail__actions form.button_to { margin: 0; display: inline-block; }

/* Add Task form: submit + cancel sit side by side (overrides the column default) */
.form-actions {
  flex-direction: row;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

/* ===========================================================================
   16. RESPONSIVE
   =========================================================================== */
/* The 4-column hours table gets cramped well before phone widths (the Status
   column can't hold the badge + Delete button), so switch it to stacked cards
   below 768px — comfortably before that point. */
@media (max-width: 768px) {
  /* Both data tables share the stacked-card treatment; each td labels itself
     via its data-label attribute. */
  table.hours-table, table.activity-table { display: block; overflow: visible; border: none; box-shadow: none; background: transparent; margin-top: var(--space-4); }
  .hours-table thead, .activity-table thead { display: none; }
  .hours-table tbody, .activity-table tbody { display: block; }
  .hours-table tbody tr, .activity-table tbody tr {
    display: block; margin-bottom: var(--space-4); padding: var(--space-4);
    border-radius: var(--radius-lg); border: 1px solid var(--border);
    box-shadow: var(--shadow-sm); background: var(--surface);
  }
  .hours-table td, .activity-table td { display: block; padding: 0.4rem 0; font-size: var(--text-sm); border: none; }
  .activity-table td { white-space: normal; } /* desktop rules nowrap some columns */
  .hours-table td::before, .activity-table td::before { content: attr(data-label); display: block; font-weight: 800; color: var(--navy); margin-bottom: 0.15rem; font-family: var(--font-display); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.04em; }
  .hours-table__hours { text-align: left; }
  .status-wrapper { gap: var(--space-2); }
  .status-wrapper .action-buttons { align-self: flex-start; }
}

@media (max-width: 720px) {
  .stat-grid { grid-template-columns: 1fr; gap: var(--space-3); }
  .donation-grid { grid-template-columns: 1fr; }
}

@media (max-width: 600px) {
  body { font-size: 1rem; }

  .main-header { flex-direction: column; align-items: flex-start; gap: var(--space-3); padding: var(--space-4); }
  .right-header { width: 100%; flex-wrap: wrap; gap: var(--space-1); }
  .right-header a, .logout-link { font-size: var(--text-sm); }

  .main-content { padding: var(--space-5) var(--space-4); margin: var(--space-4) var(--space-2) var(--space-6); border-radius: var(--radius-lg); }
  .site-footer { padding: var(--space-4); flex-direction: column; align-items: flex-start; }

  .sticky-controls { position: static; }
  #family_summaries thead th { position: static; }

  .filters-bar { flex-direction: column; align-items: stretch; }
  .filter-field input[type="text"], .filter-field select { min-width: 0; width: 100%; }
  .filter-field--range { min-width: 0; width: 100%; }
  .filters-count { margin-left: 0; }
  .add-email-form { flex-direction: column; align-items: stretch; }
  .add-email-form input[type="submit"] { width: 100%; }

  table { display: block; overflow-x: auto; }
  table:not(.hours-table) th, table:not(.hours-table) td { font-size: var(--text-sm); padding: 0.7rem 0.5rem; }
}

/* ===========================================================================
   ACTIVITY LOG
   =========================================================================== */
.activity-table { width: 100%; margin-top: var(--space-4); }
.activity-table th { white-space: nowrap; }
.activity-table__when time { white-space: nowrap; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.activity-table__who { word-break: break-word; color: var(--ink); }
.activity-table__action { word-break: break-word; }
.activity-table__record { white-space: nowrap; }

.activity-record { font-size: var(--text-sm); color: var(--ink-muted); }
.activity-record__id { font-variant-numeric: tabular-nums; color: var(--ink-subtle); }
.activity-record--none { color: var(--ink-subtle); }

/* Category chips. Always paired with a text label, so color is never the only
   cue (WCAG 1.4.1). */
.activity-chip {
  display: inline-block; white-space: nowrap;
  padding: 0.15rem 0.6rem;
  font-size: var(--text-xs); font-weight: 800;
  letter-spacing: 0.02em;
  border-radius: var(--radius-pill);
  border: 1px solid transparent;
}
.activity-chip--auth      { background: var(--sky-100);     color: var(--azure-ink);   border-color: var(--sky-200); }
.activity-chip--hours     { background: var(--success-soft); color: var(--success-ink); border-color: var(--success-soft); }
.activity-chip--reviews   { background: var(--warning-soft); color: var(--warning-ink); border-color: var(--warning-soft); }
.activity-chip--tasks     { background: var(--sky-50);      color: var(--navy);        border-color: var(--sky-200); }
.activity-chip--families  { background: var(--sky-200);     color: var(--navy-strong); border-color: var(--sky-200); }
.activity-chip--accounts  { background: var(--surface-alt); color: var(--ink-muted);   border-color: var(--border); }
.activity-chip--messaging { background: var(--danger-soft); color: var(--danger-ink);  border-color: var(--danger-soft); }
.activity-chip--other     { background: var(--surface-alt); color: var(--ink-subtle);  border-color: var(--border); }

.activity-empty {
  margin-top: var(--space-5);
  padding: var(--space-7) var(--space-5);
  text-align: center;
  background: var(--surface-alt);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
}
.activity-empty p { margin: 0 0 var(--space-2); }
.activity-empty p:last-child { margin-bottom: 0; }

.pagination {
  display: flex; align-items: center; justify-content: center;
  gap: var(--space-4);
  margin-top: var(--space-5);
}
.pagination__link {
  display: inline-flex; align-items: center; min-height: 44px;
  padding: 0.55rem 1rem;
  font-size: var(--text-sm); font-weight: 700;
  color: var(--azure-ink);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  text-decoration: none;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.pagination__link:hover, .pagination__link:focus { background: var(--sky-50); border-color: var(--azure); color: var(--navy); text-decoration: none; }
.pagination__link--disabled { color: var(--ink-subtle); background: var(--surface-alt); cursor: default; pointer-events: none; }
.pagination__status { font-size: var(--text-sm); font-weight: 700; color: var(--ink-muted); white-space: nowrap; }

/* ===========================================================================
   17. DELIGHT / MOTION
   Small, brand-warm signatures that celebrate progress. Every entrance animation
   lives inside `prefers-reduced-motion: no-preference` so reduced-motion users
   never see the "from" state (no 0-width flash, no hidden content); press/tap
   feedback is additionally neutralized in the reduced-motion block below.
   =========================================================================== */

/* Shared keyframes ---------------------------------------------------------- */
@keyframes fill-grow    { from { width: 0; } }                                   /* progress bar fills on arrival */
@keyframes count-rise   { from { opacity: 0; transform: translateY(4px); } }
@keyframes badge-pop    { 0% { transform: scale(0); opacity: 0; }
                          60% { transform: scale(1.12); opacity: 1; }
                         100% { transform: scale(1); opacity: 1; } }
@keyframes badge-bounce { 0%, 100% { transform: scale(1); }
                          30% { transform: scale(1.35); }
                          60% { transform: scale(0.9); } }
@keyframes cascade-in   { from { opacity: 0; transform: translateY(8px); } }
@keyframes flash-in     { from { opacity: 0; transform: translateY(-12px); } }

/* Confetti — a once-only celebration when a family completes its hours. Pieces
   live inside a fixed, overflow-hidden layer so their fall/drift never adds
   layout or a horizontal scrollbar (important on mobile); the JS
   (celebrate_controller) creates, animates (rAF), and removes the layer. */
.confetti-layer {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 60;
}
.confetti-piece {
  position: absolute;
  top: -16px;
  width: 10px;
  height: 10px;
  border-radius: 2px;
  will-change: transform, opacity;
}
.confetti-piece--round { border-radius: 50%; }
.confetti-piece--navy  { background: var(--navy); }
.confetti-piece--azure { background: var(--azure); }
.confetti-piece--sun   { background: var(--sun); }
.confetti-piece--green { background: var(--success); }

/* Flash leaving state (success notices auto-dismiss via flash_controller). */
.alert--leaving { opacity: 0; transform: translateY(-12px); transition: opacity 0.35s ease, transform 0.35s ease; }

/* Turbo Drive shows a cached "preview" render before the fresh page on cache-hit
   navigations. `application.js` flags <html> during that preview so entrance
   animations don't play twice; here we neutralize them for that one render.
   (The motion controllers check the same flag in JS.) */
html.motion-suppress *,
html.motion-suppress *::before,
html.motion-suppress *::after { animation: none !important; }

@media (prefers-reduced-motion: no-preference) {
  /* Tier 1 — the progress hero grows to its value on arrival; after logging,
     it visibly climbs to the new total. */
  .progress__bar { animation: fill-grow 0.9s cubic-bezier(0.22, 1, 0.36, 1); }

  /* Tier 1 — the just-counted-up Verified figure settles in under the climbing bar. */
  .stat-card__value[data-controller~="count-up"] { animation: count-rise 0.5s ease both; }

  /* Tier 1 — the "Requirement complete" note pops when the celebration fires. */
  .progress-block__done.is-celebrating { animation: badge-pop 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) both; }

  /* Tier 2 — the confirmation check springs in on the "you've signed up" screens. */
  .task-confirm__badge { animation: badge-pop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both; }

  /* Tier 2 — flashes/alerts slide + fade in rather than snapping. */
  .alert { animation: flash-in 0.45s cubic-bezier(0.22, 1, 0.36, 1) both; }

  /* Tier 3 — the nav badge bounces once when a new item lands on your plate
     (gated by nav_badge_controller so it only fires on an increase). */
  .nav-badge--pop { animation: badge-bounce 0.6s cubic-bezier(0.34, 1.56, 0.64, 1); }

  /* Tier 3 — page content assembles with a quick, light cascade. Scoped by a
     per-page main class so it only plays where it earns its keep. */
  .page-cascade-sections .summary-section { animation: cascade-in 0.5s ease both; }
  .page-cascade-sections .summary-section:nth-of-type(1) { animation-delay: 0.04s; }
  .page-cascade-sections .summary-section:nth-of-type(2) { animation-delay: 0.12s; }
  .page-cascade-sections .summary-section:nth-of-type(3) { animation-delay: 0.20s; }
  .page-cascade-sections .summary-section:nth-of-type(4) { animation-delay: 0.28s; }

  .page-cascade-cards .task-list > .task-card { animation: cascade-in 0.45s ease both; }
  .page-cascade-cards .task-list > .task-card:nth-child(1) { animation-delay: 0.03s; }
  .page-cascade-cards .task-list > .task-card:nth-child(2) { animation-delay: 0.09s; }
  .page-cascade-cards .task-list > .task-card:nth-child(3) { animation-delay: 0.15s; }
  .page-cascade-cards .task-list > .task-card:nth-child(4) { animation-delay: 0.21s; }
  .page-cascade-cards .task-list > .task-card:nth-child(5) { animation-delay: 0.27s; }
  .page-cascade-cards .task-list > .task-card:nth-child(6) { animation-delay: 0.33s; }
}

/* ===========================================================================
   18. REDUCED MOTION (WCAG 2.3.3)
   =========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .btn:hover, .show-button:hover, .archive-button:hover, .edit-button:hover,
  .delete-button:hover, .save-button:hover, .bulk-action-bar__send:hover,
  .btn-danger:hover, .bulk-email-tokens__chip:hover { transform: none; }
  /* Neutralize the tap "squish" for reduced-motion users. */
  .btn:active, form input[type="submit"]:active { transform: none; }
}
