/* ==========================================================================
   NutriFeed / SBFP Web App — Design System
   Ported directly from the Flutter mobile app's AppColors (lib/theme/app_theme.dart)
   so the web app is visually the SAME app, just laid out for a wider screen.
   ========================================================================== */

:root {
  /* Core brand greens */
  --ink: #16231b;
  --button-green: #1f5c33;   /* deep green: headings, links, text on light green */
  --mid-green: #2f7a44;
  --brand: #5ea849;          /* the mobile app's Log in button green */
  --brand-hover: #4e9a3b;
  --primary-light: #3fa35b;
  --soft-green: #d4f2d4;

  /* Page background */
  --page-green: #f4faf5;
  --bg-bottom: #edf7ee;

  /* Sidebar: a darker shade of the mobile app's floating-navbar green
     (_navBackgroundLight #DCF3D2), with each item colored to match its
     mobile counterpart's own accent (set per-item as --accent inline)
     instead of one flat sidebar color. */
  --nav-bg: #a9d894;

  --line: #dde5e0;
  --muted: #5c6b62;
  --white: #ffffff;

  /* One palette everywhere (same as the mobile app): brand green + gold, red only for danger. */
  --accent-home: var(--brand);
  --accent-forms: var(--brand);
  --accent-beneficiaries: var(--brand);
  --accent-mealplan: var(--brand);
  --accent-announcements: var(--brand);
  --accent-principal: var(--brand);
  --danger: #d23b34;

  --gold: #f5c64c;
  --gold-track: #efe3ad;

  /* Toned down from a bubblier 10/16/22 -- softened corners still read
     approachable without tipping into a "kiddie app" look; a more formal
     product keeps its corners closer to square. */
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 14px;
  --shadow-soft: 0 8px 24px rgba(22, 35, 27, 0.08);
  --shadow-pop: 0 12px 28px rgba(22, 35, 27, 0.14);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }
html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  font-family: "Segoe UI", "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
  color: var(--ink);
  background: linear-gradient(180deg, #ffffff 0%, var(--bg-bottom) 100%);
}

a { color: inherit; text-decoration: none; }
ul { list-style: none; margin: 0; padding: 0; }
button { font-family: inherit; cursor: pointer; }

/* ---------------------------------------------------------------------- */
/* App shell: fixed sidebar (web-appropriate replacement for the mobile   */
/* app's floating bottom nav bar) + scrollable content area.              */
/* ---------------------------------------------------------------------- */
.app-shell {
  display: flex;
  min-height: 100vh;
}
.app-shell.is-collapsed .sidebar { display: none; }

/* Both the close and reopen buttons are solid circles in the current
   page's own accent color (the same --active-accent every tab already
   sets on <body>) -- same colorful-badge language as the sidebar's own
   nav-icon-dot, so the control visibly belongs to whichever tab you're
   on instead of reading as generic chrome. */
.sidebar-close-btn, .sidebar-open-btn {
  border: none; background: var(--active-accent, var(--brand)); color: var(--white);
  box-shadow: 0 4px 10px color-mix(in srgb, var(--active-accent, var(--brand)) 45%, transparent);
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  transition: transform .15s ease, opacity .15s ease;
}
.sidebar-close-btn:hover, .sidebar-open-btn:hover { transform: scale(1.08); }

/* Reopen button: fixed on the page edge, only shown while the sidebar is
   collapsed (toggled via JS, not CSS, so it works regardless of :has()
   support). */
.sidebar-open-btn {
  position: fixed; top: 18px; left: 18px; z-index: 500;
  width: 40px; height: 40px; border-radius: 12px;
  /* Faded by default so it sits lightly over whatever content is
     underneath it instead of fully blocking it; hovering (meaning to
     use it) brings it back to full strength. */
  opacity: .28;
}
.sidebar-open-btn:hover, .sidebar-open-btn:focus-visible { opacity: 1; }
.sidebar-open-btn[hidden] { display: none; }

.sidebar-close-btn {
  flex-shrink: 0; margin-bottom: 14px;
  width: 32px; height: 32px; border-radius: 10px;
}

/* Light pale-green bar with a distinct accent color per item (each
   .nav-item sets --accent inline) -- the same pattern as the mobile app's
   floating navbar: colorful icons on a light ground, a solid pill in the
   item's own color when active, white icon/label on top of that pill. */
.sidebar {
  width: 258px;
  flex-shrink: 0;
  /* Same wash as every tab's own content background, so the sidebar reads
     as part of the same surface instead of a differently-colored panel. */
  background: linear-gradient(165deg, #eaf6e4 0%, #e2f2df 45%, #eef3d9 100%);
  color: var(--ink);
  display: flex;
  flex-direction: column;
  padding: 20px 14px;
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100dvh;
  /* On a short window (e.g. a 768px-tall laptop) the nav is taller than
     the screen -- scroll inside the sidebar instead of cutting off the
     bottom items or stretching the page past the content's background. */
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--active-accent, var(--brand)) 45%, transparent) transparent;
  border-right: 2px solid var(--active-accent, var(--brand));
  transition: border-color .15s ease;
  box-shadow: 2px 0 14px rgba(22, 35, 27, 0.05);
}

.sidebar-brand {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 8px 10px 20px 10px;
  margin-bottom: 10px;
  border-bottom: 1px solid rgba(22, 35, 27, 0.08);
}

.sidebar-brand .brand-row { display: flex; align-items: center; gap: 12px; }

.sidebar-brand .brand-logo {
  width: 50px;
  height: 50px;
  /* No backing tile or shadow -- just the logo itself on the sidebar. */
  object-fit: contain;
  flex-shrink: 0;
}

.sidebar-brand .brand-row strong { font-size: 21px; letter-spacing: .2px; color: var(--button-green); }
/* School name gets the same white "chip" treatment the Home page's
   heading used to show it in, now living here instead. */
.sidebar-brand .brand-school {
  display: flex; align-items: center; gap: 6px;
  background: var(--white); border: 1px solid var(--line);
  padding: 7px 12px; border-radius: 8px;
  font-size: 12.5px; font-weight: 700; color: var(--button-green);
  box-shadow: var(--shadow-soft);
  width: fit-content;
}

.nav-list { display: flex; flex-direction: column; gap: 3px; }

.nav-item {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 10px 12px;
  border-radius: 14px;
  color: var(--ink);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: .1px;
  transition: background 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}
.nav-item:hover { background: color-mix(in srgb, var(--accent, var(--brand)) 14%, transparent); }
.nav-item.active {
  background: var(--accent, var(--brand));
  color: var(--white);
  box-shadow: 0 4px 10px color-mix(in srgb, var(--accent, var(--brand)) 35%, transparent);
}
.nav-item .nav-icon-dot {
  width: 30px; height: 30px; flex-shrink: 0; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent, var(--muted)); color: var(--white);
  box-shadow: 0 2px 6px color-mix(in srgb, var(--accent, var(--muted)) 45%, transparent);
  transition: background 0.15s ease, color 0.15s ease;
}
.nav-item .nav-icon-dot svg { width: 17px; height: 17px; }
/* Active item's pill is already solid-accent -- invert the icon badge to
   white-on-accent so it still reads clearly against it. */
.nav-item.active .nav-icon-dot { background: var(--white); color: var(--accent, var(--brand)); box-shadow: none; }
.nav-item.is-danger { color: var(--danger); }

.nav-section { margin-top: 14px; }
.nav-section-label {
  font-size: 11.5px; font-weight: 800; letter-spacing: .8px; text-transform: uppercase;
  color: var(--muted); padding: 0 12px 8px;
}

.sidebar-footer { border-top: 1px solid rgba(22, 35, 27, 0.08); padding-top: 10px; margin-top: auto; }
.sidebar-profile {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; margin: 4px 0;
}

/* ---------------------------------------------------------------------- */
/* Content area */
/* ---------------------------------------------------------------------- */
.content {
  flex: 1;
  min-width: 0;
  padding: 20px 12px;
  /* White cards on the old white-to-barely-tinted body gradient had almost
     no separation near the top of the page. A background that stays
     visibly tinted all the way down (never fading to pure white) gives
     every card real contrast to sit on, at any scroll position. */
  background: linear-gradient(165deg, #eaf6e4 0%, #e2f2df 45%, #eef3d9 100%);
  min-height: 100vh;
}

/* Pages that want a pinned header (title/tabs/filters) and one scrolling
   list filling the rest of the viewport, instead of the whole page
   scrolling -- Announcements and Notifications, both effectively a feed. */
.content.content-fixed-page {
  height: 100vh;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.fixed-page-header { flex-shrink: 0; }
.fixed-page-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-right: 4px;
}
.fixed-page-scroll::-webkit-scrollbar { width: 8px; }
.fixed-page-scroll::-webkit-scrollbar-thumb { background: #c9d8cf; border-radius: 999px; }

/* Reused by the sidebar's own profile block now that notifications/profile
   no longer live in a standalone top bar. */
.topbar-user { display: flex; align-items: center; gap: 10px; }
/* A standing rounded rectangle, not a circle -- same shape as the photo
   itself uses in Settings, so the sidebar preview actually looks like the
   photo instead of cropping it into a circle. */
.topbar-user-avatar {
  width: 36px; height: 44px; border-radius: 10px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--brand); color: var(--white); font-weight: 800; font-size: 15px;
  overflow: hidden;
}
.topbar-user-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.topbar-user-info { display: flex; flex-direction: column; line-height: 1.3; }
.topbar-user-info strong { font-size: 14.5px; color: var(--ink); }
.topbar-user-info small { font-size: 12.5px; color: var(--muted); font-weight: 600; }

.topbar {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 16px;
}
.topbar h1 { flex: 1; min-width: 0; font-size: 22px; margin: 0; font-weight: 800; color: #000; }

.home-header-card { margin-bottom: 16px; }
.card.home-header-card { border-color: #d98a3d; }
.home-header-title { font-size: 18px; font-weight: 800; color: #000; margin: 0; }

/* ---------------------------------------------------------------------- */
/* Cards */
/* ---------------------------------------------------------------------- */
.card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: 0 10px 26px rgba(22, 35, 27, 0.10);
  padding: 22px;
}

/* Red theme for anything about at-risk/needs-referral students -- a
   visibly different accent from every other (green/gold) card on this
   page, so it reads as a warning the instant it comes into view. */
.card.sbfp-at-risk-card { border-color: var(--danger); border-top: 4px solid var(--danger); }

.section-title { font-size: 17px; font-weight: 800; margin: 26px 0 12px 0; color: #000; }
/* SBFP Forms' "Your Submitted Forms" card, when short (few/no
   submissions), used to leave a big gap of bare page background below it
   on a tall window -- .content's own min-height:100vh keeps it that tall
   regardless of content, but nothing made the LAST card grow to meet it.
   This stretches just that card down to match, via a flex column + a
   blank filler div (never the <table> itself, which stays a normal table
   with normal row heights either way -- only the extra space below it is
   absorbed by the filler). */
.sbfp-forms-fill-page { display: flex; flex-direction: column; min-height: calc(100vh - 40px); }
.sbfp-forms-submitted-wrap { flex: 1; display: flex; flex-direction: column; margin-bottom: 0; }
.sbfp-forms-submitted-filler { flex: 1; background: var(--white); }
.section-sub { margin: -6px 0 16px; font-size: 14.5px; color: #000; }

/* ---------------------------------------------------------------------- */
/* Home dashboard: beneficiary summary + at-risk breakdown                */
/* (green shades reuse --brand / --button-green -- the same greens used   */
/* on the login/welcome pages -- for a consistent brand identity.)        */
/* ---------------------------------------------------------------------- */
.bene-summary-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 16px; margin-bottom: 16px; }
@media (max-width: 1300px) { .bene-summary-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 1100px) { .bene-summary-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .bene-summary-grid { grid-template-columns: 1fr; } }

.stat-summary-card {
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-lg);
  padding: 18px 20px; box-shadow: var(--shadow-soft); border-top: 4px solid #d98a3d;
}
.stat-summary-head {
  display: flex; align-items: center; gap: 8px; font-size: 14.5px; font-weight: 700;
  color: var(--ink); margin-bottom: 10px;
}
.stat-summary-icon {
  width: 28px; height: 28px; border-radius: 8px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; font-size: 15px;
  background: color-mix(in srgb, var(--active-accent, var(--brand)) 16%, white);
  color: var(--active-accent, var(--button-green));
}
.stat-summary-card.is-total .stat-summary-icon { background: var(--active-accent, var(--button-green)); color: var(--white); }
.stat-summary-total { font-size: 30px; font-weight: 800; color: var(--ink); line-height: 1.1; }
.stat-summary-label { font-size: 13px; color: #000; margin-bottom: 10px; }
.stat-summary-sub { display: flex; gap: 20px; padding-top: 10px; border-top: 1px solid var(--line); }
.stat-summary-sub div { display: flex; flex-direction: column; gap: 2px; }
.stat-summary-sub span { font-size: 12px; color: #000; }
.stat-summary-sub strong { font-size: 16px; font-weight: 800; }
.sex-male { color: #4a90d9; }
.sex-female { color: #e0729c; }

.risk-card { margin-bottom: 16px; }
.risk-card-head { display: flex; align-items: center; gap: 10px; }
.risk-card-icon {
  width: 32px; height: 32px; border-radius: 8px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; font-size: 16px;
  background: #fdecea; color: var(--danger);
}
.risk-chip-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 16px; }
.risk-chip {
  padding: 6px 14px; border-radius: 999px; border: 1.5px solid var(--line);
  background: var(--white); color: var(--muted); font-size: 13.5px; font-weight: 700;
  cursor: pointer; transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.risk-chip:hover { border-color: var(--danger); color: var(--danger); }
.risk-chip.is-active { background: var(--danger); border-color: var(--danger); color: var(--white); }
.risk-table .col-male, .risk-table .col-female, .risk-table .col-count { text-align: center; }
.risk-table th.col-male { color: #4a90d9; }
.risk-table th.col-female { color: #e0729c; }
.risk-table td.col-male { color: #4a90d9; font-weight: 700; }
.risk-table td.col-female { color: #e0729c; font-weight: 700; }
.risk-table th.col-count { color: var(--danger); }
.risk-table td.col-count { color: var(--danger); font-weight: 700; }
.risk-total-row td { font-weight: 800; background: rgba(210,59,52,0.06); }
.risk-total-row td.col-count { color: var(--danger); font-size: 16px; }
.risk-findings { margin-top: 14px; padding: 12px 16px; background: rgba(210,59,52,0.06); border-radius: var(--radius-md); }
.risk-findings p { margin: 0; font-size: 13.5px; color: var(--ink); line-height: 1.6; }
.risk-findings p + p { margin-top: 6px; }
.risk-findings strong { color: var(--danger); }
.risk-findings ul { margin: 8px 0 0; padding-left: 20px; }
.risk-findings li { font-size: 13.5px; color: var(--ink); line-height: 1.7; }
.risk-findings li strong { color: var(--ink); }
.risk-findings li.is-urgent strong { color: var(--danger); }

/* ---------------------------------------------------------------------- */
/* Feeding Days card                                                      */
/* ---------------------------------------------------------------------- */
.feeding-card {
  display: flex; align-items: center; gap: 20px;
  background: linear-gradient(135deg, #aee196 0%, #dcf3d2 55%, #ffdd7e 100%);
  border: 1px solid rgba(255,255,255,.7); border-radius: var(--radius-lg);
  padding: 20px 24px; margin-bottom: 16px; box-shadow: var(--shadow-soft);
}
.feeding-ring {
  --pct: 0;
  width: 112px; height: 112px; border-radius: 50%; flex-shrink: 0;
  background: conic-gradient(var(--active-accent, var(--brand)) calc(var(--pct) * 1%), #ffdd7e 0);
  display: flex; align-items: center; justify-content: center;
}
.feeding-ring-center {
  width: 86px; height: 86px; border-radius: 50%; background: var(--white);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.feeding-ring-center strong { font-size: 28px; font-weight: 800; color: var(--active-accent, var(--button-green)); line-height: 1.05; }
.feeding-ring-center span { font-size: 12.5px; font-weight: 700; color: var(--active-accent, var(--button-green)); }
.feeding-info { flex: 1; min-width: 0; display: flex; align-items: center; justify-content: space-between; gap: 20px; }
.feeding-text { min-width: 0; }
.feeding-title { font-size: 18px; font-weight: 800; color: var(--ink); margin-bottom: 4px; }
.feeding-sub { margin: 0; font-size: 13.5px; font-weight: 600; color: var(--muted); }
/* .feeding-info prefix bumps specificity above the generic .btn rule
   (defined later in this file with equal specificity, which was silently
   winning the padding/font-size cascade before this fix). */
.feeding-info .feeding-start-btn { display: inline-block; padding: 11px 22px; font-size: 14.5px; font-weight: 800; border-radius: 999px; flex-shrink: 0; margin-left: auto; box-shadow: 0 6px 14px rgba(94,168,73,0.35); }
@media (max-width: 780px) {
  .feeding-info { flex-direction: column; align-items: flex-start; gap: 12px; }
  .feeding-info .feeding-start-btn { margin-left: 0; }
}
@media (max-width: 620px) { .feeding-card { flex-direction: column; text-align: center; } .feeding-info { align-items: center; } }

/* ---------------------------------------------------------------------- */
/* Forms hub cards (SBFP Forms tab) */
/* ---------------------------------------------------------------------- */
.forms-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
@media (max-width: 1100px) { .forms-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 700px) { .forms-grid { grid-template-columns: 1fr; } }

.form-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 22px;
  box-shadow: var(--shadow-soft);
  display: flex; flex-direction: column; gap: 10px;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.form-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-pop); }
.form-card .form-icon {
  width: 44px; height: 44px; border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  font-size: 21px; color: var(--white); background: var(--brand);
}
.form-card h3 { margin: 0; font-size: 16.5px; }
.form-card p { margin: 0; font-size: 14px; color: #000; }

/* ---------------------------------------------------------------------- */
/* "Coming soon" placeholder pages                                        */
/* ---------------------------------------------------------------------- */
.coming-soon {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 10px; max-width: 440px; margin: 60px auto; padding: 40px 32px;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-lg);
  border-top: 4px solid var(--gold); box-shadow: var(--shadow-soft);
}
.coming-soon-icon {
  width: 56px; height: 56px; border-radius: 50%; margin-bottom: 6px;
  display: flex; align-items: center; justify-content: center;
  font-size: 24px; background: var(--soft-green); color: var(--button-green);
}
.coming-soon h2 { margin: 0; font-size: 20px; color: var(--button-green); }
.coming-soon p { margin: 0; font-size: 15px; color: #000; line-height: 1.6; }

/* ---------------------------------------------------------------------- */
/* Scroll box -- "the card itself (and the page) never scrolls because of
   a long list, only this inner box does." First built for Attendance's
   own checklist (see templates/attendance/index.html's att-scroll-list/
   att-checklist-scroll), reused here app-wide: Beneficiaries' roster and
   every SBFP form's student table share this exact same behavior now
   instead of each one just growing the whole page taller. */
/* ---------------------------------------------------------------------- */
.scroll-box { max-height: 300px; overflow-y: auto; overscroll-behavior: contain; padding-right: 6px; }
.scroll-box::-webkit-scrollbar { width: 8px; }
.scroll-box::-webkit-scrollbar-thumb { background: #c9d8cf; border-radius: 999px; }
/* Viewport-relative (not a flat px) so it actually reaches the bottom of
   the screen on a tall monitor instead of leaving a blank gap below the
   card, and shrinks back down on a short one instead of overflowing it.
   Self-sufficient (own overflow/scrollbar, not just borrowed from
   .scroll-box) since a couple of call sites use this alone -- without
   its own overflow, the max-height here was a no-op and the box just
   grew or shrank with its content, which is what let expanding or
   collapsing one item (e.g. a Hot Meal Expenses Tuesday) push everything
   else on the page up or down instead of only scrolling inside the box. */
.scroll-box-tall {
  max-height: clamp(280px, calc(100vh - 540px), 900px);
  overflow-y: auto; overscroll-behavior: contain; padding-right: 6px;
}
.scroll-box-tall::-webkit-scrollbar { width: 8px; }
.scroll-box-tall::-webkit-scrollbar-thumb { background: #c9d8cf; border-radius: 999px; }

/* ---------------------------------------------------------------------- */
/* Tables */
/* ---------------------------------------------------------------------- */
.table-wrap { overflow-x: auto; border-radius: var(--radius-md); border: 1px solid var(--line); }
table.data-table { width: 100%; border-collapse: collapse; background: var(--white); font-size: 14.5px; }
table.data-table th {
  background: var(--page-green); color: var(--ink); font-weight: 700;
  text-align: left; padding: 11px 14px; border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
table.data-table td { padding: 10px 14px; border-bottom: 1px solid var(--line); vertical-align: middle; }
table.data-table tr:last-child td { border-bottom: none; }
table.data-table tr:hover td { background: #fbfdfb; }

.nav-item .nav-badge {
  margin-left: auto; background: #c0392b; color: #fff; font-size: 12px; font-weight: 800;
  padding: 1px 7px; border-radius: 999px;
}

.status-pill { display: inline-block; padding: 4px 12px; border-radius: 999px; font-size: 13px; font-weight: 700; }
.status-pending { background: #fdf2e3; color: #8a6d1f; }
.status-approved { background: var(--soft-green); color: var(--button-green); }
.status-rejected { background: #fdecea; color: #b3261e; }
.status-not_submitted { background: #f1f1f1; color: #000; }
.status-active { background: #fdecea; color: #b3261e; }
.status-referred { background: #fdf2e3; color: #8a6d1f; }
.status-cleared { background: var(--soft-green); color: var(--button-green); }

/* Bolder, solid-color variant (Documentation, SBFP Form Approvals) -- same
   per-status hue as the soft pills above, just filled-in with white text
   instead of a pastel background, so an "Approved" status reads as more
   emphatically done. */
.status-pill.is-solid.status-pending,
.status-pill.is-solid.status-referred { background: #d98a3d; color: var(--white); }
.status-pill.is-solid.status-approved,
.status-pill.is-solid.status-cleared { background: var(--brand); color: var(--white); }
.status-pill.is-solid.status-rejected,
.status-pill.is-solid.status-active { background: var(--danger); color: var(--white); }
.status-pill.is-solid.status-not_submitted { background: var(--muted); color: var(--white); }
.badge { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 12px; font-weight: 700; }
.badge-danger { background: var(--danger); color: var(--white); }
.badge-warning { background: #fdf2e3; color: #8a6d1f; }
.badge-ok { background: #f3c531; color: var(--white); }
.badge-muted { background: #eef1ef; color: #000; }

/* ---------------------------------------------------------------------- */
/* Buttons + inputs */
/* ---------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  border: none; border-radius: 999px; padding: 10px 20px;
  font-size: 14.5px; font-weight: 700; cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease, transform .15s ease;
}
/* Every button grows slightly on hover, on top of whatever color change
   it already has -- makes "this is interactive" unmistakable. Buttons
   that already lift on hover (e.g. btn-primary) combine both into one
   transform instead of one silently overwriting the other. */
.btn:hover { transform: scale(1.05); }
.btn-primary { background: var(--brand); color: var(--white); box-shadow: 0 6px 16px rgba(94, 168, 73, 0.28); transition: background .15s ease, transform .15s ease; }
.btn-primary:hover { background: var(--brand-hover); transform: translateY(-1px) scale(1.05); }
/* Every primary/confirmation button -- inside a page's own content area,
   or in the shared confirm modal (data-confirm's "Yes, continue" etc.) --
   picks up that page's own sidebar accent instead of a fixed color, so
   confirmation buttons read as "this page" everywhere, including Approve
   and Mark as Done. */
.content .btn-primary, .modal-backdrop .btn-primary {
  background: var(--active-accent, var(--brand));
  box-shadow: 0 6px 16px color-mix(in srgb, var(--active-accent, var(--brand)) 28%, transparent);
}
.content .btn-primary:hover, .modal-backdrop .btn-primary:hover {
  background: color-mix(in srgb, var(--active-accent, var(--brand)) 85%, black);
}
/* Solid destructive button -- same red the shared confirm-modal's OK
   button turns into for a danger-toned confirmation, reused here so both
   read as the same "this is the destructive choice" affordance. */
.btn-danger-solid { background: var(--danger); color: var(--white); box-shadow: 0 6px 16px rgba(210, 59, 52, 0.25); transition: background .15s ease; }
.btn-danger-solid:hover { background: #b9302a; }
/* Outline version -- red in and out of hover (no green tint like the
   default .btn-outline), just the shared .btn:hover grow effect. */
.btn-outline-danger { background: var(--white); color: var(--danger); border: 1.5px solid var(--danger); }
.btn-outline-danger:hover { background: var(--white); transform: scale(1.05); }
.btn-block { width: 100%; justify-content: center; padding: 14px 20px; font-size: 16px; }
.btn-outline { background: var(--white); color: var(--button-green); border: 1.5px solid var(--button-green); }
.btn-outline:hover { background: var(--white); transform: scale(1.05); }
/* The shared confirm modal's "Cancel" -- border matches whichever page
   triggered the confirmation (same accent as its "Yes, continue"),
   text stays plain black rather than following that color too. */
.modal-backdrop .btn-outline { color: #000; border-color: var(--active-accent, var(--brand)); }
.modal-backdrop .btn-outline:hover { background: color-mix(in srgb, var(--active-accent, var(--brand)) 12%, white); }
.btn-danger { background: #fdecea; color: #b3261e; }
.btn-danger:hover { background: #f9d5d1; }
.btn-sm { padding: 6px 14px; font-size: 13.5px; }

.field { margin-bottom: 16px; }
.field label { display: block; font-size: 14px; font-weight: 700; margin-bottom: 6px; color: var(--ink); }
.field input, .field select, .field textarea {
  width: 100%; padding: 10px 13px; border: 1.5px solid var(--line);
  border-radius: var(--radius-sm); font-size: 14.5px; background: var(--white);
  font-family: inherit;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--active-accent, var(--brand));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--active-accent, var(--brand)) 18%, transparent);
}
/* BMI Value is readonly (it's derived from Weight/Height, not typed) but
   should still look like an ordinary field, not a disabled-looking one --
   only its behavior differs from its siblings, not its appearance. */
#bmiValueInput[readonly], #ageDisplay[readonly] { background: var(--white); color: inherit; cursor: default; }
.bmi-age-note { margin: -4px 0 16px; font-size: 13px; font-weight: 600; color: var(--muted); }
.field-warning { display: block; margin-top: 6px; font-weight: 600; color: var(--danger); }
.field-warning[hidden] { display: none; }
/* Date field whose YYYY-MM-DD guide stays visible while typing: the guide
   sits behind a see-through input, offset by exactly what's been typed. */
.date-mask { display: block; position: relative; background: var(--white); border-radius: var(--radius-sm); }
.field .date-mask input { position: relative; background: transparent; }
.date-mask-ghost {
  position: absolute; inset: 0; display: flex; align-items: center; padding: 10px 13px;
  border: 1.5px solid transparent; font-size: 14.5px; white-space: pre; color: #000; pointer-events: none;
}
.date-mask-typed { visibility: hidden; }

/* Compact Yes/No segmented toggle, used in place of a plain dropdown for
   the Program Details fields -- same tap-to-select pattern as the signup
   page's role-toggle, just sized for a form field instead of a full card. */
.yesno-toggle { display: flex; gap: 8px; }
.yesno-toggle label {
  flex: 1; text-align: center; padding: 9px; border-radius: 10px; cursor: pointer;
  border: 1.5px solid var(--line); font-size: 13.5px; font-weight: 700; color: var(--muted); background: var(--white);
  transition: all .15s ease;
}
.yesno-toggle label:hover { border-color: var(--active-accent, var(--brand)); }
.yesno-toggle input { position: absolute; opacity: 0; pointer-events: none; }
.yesno-toggle label:has(input:checked) { background: var(--white); border-color: var(--active-accent, var(--brand)); color: var(--active-accent, var(--brand)); }

/* Program Details rows -- label on the left, Yes/No on the far right, one
   row per line (matches the mobile app's list-row layout instead of the
   web form's usual "label above field" pattern). */
.program-detail-row {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 13px 0; border-bottom: 1px solid var(--line);
}
.program-detail-row:last-child { border-bottom: none; }
.program-detail-row > label { margin: 0; font-size: 14px; font-weight: 700; color: var(--ink); }
.program-detail-row .yesno-toggle { flex-shrink: 0; }
.program-detail-row .yesno-toggle label { flex: initial; padding: 7px 18px; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.field-row-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px; }
@media (max-width: 700px) { .field-row, .field-row-3 { grid-template-columns: 1fr; } }

.filter-bar { display: flex; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; align-items: center; }
.filter-bar select, .filter-bar input { padding: 9px 12px; border-radius: var(--radius-sm); border: 1.5px solid var(--line); font-size: 14px; }

/* ---------------------------------------------------------------------- */
/* Attendance page                                                        */
/* ---------------------------------------------------------------------- */
.att-header-card {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  background: var(--white);
  border: 1px solid #2f7a8c; border-radius: var(--radius-lg);
  padding: 18px 22px; margin-bottom: 12px; box-shadow: 0 10px 26px rgba(22, 35, 27, 0.10);
}
.att-header-title { font-size: 20px; font-weight: 800; color: #000; margin-bottom: 9px; }
.att-header-row { display: flex; align-items: center; gap: 6px; font-size: 13.5px; font-weight: 700; color: var(--active-accent, var(--button-green)); }
.att-header-side { display: flex; flex-direction: column; align-items: center; gap: 8px; flex-shrink: 0; }
/* Solid accent pill, same size as the page's main buttons, so the current
   feeding day stands out from the date/time beside it. */
.att-day-pill {
  background: var(--active-accent, var(--brand)); color: var(--white);
  font-weight: 800; font-size: 15px; letter-spacing: .2px;
  padding: 10px 22px; border-radius: 999px; white-space: nowrap;
  box-shadow: 0 4px 12px color-mix(in srgb, var(--active-accent, var(--brand)) 35%, transparent);
}
.att-header-side .att-header-row { color: var(--ink); }

/* Session status cards -- colors match the mobile app's _SessionBadge
   exactly: Completed is bright yellow, In progress is a deeper gold/amber
   (not green), Pending is plain gray. No red "missed" state exists in the
   mobile app -- a missed morning instead surfaces via the catch-up banner
   below, and Afternoon is always tappable, never locked. */
/* Experiment (2026-10-24): groups the session-status bar, the optional
   catch-up/locked banners, and the Attendance/Summary tabs into one white
   card instead of leaving them loose on the green page background. The
   last piece inside keeps its own margin-bottom, so this just adds the
   16px gap before the next card on top of that. */
.att-session-card { margin-bottom: 16px; }
.att-session-bar { display: flex; align-items: stretch; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
.att-status-card {
  flex: 1; min-width: 170px; display: flex; align-items: center; justify-content: center; gap: 9px;
  padding: 15px 18px; border-radius: var(--radius-md); border: none;
  transition: transform .12s ease, box-shadow .12s ease;
}
.att-status-card:hover { transform: translateY(-1px); box-shadow: var(--shadow-soft); }
.att-status-name { font-size: 15px; font-weight: 800; }
.att-status-label { font-size: 12px; font-weight: 700; opacity: .85; }
.att-status-card.is-pending { background: #f2f2f2; border: 2px solid var(--muted); }
.att-status-card.is-pending .att-status-name, .att-status-card.is-pending .att-status-label { color: #000; }
.att-status-card.is-in-progress { background: #c98a1f; }
.att-status-card.is-in-progress .att-status-name, .att-status-card.is-in-progress .att-status-label { color: var(--white); }
.att-status-card.is-completed { background: #f3c531; }
.att-status-card.is-completed .att-status-name, .att-status-card.is-completed .att-status-label { color: #6b4e00; }
/* Which session is actually being viewed right now is a different thing
   from whether it's completed/in-progress/pending -- two Completed cards
   look identical otherwise, giving no sense of which one you're actually
   looking at below. A thin border in the tab's own accent color plus
   forcing the text to white together read as "selected" without a heavy
   ring fighting the card's own status color. */
.att-status-card.is-current-session {
  border: 2px solid var(--active-accent, #2f7a8c);
}
.att-status-card.is-current-session .att-status-name,
.att-status-card.is-current-session .att-status-label {
  color: var(--white);
}

.att-catchup-banner {
  display: flex; align-items: center; gap: 10px; margin-bottom: 12px;
  padding: 11px 14px; border-radius: var(--radius-md);
  background: rgba(201,138,31,0.12); border: 1px solid rgba(201,138,31,0.4);
  color: var(--button-green); font-size: 12.5px; font-weight: 600;
}
.att-catchup-banner svg:first-child { color: #c98a1f; flex-shrink: 0; }
.att-catchup-banner span { flex: 1; }
.att-catchup-banner svg:last-child { color: #c98a1f; flex-shrink: 0; }

.att-locked-banner {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  background: #fff3c7; color: #8a6d1f; border: 1px solid var(--gold);
  padding: 12px 16px; border-radius: var(--radius-md); margin-bottom: 12px; font-size: 14px; font-weight: 600;
}
/* Matches the banner's own gold instead of the app-wide green outline
   button, so it doesn't clash sitting on this specific yellow banner. */
.att-locked-banner .btn-outline { color: #8a6d1f; border-color: var(--gold); background: var(--white); }
.att-locked-banner .btn-outline:hover { background: #fff3c7; }
.import-row-incomplete td { background: #fff8e1; }
.import-row-bmi-exempt td { background: #e8f1fc; }
.import-missing-tag {
  display: inline-block; padding: 3px 9px; border-radius: 999px;
  background: var(--gold); color: var(--white); font-size: 11.5px; font-weight: 700;
}
.sbfp-save-btn { color: var(--active-accent, var(--brand)); border-color: var(--active-accent, var(--brand)); }
.sbfp-save-btn:hover { background: color-mix(in srgb, var(--active-accent, var(--brand)) 12%, white); }

/* Tells a Coordinator what's happening on their Principal's side for the
   form they're currently compiling -- neutral gray by default (not yet
   submitted), colored once it's actually moved somewhere. */
.sbfp-status-banner {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px 14px;
  padding: 12px 16px; border-radius: var(--radius-md); margin-bottom: 12px;
  font-size: 13.5px; border: 1px solid var(--line); background: #f7f7f7; color: var(--ink);
}
.sbfp-status-banner-pill {
  flex-shrink: 0; padding: 4px 12px; border-radius: 999px; font-size: 12.5px; font-weight: 800;
  background: #f1f1f1; color: var(--muted);
}
.sbfp-status-banner-text { flex: 1; min-width: 200px; }
.sbfp-status-banner-link { flex-shrink: 0; font-weight: 700; color: var(--button-green); }
.sbfp-status-banner-link:hover { color: var(--brand); }
.sbfp-status-banner.is-pending { background: #fdf2e3; border-color: var(--gold); }
.sbfp-status-banner.is-pending .sbfp-status-banner-pill { background: var(--gold); color: var(--white); }
.sbfp-status-banner.is-approved { background: var(--soft-green); border-color: var(--button-green); }
.sbfp-status-banner.is-approved .sbfp-status-banner-pill { background: var(--button-green); color: var(--white); }
.sbfp-status-banner.is-rejected { background: #fdecea; border-color: var(--danger); }
.sbfp-status-banner.is-rejected .sbfp-status-banner-pill { background: var(--danger); color: var(--white); }

/* The bottom row: why-not-showing notes on the left, Save on the right --
   same row so neither needs its own extra vertical space on the card,
   with enough gap between them (space-between, flex-wrap as a fallback)
   that they never read as touching. */
.att-bottom-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-top: 18px; flex-wrap: wrap; }
.att-bottom-row .btn { margin-left: auto; }

/* Small, colored explanations for why a checklist option isn't showing
   right now -- Hot Meal's own weekday rule, Milk waiting on the Division
   -- a short, compact pill each (not a tall banner), tinted to match what
   each is about so the two read as distinct at a glance. */
.att-inline-notes { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.att-note-pill {
  font-size: 11.5px; font-weight: 700; line-height: 1.3;
  padding: 5px 10px; border-radius: 999px; max-width: 340px;
}
.att-note-pill-hot { background: rgba(201,138,31,0.14); border: 1px solid rgba(201,138,31,0.35); color: #8a661a; }
.att-note-pill-milk { background: rgba(74,144,217,0.12); border: 1px solid rgba(74,144,217,0.35); color: #2f6690; }

.att-bulk-actions { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
.att-bulk-actions span:first-child { font-size: 13px; color: var(--muted); font-weight: 600; margin-right: 4px; }
.att-btn-danger { color: var(--danger); border-color: var(--danger); }
.att-btn-danger:hover { background: var(--danger); color: var(--white); }
/* The Select-all button itself turns solid green once pressed -- "Clear
   All" is what turns it back off. */
.att-bulk-actions button[data-bulk].is-selected { background: var(--active-accent, var(--brand)); color: var(--white); border-color: var(--active-accent, var(--brand)); }
/* Food bulk button + its "Twice" toggle, joined into one split button
   (shared border). Words say what they do on their own -- "Once" /
   "Twice" -- so there's nothing extra to keep aligned underneath. They
   stay together on one line when the row wraps on a phone. */
.att-bulk-group { display: inline-flex; align-items: stretch; white-space: nowrap; }
.att-bulk-group .btn { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.att-bulk-group .btn:hover, .att-bulk-x2:hover { transform: none; }
.att-bulk-x2 {
  padding: 0 14px; font-size: 13.5px; font-weight: 800;
  background: var(--white); color: var(--button-green);
  border: 1.5px solid var(--button-green); border-left: none;
  border-radius: 0 999px 999px 0; cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.att-bulk-group .btn.is-selected + .att-bulk-x2 { border-color: var(--active-accent, var(--brand)); }
.att-bulk-x2:hover { background: rgba(47, 122, 140, .08); }
.att-bulk-x2[aria-pressed="true"] { background: #2f7a8c; color: var(--white); border-color: #2f7a8c; box-shadow: inset 1.5px 0 0 rgba(255,255,255,.55); }
.att-bulk-x2:focus-visible { outline: 2px solid #2f7a8c; outline-offset: 2px; }
/* Stays in the DOM even when empty (no display:none) so screen readers
   reliably announce it; it just takes no space until it has text. */
.att-bulk-status { margin: 0; font-size: 12.5px; font-weight: 600; color: #2f7a8c; }
.att-bulk-status:not(:empty) { margin: -4px 0 12px; }
@media (max-width: 560px) {
  .att-bulk-actions > span:first-child { flex-basis: 100%; }
  .att-bulk-actions .btn, .att-bulk-x2 { min-height: 40px; }
}
.att-bulk-group-label { font-size: 12.5px; font-weight: 700; color: var(--text); margin-right: 6px; }

/* Plain inline caption on the same line as "Attendance" -- no boxed
   background, so it doesn't add its own row of height to an already-busy
   card header. */
.att-rules-note { margin: 0; font-size: 12px; color: var(--muted); font-weight: 600; text-align: right; }
.att-rules-note strong { color: var(--text); }
@media (max-width: 720px) {
  .bene-title-row:has(.att-rules-note) { flex-wrap: wrap; row-gap: 4px; }
  .att-rules-note { flex-basis: 100%; text-align: left; }
}

.att-form-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px; }
@media (max-width: 560px) {
  .att-form-actions { flex-direction: column-reverse; }
  .att-form-actions .btn { width: 100%; text-align: center; }
}

/* Custom-drawn box (not native accent-color, which renders inconsistently
   across browsers) so the checkmark is reliably white on a solid color
   fill -- exactly matching the mobile app's own checkbox: a solid green
   (or red, for Absent) square with a white check icon on top. */
.att-check {
  appearance: none; -webkit-appearance: none; margin: 0;
  width: 20px; height: 20px; border-radius: 5px; flex-shrink: 0;
  border: 1.5px solid var(--line); background: var(--white); cursor: pointer;
  position: relative; transition: background .12s ease, border-color .12s ease;
}
.att-check:checked { background: #2f7a8c; border-color: #2f7a8c; }
.att-check.att-absent:checked { background: var(--danger); border-color: var(--danger); }
.att-check:checked::after {
  content: ""; position: absolute; left: 6px; top: 2px;
  width: 5px; height: 10px; border: solid var(--white);
  border-width: 0 2px 2px 0; transform: rotate(45deg);
}

/* Each grade level gets its own accent color (--group-color, set inline
   per group -- the same colors already used for that grade's counterpart
   in the sidebar nav), so a grade/section reads as one consistent color
   identity everywhere: the group header, and a thin accent on every
   student card that belongs to it. */
.att-group-label {
  background: color-mix(in srgb, var(--group-color, var(--brand)) 12%, white);
  color: var(--group-color, var(--button-green));
  border-left: 4px solid var(--group-color, var(--brand));
  font-weight: 800; font-size: 12.5px; text-transform: uppercase; letter-spacing: .3px;
  padding: 8px 14px; border-radius: var(--radius-sm); margin: 18px 0 8px;
}
.att-group-label:first-child { margin-top: 0; }

/* A circle crops away most of a face -- a standing (portrait) rounded
   rectangle keeps the whole photo visible so a Coordinator can actually
   recognize who it is at a glance, not just a coin-sized crop of it. */
.att-avatar {
  width: 38px; height: 46px; border-radius: 8px; flex-shrink: 0; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: var(--brand); color: var(--white); font-weight: 800; font-size: 13px;
  border: 2px solid transparent;
}
.att-avatar img { width: 100%; height: 100%; object-fit: cover; }
/* Sex color coding -- same blue/pink used for the Home dashboard's
   male/female breakdown (.sex-male / .sex-female), applied as a ring
   around the avatar now that the "Male · Grade 2" text label is gone. */
.att-avatar.is-male { border-color: #4a90d9; }
.att-avatar.is-female { border-color: #e0729c; }
/* A plain <span> when there's no photo to view (nothing to enlarge), a
   real <button> (unstyled back to looking exactly like that same span)
   wherever there is one, so it's keyboard/click-reachable. */
button.att-avatar {
  padding: 0; font: inherit; cursor: pointer;
}
button.att-avatar:disabled { cursor: default; }

.bene-avatar-stack { position: relative; flex-shrink: 0; display: block; }
.bene-avatar-camera {
  position: absolute; bottom: -3px; right: -3px; width: 15px; height: 15px; border-radius: 50%;
  background: var(--active-accent, var(--brand)); color: #fff; display: flex; align-items: center;
  justify-content: center; border: 2px solid var(--white); cursor: pointer;
}
.bene-avatar-view { all: unset; display: block; cursor: pointer; }
.bene-avatar-view:disabled { cursor: default; }

/* One card per student -- checkbox labels live right next to each
   checkbox (not as a table header far above), so they stay readable no
   matter how far down the list is scrolled. Tint mirrors the mobile
   app's row coloring: green while actively marking a present student,
   yellow once a present record is saved/locked, red for a locked absent
   record, plain otherwise. */
.att-student-row {
  background: #fafafa; border: 1.5px solid var(--line); border-radius: var(--radius-md);
  border-left: 4px solid var(--group-color, var(--line));
  padding: 12px 14px; margin-bottom: 8px;
}
.att-student-row.is-editable.is-present { background: var(--soft-green); border-color: var(--brand); border-left-color: var(--group-color, var(--brand)); }
.att-student-row.is-present:not(.is-editable) { background: #eaf3fc; border-color: #4a90d9; border-left-color: var(--group-color, #4a90d9); }
.att-student-row.is-absent:not(.is-editable) { background: #fdecea; border-color: var(--danger); border-left-color: var(--group-color, var(--danger)); }

/* Identity (avatar/name/BMI-HFA), the Hot Meal/NFP/Milk/Absent checkboxes,
   and the Present/Absent badge all share this one line now, in 3 visual
   groups: identity stays left, the checkboxes land in the middle of
   whatever room is left (an auto margin on each side of the field-row
   splits that leftover space evenly, skewing them left-of-true-center
   since identity already ate into the left side), and the badge is
   pinned flush to the far right edge. flex-wrap lets the row break onto
   a second line on a narrow screen instead of overflowing sideways.

   Identity gets a FIXED width (not just a cap) so every card's checkbox
   group lands at the exact same X position down the whole list -- a
   longer name/grade/section used to widen that one card's identity block
   and shove its checkboxes further right than every other card's,
   breaking the pantay-pantay (evenly-lined-up) look; a name/section too
   long for the fixed width simply wraps inside it instead of stretching
   it. The badge gets a matching fixed width for the same reason: "Present"
   and "Absent" aren't the same number of letters, and that difference was
   enough to nudge the checkboxes' centered position slightly from row to
   row too. */
.att-student-top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; row-gap: 10px; }
.att-student-info { flex: 0 0 230px; min-width: 0; }
.att-student-top .att-field-row { margin-left: auto; }
.att-student-top .badge { margin-left: auto; min-width: 70px; text-align: center; }
.att-student-name { font-size: 14px; font-weight: 700; color: var(--ink); }
.att-student-sub { font-size: 11.5px; color: var(--group-color, var(--muted)); font-weight: 600; margin-top: 1px; }

/* BMI-A / HFA status chips -- red for an at-risk status (matches the
   Home dashboard's own at-risk definition exactly: Severely Wasted /
   Wasted / Severely Stunted / Stunted), green for Normal, orange for a
   watch-list status (Overweight, Obese, Tall) that isn't itself flagged
   at-risk but is worth a second look. */
.att-status-line { display: flex; gap: 6px; margin-top: 5px; flex-wrap: wrap; }
.att-status-chip { font-size: 10.5px; font-weight: 700; padding: 2px 9px; border-radius: 999px; white-space: nowrap; }
.att-status-chip.is-red { background: #fdecea; color: var(--danger); }
.att-status-chip.is-green { background: var(--soft-green); color: var(--button-green); }
.att-status-chip.is-orange { background: #fff3e0; color: #b8621b; }
.att-status-chip.is-none { background: #f1f1f1; color: #000; }

/* nowrap on purpose -- Hot Meal/NFP/Milk/Absent must always sit on the
   SAME line as each other (pantay-pantay), never one of the 4 dropping to
   its own line because the row got tight. If there's truly no room, the
   whole field-row (as one flex-shrink:0 block) wraps down to its own new
   line below the name -- the group stays intact either way. */
.att-field-row { display: flex; align-items: flex-start; gap: 14px; flex-shrink: 0; }
.att-field-cell { display: flex; flex-direction: column; align-items: center; gap: 4px; min-width: 84px; flex-shrink: 0; }
.att-field-label { font-size: 10.5px; font-weight: 700; color: var(--ink); text-align: center; cursor: pointer; }
/* Meal cell: a "1 | 2" pair of toggle buttons (no checkbox). Nothing lit
   = not served: both outlined in grey. The chosen number fills teal. */
.att-serve { display: inline-flex; }
.att-serve-btn {
  width: 40px; height: 40px; margin: 0; padding: 0;
  font: inherit; font-size: 14px; font-weight: 800; color: #8a979e;
  background: var(--white); border: 1.5px solid #cfd6da; cursor: pointer;
  transition: background .12s ease, color .12s ease, border-color .12s ease, opacity .12s ease;
}
.att-serve-btn:first-child { border-radius: 8px 0 0 8px; }
.att-serve-btn + .att-serve-btn { border-left: none; border-radius: 0 8px 8px 0; }
.att-serve-btn:hover { background: rgba(47, 122, 140, .08); color: #2f7a8c; }
.att-serve-btn:focus-visible { outline: 2px solid #2f7a8c; outline-offset: 1px; position: relative; z-index: 1; }
.att-serve-btn[aria-pressed="true"] { background: #2f7a8c; border-color: #2f7a8c; color: var(--white); }

/* Attendance / Summary & Findings page switch -- same tab pattern as
   Announcements' track tabs, teal to match this page's own sidebar
   accent. */
.att-page-tabbar { display: flex; gap: 4px; padding: 4px; background: var(--white); border: 1px solid var(--line); border-radius: 999px; margin-bottom: 12px; }
.att-page-tab { flex: 1; text-align: center; padding: 10px 12px; border-radius: 999px; font-size: 12.5px; font-weight: 800; color: #1c4f5a; transition: background .15s ease, color .15s ease; }
.att-page-tab.is-selected { background: #2f7a8c; color: #fff; }

/* Summary & Findings -- ported from the mobile app's
   _SummaryFindingsPage (feeding_tab.dart): a Filter card, a Present/
   Absent/Total Summary card, a Meal Breakdown card, a Findings card, and
   an Endline Results card gated behind the feeding cycle's target days. */
.att-summary-card { padding: 16px; margin-bottom: 10px; }
.att-summary-card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-bottom: 4px; }
.att-summary-card-head form { margin: 0; }

.att-summary-stats { display: flex; gap: 10px; }
.att-summary-stat { flex: 1; text-align: center; padding: 12px 8px; border-radius: 12px; background: var(--page-green); }
.att-summary-stat-value { font-size: 24px; font-weight: 800; line-height: 1.1; }
.att-summary-stat-label { font-size: 11.5px; font-weight: 700; color: var(--muted); margin-top: 2px; }
.att-summary-stat.is-green .att-summary-stat-value { color: var(--button-green); }
.att-summary-stat.is-red .att-summary-stat-value { color: var(--danger); }
.att-summary-stat.is-teal .att-summary-stat-value { color: #2f7a8c; }

.att-double-served-badge {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; font-weight: 800; color: #2f7a8c;
  background: rgba(47, 122, 140, .12); border: 1px solid rgba(47, 122, 140, .35);
  padding: 4px 9px; border-radius: 999px;
}

/* A compact header band, not a list -- every category on one or two
   wrapped lines instead of a row each, with a border under it to read as
   "this is the day's fixed totals," clearly set apart from the
   scrollable per-student list right below it. */
.att-category-summary {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 8px 0 14px; margin-bottom: 4px; border-bottom: 1px solid var(--line);
}
.att-category-pill {
  display: inline-flex; align-items: center; gap: 6px;
  background: rgba(94, 168, 79, .12); color: var(--ink);
  font-size: 12px; font-weight: 700; padding: 6px 12px; border-radius: 999px; white-space: nowrap;
}
.att-category-pill strong {
  background: rgba(94, 168, 73, .16); color: var(--button-green); font-size: 11.5px; font-weight: 800;
  padding: 1px 8px; border-radius: 999px;
}

.att-per-student-title { font-size: 12.5px; font-weight: 700; color: var(--ink); margin: 12px 0 6px; }
.att-per-student-row { display: flex; align-items: center; gap: 8px; padding: 5px 0; }
.att-per-student-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; background: var(--muted); }
.att-per-student-dot.is-green { background: var(--button-green); }
.att-per-student-dot.is-red { background: var(--danger); }
.att-per-student-dot.is-teal { background: #2f7a8c; }
.att-per-student-name { flex: 1; font-size: 13.5px; font-weight: 600; color: var(--ink); }
.att-per-student-meta { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
.att-per-student-category { font-size: 11.5px; font-weight: 700; color: var(--button-green); }
.att-per-student-category.is-teal { color: #2f7a8c; }
.att-per-student-code { font-size: 10px; font-weight: 600; color: var(--muted); }

.att-findings-empty { font-size: 13px; font-weight: 600; color: var(--muted); margin: 0; }
.att-findings-empty.is-green { color: var(--button-green); }
.att-findings-label { font-size: 12.5px; font-weight: 700; color: var(--ink); margin-bottom: 6px; }

.att-save-summary-modal h3 { color: var(--ink); }
.att-save-summary-absentees { text-align: left; max-height: 220px; overflow-y: auto; margin-bottom: 18px; border-top: 1px solid var(--line); padding-top: 10px; }

/* ---------------------------------------------------------------------- */
/* Welcome page: photo tour in a card (mirrors the mobile onboarding)     */
/* ---------------------------------------------------------------------- */
.wl { position: relative; min-height: 100vh; background: var(--white); }
.wl-stage { position: relative; z-index: 1; }

/* ---------------------------------------------------------------------- */
/* Landing page -- full-bleed hero photo, a stats strip, two feature       */
/* sections and a footer. Scrolls normally (this isn't the single-        */
/* viewport onboarding card the welcome page used to be).                 */
/* ---------------------------------------------------------------------- */
.btn-outline-light { background: rgba(255,255,255,.06); color: var(--white); border: 1.5px solid rgba(255,255,255,.75); }
.btn-outline-light:hover { background: rgba(255,255,255,.16); }

.lp-hero { position: relative; color: var(--white); overflow: hidden; }
.lp-hero-bg { position: absolute; inset: 0; background-size: cover; background-position: center; }
.lp-hero-overlay { position: absolute; inset: 0; background: linear-gradient(100deg, rgba(10,30,18,.88) 0%, rgba(10,30,18,.72) 42%, rgba(10,30,18,.4) 75%); }
.lp-hero-inner { position: relative; z-index: 1; max-width: 1240px; margin: 0 auto; padding: 0 clamp(20px, 4vw, 56px) clamp(56px, 9vh, 120px); display: flex; flex-direction: column; min-height: clamp(560px, 86vh, 820px); }

.lp-header { display: flex; align-items: center; justify-content: space-between; padding: 24px 0; }
.lp-brand { display: flex; align-items: center; gap: 12px; font-size: 21px; font-weight: 800; color: var(--white); }
.lp-brand img { width: 40px; height: 40px; border-radius: 50%; }
.lp-nav { display: flex; gap: 28px; }
.lp-nav-link { font-size: 14.5px; font-weight: 700; color: rgba(255,255,255,.88); padding-bottom: 2px; border-bottom: 1.5px solid transparent; transition: border-color .15s ease, color .15s ease; }
.lp-nav-link:hover { color: var(--white); border-color: rgba(255,255,255,.7); }

.lp-hero-content { margin-top: auto; max-width: 620px; }
.lp-hero-content h1 { margin: 0 0 20px; font-size: clamp(34px, 5.4vw, 58px); font-weight: 800; line-height: 1.12; }
.lp-hero-content p { margin: 0; font-size: clamp(15px, 1.6vw, 18px); line-height: 1.6; color: rgba(255,255,255,.88); max-width: 50ch; }
.lp-hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 14px; margin-top: 30px; }
.lp-hero-actions .btn { padding: 14px 28px; font-size: 15.5px; }
.lp-hero-caption { margin-top: 20px !important; font-size: 13.5px !important; color: rgba(255,255,255,.65) !important; }

.lp-stats { background: var(--button-green); }
.lp-stats-inner {
  max-width: 1240px; margin: 0 auto; padding: clamp(22px, 3.5vh, 32px) clamp(20px, 4vw, 56px);
  display: grid; grid-template-columns: repeat(4, 1fr);
}
.lp-stat { padding: 0 20px; border-left: 1px solid rgba(255,255,255,.18); }
.lp-stat:first-child { border-left: none; padding-left: 0; }
.lp-stat h3 { margin: 0 0 4px; color: var(--white); font-size: 16px; font-weight: 800; }
.lp-stat p { margin: 0; color: rgba(255,255,255,.75); font-size: 13.5px; }

.lp-tasks { background: var(--white); }
.lp-tasks-inner { max-width: 1240px; margin: 0 auto; padding: clamp(56px, 8vh, 88px) clamp(20px, 4vw, 56px) clamp(40px, 6vh, 64px); }
.lp-tasks-inner > h2 { margin: 0 0 8px; font-size: clamp(24px, 2.8vw, 32px); color: var(--button-green); font-weight: 800; }
.lp-tasks-inner > p { margin: 0 0 clamp(28px, 4vh, 40px); color: var(--muted); font-size: 15px; max-width: 60ch; }
.lp-tasks-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 20px; }
.lp-task-photo { width: 100%; aspect-ratio: 1.15 / 1; border-radius: 16px; background-size: cover; background-position: center; margin-bottom: 14px; }
.lp-task h3 { margin: 0 0 6px; font-size: 15px; color: var(--button-green); font-weight: 800; }
.lp-task p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.55; }

.lp-footer { background: var(--page-green); border-top: 1px solid var(--line); }
.lp-footer-top { max-width: 1240px; margin: 0 auto; padding: clamp(28px, 4vh, 40px) clamp(20px, 4vw, 56px) 20px; display: flex; align-items: center; gap: 16px; }
.lp-footer-logo { width: 46px; height: 46px; object-fit: contain; flex-shrink: 0; }
.lp-footer-top p { margin: 0; color: var(--ink); font-size: 13.5px; line-height: 1.5; }
.lp-footer-bottom {
  max-width: 1240px; margin: 0 auto; padding: 18px clamp(20px, 4vw, 56px) clamp(24px, 4vh, 36px);
  border-top: 1px solid var(--line); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 8px;
  font-size: 12.5px; color: var(--muted);
}

@media (max-width: 900px) {
  .lp-stats-inner { grid-template-columns: repeat(2, 1fr); row-gap: 20px; }
  .lp-stat:nth-child(3) { border-left: none; padding-left: 0; }
  .lp-tasks-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .lp-tasks-grid { grid-template-columns: 1fr 1fr; }
}

/* >>> MORPH-LANDING (experiment) -- start ------------------------------- */
/* Log in / Sign up open on top of the landing page: .wl[data-mode] switches
   from "tour" to "login" / "signup", the landing content dims and fades,
   and a small see-through form card sits in the center. data-form remembers
   which form to show, so it can fade out on the way back. */
.wl-stage::after {
  content: ""; position: fixed; inset: 0; z-index: 1; background: rgba(12, 38, 22, .34);
  opacity: 0; pointer-events: none; transition: opacity .45s ease;
}
.wl:not([data-mode="tour"]) .wl-stage::after { opacity: 1; }
.lp-content { transition: opacity .4s ease, filter .4s ease; }
.wl:not([data-mode="tour"]) .lp-content { opacity: .55; filter: blur(2px); }

.wl-auth {
  position: fixed; inset: 0; z-index: 2; display: flex; align-items: center; justify-content: center;
  padding: 112px 16px 24px; overflow-y: auto;
  opacity: 0; visibility: hidden; transition: opacity .3s ease, visibility 0s linear .3s;
}
.wl:not([data-mode="tour"]) .wl-auth { opacity: 1; visibility: visible; transition: opacity .4s ease .08s, visibility 0s; }
.wl-auth .split-card.card-fit {
  --gap: 16px;
  display: none; flex: 0 1 auto; width: 100%; max-width: 430px; height: auto; max-height: 100%; min-height: 0; margin: 0;
  padding: 46px 32px 24px;
  background: rgba(255,255,255,.84); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(255,255,255,.6); border-top: 5px solid var(--gold); border-radius: 24px;
  box-shadow: 0 24px 60px rgba(8, 30, 16, .35);
  transition: translate .5s cubic-bezier(.22, 1, .36, 1), scale .5s cubic-bezier(.22, 1, .36, 1);
  animation: wl-form-in .3s ease both;
}
.wl[data-form="login"] .wl-auth .card-login,
.wl[data-form="signup"] .wl-auth .card-signup { display: flex; }
.wl[data-mode="tour"] .wl-auth .split-card.card-fit { translate: 0 -18px; scale: .95; }
@keyframes wl-form-in { from { opacity: 0; } }

/* Smaller type and fields than the full-page versions of these forms. */
.wl-auth .card-fit .back-link { top: 16px; left: 24px; font-size: 13.5px; }
.wl-auth .card-fit h1 { font-size: 28px; }
.wl-auth .card-fit .split-sub { font-size: 14.5px; }
.wl-auth .card-fit form { flex: 0 1 auto; }
.wl-auth .card-fit .field label { font-size: 14px; margin-bottom: 6px; }
.wl-auth .card-fit .field input, .wl-auth .card-fit .sp-trigger { padding: 12px 15px; font-size: 15px; border-radius: 12px; background: rgba(246,250,246,.9); }
.wl-auth .card-fit .btn-block { padding: 13px 20px; font-size: 16px; }
.wl-auth .card-fit .btn-block:hover { transform: translateY(-1px); }
.wl-auth .card-fit .auth-footer-link { font-size: 14px; }
.wl-auth .card-fit .auth-footer-link a { color: var(--brand); }
.wl-auth .card-fit .auth-footer-link a:hover { color: var(--brand-hover); }

/* Log in has only two fields, so it gets regular-sized type and fields. */
.wl-auth .split-card.card-login { --gap: 20px; max-width: 500px; padding: 54px 40px 30px; }
.wl-auth .card-login .back-link { top: 18px; left: 28px; font-size: 14.5px; }
.wl-auth .card-login h1 { font-size: 34px; }
.wl-auth .card-login .split-sub { font-size: 16px; }
.wl-auth .card-login .field label { font-size: 15px; margin-bottom: 7px; }
.wl-auth .card-login .field input { padding: 15px 17px; font-size: 16px; border-radius: 14px; }
.wl-auth .card-login .btn-block { padding: 16px 20px; font-size: 17px; }
.wl-auth .card-login .auth-footer-link { font-size: 15px; }

.wl-auth .split-card.card-signup { --gap: 12px; max-width: 600px; padding: 42px 30px 20px; }
.wl-auth .card-signup h1 { font-size: 26px; }
.wl-auth .card-signup .split-sub { font-size: 14px; }
.wl-auth .card-signup .role-toggle label { padding: 9px; font-size: 14px; }
.wl-auth .card-signup .role-hint { font-size: 12px; }
.wl-auth .card-signup .field label { font-size: 13px; margin-bottom: 4px; }
.wl-auth .card-signup .field input, .wl-auth .card-signup .sp-trigger { padding: 9px 13px; font-size: 14.5px; }
.wl-auth .card-signup .field-row, .wl-auth .card-signup .field-row-3 { gap: 12px; }
.wl-auth .card-signup .pw-strength { margin-top: 6px; }
.wl-auth .card-signup .pw-rules { gap: 2px 10px; margin-top: 5px; }
.wl-auth .card-signup .pw-rules li { font-size: 12px; }
.wl-auth .card-signup .btn-block { padding: 12px 20px; font-size: 15.5px; }
@media (max-width: 700px) {
  .wl-auth { padding: 96px 12px 16px; }
  .wl-auth .split-card.card-fit { padding-left: 20px; padding-right: 20px; }
}
/* <<< MORPH-LANDING (experiment) -- end --------------------------------- */

/* ---------------------------------------------------------------------- */
/* Log in / Sign up: SBFP picture + form                                  */
/* ---------------------------------------------------------------------- */
.split { min-height: 100vh; display: grid; grid-template-columns: 1fr 1fr; animation: fade .4s ease both; }
.split-art {
  position: relative; display: flex; flex-direction: column; justify-content: flex-end; align-items: flex-start;
  text-align: left; color: var(--white); padding: 40px clamp(24px, 4vw, 56px) 48px; gap: 12px; overflow: hidden;
  background: var(--art, url("../img/girl-tray.jpg")) center / cover no-repeat, #1f5c33;
}
.split-art::before { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(23,71,42,.15) 0%, rgba(23,71,42,.55) 55%, rgba(23,71,42,.92) 100%); }
.split-art > * { position: relative; }
.split-art::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 6px; background: var(--gold); }
.split-brand { position: absolute; top: 22px; left: clamp(24px, 4vw, 48px); display: flex; align-items: center; gap: 10px; font-weight: 800; font-size: 18px; color: var(--button-green); background: rgba(255,255,255,.92); padding: 6px 16px 6px 8px; border-radius: 999px; box-shadow: var(--shadow-soft); }
.split-brand img { width: 36px; height: 36px; border-radius: 50%; }
.split-art h2 { margin: 0; font-size: 30px; line-height: 1.2; max-width: 440px; }
/* The poster fills the panel; on very wide, short screens it is shown whole and a matching gradient fills the sides. */
.split-art.art-poster { padding: 0; background: #e3f0dc; }
.split-art.art-poster::before { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, #cfe8c9 0%, #eff3d5 55%, #f7e29a 100%); }
.split-art.art-poster::after { content: ""; position: absolute; inset: 0; height: auto; background: var(--art) center / cover no-repeat; }
@media (min-aspect-ratio: 19/10) and (min-width: 901px) { .split-art.art-poster::after { background-size: contain; } }
.split-art.art-poster > * { display: none; }
.split-art .art-tag { background: var(--gold); color: #5b4300; font-weight: 800; font-size: 13.5px; padding: 5px 14px; border-radius: 999px; }
.split-art p { margin: 0; color: rgba(255,255,255,.82); max-width: 400px; line-height: 1.55; font-size: 15.5px; }

.split-form {
  display: flex; align-items: center; justify-content: center; padding: 32px 24px;
  background: linear-gradient(180deg, #ffffff 0%, var(--bg-bottom) 100%);
}
.split-card { width: 100%; max-width: 500px; background: var(--white); border: 1px solid var(--line); border-top: 5px solid var(--gold); border-radius: 16px; box-shadow: var(--shadow-pop); padding: 28px 32px 30px; }
.split-card.card-lg { max-width: 640px; padding: clamp(24px, 5vh, 48px) clamp(28px, 4vw, 56px) clamp(26px, 5vh, 50px); }
.split-card.card-lg h1 { font-size: clamp(30px, 4.6vh, 42px); margin: clamp(10px, 2vh, 18px) 0 6px; }
.split-card.card-lg .split-sub { font-size: clamp(15px, 2.2vh, 18px); margin-bottom: clamp(18px, 3.6vh, 34px); }
.split-card.card-lg .field { margin-bottom: clamp(14px, 2.6vh, 22px); }
.split-card.card-lg .field label { font-size: clamp(14px, 2vh, 16px); margin-bottom: 8px; }
.split-card.card-lg .field input { padding: clamp(13px, 2.2vh, 18px) 20px; font-size: clamp(15px, 2.1vh, 17px); border-radius: 16px; }
.split-card.card-lg .btn-block { padding: clamp(14px, 2.4vh, 19px) 20px; font-size: clamp(16px, 2.2vh, 18px); margin-top: 6px; }
.split-card.card-lg .auth-footer-link { font-size: clamp(14px, 2vh, 16px); margin-top: clamp(16px, 3vh, 26px); }
.split-card.card-lg .back-link { font-size: 15px; }
.split-card h1 { font-size: 30px; margin: 10px 0 4px; color: var(--button-green); font-weight: 800; }
.split-sub { color: #000; margin: 0 0 24px; font-size: 16px; }
.back-link { font-size: 14px; font-weight: 700; color: var(--muted); }
.back-link:hover { color: var(--button-green); }
.split-card .field input, .split-card .field select { padding: 13px 15px; border-radius: 14px; background: #f6faf6; font-size: 15.5px; }
.split-card .field label { font-size: 15px; }
@media (max-width: 860px) {
  .split { grid-template-columns: 1fr; }
  .split-art { padding: 120px 24px 28px; min-height: 260px; }
  .split-art h2 { font-size: 21px; }
  .split-art p { display: none; }
}
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

.auth-footer-link { text-align: center; margin-top: 18px; font-size: 15px; color: #000; }
.auth-footer-link a { color: var(--button-green); font-weight: 800; }

.role-toggle { display: flex; gap: 10px; margin-bottom: 10px; }
.role-toggle label {
  flex: 1; text-align: center; padding: 12px; border-radius: 14px; cursor: pointer;
  border: 1.5px solid var(--line); font-size: 15px; font-weight: 700; color: var(--muted); background: var(--white);
  transition: all .15s ease;
}
.role-toggle label:hover { border-color: var(--brand); }
.role-toggle input { position: absolute; opacity: 0; pointer-events: none; }
.role-toggle label:has(input:checked) { background: var(--brand); border-color: var(--brand); color: var(--white); box-shadow: 0 6px 16px rgba(94,168,73,.28); }
.role-hint { font-size: 13.5px; color: #000; margin: 0 0 16px; }

/* ---------------------------------------------------------------------- */
/* Flash messages */
/* ---------------------------------------------------------------------- */
/* Bottom, not top -- a successful action's feedback should read like a
   toast confirming what just happened, not compete with the page header
   for attention at the top of the screen. */
/* Full-width bar spanning the whole tab, not a small corner toast -- meant
   to be unmissable ("kitang kita") rather than something you might not
   notice off in a corner. */
.flash-stack { position: fixed; left: 0; right: 0; bottom: 0; display: flex; flex-direction: column-reverse; gap: 3px; z-index: 999; }

/* Top-of-screen banner for a freshly-arrived notification/announcement
   (see data-poll-url on #notifBannerStack and the poll script in
   app.js) -- stacks above the page content, never pushes it down. */
.notif-banner-stack {
  position: fixed; top: 14px; left: 50%; transform: translateX(-50%);
  z-index: 1000; display: flex; flex-direction: column; gap: 8px;
  width: min(420px, calc(100vw - 32px));
}
.notif-banner {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--white); border: 1.5px solid var(--line); border-left: 4px solid var(--cat, var(--brand));
  border-radius: var(--radius-md); box-shadow: var(--shadow-pop);
  padding: 12px 14px; cursor: pointer;
  animation: notifBannerIn .18s ease;
}
.notif-banner:hover { background: #fafafa; }
.notif-banner-body { flex: 1; min-width: 0; }
.notif-banner-title { display: block; font-size: 13.5px; font-weight: 800; color: #000; }
.notif-banner-text {
  margin: 2px 0 0; font-size: 12.5px; color: #555;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.notif-banner-close {
  flex-shrink: 0; width: 22px; height: 22px; border-radius: 50%; border: none;
  background: #f2f2f2; color: #666; font-size: 14px; line-height: 1; cursor: pointer;
}
.notif-banner-close:hover { background: #e7e7e7; color: #222; }
@keyframes notifBannerIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } }
.flash {
  width: 100%; text-align: center; padding: 14px 20px; font-size: 15px; font-weight: 700;
  box-shadow: var(--shadow-pop); border-top: 2px solid transparent;
  animation: flashPop .12s ease;
}
@keyframes flashPop {
  from { opacity: 0; transform: translateY(100%); }
  to { opacity: 1; transform: translateY(0); }
}
/* Solid, unmistakably green -- every successful action app-wide renders
   through this one shared flash-success class, so this single rule is
   what makes "did that work?" answer itself everywhere at once. */
.flash-success { background: #1f9d55; color: #fff; border-color: #1f9d55; }
.flash-error { background: #fdecea; color: #b3261e; border-color: #f5c2bd; }
.flash-warning { background: #fdf2e3; color: #8a6d1f; border-color: #f0dca8; }

/* ---------------------------------------------------------------------- */
/* Empty / coming-soon states */
/* ---------------------------------------------------------------------- */
.empty-state {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 70px 20px; color: #000;
}
.empty-state .empty-icon {
  width: 64px; height: 64px; border-radius: 50%; display: flex; align-items: center;
  justify-content: center; font-size: 28px; color: var(--white); margin-bottom: 14px;
  background: var(--active-accent, var(--brand));
}
.empty-state .empty-icon svg { width: 30px; height: 30px; }
.empty-state h3 { color: var(--ink); font-size: 18px; margin: 0 0 6px 0; }

/* ---------------------------------------------------------------------- */
/* Beneficiaries page                                                     */
/* ---------------------------------------------------------------------- */
.bene-header-card {
  font-size: 18px; font-weight: 800; color: #000; margin-bottom: 10px;
  border-color: #c1592e;
}
/* Title on the left, total count on the right. */
.bene-header-with-total {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px;
  margin-bottom: 14px;
}
/* Both counts sit on the same line as the title -- below-6/no-BMI to the
   left of the total, right-aligned together as one group. */
.bene-header-counts { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
.bene-count-badge {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--white); color: #000; border: 1px solid #c1592e;
  font-size: 12.5px; font-weight: 800; padding: 8px 16px; border-radius: 999px; margin-bottom: 0;
}
.bene-count-badge.is-info { border-color: #4a90d9; color: #1a5ba8; background: #e8f1fc; }

.bene-main-card { padding: 20px; }
.bene-title-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.bene-title-row h2 { margin: 0; font-size: 19px; font-weight: 800; color: var(--ink); }
/* Select All / Delete / + Add, together on the right of the title row.
   Delete is the same size as + Add but outlined, so the solid Add stays
   the main action; in select mode it turns into a neutral "Cancel". */
.bene-title-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
.bene-delete-btn {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--white); color: var(--danger); border: 1.5px solid var(--danger); border-radius: 999px;
  padding: 10px 22px; font-size: 14px; font-weight: 800; cursor: pointer;
  transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.bene-delete-btn:hover { background: #fdecea; }
.bene-delete-btn.is-selecting { color: var(--ink); border-color: var(--line); }
.bene-delete-btn.is-selecting:hover { background: #f3f5f4; }
.btn-add-bene {
  background: #c1592e; color: var(--white); border: none; border-radius: 999px;
  padding: 10px 22px; font-size: 14px; font-weight: 800; cursor: pointer;
  box-shadow: 0 4px 12px rgba(193, 89, 46, 0.35);
}
.btn-add-bene:hover { background: #a84a24; }
.bene-edit-btn.btn-outline { color: #c1592e; border-color: #c1592e; }
.bene-edit-btn.btn-outline:hover { background: color-mix(in srgb, #c1592e 12%, white); }
/* Same size as the "+ Add" button. */
.bene-edit-btn-sm.btn-sm { padding: 10px 22px; font-size: 14px; font-weight: 800; }

.bene-toolbar-row { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
/* Shared with Attendance's own filter row (same classes, reused) -- these
   pick up whichever page's --active-accent they're rendered on, instead
   of a color hardcoded to one specific page, so Beneficiaries reads
   orange and Attendance reads teal from this one shared rule. */
.bene-pill-select, .bene-pill-btn {
  display: inline-flex; align-items: center; gap: 5px;
  background: color-mix(in srgb, var(--active-accent, var(--brand)) 14%, white);
  color: var(--active-accent, var(--brand)); border: none;
  padding: 8px 14px; border-radius: 999px; font-size: 12.5px; font-weight: 800; cursor: pointer;
}
.bene-pill-select, .bene-section-select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231f5c33' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 12px;
  padding-right: 30px;
}
.bene-pill-btn:hover { background: color-mix(in srgb, var(--active-accent, var(--brand)) 14%, white); }
.bene-pill-btn.is-active { background: var(--active-accent, var(--brand)); color: var(--white); }
.bene-pill-danger { background: var(--danger); color: var(--white); }
.bene-pill-danger:hover { background: #b9302a; }
.bene-pill-danger.is-selecting { background: var(--danger); color: var(--white); }
.bene-select-all-wrap {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; font-weight: 800; color: var(--active-accent, var(--brand));
  cursor: pointer; user-select: none;
}
.bene-select-all-wrap input { width: 16px; height: 16px; accent-color: var(--danger); cursor: pointer; }
.bene-select-all-wrap[hidden] { display: none; }


.bene-grade-chip-row { display: flex; align-items: center; gap: 4px; overflow-x: auto; padding-bottom: 2px; }
.bene-grade-chip { padding: 7px 13px; border-radius: 8px; font-size: 13px; font-weight: 700; color: var(--muted); white-space: nowrap; }
.bene-grade-chip.is-active { background: var(--active-accent, var(--brand)); color: var(--white); }
.bene-grade-chip-divider { width: 1px; height: 16px; background: var(--line); flex-shrink: 0; }

/* The grade chips and the "All sections" dropdown now share one line --
   chips keep their own horizontal scroll (there can be many of them) and
   are free to shrink, while the dropdown keeps its natural width and
   never shrinks, staying put at the right of the chip row (right after
   the last chip, e.g. "Grade 6 (16)") instead of needing its own row
   below. */
.bene-grade-row-wrap { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.bene-grade-row-wrap .bene-grade-chip-row { flex: 1 1 auto; min-width: 0; }
.bene-grade-row-wrap form { flex-shrink: 0; }

.bene-section-select {
  width: auto; min-width: 170px; background-color: color-mix(in srgb, var(--active-accent, var(--brand)) 10%, white); border: none; border-radius: var(--radius-sm);
  padding: 11px 30px 11px 14px; font-size: 13.5px; font-weight: 600; color: var(--ink);
}

/* Now one of the pill filters in the toolbar row (left of Nutrition/Sex/
   Sort) instead of its own full-width row below them. */
.bene-search-row { position: relative; flex: 1 1 200px; min-width: 160px; }
.bene-search-icon { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); color: var(--active-accent, var(--brand)); font-size: 14px; }
.bene-search-input {
  width: 100%; background: color-mix(in srgb, var(--active-accent, var(--brand)) 10%, white); border: none; border-radius: var(--radius-sm);
  padding: 11px 14px 11px 38px; font-size: 13.5px; color: var(--ink);
}
.bene-search-input:focus { outline: 2px solid var(--active-accent, var(--brand)); }

.bene-select-checkbox { display: none; width: 18px; height: 18px; accent-color: var(--danger); cursor: pointer; flex-shrink: 0; }
.bene-roster.is-selecting .bene-select-checkbox { display: inline-block; }

.bene-roster { display: flex; flex-direction: column; gap: 8px; }
/* Dragging the mouse down a column of checkboxes to bulk-select would
   otherwise also drag-select the row text along the way. */
.bene-roster.is-selecting { user-select: none; }
.bene-student-row {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px;
  background: #fafafa; border: 1px solid var(--line); border-radius: var(--radius-md);
  border-left: 4px solid var(--group-color, var(--line));
}
.bene-student-row[hidden], .att-student-row[hidden], .att-group-label[hidden] { display: none; }
.bene-student-info { flex: 1; min-width: 0; }
.bene-student-name { font-size: 14px; font-weight: 700; color: var(--ink); }
.bene-student-sub { font-size: 12px; color: var(--group-color, var(--muted)); font-weight: 600; margin: 1px 0 4px; }
.bene-student-actions { display: flex; gap: 6px; flex-shrink: 0; }

.bene-select-bar {
  position: sticky; bottom: 16px; display: flex; align-items: center; justify-content: space-between;
  gap: 12px; background: var(--danger); color: var(--white); padding: 12px 18px;
  border-radius: var(--radius-md); margin-top: 14px; box-shadow: var(--shadow-pop); font-size: 13.5px; font-weight: 600;
  /* Above the roster table's pinned header/name cells (z-index up to 4),
     which otherwise paint over the bar as it floats past them. */
  z-index: 20;
}
.bene-select-bar[hidden] { display: none; }
/* The bar is solid red -- invert the button so it still stands out
   instead of blending into its own background. */
.bene-select-bar .btn-danger-solid { background: var(--white); color: var(--danger); box-shadow: none; }
.bene-select-bar .btn-danger-solid:hover { background: #fdecea; }

.add-bene-dropdown { position: relative; }
.add-bene-menu {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 30; width: 320px;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop); padding: 8px;
}
.add-bene-menu-title { font-size: 13px; font-weight: 800; color: var(--ink); padding: 8px 10px 4px; }
.add-bene-option {
  display: flex; align-items: center; gap: 12px; padding: 12px; border-radius: var(--radius-md);
  background: color-mix(in srgb, #c1592e 10%, white);
  border: 1px solid color-mix(in srgb, #c1592e 16%, white);
  transition: background .12s ease;
}
.add-bene-option:hover { background: color-mix(in srgb, #c1592e 18%, white); }
.add-bene-option + .add-bene-option { margin-top: 8px; }
.add-bene-icon {
  width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; font-size: 17px;
  background: #c1592e; color: var(--white);
}
.add-bene-text strong { display: block; font-size: 14px; color: var(--ink); }
.add-bene-text small { display: block; font-size: 11.5px; color: #000; margin-top: 2px; line-height: 1.4; }

/* Print styles for Form 1A/1B */
.print-only { display: none; }
/* Form 3's day-chunked print pages (see preview_form3.html) exist only to
   be printed -- never shown on screen, where the normal horizontally-
   scrolling sheet is what you actually edit. */
.sbfp-print-chunks { display: none; }
@media print {
  /* Chrome's own print dialog draws a date/title/URL header and a page-
     number footer inside the page margin by default -- there's no
     "Headers and footers" checkbox this app can flip on someone else's
     behalf, but giving the page zero margin leaves it no room to draw
     them at all, which is the standard way to suppress them from CSS.
     The margin they'd have occupied is added back below as ordinary
     padding on the content itself, so the printed/PDF'd page still has
     breathing room -- it's just no longer space Chrome can stamp on. */
  @page { margin: 0; }
  body { margin: 1.2cm; background: white; }
  .sidebar, .topbar, .filter-bar, .no-print { display: none !important; }
  .print-only { display: table-cell; }
  .content { padding: 0; }
  /* A wide sheet (e.g. Form 1A/1B's 16 columns) scrolls horizontally on
     screen -- during print/PDF that overflow must render in full instead
     of silently clipping at the visible edge, since the PDF is meant to
     stand in for the actual printed paper, not a screenshot of whatever
     fit in the browser window. Form 3 handles this differently (see
     below) since 120 days is too wide for this alone to be enough. */
  .sbfp-sheet-table-wrap { overflow: visible !important; }

  /* Any roster long enough to spill across multiple printed pages should
     still read like a table on every page it lands on -- the header row
     repeats at the top of each page instead of only appearing once, and
     a row never gets sliced in half across a page break. Applies to
     every SBFP form's table, not just Form 3's. */
  table.sbfp-sheet-table thead { display: table-header-group; }
  table.sbfp-sheet-table tr { page-break-inside: avoid; }

  /* Form 3: the interactive wide sheet is replaced entirely by its
     print-only, day-chunked pages (30 days each, landscape, roster
     repeated with its own header per chunk -- see preview_form3.html) --
     :has() is already relied on elsewhere in this file (see
     .sbfp-editable-row:has(...)), so this is a safe, already-established
     pattern to lean on again here. */
  .card.sbfp-sheet:has(.sbfp-print-chunks) > .sbfp-sheet-table-wrap { display: none; }
  .sbfp-print-chunks { display: block; }
  .sbfp-print-chunk-table { page-break-after: always; }
  .sbfp-print-chunk-table:last-of-type { page-break-after: auto; }
}

/* Show / hide password */
.pw-wrap { position: relative; }
.pw-wrap input { padding-right: 52px !important; }
.pw-toggle { position: absolute; top: 50%; right: 10px; transform: translateY(-50%); width: 36px; height: 36px; border: none; background: transparent; color: #000; border-radius: 50%; display: flex; align-items: center; justify-content: center; padding: 0; cursor: pointer; }
.pw-toggle:hover { color: var(--button-green); background: rgba(94,168,73,.12); }
.pw-toggle svg { width: 20px; height: 20px; }
.pw-toggle .eye-off { display: none; }
.pw-toggle.is-shown .eye { display: none; }
.pw-toggle.is-shown .eye-off { display: block; }

/* Live password-strength meter + checklist */
.pw-strength { margin-top: 10px; }
.pw-meter { height: 6px; border-radius: 999px; background: var(--line); overflow: hidden; }
.pw-meter-fill { height: 100%; width: 0%; border-radius: 999px; background: var(--danger); transition: width .25s ease, background-color .25s ease; }
.pw-meter-fill.is-medium { background: var(--gold); }
.pw-meter-fill.is-strong { background: var(--brand); }
.pw-rules { list-style: none; margin: 8px 0 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 5px 12px; }
.pw-rules li { font-size: 13px; color: #000; display: flex; align-items: center; gap: 6px; transition: color .2s ease; }
.pw-rules li::before { content: "\2715"; color: var(--danger); font-size: 11px; font-weight: 700; width: 14px; flex: none; text-align: center; transition: color .2s ease; }
.pw-rules li.is-met { color: var(--button-green); }
.pw-rules li.is-met::before { content: "\2713"; color: var(--brand); }

/* School picker: district first, then the schools in that district */
.school-picker { position: relative; }
.school-auto-out { width: 100%; padding: 13px 15px; border: 1.5px dashed var(--line); border-radius: 14px; background: transparent; font-size: 15.5px; color: #000; cursor: default; }
.school-auto-out:focus { outline: none; }
.school-auto-out::placeholder { color: #000; opacity: .7; }
.sp-trigger { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 10px; text-align: left; padding: 13px 15px; border: 1.5px solid var(--line); border-radius: 14px; background: #f6faf6; font: inherit; font-size: 15.5px; color: #000; cursor: pointer; }
.sp-trigger.has-value { color: var(--ink); }
.sp-trigger:focus-visible, .school-picker.is-open .sp-trigger { outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px rgba(94,168,73,.18); }
.sp-trigger.is-invalid { border-color: #d23b34; }
.sp-trigger svg { flex-shrink: 0; transition: transform .15s ease; }
.school-picker.is-open .sp-trigger svg { transform: rotate(180deg); }
.sp-menu { position: absolute; z-index: 20; left: 0; right: 0; top: calc(100% + 6px); background: var(--white); border: 1.5px solid var(--line); border-radius: 16px; box-shadow: var(--shadow-pop); max-height: 300px; overflow-y: auto; padding: 6px; }
.sp-menu [hidden] { display: none !important; }
.sp-head { padding: 8px 12px 6px; font-size: 12.5px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase; color: var(--muted); }
.sp-item, .sp-back { width: 100%; display: flex; align-items: center; gap: 10px; padding: 11px 12px; border: none; border-radius: 12px; background: transparent; font: inherit; font-size: 15px; color: var(--ink); text-align: left; cursor: pointer; }
.sp-item:hover, .sp-back:hover { background: var(--soft-green); }
.sp-district { font-weight: 800; color: var(--button-green); }
.sp-district small { margin-left: auto; font-weight: 600; color: var(--muted); }
.sp-district svg { color: var(--brand); flex-shrink: 0; }
.sp-back { font-weight: 800; color: var(--button-green); border-bottom: 1px solid var(--line); border-radius: 12px 12px 0 0; margin-bottom: 4px; position: sticky; top: -6px; background: var(--white); }
.sp-school.is-selected { background: #fff3c7; font-weight: 700; }

table.data-table a { color: var(--button-green); font-weight: 700; }
table.data-table a:hover { color: var(--brand); text-decoration: underline; }
/* Outline buttons inside tables keep their own color on hover -- only grow. */
table.data-table a.btn-outline:hover { color: var(--button-green); text-decoration: none; }
.btn-danger { background: #fdecea; color: var(--danger); }

/* ---------------------------------------------------------------------- */
/* Confirmation pop-up                                                    */
/* ---------------------------------------------------------------------- */
.modal-backdrop { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center; padding: 20px; background: rgba(14, 40, 24, .5); backdrop-filter: blur(3px); animation: fade .2s ease both; }
.modal-backdrop[hidden] { display: none; }
.modal { width: 100%; max-width: 420px; background: var(--white); border-radius: 16px; border-top: 5px solid var(--gold); box-shadow: 0 24px 60px rgba(0,0,0,.3); padding: 28px 28px 24px; text-align: center; animation: pop .22s ease both; }
.modal-icon {
  width: 58px; height: 58px; margin: 0 auto 14px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 26px; font-weight: 800;
  background: color-mix(in srgb, var(--active-accent, var(--brand)) 16%, white); color: var(--active-accent, var(--brand));
}
.modal.is-danger .modal-icon { background: #fdecea; color: var(--danger); }
.modal h3 { margin: 0 0 8px; font-size: 21px; color: #000; }
.modal p { margin: 0 0 22px; color: #000; font-size: 15.5px; line-height: 1.55; }
.modal-actions { display: flex; gap: 12px; }
.modal-actions .btn { flex: 1; justify-content: center; padding: 12px 18px; font-size: 15.5px; }
/* A choice with more than the usual OK/Cancel pair (e.g. "delete" vs
   "keep" vs "cancel") reads better stacked than squeezed into one row. */
.modal-actions.is-stacked { flex-direction: column; }
.modal-actions.is-stacked .btn { width: 100%; }
.modal-cancel-text {
  background: none; border: none; color: var(--muted); font-weight: 700;
  font-size: 14px; padding: 10px; cursor: pointer; width: 100%;
}
.modal-cancel-text:hover { color: var(--ink); }
.modal.is-danger #confirmOk { background: var(--danger); box-shadow: 0 6px 16px rgba(210, 59, 52, .25); }
.modal.is-danger #confirmOk:hover { background: #b9302a; }
.modal.is-danger #confirmCancel { border-color: var(--danger); }
.modal.is-danger #confirmCancel:hover { background: color-mix(in srgb, var(--danger) 12%, white); }
.photo-preview-frame {
  width: 160px; height: 195px; margin: 0 auto 22px; border-radius: 14px; overflow: hidden;
  border: 3px solid var(--line); background: #f1f1f1;
}
.photo-preview-frame img { width: 100%; height: 100%; object-fit: cover; }
/* Tapping any profile/student photo opens it here, full-size -- no crop,
   no upscaling past its real dimensions. */
.photo-view-box { position: relative; max-width: 90vw; max-height: 90vh; }
.photo-view-box img { display: block; max-width: 90vw; max-height: 90vh; border-radius: 14px; box-shadow: var(--shadow-pop); }
.photo-view-close {
  position: absolute; top: -14px; right: -14px; width: 32px; height: 32px; border-radius: 50%;
  background: var(--white); border: 1px solid var(--line); color: #000; font-size: 20px; line-height: 1;
  cursor: pointer; display: flex; align-items: center; justify-content: center; box-shadow: var(--shadow-soft);
}
@keyframes pop { from { opacity: 0; transform: translateY(10px) scale(.96); } to { opacity: 1; transform: none; } }

/* ---------------------------------------------------------------------- */
/* Error pages                                                            */
/* ---------------------------------------------------------------------- */
.err-wrap { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 24px; background: linear-gradient(135deg, #cfe8c9 0%, #e6f0cf 45%, #f7e6a3 100%); }
.app-shell .err-wrap { min-height: 70vh; background: transparent; }
.err-card { width: 100%; max-width: 480px; text-align: center; background: var(--white); border-radius: 16px; border-top: 5px solid var(--gold); box-shadow: var(--shadow-pop); padding: 40px 34px 34px; }
.err-icon { width: 68px; height: 68px; margin: 0 auto 14px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 30px; }
.err-error { background: #fdecea; color: var(--danger); }
.err-warning { background: #fff3c7; color: #8a6d1f; }
.err-code { display: inline-block; font-size: 13.5px; font-weight: 800; letter-spacing: .5px; color: #7a5b00; background: #fff3c7; border: 1px solid var(--gold); padding: 3px 12px; border-radius: 999px; }
.err-card h1 { margin: 12px 0 8px; font-size: 26px; color: var(--button-green); }
.err-card p { margin: 0 0 24px; color: #000; line-height: 1.6; }
.err-actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

/* Sign-up: the card fills the screen height (no page scroll); its content spreads out to match.
   Scoped to the actual split-screen login/register pages (.split) -- not just any page that
   happens to have a .card-fit element in the DOM, which also matches the welcome page's
   (usually hidden) in-page login/signup card and would wrongly lock its scroll too. */
@media (min-width: 901px) {
  body:has(.split .card-fit) { overflow: hidden; }
  .split:has(.card-fit) { height: 100vh; height: 100dvh; min-height: 0; }
  .split:has(.card-fit) .split-form { padding: clamp(14px, 3vh, 32px) 24px; align-items: stretch; height: 100%; min-height: 0; }
  .split:has(.card-fit) .split-card.card-fit { min-height: 0; }
}
/* Content is one centered group with a single, even gap between every block. */
.split-card.card-fit {
  --gap: clamp(13px, 2.9vh, 30px);
  position: relative; max-width: 640px; display: flex; flex-direction: column; justify-content: center; gap: var(--gap);
  height: 100%; margin: 0 auto; box-sizing: border-box;
  padding: clamp(40px, 6vh, 56px) clamp(24px, 3.2vw, 44px) clamp(16px, 3.4vh, 36px);
}
.card-fit .back-link { position: absolute; top: clamp(14px, 2.6vh, 24px); left: clamp(24px, 3.2vw, 44px); font-size: 14px; }
.card-fit h1 { font-size: clamp(24px, 4.6vh, 40px); margin: 0; text-align: center; }
.card-fit .split-sub { font-size: clamp(13px, 2vh, 16px); margin: calc(var(--gap) * -.55) 0 0; text-align: center; }
.card-fit form { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: var(--gap); padding: 4px 6px 4px 2px; overflow-y: auto; overflow-x: hidden; scrollbar-width: thin; scrollbar-color: var(--brand) transparent; }
.card-fit form::-webkit-scrollbar { width: 7px; }
.card-fit form::-webkit-scrollbar-track { background: transparent; }
.card-fit form::-webkit-scrollbar-thumb { background: var(--line); border-radius: 999px; }
.card-fit form::-webkit-scrollbar-thumb:hover { background: var(--brand); }
.card-fit .field { margin-bottom: 0; }
.card-fit .fit-group { display: flex; flex-direction: column; gap: clamp(5px, 1vh, 10px); }
.card-fit .role-toggle { margin-bottom: 0; }
.card-fit .role-toggle label { padding: clamp(9px, 1.9vh, 16px); font-size: clamp(13px, 2vh, 15px); }
.card-fit .role-hint { font-size: clamp(11.5px, 1.7vh, 13px); margin: 0; text-align: center; }
.card-fit .field label { font-size: clamp(12.5px, 1.8vh, 14.5px); margin-bottom: clamp(4px, .8vh, 8px); }
.card-fit .field input, .card-fit .sp-trigger { padding: clamp(10px, 2vh, 17px) 15px; font-size: clamp(13px, 2vh, 16px); border-radius: 14px; }
.card-fit .field-row, .card-fit .field-row-3 { gap: 14px; }
.card-fit .btn-block { padding: clamp(12px, 2.2vh, 18px) 20px; font-size: clamp(14px, 2.1vh, 17px); margin-top: 0; }
.card-fit .auth-footer-link { margin: 0; text-align: center; font-size: clamp(12.5px, 1.9vh, 15px); }
.card-fit .sp-menu { max-height: min(300px, 34vh); }

/* Log in: same full-height card, with larger type/fields because there are fewer of them */
.card-login h1 { font-size: clamp(28px, 5.6vh, 50px); }
.card-login .split-sub { font-size: clamp(14px, 2.4vh, 19px); }
.card-login .field label { font-size: clamp(13.5px, 2.2vh, 18px); margin-bottom: clamp(6px, 1.2vh, 12px); }
.card-login .field input { padding: clamp(13px, 3vh, 26px) 20px; font-size: clamp(14.5px, 2.5vh, 20px); border-radius: 16px; }
.card-login .btn-block { padding: clamp(14px, 3.2vh, 26px) 20px; font-size: clamp(15px, 2.5vh, 20px); }
/* No grow on hover here: the button spans the form's full width, so scaling
   it gets clipped by the form's overflow. Color change + lift only. */
.card-login .btn-block:hover { transform: translateY(-1px); }
.card-login .auth-footer-link { font-size: clamp(13.5px, 2.1vh, 17px); }
.card-login .auth-footer-link a { color: var(--brand); }
.card-login .auth-footer-link a:hover { color: var(--brand-hover); }
/* Log in card stretches across its half of the screen, leaving only the
   pane's own side padding as breathing room; fields and button follow. */
.split-card.card-login { max-width: none; }
/* The form only takes the height it needs, so heading, fields, button and
   the sign-up line sit together as one vertically centered group instead of
   the sign-up line being pushed to the bottom of the card. */
.card-login form { flex: 0 1 auto; }
/* Like the picture beside it, the card runs edge to edge top and bottom. */
@media (min-width: 901px) {
  .split:has(.card-login) .split-form { padding: 0 24px; }
  .split-card.card-login { border-radius: 0; border-bottom: none; }
}
.card-login .back-link { font-size: 15px; }

/* ---------------------------------------------------------------------- */
/* Meal Plan -- goldenrod accent, matching this tab's own sidebar icon    */
/* color (mobile main_shell.dart), ported from mealplan_tab.dart. Every   */
/* card on this page gets the same green top border Home's cards use, so */
/* they read as belonging to the same app.                                */
/* ---------------------------------------------------------------------- */
.mealplan-header-card {
  font-size: 18px; font-weight: 800; color: #000; margin-bottom: 16px;
  border-color: #b8860b;
}
.mealplan-table-card, .mealplan-expenses-card, .mealplan-history-card { margin-bottom: 12px; }

/* A title bar attached directly to the top of the table card itself --
   title left, date right -- instead of floating as its own element
   above it. The rich green (soft highlight sheen included) now lives
   here instead of on the column-header row below it. */
.mealplan-table-titlebar {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 18px 22px;
  background: linear-gradient(180deg, #f0d78c 0%, #dcb04a 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.55);
  border-bottom: 2px solid #a67c00;
}
.mealplan-week-title { font-size: 16px; font-weight: 700; color: #000; }
.mealplan-date-chip { font-size: 13px; font-weight: 600; color: #000; }

.mealplan-tuesday-note {
  display: flex; align-items: center; gap: 7px;
  font-size: 12.5px; font-weight: 700; color: #8a661a;
  background: rgba(201,138,31,0.14); border: 1px solid rgba(201,138,31,0.35);
  padding: 8px 14px; margin: 0; border-radius: 0;
}
.mealplan-tuesday-note svg { flex-shrink: 0; }

/* A calm, legible table: generous row padding, no hover flicker, one
   heavier rule between days (not between a day's own AM/PM pair, so
   that pair still reads as one grouped unit), and the Meal(s) column
   given most of the width instead of forcing every column equal. The
   table fills its card exactly -- no padding gap around it; overflow
   hidden clips its corners to the card's own rounded corners instead. */
.mealplan-table-card { padding: 0; overflow: hidden; }
.mealplan-table-card .table-wrap { border: none; border-radius: 0; }

.mealplan-table { width: 100%; border-collapse: collapse; table-layout: fixed; }

/* Column-header row is plain white now -- the green moved up to the
   titlebar above it instead. */
.mealplan-table thead th {
  background: var(--white);
  color: #000; font-weight: 800;
  font-size: 12px; text-transform: uppercase; letter-spacing: .5px;
  padding: 16px 20px; border-bottom: 1px solid var(--line);
}
.mealplan-table th.col-meals { text-align: left; }
.mealplan-table th.col-day, .mealplan-table th.col-session { text-align: center; }

.mealplan-table td { padding: 13px 20px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.mealplan-table tbody tr:last-child td { border-bottom: none; }
.mealplan-row-day-start:not(:first-child) td { border-top: 2px solid var(--line); }

/* The one deliberate vertical divider in the whole table -- between Day
   and Session only, since Day spans two rows and benefits from a clean
   edge separating it from the rest of its own row pair. */
.mealplan-table th.col-day, .mealplan-td-day { border-right: 1.5px solid var(--line); }

.mealplan-td-day { text-align: center; font-weight: 800; color: #000; font-size: 14px; }
.mealplan-today-tag {
  display: block; width: fit-content; margin: 6px auto 0;
  font-size: 10px; font-weight: 800; text-transform: uppercase; letter-spacing: .4px;
  color: #fff; background: #b8860b;
  padding: 3px 9px; border-radius: 999px;
  box-shadow: 0 1px 4px rgba(184, 134, 11, .5);
}

.mealplan-td-session {
  text-align: center; font-size: 11.5px; font-weight: 800;
  text-transform: uppercase; letter-spacing: .5px; color: #000;
}

.mealplan-td-meals { text-align: left; }
.mealplan-dish-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }
/* Text color alone carries which component a dish belongs to -- no pill
   or background, just the label's own color (set inline per component). */
.mealplan-dish-type {
  display: block; font-size: 10px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .4px; margin-bottom: 2px;
}
.mealplan-dish-name { display: block; font-size: 13.5px; font-weight: 600; color: #000; line-height: 1.35; }
.mealplan-no-items { color: #000; font-size: 13px; font-style: italic; }

/* Small, fit-to-content pill -- solid full-opacity color per status, not
   a pale tint, so it actually reads as colored at a glance. Each status
   picks its own text color so it stays legible against its own
   background (dark text on the yellow "Now Serving", white elsewhere). */
.mealplan-status-tag {
  display: inline-flex; align-items: center; width: fit-content;
  font-size: 11px; font-weight: 800; letter-spacing: .3px;
  padding: 5px 12px; border-radius: 999px;
  box-shadow: 0 1px 4px rgba(0,0,0,.18);
}
.mealplan-status-not_yet_served { background: #f2f2f2; color: #000; border: 2px solid var(--muted); }
.mealplan-status-now_serving { background: #b8860b; color: #fff; }
.mealplan-status-served { background: #b8860b; color: #fff; }

.mealplan-history-card { padding: 20px; }
.mealplan-history-title { font-weight: 700; }
.mealplan-history-sub { color: #000; font-weight: 400; margin-top: -10px; margin-bottom: 16px; }
.mealplan-history-card .empty-state { color: #000; }
.mealplan-history-card .empty-state h3 { color: #000; font-weight: 600; }
.mealplan-history-card .empty-state p { color: #000; font-weight: 400; }
/* A scannable list of rows instead of wrapping chips -- each week's
   full date range (with weekday names) as the primary label, so you
   know exactly what it covers without opening it. */
.mealplan-history-list { display: flex; flex-direction: column; gap: 2px; }
.mealplan-history-row {
  display: flex; align-items: center; gap: 14px; padding: 14px 12px;
  border-radius: var(--radius-md); border-bottom: 1px solid var(--line);
  transition: background .15s ease;
}
.mealplan-history-list a.mealplan-history-row:last-child { border-bottom: none; }
.mealplan-history-row:hover { background: var(--page-green); }
.mealplan-history-week {
  flex-shrink: 0; width: 150px; font-size: 13.5px; font-weight: 700; color: #000;
}
.mealplan-history-date { flex: 1; font-size: 13px; font-weight: 400; color: #000; }
.mealplan-history-arrow { font-size: 15px; color: #000; flex-shrink: 0; }

/* Hot Meal Expenses -- separate system from the table above (Division's
   own cycle_menus/cycle_menu_days catalog, not meal_plans/meal_plan_items),
   so it gets its own card rather than living inside mealplan-table-card. */
.mealplan-expenses-card { padding: 20px; }
.mealplan-expenses-title { font-weight: 700; }
.mealplan-expenses-note { color: #000; font-weight: 400; margin-top: -10px; margin-bottom: 16px; font-size: 13.5px; line-height: 1.5; }
.mealplan-expenses-table .mealplan-expense-input {
  width: 100%; max-width: 120px; border: 1.5px solid var(--line); background: var(--white);
  font: inherit; font-size: 13.5px; text-align: center; padding: 6px 8px; border-radius: 8px;
}
.mealplan-expenses-table .mealplan-expense-input:focus { outline: 2px solid var(--active-accent, #b8860b); border-color: transparent; }
.mealplan-expense-amount { display: inline-block; font-size: 13.5px; font-weight: 700; color: #000; margin-right: 10px; }
.mealplan-expenses-done { text-align: center; color: #2E6B3E; font-weight: 600; font-size: 13.5px; margin: 14px 0 0; }

.mealplan-ingredients-label { margin: 0 0 10px; font-size: 12.5px; font-weight: 600; color: #000; }
.mealplan-ingredients-note { margin: 10px 0 0; font-size: 12px; color: #666; font-style: italic; }

/* Each dish's name shown once, as a heading above its own rows -- never
   repeated per row/column, so two dishes under one Tuesday read as two
   clearly separate, labeled groups instead of one duplicated block. */
.mealplan-dish-heading { font-size: 13px; font-weight: 800; color: #000; margin: 0 0 8px; }
.mealplan-dish-heading-label { color: #666; font-weight: 700; }

/* Ingredient entry rows, always typable (no more collapse/edit toggle):
   just Ingredient / Amount (typed in directly, not computed from a
   quantity/unit-cost breakdown) / Remove. */
.mealplan-ingredient-row-header {
  display: grid; grid-template-columns: 2fr 1fr 26px; gap: 8px;
  font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .4px;
  color: #666; padding: 0 0 6px;
}
.mealplan-ingredient-rows { display: flex; flex-direction: column; gap: 8px; }
.mealplan-ingredient-row { display: grid; grid-template-columns: 2fr 1fr 26px; gap: 8px; align-items: center; }
.mealplan-ingredient-row .sbfp-cell-input {
  width: 100%; border: 1.5px solid var(--line); background: var(--white); border-radius: 8px; padding: 7px 10px;
}
.mealplan-ingredient-row .sbfp-cell-input:focus { outline: 2px solid var(--active-accent, #b8860b); border-color: transparent; }
/* A dish already saved opens read-only (see data-locked on its rows) --
   Edit unlocks it. Visibly distinct from an editable field so it's clear
   at a glance which dishes still need an Edit click first. */
.mealplan-ingredient-row .sbfp-cell-input:read-only { background: #f4f4f4; color: #555; cursor: default; }
.mealplan-ingredient-remove {
  flex-shrink: 0; width: 26px; height: 26px; border-radius: 50%; border: none;
  background: #f2f2f2; color: #666; font-size: 16px; line-height: 1; cursor: pointer;
}
.mealplan-ingredient-remove:hover { background: #fdecea; color: #b3261e; }
.mealplan-dish-actions { display: flex; align-items: center; gap: 10px; margin-top: 10px; }

/* Ingredient list (or read-only table) on the left, Receipt as its own
   column on the right -- a single dish-level control (not per
   ingredient), but still laid out beside the Amount column like the
   rest of the sheet, not stacked underneath it. */
.mealplan-dish-body { display: flex; align-items: flex-start; gap: 18px; }
.mealplan-dish-body-main { flex: 1; min-width: 0; }
.mealplan-dish-body .mealplan-ingredient-table { flex: 1; min-width: 0; width: auto; }

/* Receipts, once per dish (not per ingredient) -- a market trip commonly
   produces several, so this is a thumbnail strip (clicking one opens it
   full-size in the shared #photoViewModal lightbox, or a new tab for a
   PDF) plus a single Upload control that accepts multiple files at once
   and adds to the strip rather than replacing it. */
.mealplan-dish-receipts-col {
  flex-shrink: 0; width: 120px;
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
}
.mealplan-dish-receipts-label {
  font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .4px; color: #666;
}
.mealplan-receipt-thumbs { display: flex; flex-wrap: wrap; gap: 8px; }
.mealplan-receipt-thumb-wrap { position: relative; flex-shrink: 0; }
.mealplan-receipt-thumb {
  width: 44px; height: 44px; border-radius: 8px; overflow: hidden;
  border: 1.5px solid var(--line); background: #f7f7f7;
  display: flex; align-items: center; justify-content: center;
  transition: border-color .15s ease;
}
.mealplan-receipt-thumb:hover { border-color: var(--active-accent, #b8860b); }
.mealplan-receipt-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mealplan-receipt-thumb-pdf { font-size: 10px; font-weight: 800; color: #b3261e; }
.mealplan-receipt-thumb-delete {
  position: absolute; top: -6px; right: -6px; width: 17px; height: 17px;
  border-radius: 50%; border: 1.5px solid var(--white); background: #b3261e; color: #fff;
  font-size: 12px; line-height: 1; cursor: pointer; padding: 0;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 1px 3px rgba(0,0,0,.3);
}
.mealplan-receipt-thumb-delete:hover { background: #8f1d17; }
@media (max-width: 640px) {
  .mealplan-dish-body { flex-direction: column; }
  .mealplan-dish-receipts-col { width: auto; flex-direction: row; align-items: center; flex-wrap: wrap; }
}

/* Read-only view (locked, once the whole Tuesday is submitted) -- one
   small table per dish, each under its own heading (see
   .mealplan-dish-heading): just Ingredient / Amount, with the dish's
   receipt thumbnails below it. One shared Total spent line covers both
   dishes, instead of a confusing per-table footer. */
.mealplan-combined-dishes { display: flex; flex-direction: column; gap: 18px; }
.mealplan-dish-block + .mealplan-dish-block { padding-top: 18px; border-top: 1px dashed var(--line); }
.mealplan-ingredient-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.mealplan-ingredient-table th {
  text-align: left; font-size: 11px; font-weight: 800; vertical-align: middle;
  color: #2f4a37; background: var(--page-green); padding: 9px 12px; border-bottom: 1.5px solid var(--line);
}
.mealplan-ingredient-table th:nth-child(2), .mealplan-ingredient-table td:nth-child(2) { text-align: right; }
.mealplan-ingredient-table td { padding: 9px 12px; border-bottom: 1px solid var(--line); color: #000; vertical-align: middle; }
.mealplan-ingredient-table tbody tr:last-child td { border-bottom: 1.5px solid var(--line); }
.mealplan-combined-total {
  display: flex; align-items: center; justify-content: space-between;
  font-weight: 800; font-size: 14px; color: #000;
  margin-top: 14px; padding-top: 10px; border-top: 2px solid var(--line);
}
.mealplan-receipt-upload-label {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer; white-space: nowrap;
}
.mealplan-add-ingredient {
  margin-top: 10px; background: none; border: 1.5px dashed var(--muted); border-radius: 8px;
  padding: 7px 14px; font-size: 12.5px; font-weight: 700; color: var(--active-accent, #b8860b); cursor: pointer;
}
.mealplan-add-ingredient:hover { background: color-mix(in srgb, var(--active-accent, #b8860b) 8%, white); }

/* Hot Meal Expenses as a one-at-a-time pager instead of a scrollable
   list of every Tuesday -- the arrows swap which .mealplan-tuesday-slide
   is visible (see the DOMContentLoaded block in app.js), so only ever
   one Tuesday is in view, no collapse/expand needed. */
.mealplan-tuesday-pager {
  display: flex; align-items: center; justify-content: center; gap: 16px;
  margin-bottom: 12px;
}
.mealplan-pager-arrow {
  flex-shrink: 0; width: 34px; height: 34px; border-radius: 50%;
  border: 1.5px solid var(--line); background: var(--white); color: #000;
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  transition: background .15s ease, opacity .15s ease;
}
.mealplan-pager-arrow:hover:not(:disabled) { background: var(--page-green); }
.mealplan-pager-arrow:disabled { opacity: .35; cursor: not-allowed; }
.mealplan-pager-position { font-size: 12.5px; font-weight: 800; color: #666; min-width: 56px; text-align: center; }
.mealplan-tuesday-slide {
  border: 1.5px solid var(--line); border-radius: var(--radius-md);
  background: var(--white);
}
.mealplan-tuesday-slide[hidden] { display: none; }
.mealplan-tuesday-summary {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 13px 16px;
}
.mealplan-tuesday-daynum { font-size: 13px; font-weight: 800; color: #000; flex-shrink: 0; }
.mealplan-tuesday-date { font-size: 13px; color: #000; flex: 1; }
.mealplan-tuesday-body { padding: 0 16px 16px; border-top: 1px solid var(--line); padding-top: 14px; }

/* Both of the Tuesday's hot meal dishes, one after another -- no more
   AM/PM split into side-by-side panes, since a single market trip's
   receipt usually covers both anyway. Each dish keeps its own ingredient
   table underneath it, full card width. */
.mealplan-expense-session-row { display: flex; flex-direction: column; gap: 18px; }
.mealplan-expense-session-block + .mealplan-expense-session-block { padding-top: 18px; border-top: 1px dashed var(--line); }

/* Running monthly totals for the 120-day Hot Meal cycle -- separate from
   the per-week submit above since it spans every week submitted so far,
   not just this one. */
.mealplan-monthly-totals { margin-top: 20px; padding-top: 16px; border-top: 1.5px solid var(--line); }
.mealplan-month-total-list { list-style: none; margin: 0 0 10px; padding: 0; display: flex; flex-direction: column; gap: 4px; max-width: 420px; }
.mealplan-month-total-list li { display: flex; align-items: center; justify-content: space-between; font-size: 13px; padding: 6px 0; border-bottom: 1px dashed var(--line); }
.mealplan-month-total-list li:last-child { border-bottom: none; }
.mealplan-grand-total {
  display: flex; align-items: center; justify-content: space-between; max-width: 420px;
  font-size: 14px; font-weight: 800; color: #000; padding-top: 8px; border-top: 2px solid var(--line);
}

/* ---------------------------------------------------------------------- */
/* Announcements -- ported 1:1 from the mobile app's announcements_tab.dart
   and announcement_detail_screen.dart, same colors, same two-track
   Pending/Done workflow, just laid out for a wider screen (a single
   scrollable list instead of a swipeable PageView; both tracks' tabs are
   plain links instead of swipe+tap). */
/* ---------------------------------------------------------------------- */
.announce-header-card { font-size: 18px; font-weight: 800; color: #000; margin-bottom: 16px; border-color: #8b3a3a; }

/* With Deadline / No Deadline -- plain side-by-side tabs again, not
   dropdowns themselves. Which sub-page (Pending/Done, or
   Pending/Acknowledged) is showing is a separate dropdown on the line
   underneath, whose options change depending on which tab is active. */
.announce-tabbar { display: flex; gap: 4px; padding: 4px; background: var(--white); border: 1px solid var(--line); border-radius: 999px; margin-bottom: 12px; }
.announce-tab {
  flex: 1; text-align: center; padding: 10px 12px;
  border-radius: 999px; font-size: 12.5px; font-weight: 800; color: #5c2626;
  transition: background .15s ease, color .15s ease;
}
.announce-tab.is-selected { background: #8b3a3a; color: #fff; }

.announce-page-form { margin-bottom: 12px; }
.announce-page-select {
  appearance: none; width: fit-content; min-width: 180px;
  background-color: var(--white); color: #8b3a3a;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238b3a3a' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center; background-size: 13px;
  border: 1.5px solid #8b3a3a; border-radius: 999px; padding: 9px 38px 9px 16px;
  font-size: 13px; font-weight: 800; cursor: pointer;
  transition: transform .15s ease;
}
.announce-page-select:hover { transform: scale(1.03); }

.announce-list { display: flex; flex-direction: column; gap: 10px; }
.announce-card {
  background: var(--white); border: 1px solid var(--line); border-radius: 16px;
  padding: 14px;
}
.announce-card-top { display: flex; align-items: flex-start; gap: 8px; }
.announce-card-title {
  flex: 1; font-size: 14.5px; font-weight: 800; color: #000;
}
.announce-card-title:hover { text-decoration: underline; }
.announce-deadline-badge {
  flex-shrink: 0; font-size: 10px; font-weight: 800; letter-spacing: .2px;
  padding: 4px 8px; border-radius: 999px;
  background: color-mix(in srgb, var(--u, #8A8F87) 14%, white);
  color: var(--u, #8A8F87);
}
.announce-card-meta { font-size: 11px; color: #000; margin-top: 4px; }
.announce-card-body {
  font-size: 12.5px; line-height: 1.4; color: #000; margin: 8px 0 0;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.announce-card-bottom {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line);
}
.announce-comments-link {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 700; color: #8b3a3a;
  background: rgba(139, 58, 58, .12); border: 1px solid rgba(139, 58, 58, .4);
  padding: 5px 12px; border-radius: 999px;
  transition: background .15s ease, color .15s ease, transform .15s ease;
}
.announce-comments-link:hover { background: #8b3a3a; color: #fff; border-color: #8b3a3a; transform: scale(1.05); }

.announce-action-btn {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; font-weight: 800; padding: 6px 12px; border-radius: 999px; border: none;
  cursor: pointer; transition: transform .12s ease;
}
.announce-action-btn:hover { transform: scale(1.05); }
.announce-action-btn.is-plum { background: #8b3a3a; color: #fff; }
.announce-action-btn.is-plum-pale { background: rgba(139, 58, 58, .16); color: #5c2626; }
.announce-action-btn.is-green { background: #8b3a3a; color: #fff; }

.announce-back-link {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; font-weight: 700; color: #8b3a3a;
  background: var(--white); border: 1.5px solid #8b3a3a;
  padding: 8px 16px; border-radius: 999px; margin-bottom: 14px;
  transition: background .15s ease, transform .15s ease;
}
.announce-back-link:hover { background: #8b3a3a; color: var(--white); transform: scale(1.05); }

.announce-detail-card { padding: 20px; }
.announce-detail-title { font-size: 18px; font-weight: 800; color: #000; margin-bottom: 6px; }
.announce-deadline-badge-lg { display: inline-flex; padding: 7px 12px; font-size: 11.5px; margin-top: 10px; }
.announce-detail-body { font-size: 14px; line-height: 1.5; color: #000; margin: 14px 0 0; }

.announce-comments-title { font-size: 14px; font-weight: 800; color: #000; margin: 18px 0 10px; }
.announce-comments-empty { padding: 18px 16px; font-size: 12.5px; color: #000; }

.announce-comment-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
.announce-comment { background: var(--white); border: 1px solid var(--line); border-radius: 14px; padding: 12px; }
.announce-comment-head { display: flex; align-items: center; gap: 8px; }
.announce-role-tag {
  font-size: 9.5px; font-weight: 800; padding: 3px 8px; border-radius: 999px; flex-shrink: 0;
}
.announce-role-tag.is-division { background: rgba(139, 58, 58, .16); color: #8b3a3a; }
.announce-role-tag.is-teacher { background: rgba(220, 243, 210, .7); color: #2E6B3E; }
.announce-comment-author { flex: 1; font-size: 12.5px; font-weight: 800; color: #000; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.announce-comment-time { font-size: 10.5px; color: #000; flex-shrink: 0; }
.announce-comment-message { font-size: 13px; line-height: 1.4; color: #000; margin: 6px 0; }
/* "@Name" inside a comment -- who this reply is specifically addressed
   to, so it reads clearly in a thread with more than two people in it. */
.mention-tag { color: var(--active-accent, var(--brand)); font-weight: 700; background: color-mix(in srgb, var(--active-accent, var(--brand)) 12%, white); padding: 1px 5px; border-radius: 5px; }

/* @mention autocomplete dropdown -- one shared element (see app.js),
   positioned under whichever comment input currently has focus. */
.mention-dropdown {
  position: fixed; z-index: 500;
  background: var(--white); border: 1.5px solid var(--line); border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0,0,0,.16);
  max-height: 240px; overflow-y: auto; padding: 6px;
}
.mention-dropdown-item {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; text-align: left; background: none; border: none; border-radius: 7px;
  padding: 8px 10px; cursor: pointer; font: inherit;
}
.mention-dropdown-item:hover, .mention-dropdown-item.is-active { background: var(--page-green); }
.mention-dropdown-name { font-size: 13.5px; font-weight: 700; color: #000; }
.mention-dropdown-position {
  font-size: 11px; font-weight: 700; color: var(--muted);
  background: #f2f2f2; padding: 2px 8px; border-radius: 999px; flex-shrink: 0;
}
/* Edit / Delete icons on your own comment or reply. */
.announce-comment-actions { display: inline-flex; align-items: center; gap: 2px; flex-shrink: 0; }
.announce-comment-actions form { display: inline-flex; }
.announce-icon-btn {
  width: 26px; height: 26px; border-radius: 50%; border: none; background: transparent; color: #000;
  display: inline-flex; align-items: center; justify-content: center; padding: 0; cursor: pointer; flex-shrink: 0; font-size: 12px;
  transition: background .12s ease, color .12s ease;
}
.announce-icon-btn:hover { background: rgba(139, 58, 58, .14); color: #8b3a3a; }
.announce-icon-btn.is-danger:hover { background: #fdecea; color: var(--danger); }
.announce-edit-form { margin: 6px 0; }
.announce-edit-form[hidden] { display: none; }

/* Reaction bar -- a small always-visible row of 5 emoji, each its own
   tiny form/button (no JS picker needed for just 5 options), plus the
   aggregated per-emoji counts next to it. */
.announce-reaction-bar { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-top: 4px; }
.announce-reaction-picker { display: flex; gap: 2px; }
.announce-reaction-pick {
  background: none; border: none; cursor: pointer; padding: 3px 5px; border-radius: 8px;
  font-size: 15px; line-height: 1; transition: transform .12s ease, background .12s ease;
}
.announce-reaction-pick:hover { background: var(--page-green); transform: scale(1.2); }
.announce-reaction-pick.is-active { background: rgba(139, 58, 58, .18); }
.announce-reaction-counts { display: flex; gap: 6px; flex-wrap: wrap; }
.announce-reaction-count {
  font-size: 11px; font-weight: 700; color: var(--muted);
  background: var(--page-green); border-radius: 999px; padding: 2px 8px;
}
.announce-reaction-count.is-mine { color: #8b3a3a; background: rgba(139, 58, 58, .5); }

/* Reply -- native <details>/<summary> for the toggle, no JS needed. */
.announce-reply-toggle { margin-top: 8px; }
.announce-reply-toggle summary {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  font-size: 11.5px; font-weight: 700; color: #8b3a3a;
  list-style: none; width: fit-content;
  background: rgba(139, 58, 58, .35); border: 1px solid rgba(139, 58, 58, .3);
  padding: 5px 12px; border-radius: 999px;
  transition: background .15s ease, transform .15s ease;
}
.announce-reply-toggle summary::-webkit-details-marker { display: none; }
.announce-reply-toggle summary:hover { background: rgba(139, 58, 58, .28); transform: scale(1.05); }
.announce-reply-toggle[open] summary { margin-bottom: 8px; }
.announce-reply-form { display: flex; gap: 8px; align-items: center; }
.announce-send-btn-sm { width: 32px; height: 32px; font-size: 13px; }

/* Hide/show the whole comment list -- the "Comments (N)" heading is
   itself the toggle (same native details/summary as Reply above, no JS).
   Defaults open so nothing looks different until someone actually
   collapses it. */
details.announce-comments-toggle summary {
  cursor: pointer; list-style: none; width: fit-content;
}
details.announce-comments-toggle summary::-webkit-details-marker { display: none; }
details.announce-comments-toggle summary::before {
  content: "\25B8\00a0"; font-size: 17px; font-weight: 800; color: var(--active-accent, var(--brand));
  display: inline-block; vertical-align: -2px;
}
details.announce-comments-toggle[open] summary::before { content: "\25BE\00a0"; }
details.announce-comments-toggle summary:hover { opacity: .7; }

/* Hide/show one comment's OWN replies, separate from (and visually
   distinct in color from) the "write a reply" toggle above -- also
   defaults open, since collapsing is an opt-in way to cut down on
   what's on screen, not the new default. */
.announce-replies-toggle { margin-top: 8px; }
.announce-replies-toggle summary {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  font-size: 11px; font-weight: 700; color: var(--muted);
  list-style: none; width: fit-content;
  background: var(--page-green); border: 1px solid var(--line);
  padding: 4px 11px; border-radius: 999px;
  transition: background .15s ease, transform .15s ease;
}
.announce-replies-toggle summary::-webkit-details-marker { display: none; }
.announce-replies-toggle summary:hover { background: color-mix(in srgb, var(--active-accent, var(--brand)) 16%, white); transform: scale(1.05); }

.announce-reply-list { margin: 10px 0 0 22px; padding-left: 12px; border-left: 2px solid var(--line); display: flex; flex-direction: column; gap: 10px; }
.announce-reply { padding: 10px; }

.announce-message-form {
  display: flex; gap: 10px; align-items: center; margin-top: 16px;
  padding: 14px; background: var(--white); border: 1px solid var(--line); border-radius: 16px;
}
.announce-message-input {
  flex: 1; border: 1.5px solid var(--line); border-radius: 999px; padding: 11px 16px;
  background: var(--page-green); font-size: 13.5px; color: #000; font-family: inherit;
}
.announce-message-input:focus { outline: none; border-color: #8b3a3a; background: var(--white); }
.announce-send-btn {
  flex-shrink: 0; width: 38px; height: 38px; border-radius: 50%; border: none;
  background: #8b3a3a; color: #fff; font-size: 15px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: transform .12s ease;
}
.announce-send-btn:hover { transform: scale(1.08); }

/* ---------------------------------------------------------------------- */
/* Notifications -- ported 1:1 from the mobile app's notifications_tab.dart
   and notification_store.dart: same header, All/Unread filter chips, and
   per-category icon color (each one matches that feature's own tab
   accent) on every card. */
/* ---------------------------------------------------------------------- */
.notif-header-card { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 16px; }
.card.notif-header-card { border-color: #5ea849; }
/* Nothing unread -- stays in place (so the header doesn't shift) but greyed out. */
.notif-mark-all-btn.btn-sm { padding: 10px 22px; font-size: 14px; font-weight: 800; }
.notif-mark-all-btn:disabled { color: var(--muted); border-color: var(--line); cursor: default; }
.notif-mark-all-btn:disabled:hover { transform: none; }

.notif-filter-row { display: flex; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
.notif-filter-chip {
  display: inline-flex; align-items: center;
  padding: 10px 22px; border-radius: 999px;
  background: rgba(94, 168, 73, .12); color: #2E6B3E;
  font-size: 14px; font-weight: 800;
  transition: background .15s ease, color .15s ease;
}
.notif-filter-chip.is-selected { background: #5ea849; color: #fff; }

.notif-list { display: flex; flex-direction: column; gap: 8px; }
.notif-card {
  display: flex; align-items: center; gap: 12px;
  background: var(--white); border: 1px solid var(--line); border-radius: 14px; padding: 14px;
}
.notif-card.is-unread {
  background: color-mix(in srgb, var(--cat, #5ea849) 8%, white);
  border: 1.2px solid color-mix(in srgb, var(--cat, #5ea849) 50%, white);
}
.notif-icon {
  width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--cat, #5ea849) 18%, white); color: var(--cat, #5ea849);
}
.notif-icon.is-unread { background: var(--cat, #5ea849); color: #fff; }

/* The icon + body are wrapped in this link (to open the page the
   notification is about) -- display:contents so the anchor itself adds
   no box of its own and its children keep acting as direct flex items of
   .notif-card, exactly as before the link existed. */
.notif-card-link { display: contents; color: inherit; text-decoration: none; cursor: pointer; }
.notif-body { flex: 1; min-width: 0; }
.notif-title-row { display: flex; align-items: flex-start; gap: 6px; }
.notif-title { flex: 1; font-size: 13.5px; font-weight: 600; color: #000; }
.notif-title.is-unread { font-weight: 800; }
.notif-text { font-size: 12px; line-height: 1.4; color: #000; margin: 3px 0 8px; }
.notif-time { font-size: 11px; color: #000; }
/* Sits as its own column at the far right of the whole card, not tucked
   under the body text -- easy to tap without hunting for it. */
.notif-ack-form { flex-shrink: 0; }
.notif-ack-btn {
  display: inline-flex; align-items: center; gap: 4px;
  background: #5ea849; color: #fff; border: none; cursor: pointer;
  padding: 10px 22px; border-radius: 999px; font-size: 14px; font-weight: 800;
  transition: transform .12s ease, background .12s ease;
}
.notif-ack-btn:hover { background: #4e9a3b; transform: scale(1.05); }

/* ---------------------------------------------------------------------- */
/* Settings tab (ported from settings_tab.dart)                          */
/* ---------------------------------------------------------------------- */
.settings-header-card { margin-bottom: 16px; }
.card.settings-header-card { border-color: #7a4fa0; }
.settings-card { margin-bottom: 12px; }
.settings-section-label {
  font-size: 12.5px; font-weight: 800; letter-spacing: .4px; text-transform: uppercase;
  color: #000; margin: 0 0 10px;
}

/* Profile card */
.settings-profile-row { display: flex; align-items: center; gap: 18px; }
.settings-avatar-stack { position: relative; flex-shrink: 0; display: block; }
.settings-avatar-view { all: unset; display: block; cursor: pointer; }
.settings-avatar-view:disabled { cursor: default; }
/* A standing rounded rectangle, not a circle -- keeps the whole photo
   visible (a circle crops the sides off) so it's actually recognizable. */
.settings-avatar {
  width: 74px; height: 90px; border-radius: 12px; object-fit: cover;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--active-accent, var(--brand)) 16%, white);
  color: var(--active-accent, var(--brand)); font-size: 26px; font-weight: 800;
}
.settings-avatar img { width: 100%; height: 100%; border-radius: 12px; object-fit: cover; }
.settings-avatar-camera {
  position: absolute; bottom: -2px; right: -2px; width: 26px; height: 26px; border-radius: 50%;
  background: var(--active-accent, var(--brand)); color: #fff; display: flex; align-items: center;
  justify-content: center; border: 3px solid var(--white); cursor: pointer;
}
.settings-profile-name { font-size: 18px; font-weight: 800; color: #000; margin: 0 0 4px; }
.settings-role-pill {
  display: inline-flex; align-items: center; padding: 3px 12px; border-radius: 999px;
  background: color-mix(in srgb, var(--active-accent, var(--brand)) 14%, white);
  color: var(--active-accent, var(--brand)); font-size: 12px; font-weight: 800; margin-bottom: 6px;
}
.settings-profile-email { display: flex; align-items: center; gap: 6px; font-size: 13.5px; color: #000; }
.settings-profile-email svg { flex-shrink: 0; color: var(--active-accent, var(--brand)); }

/* Info rows (School Info card) */
.settings-info-row { display: flex; align-items: flex-start; gap: 10px; padding: 8px 0; font-size: 14px; color: #000; }
.settings-info-row svg { flex-shrink: 0; margin-top: 1px; color: var(--active-accent, var(--brand)); stroke-width: 2.3; }
.settings-info-row + .settings-info-row { border-top: 1px solid var(--line); }

/* Tiles (Change Password / Change Contact / Logout) */
.settings-tile {
  display: flex; align-items: center; gap: 14px; width: 100%; background: none; border: none;
  padding: 10px 0; cursor: pointer; text-align: left; font: inherit; color: inherit;
}
.settings-tile-icon {
  width: 38px; height: 38px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center;
  justify-content: center; background: color-mix(in srgb, var(--active-accent, var(--brand)) 22%, white);
  color: var(--active-accent, var(--brand));
}
.settings-tile-icon svg { stroke-width: 2.3; }
.settings-tile-body { flex: 1; min-width: 0; }
.settings-tile-title { font-size: 14.5px; font-weight: 700; color: #000; }
.settings-tile-sub { font-size: 12.5px; color: #000; margin-top: 2px; }
.settings-tile-chevron { color: #000; flex-shrink: 0; }
.settings-divider { height: 1px; background: var(--line); margin: 0; }

/* Toggle switch */
.toggle-switch {
  position: relative; width: 44px; height: 26px; border-radius: 999px; border: none; cursor: pointer;
  background: #d9d9d9; flex-shrink: 0; padding: 0; transition: background .15s ease;
}
.toggle-switch.is-on { background: var(--active-accent, var(--brand)); }
.toggle-knob {
  position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.3); transition: left .15s ease;
}
.toggle-switch.is-on .toggle-knob { left: 21px; }

.settings-toggle-row { display: flex; align-items: center; gap: 12px; padding: 8px 0; }
.settings-toggle-row[hidden] { display: none; }
.settings-toggle-row-icon {
  width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center;
  justify-content: center; background: color-mix(in srgb, var(--active-accent, var(--brand)) 22%, white);
  color: var(--active-accent, var(--brand));
}
.settings-toggle-row-icon svg { stroke-width: 2.3; }
.settings-toggle-row-body { flex: 1; min-width: 0; }
.settings-toggle-row-title { font-size: 14px; font-weight: 700; color: #000; }
.settings-toggle-row-sub { font-size: 12px; color: #000; margin-top: 1px; }
.settings-toggle-dimmed { opacity: .4; pointer-events: none; }
.settings-reminder-select {
  flex-shrink: 0; padding: 7px 10px; border-radius: 10px; border: 1.5px solid var(--line);
  background: var(--white); font-size: 13px; font-weight: 700; color: var(--ink); font-family: inherit;
}
.settings-reminder-number {
  width: 64px; flex-shrink: 0; padding: 7px 10px; border-radius: 10px; border: 1.5px solid var(--line);
  background: var(--white); font-size: 13px; font-weight: 700; color: var(--ink); font-family: inherit;
}

/* "Notify Me About" category toggle rows (bell icon + label + switch,
   each keeping that category's own color -- same colors notifications
   use -- via an inline --active-accent override on the switch itself). */
.settings-chip-row { display: flex; flex-direction: column; margin-top: 4px; }

/* Sync status row */
.settings-sync-status { display: flex; align-items: center; gap: 8px; font-size: 13.5px; font-weight: 700; margin: 14px 0 8px; }
.settings-sync-status.is-synced { color: var(--brand); }
.settings-sync-status.is-not-synced { color: var(--danger); }
.settings-sync-note { font-size: 13px; color: #000; line-height: 1.5; margin: 0 0 16px; }

/* About card: a single indented, justified paragraph, with breathing room
   from the card's own edges instead of running flush to them. */
.settings-about { text-align: left; padding: 16px 20px; }
.settings-about p { font-size: 13.5px; color: rgba(0, 0, 0, .88); line-height: 1.6; margin: 0; text-align: justify; text-indent: 26px; }

/* Field-entry modals (Change Password / Change Contact Number) */
.modal-form { max-width: 440px; text-align: left; }
.modal-form h3 { text-align: center; }
.modal-form .field { margin-bottom: 14px; }
.modal-form .field-error { color: var(--danger); font-size: 12.5px; margin: -8px 0 14px; min-height: 1px; }
.modal-form .modal-actions { margin-top: 6px; }

/* ---------------------------------------------------------------------- */
/* SBFP Forms: form-type picker + the printable "excel-like" master list  */
/* ---------------------------------------------------------------------- */
.sbfp-header-card { margin-bottom: 16px; }
.card.sbfp-header-card { border-color: #8b6f3a; }

/* Back link sits on its own line, top-left, above the title -- same
   pattern as Announcements' own back link. */
.sbfp-back-link {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; font-weight: 700; color: var(--white);
  background: var(--active-accent, var(--brand)); border: 1.5px solid var(--active-accent, var(--brand));
  padding: 8px 16px; border-radius: 999px; margin-bottom: 14px;
  box-shadow: 0 4px 10px color-mix(in srgb, var(--active-accent, var(--brand)) 35%, transparent);
  transition: background .15s ease, transform .15s ease;
}
.sbfp-back-link:hover {
  background: color-mix(in srgb, var(--active-accent, var(--brand)) 82%, black);
  transform: scale(1.05);
}

.sbfp-toolbar { display: flex; gap: 10px; align-items: center; }
.sbfp-icon-btn {
  width: 38px; height: 38px; border-radius: 50%; border: none; flex-shrink: 0;
  background: var(--active-accent, var(--brand)); color: #fff;
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  box-shadow: 0 4px 10px color-mix(in srgb, var(--active-accent, var(--brand)) 40%, transparent);
  transition: transform .15s ease;
}
.sbfp-icon-btn:hover { transform: scale(1.08); }
/* Download's icon button opens a small format-choice menu instead of
   downloading directly -- same open/close/outside-click pattern as the
   Beneficiaries tab's own "+ Add" dropdown, dressed up with a per-format
   color badge and a quick pop-in instead of just appearing instantly. */
.sbfp-download-dropdown { position: relative; }
.sbfp-download-menu {
  position: absolute; right: 0; top: calc(100% + 10px); z-index: 30; width: 230px;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop); padding: 8px;
  transform-origin: top right;
  animation: sbfpDownloadPop .14s ease;
}
@keyframes sbfpDownloadPop {
  from { opacity: 0; transform: scale(.94) translateY(-4px); }
  to { opacity: 1; transform: scale(1) translateY(0); }
}
.sbfp-download-section-label {
  font-size: 10px; font-weight: 800; color: var(--muted); text-transform: uppercase;
  letter-spacing: .5px; padding: 8px 10px 6px;
}
.sbfp-download-divider { height: 1px; background: var(--line); margin: 4px 6px; }
.sbfp-download-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; border-radius: var(--radius-md); border: none; background: none;
  font: inherit; font-size: 13.5px; font-weight: 700; color: var(--ink); text-align: left; cursor: pointer;
}
.sbfp-download-item:hover, .sbfp-download-item:focus-visible {
  background: color-mix(in srgb, var(--active-accent, var(--brand)) 10%, white);
}
.sbfp-download-item:disabled { opacity: .5; cursor: default; background: none; }
.content .sbfp-division-submit { background: var(--brand); box-shadow: 0 6px 16px rgba(94, 168, 73, 0.28); }
.content .sbfp-division-submit:hover { background: var(--brand-hover); }
.sbfp-division-disabled:disabled { cursor: not-allowed; color: var(--muted); border-color: #cdd8d1; background: #f3f6f4; }
.sbfp-form-actions { display: flex; justify-content: center; gap: 12px; margin-top: 18px; flex-wrap: wrap; }
.sbfp-add-row-wrap { margin-top: 8px; }
.sbfp-forms-submitted-wrap table.data-table th { text-align: center; }
/* Buttons in the submitted table only grow on hover -- no green fill. */
.sbfp-forms-submitted-wrap .btn-outline:hover { background: var(--white); transform: scale(1.05); }
/* Comment send buttons on SBFP forms use the same accent as the SBFP tab. */
.sbfp-comments .announce-send-btn { background: var(--active-accent, #8b6f3a); }
.sbfp-derived-note { margin-top: 18px; padding: 12px 14px; border-radius: 12px; background: var(--page-green); border: 1px solid var(--line); color: #000; font-size: 13.5px; text-align: left; }
.sbfp-download-badge {
  flex-shrink: 0; width: 36px; height: 26px; border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  font-size: 9.5px; font-weight: 800; color: #fff; letter-spacing: .2px;
}
.sbfp-download-badge.is-csv { background: #2f7a44; }
.sbfp-download-badge.is-xlsx { background: #1d6f42; }
.sbfp-download-badge.is-pdf { background: #c0392b; }
.sbfp-download-badge.is-png, .sbfp-download-badge.is-jpg { background: #2f7a8c; }

.sbfp-form-picker { display: flex; flex-wrap: wrap; gap: 14px; }
.sbfp-form-option {
  display: flex; align-items: center; gap: 12px; flex: 1 1 260px;
  padding: 16px 18px; border-radius: 14px; border: 1.5px solid var(--line);
  background: var(--white); cursor: pointer; text-align: left; font: inherit; color: inherit;
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.sbfp-form-option:hover {
  border-color: var(--active-accent, var(--brand));
  box-shadow: 0 6px 16px color-mix(in srgb, var(--active-accent, var(--brand)) 18%, transparent);
  transform: translateY(-1px);
}
.sbfp-form-option-icon {
  width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--active-accent, var(--brand)) 16%, white);
  color: var(--active-accent, var(--brand));
}
.sbfp-form-option-title { flex: 1; font-size: 14.5px; font-weight: 700; color: #000; }
.sbfp-form-option-sub { font-weight: 400; }
.sbfp-form-option-arrow { color: #000; flex-shrink: 0; }

/* The printable sheet itself -- a compact, gridded, small-font table that
   reads like the actual DepEd Form 1A/1B, not a generic app table. */
.sbfp-sheet { padding: 24px; }

/* Dual letterhead -- DepEd seal + the SBFP "Oplan Kalusugan" program logo,
   the same pairing the real printed form carries. */
.sbfp-sheet-letterhead {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding-bottom: 16px; margin-bottom: 20px; border-bottom: 2px solid var(--line);
}
.sbfp-sheet-letterhead img { height: 60px; width: auto; flex-shrink: 0; }
.sbfp-sheet-letterhead-label { flex: 1; text-align: center; font-size: 14.5px; font-weight: 800; color: #000; letter-spacing: .2px; line-height: 1.35; }

/* Each <p> is a DIRECT grid child (not nested in a per-column wrapper),
   listed left1/right1/left2/right2/... in the template -- real CSS Grid
   auto-placement then pairs them into true grid ROWS, and a grid row
   always sizes to its tallest cell. That's what actually keeps the two
   columns lined up even when one side's text wraps to two lines; two
   independent flex columns side by side (the previous approach) can't
   do that, since neither column knows how tall the other one's row is. */
.sbfp-sheet-head { display: grid; grid-template-columns: 1fr 1fr; gap: 0 32px; margin-bottom: 18px; }
.sbfp-sheet-head p {
  display: flex; align-items: center; gap: 6px; margin: 0; padding: 7px 0; font-size: 13px; color: #000;
  border-bottom: 1px dashed var(--line);
}
.sbfp-sheet-head p strong { flex-shrink: 0; color: #000; font-weight: 700; }
.sbfp-sheet-head p .sbfp-placeholder { color: #000; font-style: italic; }
/* Every SBFP form's data table shares this one class already, so this
   one rule is "apply to all SBFP forms" -- same scroll-box behavior as
   Attendance/Beneficiaries (vertical), on top of the horizontal scroll
   a wide sheet (Form 3's 120 day columns) already needed. The PDF/PNG/JPG
   download buttons already had to work around the horizontal clipping
   (see app.js's restoreScrollWrap) and now also reset max-height the
   same way, so a capture is never cropped to just what's visible. */
.sbfp-sheet-table-wrap {
  overflow-x: auto; overflow-y: auto; overscroll-behavior: contain;
  max-height: clamp(280px, calc(100vh - 540px), 900px);
}
.sbfp-sheet-table-wrap::-webkit-scrollbar { width: 8px; height: 8px; }
.sbfp-sheet-table-wrap::-webkit-scrollbar-thumb { background: #c9d8cf; border-radius: 999px; }
table.sbfp-sheet-table {
  width: 100%; min-width: 1400px; border-collapse: collapse; background: var(--white); font-size: 11.5px;
}
table.sbfp-sheet-table th, table.sbfp-sheet-table td {
  border: 1px solid #444; padding: 5px 6px; text-align: center; vertical-align: middle;
}
table.sbfp-sheet-table thead th { background: #f2f2f2; font-weight: 700; color: #000; line-height: 1.3; }
table.sbfp-sheet-table td.sbfp-cell-name { text-align: left; font-weight: 600; white-space: nowrap; }
/* Excel-style inline editing: an input fills its cell edge-to-edge and
   only shows its own focus ring, so typing straight into the sheet reads
   like a spreadsheet, not a form dropped on top of a table. */
table.sbfp-sheet-table .sbfp-cell-input {
  width: 100%; min-width: 72px; border: none; background: transparent;
  font: inherit; font-size: 11.5px; text-align: center; padding: 2px; border-radius: 4px;
}
table.sbfp-sheet-table .sbfp-cell-input:focus { outline: 2px solid var(--active-accent, var(--brand)); background: var(--white); }
table.sbfp-sheet-table .sbfp-editable-row:has(.sbfp-cell-input:focus) { background: color-mix(in srgb, var(--active-accent, var(--brand)) 6%, white); }
table.sbfp-sheet-table tbody tr:nth-child(even) td { background: #fafafa; }
table.sbfp-sheet-table tbody tr.sbfp-summary-grand-row td { background: #f2f2f2; font-weight: 800; }
/* A row missing Sex/Grade/Date of Birth stays visibly red until every one
   of those is filled in -- this is what the Beneficiaries tab's own
   "N beneficiaries missing data" banner links straight into. */
table.sbfp-sheet-table tbody tr.sbfp-row-missing td { background: #fdecea; }
table.sbfp-sheet-table tbody tr.sbfp-row-missing:nth-child(even) td { background: #fbe0dd; }
/* A learner 5 years old or below has a blank BMI/BMI-A by design (BMI
   only applies from 6 up) -- shown in blue rather than red so it never
   reads as the same kind of problem as an actually-missing field. */
table.sbfp-sheet-table tbody tr.sbfp-row-bmi-exempt td { background: #e8f1fc; }
/* Every one of Form 3's 120 day cells is the same fixed width, so the
   grid reads as an even grid regardless of which cells happen to hold a
   wider code like "H/N+M2" vs a blank or single "A". */
table.sbfp-sheet-table .sbfp-day-col {
  width: 30px; min-width: 30px; max-width: 30px; padding: 5px 2px;
  font-size: 10.5px; line-height: 1.25; word-break: keep-all;
}
/* Each day column is one Morning code stacked over one Afternoon code
   (matching the Attendance tab's own AM/PM session split) rather than a
   single merged code -- a thin rule between them is the only thing that
   separates the two stacked values within the same fixed-width cell. */
.sbfp-day-col .sbfp-day-am { padding-bottom: 3px; min-height: 1.25em; }
.sbfp-day-col .sbfp-day-pm { border-top: 1px solid #ccc; padding-top: 3px; min-height: 1.25em; }
th.sbfp-day-subhead { font-size: 9px; font-weight: 700; color: var(--muted); line-height: 1.5; padding: 3px 2px; }
.sbfp-form3-legend { margin-top: 14px; padding: 10px 12px; background: #f8f8f8; border-radius: 8px; }
.sbfp-form3-legend div { font-size: 11.5px; color: #000; line-height: 1.6; }
/* Footnote under a sheet's table -- prints with the form. */
.sbfp-sheet-note { margin: 12px 0 0; font-size: 12px; line-height: 1.45; color: #333; }
.sbfp-sheet-note.is-danger { background: #fdecea; border: 1px solid var(--danger); color: #b3261e; padding: 8px 12px; border-radius: 8px; }
.sbfp-sheet-note.is-info { background: #e8f1fc; border: 1px solid #4a90d9; color: #1a5ba8; padding: 8px 12px; border-radius: 8px; }
.sbfp-sheet-note + .sbfp-sheet-note { margin-top: 8px; }
.sbfp-sheet-footer { margin-top: 26px; }
.sbfp-sheet-footer p { margin: 3px 0; font-size: 13px; color: #000; }
.sbfp-sheet-signee { font-weight: 800; margin-top: 28px !important; }
/* Once a Principal has actually approved it, their name renders as the
   "signature" itself (a script-ish weight/italic reads as signed rather
   than typed), with the role label underneath like a real signature block. */
.sbfp-sheet-signee.is-signed { font-size: 17px; font-style: italic; color: var(--brand); margin-top: 22px !important; }
.sbfp-sheet-signee-role { font-weight: 700; font-size: 12px; color: var(--muted); margin-top: 2px !important; }
@media print {
  .sbfp-sheet { padding: 0; box-shadow: none; border: none; }
  /* Most forms (1A/1B, 2A/2B, 4, 5, 6) print this wrap directly -- only
     3A/3B have a separate .sbfp-print-chunks fallback. Printing must
     always see the whole table, never just whatever fit in the on-screen
     scroll box, so the scroll-box sizing is undone here for every form,
     not only the ones with that fallback. */
  .sbfp-sheet-table-wrap { max-height: none; overflow: visible; }
}

/* Instant hover tooltips: browsers add a long native delay to title=,
   so icon-only controls (Print/Download, sidebar toggles, reaction
   picks) use data-tooltip= instead, shown immediately on hover/focus. */
[data-tooltip] { position: relative; }
[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%) translateY(3px);
  background: rgba(20, 20, 20, 0.92);
  color: #fff;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  padding: 5px 9px;
  border-radius: 6px;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.08s ease, transform 0.08s ease;
  z-index: 1000;
}
[data-tooltip]:hover::after, [data-tooltip]:focus-visible::after {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
}
/* The generic [data-tooltip] { position: relative } rule above would
   otherwise clobber this button's own position: fixed (same specificity,
   later rule wins) and drop it into normal flow, pushing the whole page
   down whenever the sidebar is collapsed -- an ID selector always outranks
   that regardless of source order, so it stays fixed. */
#sidebarOpenBtn[data-tooltip] { position: fixed; }
.sidebar-open-btn[data-tooltip]::after, .sidebar-close-btn[data-tooltip]::after {
  bottom: auto;
  top: calc(100% + 8px);
  left: 0;
  transform: translateY(-3px);
}
.sidebar-open-btn[data-tooltip]:hover::after, .sidebar-open-btn[data-tooltip]:focus-visible::after,
.sidebar-close-btn[data-tooltip]:hover::after, .sidebar-close-btn[data-tooltip]:focus-visible::after {
  transform: translateY(0);
}

/* ---------------------------------------------------------------------- */
/* Documentation -- feeding program photo gallery, grouped by day         */
/* ---------------------------------------------------------------------- */
.doc-header-card { border-color: #2f8c6a; margin-bottom: 16px; }
.doc-photo-preview-row {
  display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px;
}
.doc-photo-preview-thumb {
  width: 64px; height: 64px; object-fit: cover; border-radius: 10px;
  border: 1px solid var(--line);
}
.doc-week-card { margin-bottom: 12px; }
.doc-week-card.is-pending { border-left: 4px solid var(--gold); }
.doc-week-card.is-approved { border-left: 4px solid var(--button-green); }
/* Each feeding day is its own <details> -- native, zero-JS collapse, and
   sharing one `name` attribute per week makes them a true accordion
   (opening one closes whichever other day was open), a browser feature
   with no JS needed to coordinate it. Today's day defaults open. */
.doc-subday {
  margin-top: 14px; border: 1.5px solid var(--line); border-radius: var(--radius-md);
  padding: 14px 16px; background: var(--white);
}
.doc-subday-label { font-size: 14px; font-weight: 800; color: var(--ink); }
.doc-subday-caret { flex-shrink: 0; color: var(--ink); transition: transform .15s ease; vertical-align: middle; }
.doc-subday[open] .doc-subday-caret { transform: rotate(90deg); }
.status-pill.is-sm { padding: 2px 9px; font-size: 11px; }
.doc-day-head {
  display: flex; align-items: center; flex-wrap: wrap; justify-content: space-between; gap: 10px;
  margin: -14px -16px 14px; padding: 14px 16px; cursor: pointer; list-style: none;
}
.doc-day-head::-webkit-details-marker { display: none; }
.doc-subday[open] .doc-day-head { border-bottom: 1px solid var(--line); margin-bottom: 14px; }
.doc-day-head-right { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.doc-day-date { margin-left: 10px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
.doc-day-count { font-size: 12.5px; font-weight: 700; color: var(--muted); }
.doc-photo-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 14px;
}
.doc-photo-card {
  background: var(--white); border: 1px solid var(--line); border-radius: 14px;
  overflow: hidden; display: flex; flex-direction: column;
  transition: box-shadow .15s ease, transform .15s ease;
}
.doc-photo-card:hover { box-shadow: var(--shadow-pop); transform: translateY(-2px); }
.doc-photo-thumb {
  all: unset; display: block; cursor: pointer; aspect-ratio: 1 / 1; overflow: hidden; background: #f1f1f1;
}
.doc-photo-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .2s ease; }
.doc-photo-thumb:hover img { transform: scale(1.06); }
.doc-photo-thumb:disabled { cursor: default; }
.doc-photo-broken {
  width: 100%; height: 100%; display: none; align-items: center; justify-content: center;
  text-align: center; padding: 10px; font-size: 12px; font-weight: 700; color: var(--muted);
  background: #f1f1f1;
}
.doc-photo-caption {
  margin: 10px 12px 0; font-size: 12.5px; font-weight: 600; color: var(--ink);
  line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.doc-photo-meta {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-top: auto; padding: 8px 12px 10px; font-size: 11px; font-weight: 700; color: var(--muted);
}
.doc-photo-uploader { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.doc-future-note { color: #000; font-size: 13px; margin: 4px 0 0; }
.doc-upload-form { background: var(--page-green); border: 1px solid var(--line); border-radius: 14px; padding: 14px; margin-bottom: 14px; }
.doc-history-card { margin-top: 18px; }
.doc-day-comments { margin-top: 16px; padding-top: 14px; border-top: 1px dashed var(--line); }
.doc-day-comments-title { font-size: 13px; font-weight: 800; color: var(--ink); margin-bottom: 10px; }

/* The comment widget markup is shared with Announcements/SBFP Forms (the
   .announce-* classes), which are themed in Announcements' own maroon
   (#8b3a3a). Scoped here to Documentation's own tab color (#2f8c6a)
   instead, so borders/accents/the send button all read as part of this
   tab rather than a leftover Announcements look. Destructive actions
   (delete) stay the app's universal danger red on purpose. */
.doc-day-comments .announce-role-tag.is-division { background: rgba(47, 140, 106, .16); color: #2f8c6a; }
.doc-day-comments .announce-icon-btn:hover { background: rgba(47, 140, 106, .14); color: #2f8c6a; }
.doc-day-comments .announce-reaction-pick.is-active { background: rgba(47, 140, 106, .18); }
.doc-day-comments .announce-reaction-count.is-mine { color: #2f8c6a; background: rgba(47, 140, 106, .3); }
.doc-day-comments .announce-reply-toggle summary {
  color: #2f8c6a; background: rgba(47, 140, 106, .14); border-color: rgba(47, 140, 106, .3);
}
.doc-day-comments .announce-reply-toggle summary:hover { background: rgba(47, 140, 106, .22); }
.doc-day-comments .announce-message-input:focus { border-color: #2f8c6a; }
.doc-day-comments .announce-message-form { border-color: rgba(47, 140, 106, .35); }
.doc-day-comments .announce-comment { border-color: rgba(47, 140, 106, .2); }
.doc-day-comments .announce-send-btn { background: #2f8c6a; }

/* ---------------------------------------------------------------------- */
/* Page headings: drop the card container so each page's title sits      */
/* straight on the page background. Kept last so it wins over the        */
/* per-page *-header-card rules above.                                    */
/* ---------------------------------------------------------------------- */
.card.home-header-card, .att-header-card, .card.bene-header-card,
.card.mealplan-header-card, .card.announce-header-card, .card.notif-header-card,
.card.settings-header-card, .card.sbfp-header-card, .card.doc-header-card {
  background: none; border: 0; border-radius: 0; box-shadow: none; padding: 0;
}


/* ---------------------------------------------------------------------- */
/* Responsive: tablets and phones (900px and below)                       */
/* The sidebar turns into a slide-in drawer over the page instead of      */
/* taking 258px of width, opened by the (now always visible) open button. */
/* Page header rows, toolbars and two-column grids wrap or stack so       */
/* nothing runs off the right edge; wide tables keep scrolling sideways   */
/* inside their own .table-wrap.                                          */
/* ---------------------------------------------------------------------- */
.sidebar-backdrop { display: none; }

@media (max-width: 900px) {
  .sidebar {
    position: fixed; left: 0; top: 0; z-index: 600;
    height: 100vh; height: 100dvh; max-width: 85vw; overflow-y: auto;
    transform: translateX(-100%); transition: transform .22s ease;
    box-shadow: 6px 0 24px rgba(22, 35, 27, 0.18);
  }
  /* On a small screen the sidebar is always "collapsed" out of the
     layout; .is-drawer-open slides it in on top instead. */
  .app-shell.is-collapsed .sidebar { display: flex; }
  .app-shell.is-drawer-open .sidebar { transform: none; }
  .app-shell.is-drawer-open .sidebar-backdrop {
    display: block; position: fixed; inset: 0; z-index: 550;
    background: rgba(22, 35, 27, 0.35);
  }
  .sidebar-open-btn { opacity: 1; top: 12px; left: 12px; }

  .content { padding: 64px 12px 20px; min-height: 100dvh; }
  .content.content-fixed-page { height: 100vh; height: 100dvh; }

  /* Header and toolbar rows: let them wrap instead of overflowing. */
  .notif-header-card, .bene-header-with-total, .bene-title-row, .att-header-card,
  .mealplan-table-titlebar, .program-detail-row, .att-locked-banner, .bene-select-bar,
  .announce-card-bottom, .sbfp-sheet-letterhead, .doc-day-head, .home-header-card {
    flex-wrap: wrap;
  }
  .att-header-side { flex-direction: row; align-items: center; }
  .sbfp-sheet-head { grid-template-columns: 1fr; }
  .card { padding: 16px; }
  .home-header-title, .att-header-title { font-size: 17px; }
  .bene-header-card, .mealplan-header-card, .announce-header-card { font-size: 16px; }
}

@media (max-width: 560px) {
  .content { padding-left: 10px; padding-right: 10px; }
  .btn { padding: 9px 16px; }
  .modal { max-width: calc(100vw - 32px); padding: 22px 18px 18px; }
  .notif-card { flex-wrap: wrap; }
  .notif-ack-form { width: 100%; display: flex; justify-content: flex-end; }
  .pw-rules { grid-template-columns: 1fr; }
}

/* Short windows (laptops, landscape tablets/phones): tighten the sidebar
   so the whole nav, profile and Log Out usually fit without scrolling. */
@media (max-height: 820px) {
  .sidebar { padding: 14px 12px; }
  .sidebar-close-btn { margin-bottom: 8px; }
  .sidebar-brand { gap: 8px; padding: 4px 8px 12px; margin-bottom: 6px; }
  .sidebar-brand .brand-logo { width: 40px; height: 40px; }
  .sidebar-brand .brand-row strong { font-size: 19px; }
  .nav-item { padding: 7px 12px; font-size: 14px; }
  .nav-item .nav-icon-dot { width: 26px; height: 26px; }
  .nav-item .nav-icon-dot svg { width: 15px; height: 15px; }
  .sidebar-footer { padding-top: 6px; }
  .sidebar-profile { padding: 6px 12px; margin: 2px 0; }
}
@media (max-height: 640px) {
  .nav-list { gap: 1px; }
  .nav-item { padding: 5px 10px; }
  .sidebar-brand .brand-school { padding: 5px 10px; font-size: 12px; }
}

/* Phones: the 1 | 2 pair fits an ~80px meal column. */
@media (max-width: 560px) {
  .att-serve-btn { width: 36px; height: 38px; }
}

/* ---------------------------------------------------------------------- */
/* Attendance roster table (replaces the one-card-per-student list).      */
/* # | Learner | Nutritional Status | Hot Meal | NFP | Milk | Attendance, */
/* one header row. The header and the #/Learner columns stay put while the */
/* table scrolls, so the column names and the learner's name are always  */
/* in view. Overrides the old card styling of .att-student-row /          */
/* .att-field-row / .att-field-cell, which the rows still carry for JS.   */
/* ---------------------------------------------------------------------- */
.att-table-wrap {
  overflow: auto; overscroll-behavior: contain;
  max-height: max(380px, calc(100vh - 260px)); max-height: max(380px, calc(100dvh - 260px));
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-md);
}
.att-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px; }
.att-table thead { position: sticky; top: 0; z-index: 3; }
.att-table thead th {
  background: #f3f8f6; color: var(--ink); font-size: 12px; font-weight: 800;
  text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--line); white-space: nowrap;
}
.att-table thead .att-col-meal, .att-table thead .att-col-attendance, .att-table thead .att-col-num { text-align: center; }

.att-table td, .att-table tbody th {
  padding: 8px 10px; border-bottom: 1px solid var(--line); vertical-align: middle;
  background: var(--white); text-align: left; font-weight: normal;
}
.att-table .att-col-num { width: 40px; text-align: center; color: var(--muted); font-weight: 700; }
.att-table .att-col-meal, .att-table .att-meal-cell, .att-table .att-col-attendance { width: 104px; text-align: center; }

/* Rows: drop the old card look; the tint goes on the cells instead, and
   the grade's color becomes a stripe down the row's left edge. */
.att-table .att-student-row { background: none; border: 0; border-radius: 0; padding: 0; margin: 0; }
.att-table tbody tr.att-field-row:not([hidden]) { display: table-row; }
.att-table .att-student-row > :first-child { box-shadow: inset 4px 0 0 var(--group-color, var(--line)); }
.att-table .att-student-row.is-editable.is-present > * { background: var(--soft-green); }
.att-table .att-student-row.is-present:not(.is-editable) > * { background: #eaf3fc; }
.att-table .att-student-row.is-absent:not(.is-editable) > * { background: #fdecea; }

/* Grade/section header: one full-width row per group. */
.att-table .att-group-label { background: none; border: 0; padding: 0; margin: 0; }
.att-table .att-group-label th {
  background: color-mix(in srgb, var(--group-color, var(--brand)) 12%, white);
  color: var(--group-color, var(--button-green));
  box-shadow: inset 4px 0 0 var(--group-color, var(--brand));
  font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .3px;
  padding: 8px 14px;
}

/* #/Learner stay pinned on the left when the table scrolls sideways. */
.att-table .att-col-num { position: sticky; left: 0; z-index: 1; }
.att-table .att-col-learner { position: sticky; left: 40px; z-index: 1; }
.att-table thead .att-col-num, .att-table thead .att-col-learner { z-index: 4; }
.att-learner { display: flex; align-items: center; gap: 10px; min-width: 170px; }
/* Grade & Section column (only on the ungrouped "All grades" list). */
.att-table .att-col-section { white-space: nowrap; }
.att-table .att-avatar { width: 32px; height: 38px; font-size: 12px; }
.att-table .att-status-line { margin-top: 0; }

/* Checkbox cells: the whole cell is the click/drag target. */
.att-table td.att-field-cell { display: table-cell; min-width: 0; }
.att-cell-stack { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.att-table .badge { min-width: 70px; text-align: center; }
.att-meal-served { color: #2f7a8c; font-weight: 800; }
.att-meal-none { color: var(--muted); }

/* Phones: drop the Nutritional Status column (a red dot by the name
   flags an at-risk learner instead) and tighten the cells; anything
   still too wide scrolls sideways with the name pinned. */
@media (max-width: 560px) {
  .att-table .att-col-status { display: none; }
  .att-table td, .att-table tbody th, .att-table thead th { padding: 6px 6px; }
  .att-table .att-col-meal, .att-table .att-meal-cell, .att-table .att-col-attendance { width: 80px; }
  .att-learner { min-width: 120px; gap: 6px; }
  .att-table:not(.bene-table) .att-avatar { display: none; }
  .att-table .is-at-risk .att-student-name::before {
    content: ""; display: inline-block; width: 8px; height: 8px; border-radius: 50%;
    background: var(--danger); margin-right: 5px; vertical-align: middle;
  }
}

/* Screen-reader-only text (e.g. a header for a column of buttons). */
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------------------- */
/* Beneficiaries roster table -- shares the Attendance table's look      */
/* (.att-table); these only undo the old card styling of                  */
/* .bene-roster / .bene-student-row and add the Edit + select columns.    */
/* ---------------------------------------------------------------------- */
.bene-table.bene-roster { display: table; }
.att-table .bene-student-row { background: none; border: 0; border-radius: 0; padding: 0; gap: 0; }
.att-table .bene-student-row:not([hidden]) { display: table-row; }
.att-table .bene-student-row > :first-child { box-shadow: inset 4px 0 0 var(--group-color, var(--line)); }
.bene-table .bene-col-edit { width: 1%; text-align: right; white-space: nowrap; }
.bene-table .bene-avatar-stack { flex-shrink: 0; }
/* Delete mode: the # cell shows the select checkbox instead of the number. */
.bene-table .bene-select-checkbox { margin: 0 auto; }
.bene-table.is-selecting .bene-row-num { display: none; }
.bene-table .bene-student-row:has(.bene-select-checkbox:checked) > * { background: #fdecea; }

/* Announcements: the list scrolls inside one framed box (same frame as
   the Attendance/Beneficiaries tables) instead of loose on the page. */
.announce-scroll-box {
  background: var(--page-green); border: 1px solid var(--line); border-radius: var(--radius-md);
  padding: 10px; margin-bottom: 4px;
}
.announce-scroll-box > .card { box-shadow: none; }

/* Stretches the header card + main card down to the bottom of the
   viewport (only .content's own 20px padding left below), instead of the
   fixed "-260px" guess the Attendance table uses -- computed by flex so it
   stays right no matter how tall the tabbar/filter row above it is. */
.announce-page-fill { display: flex; flex-direction: column; min-height: calc(100vh - 40px); }
.announce-page-fill > .card.announce-header-card { flex-shrink: 0; }
.announce-page-fill > .card.bene-main-card { display: flex; flex-direction: column; flex: 1; min-height: 0; margin-bottom: 0; }
.announce-page-fill .announce-scroll-box { flex: 1; min-height: 0; max-height: none; }
