/* ─── KAL Portal — Design System (V2 "Warm Notebook") ───
   Cream canvas, paper surfaces, Josefin Sans, coral + green accents.
   Class names preserved from the previous system so every page inherits
   the new look without markup changes.
*/

/* ═══════════════════════════════════
   JOSEFIN SANS — self-hosted
   ═══════════════════════════════════ */

@font-face {
  font-family: 'Josefin Sans';
  src: url('/fonts/JosefinSans-Light.ttf') format('truetype');
  font-weight: 300; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Josefin Sans';
  src: url('/fonts/JosefinSans-Regular.ttf') format('truetype');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Josefin Sans';
  src: url('/fonts/JosefinSans-Italic.ttf') format('truetype');
  font-weight: 400; font-style: italic; font-display: swap;
}
@font-face {
  font-family: 'Josefin Sans';
  src: url('/fonts/JosefinSans-SemiBold.ttf') format('truetype');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Josefin Sans';
  src: url('/fonts/JosefinSans-Bold.ttf') format('truetype');
  font-weight: 700; font-style: normal; font-display: swap;
}

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

:root {
  /* Brand — coral logo red */
  --kal-coral: #d94f3a;
  --kal-coral-deep: #b83e2c;
  --kal-coral-soft: #f4b8ad;
  --kal-coral-tint: #fbe8e4;
  --kal-coral-wash: #fdf3f0;

  /* Success green — Completed */
  --kal-green: #4a9f5f;
  --kal-green-deep: #2f7a42;
  --kal-green-soft: #b7dcc1;
  --kal-green-tint: #e6f3ea;

  --kal-amber: #d98f2e;
  --kal-amber-tint: #fbecd1;

  /* Warm neutrals — ink over cream */
  --ink-900: #1d1813;
  --ink-800: #2c251e;
  --ink-700: #4a3f34;
  --ink-500: #7a6d5f;
  --ink-400: #9b8f7f;
  --ink-300: #c4b9a8;
  --ink-200: #e2dbce;
  --ink-100: #efeae0;
  --ink-50:  #f7f3ea;

  --cream:   #f5ead7;   /* page canvas */
  --paper:   #fffaf2;   /* card / panel surface */
  --white:   #ffffff;

  --border: #e8e0d1;
  --border-strong: #d4c9b4;

  /* Legacy aliases — keep existing selectors working */
  --brand: var(--kal-coral);
  --brand-dark: var(--kal-coral-deep);
  --brand-light: var(--kal-coral-tint);
  --brand-50: var(--kal-coral-wash);
  --brand-10: rgba(217, 79, 58, 0.12);

  --text: var(--ink-900);
  --text-primary: var(--ink-900);
  --text-secondary: var(--ink-700);
  --text-light: var(--ink-500);

  --bg: var(--cream);
  --border-light: var(--ink-100);

  --success: var(--kal-green);
  --warning: var(--kal-amber);
  --danger: var(--kal-coral);
  --info: #0f6b8c;
  --purple: #6C5CE7;

  --shadow-xs: 0 1px 0 rgba(45, 35, 25, 0.04);
  --shadow-sm: 0 1px 2px rgba(45, 35, 25, 0.06), 0 1px 1px rgba(45, 35, 25, 0.04);
  --shadow: 0 4px 12px rgba(45, 35, 25, 0.08), 0 1px 3px rgba(45, 35, 25, 0.06);
  --shadow-md: 0 4px 12px rgba(45, 35, 25, 0.08), 0 1px 3px rgba(45, 35, 25, 0.06);
  --shadow-lg: 0 12px 32px rgba(45, 35, 25, 0.1), 0 2px 6px rgba(45, 35, 25, 0.06);

  --radius-xs: 4px;
  --radius-sm: 6px;
  --radius: 10px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 20px;

  /* Display / branding — Josefin Sans (self-hosted above). Used on
     all headings, the page-title-header, group + centre headers, and
     anywhere we want the wordmark feel. Body / data text uses
     --font-body (Open Sans) — switched off Josefin 2026-04-28 because
     its wide tracking + low x-height made small data hard to read.
     Tried Nunito Sans first; its x-height was too high (data felt
     chunky even after dropping a px), so moved to Open Sans which
     sits between the two and reads cleanly at 13 px. */
  --font: 'Josefin Sans', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  --font-body: 'Open Sans', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;

  /* Font-size scale.
     Originally even-integer-only because Josefin Sans's sub-pixel
     hinting was choppy at 11/13/15 px. After 2026-04-28 Nunito Sans
     became the body font and that constraint no longer applies — Nunito
     hints cleanly at every integer. Body / data tokens dropped 1 px to
     compensate for Nunito's higher x-height (a glyph at 14 px Nunito
     reads visibly bigger than the same glyph at 14 px Josefin).
     Heading tokens (--fs-xl and up) are untouched because they're
     still Josefin and the optical size is correct.
     If we ever swap the body font again, revisit this scale. */
  --fs-2xs:  10px;   /* micro labels, status ticks, caret */
  --fs-xs:   11px;   /* tiny metadata / badges */
  --fs-sm:   12px;   /* small text, button-sm, form labels */
  --fs-md:   13px;   /* secondary info, filter chips */
  --fs-base: 13px;   /* body default, table cells, summary preview */
  --fs-lg:   15px;   /* page-intro, card titles, form inputs */
  --fs-nav:  15px;   /* top nav, primary menu */
  --fs-xl:   18px;   /* h3, card values, subheads */
  --fs-2xl:  20px;   /* filter modal h3 */
  --fs-3xl:  22px;   /* filter modal close, mobile h1 */
  --fs-4xl:  22px;   /* filter-modal overlay title */
  --fs-5xl:  24px;   /* mobile page-title h2 */
  --fs-h2:   26px;   /* desktop h2 */
  --fs-hero: 30px;   /* welcome banner */
  --fs-page: 30px;   /* page-title-header h2 */
  --fs-err:  36px;   /* error-page h1 */
  --fs-caret: 10px;  /* dropdown caret glyph */
}

body {
  font-family: var(--font-body);
  background: var(--cream);
  background-image:
    radial-gradient(circle at 20% 10%, rgba(217, 79, 58, 0.04), transparent 40%),
    radial-gradient(circle at 80% 90%, rgba(74, 159, 95, 0.05), transparent 40%);
  background-attachment: fixed;
  color: var(--ink-700);
  min-height: 100vh;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-size: var(--fs-base);
}

a { color: inherit; text-decoration: none; }

/* ─── HEADER + BRAND TYPE LOCK ──────────────────────────────────────
   Body / data text inherits --font-body (Nunito Sans). These are the
   only places where Josefin Sans should appear — anything that's
   header-shaped, brand-shaped, or display-shaped. Add a class here
   when introducing a new heading-style element so it picks up
   Josefin without needing per-page font-family overrides.

   Rule of thumb: if it's a label, a column heading, a data cell, a
   button, a paragraph of prose, or a form value — leave it on
   --font-body. If it's a title, a section heading, a wordmark, or
   the centre/group banner that anchors a section — use --font.
   ──────────────────────────────────────────────────────────────── */
h1, h2, h3, h4, h5, h6,
.page-title-header h2,
.group-header,
.centre-header,
.brand,
.wordmark {
  font-family: var(--font);
}

/* ═══════════════════════════════════
   PAGE LOADER
   ═══════════════════════════════════ */

.page-loader {
  position: fixed; inset: 0; z-index: 9999;
  background: var(--cream);
  display: flex; align-items: center; justify-content: center;
  transition: opacity 0.3s ease;
}
.page-loader.hidden { opacity: 0; pointer-events: none; }
.loader-logo { width: 80px; height: auto; animation: loader-bounce 1s ease-in-out infinite; }
@keyframes loader-bounce {
  0%, 100% { transform: translateY(0) scale(1); }
  30% { transform: translateY(-24px) scale(1.05); }
  50% { transform: translateY(0) scale(0.95); }
  70% { transform: translateY(-10px) scale(1.02); }
}

/* ═══════════════════════════════════
   TOP NAVIGATION
   ═══════════════════════════════════ */

.top-nav {
  display: flex; align-items: center;
  background: var(--paper);
  border-bottom: 2px solid var(--kal-coral);
  padding: 0 1.75rem;
  height: 64px;
  position: sticky; top: 0; z-index: 100;
  box-shadow: var(--shadow-sm);
  gap: 1.25rem;
}

.nav-brand { display: flex; align-items: center; flex: 0 0 auto; }
.nav-logo { height: 36px; width: auto; display: block; }

.nav-items {
  display: flex; align-items: center;
  gap: 0.15rem; flex: 1; justify-content: center;
}

.nav-link {
  color: var(--ink-700);
  padding: 0.45rem 0.9rem;
  font-size: var(--fs-nav);
  font-weight: 600;
  border-radius: 8px;
  transition: all 0.15s;
  white-space: nowrap;
  letter-spacing: 0.01em;
}

.nav-link:hover { color: var(--kal-coral); background: var(--kal-coral-wash); }
.nav-link.active {
  color: var(--kal-coral);
  background: var(--kal-coral-wash);
  font-weight: 600;
}

.nav-logout { color: var(--ink-500); font-size: var(--fs-base); }
.nav-logout:hover { color: var(--kal-coral); background: transparent; }

.caret { font-size: var(--fs-caret); opacity: 0.6; margin-left: 2px; }
.caret::after { content: '▾'; }

.nav-dropdown { position: relative; }
.dropdown-menu {
  display: none;
  position: absolute;
  top: calc(100% + 4px); left: 0;
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: 10px;
  min-width: 190px;
  box-shadow: var(--shadow-lg);
  z-index: 200;
  padding: 0.3rem 0;
  overflow: hidden;
}
.nav-dropdown:hover .dropdown-menu { display: block; }
.dropdown-menu a {
  display: block;
  padding: 0.55rem 1rem;
  color: var(--ink-800);
  font-size: var(--fs-base);
  white-space: nowrap;
  transition: all 0.1s;
}
.dropdown-menu a:hover { background: var(--kal-coral-wash); color: var(--kal-coral); }

.nav-user-menu { flex: 0 0 auto; }
.nav-user-menu .nav-link { color: var(--ink-700); }
.nav-user-menu .nav-link::before {
  content: '';
  display: inline-block;
  width: 8px; height: 8px; border-radius: 999px;
  background: var(--kal-green);
  margin-right: 8px;
  vertical-align: middle;
}

/* ═══════════════════════════════════
   CENTRE & DATE SELECTORS (Home only)
   ═══════════════════════════════════ */

.centre-bar {
  background: var(--paper);
  padding: 0.6rem 1.5rem;
  border-bottom: 1px solid var(--border);
  display: flex; justify-content: center;
  /* Pin under the 64px-tall .top-nav. One lower z-index so the user
     dropdown in the nav still renders above the centre bar when open. */
  position: sticky;
  top: 64px;
  z-index: 99;
  box-shadow: 0 1px 0 rgba(45, 35, 25, 0.04);
}
.centre-tabs { display: flex; gap: 0.3rem; flex-wrap: wrap; justify-content: center; }
.centre-tab {
  padding: 0.35rem 0.85rem;
  font-size: var(--fs-md);
  font-weight: 500;
  color: var(--ink-700);
  border-radius: 999px;
  border: 1px solid transparent;
  transition: all 0.15s;
}
.centre-tab:hover { background: var(--kal-coral-wash); color: var(--kal-coral); border-color: var(--kal-coral-soft); }
.centre-tab.active {
  background: var(--kal-coral);
  color: var(--white);
  font-weight: 600;
  border-color: var(--kal-coral);
  box-shadow: 0 2px 6px rgba(217, 79, 58, 0.25);
}

.date-bar {
  display: flex;
  border-bottom: 1px solid var(--border);
  background: var(--paper);
}
.year-selector {
  display: flex; gap: 0.15rem;
  justify-content: flex-end;
  flex: 1;
  padding: 0.5rem 0.75rem 0.5rem 1rem;
  background: var(--ink-50);
  align-items: center;
}
.month-selector {
  display: flex; gap: 0.15rem;
  justify-content: flex-start;
  flex: 1;
  padding: 0.5rem 1rem 0.5rem 0.75rem;
  align-items: center;
}
.year-tab, .month-tab {
  padding: 0.3rem 0.7rem;
  font-size: var(--fs-md);
  font-weight: 500;
  color: var(--ink-500);
  border-radius: 999px;
  transition: all 0.15s;
}
.year-tab:hover, .month-tab:hover { color: var(--ink-800); background: var(--ink-100); }
.year-tab.active { background: var(--kal-coral-tint); color: var(--kal-coral-deep); font-weight: 700; }
.month-tab.active { background: var(--kal-coral); color: var(--white); font-weight: 600; }

/* ═══════════════════════════════════
   MAIN CONTENT
   ═══════════════════════════════════ */

.main-content {
  padding: 2rem 2.5rem 3rem;
  max-width: 1600px;
  margin: 0 auto;
  text-align: center;
}

.main-content .data-table,
.main-content .form-card,
.main-content .group-section,
.main-content .notes-grid,
.main-content .filter-tabs,
.main-content .toolbar,
.main-content .note-card,
.main-content .note-content,
.main-content form,
.main-content p,
.main-content ul,
.main-content ol {
  text-align: left;
}

h2 {
  font-size: var(--fs-h2);
  font-weight: 700;
  color: var(--ink-900);
  letter-spacing: -0.02em;
  margin-bottom: 1rem;
  text-align: center;
}

h3 {
  font-size: var(--fs-xl);
  font-weight: 600;
  color: var(--ink-700);
  margin: 1.5rem 0 0.75rem;
  text-align: center;
}

h4 {
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--ink-800);
}

/* ═══════════════════════════════════
   PAGE TITLE HEADER (w/ brushy underline)
   ═══════════════════════════════════ */

.page-title-header {
  margin: 0 0 1.75rem;
  padding: 0 0 0.75rem;
  text-align: center;
  border-bottom: 1px dashed var(--border-strong);
}

.page-title-header h2 {
  position: relative;
  display: inline-block;
  margin: 0;
  font-size: var(--fs-page);
  font-weight: 700;
  letter-spacing: -0.025em;
  color: var(--ink-900);
  padding-bottom: 4px;
}

/* Brushy coral underline — echoes the hand-drawn logo strokes. */
.page-title-header h2::after {
  content: '';
  position: absolute;
  left: 50%; bottom: -6px;
  width: 100%;
  max-width: 240px;
  height: 12px;
  transform: translateX(-50%);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 12' preserveAspectRatio='none'><path d='M2 8 Q 60 2 120 6 T 238 5' stroke='%23d94f3a' stroke-width='3.5' fill='none' stroke-linecap='round'/></svg>");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  pointer-events: none;
}

/* Page-intro banner (legacy — now warm paper) */
.page-intro {
  background: linear-gradient(135deg, var(--paper) 0%, var(--kal-coral-wash) 100%);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: 1rem 1.1rem;
  margin-bottom: 1rem;
}
.page-intro h2 { text-align: left; margin-bottom: 0.35rem; }
.page-intro p { color: var(--ink-700); font-size: var(--fs-lg); }

/* ═══════════════════════════════════
   DASHBOARD
   ═══════════════════════════════════ */

.welcome-banner { text-align: center; padding: 1.5rem 0 1rem; }
.welcome-banner h1 {
  font-size: var(--fs-hero);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--kal-coral);
}

/* Compact operational stats — links through to full pages */
.dashboard-health-snapshot {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  margin: 0.5rem 0 1.25rem;
}
.health-pill {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.2rem;
  padding: 1rem 0.85rem;
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.health-pill:hover,
.health-pill:focus-visible {
  border-color: var(--kal-coral-soft);
  box-shadow: var(--shadow-md, 0 4px 14px rgba(0, 0, 0, 0.08));
}
.health-pill-value {
  font-size: var(--fs-2xl);
  font-weight: 700;
  color: var(--ink-900);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.health-pill-label {
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--kal-coral);
}
.health-pill-hint {
  font-size: var(--fs-xs);
  color: var(--ink-700);
  line-height: 1.3;
}
.health-pill-alert .health-pill-value { color: var(--kal-coral-deep, var(--kal-coral)); }

.card-value .card-delta {
  display: block;
  margin-top: 0.15rem;
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0;
  line-height: 1.2;
}
.card-delta.positive { color: var(--kal-green-deep, var(--kal-green)); }
.card-delta.negative { color: var(--kal-coral-deep, var(--kal-coral)); }
.card-delta.neutral { color: var(--ink-700); }

@media (max-width: 900px) {
  .dashboard-health-snapshot { grid-template-columns: 1fr; }
}

.dashboard-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem;
  margin-top: 1rem;
}

.dashboard-card {
  background: var(--paper);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow);
  border: 1px solid var(--border);
}

.card-header {
  background: var(--kal-coral);
  color: var(--white);
  text-align: center;
  padding: 0.75rem 0.75rem 0.85rem;
}
.card-header .card-title {
  font-weight: 700;
  font-size: var(--fs-xl);
  letter-spacing: 0.01em;
  line-height: 1.1;
}
.card-header .card-subtitle {
  margin-top: 0.3rem;
  font-weight: 500;
  font-size: var(--fs-sm);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  opacity: 0.95;
}
.card-header .card-status {
  margin-left: 0.3rem;
  font-weight: 400;
  font-style: italic;
  text-transform: none;
  letter-spacing: 0;
  opacity: 0.9;
}

/* Mini section headers inside the card body (e.g. "Profit & Loss", "Staff Costs") */
.card-section-header {
  padding: 0.55rem 1.25rem 0.35rem;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-600, var(--ink-700));
  background: var(--cream, #fbf7f3);
  border-top: 1px solid var(--border);
}
.card-section-header:first-of-type { border-top: none; }

.card-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.65rem 1.25rem;
  border-bottom: 1px dashed var(--border);
}
.card-row:last-child { border-bottom: none; }
.card-label { font-weight: 500; font-size: var(--fs-base); color: var(--ink-700); }
.card-value { font-size: var(--fs-xl); font-weight: 700; color: var(--ink-900); font-variant-numeric: tabular-nums; }

/* Secondary "per operating day" line under Income / Net — a muted, smaller
   sub-row that sits flush under its parent figure (no border, tighter pad). */
.card-subrow {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 0.1rem 1.25rem 0.5rem;
  border-bottom: 1px dashed var(--border);
}
.card-sublabel { font-size: var(--fs-sm); color: var(--ink-500); font-weight: 500; }
.card-subvalue { font-size: var(--fs-base); font-weight: 600; color: var(--ink-700); font-variant-numeric: tabular-nums; }
.card-subhint { font-size: var(--fs-xs); color: var(--ink-500); font-weight: 400; }

/* Net = Income − Expenses */
.card-row-net .card-value { font-weight: 700; }
.card-row-net.positive .card-value { color: var(--kal-green-deep, var(--kal-green)); }
.card-row-net.negative .card-value { color: var(--kal-coral-deep, var(--kal-coral)); }

/* Gross Wages subtotal */
.card-row-total {
  background: var(--kal-coral-wash, #fdf3f0);
  border-top: 2px solid var(--kal-coral);
}
.card-row-total .card-label,
.card-row-total .card-value { font-weight: 700; }

/* Fees → Wages KPI footer strip */
.card-footer-kpi {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.85rem 1.25rem;
  background: var(--ink-900);
  color: var(--white);
}
.card-footer-kpi .card-label {
  font-weight: 600;
  font-size: var(--fs-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.92);
}
.card-footer-kpi .card-value {
  font-size: var(--fs-xl);
  font-weight: 700;
  color: var(--white);
}

/* ═══════════════════════════════════
   LOGIN PAGE
   ═══════════════════════════════════ */

.login-page {
  display: flex; justify-content: center; align-items: center;
  min-height: 100vh;
  background:
    radial-gradient(circle at 20% 15%, rgba(217, 79, 58, 0.18), transparent 45%),
    radial-gradient(circle at 80% 85%, rgba(74, 159, 95, 0.14), transparent 45%),
    var(--cream);
}

.login-container {
  background: var(--paper);
  border-radius: 18px;
  padding: 2.5rem;
  width: 100%;
  max-width: 420px;
  box-shadow: var(--shadow-lg);
  border: 1px solid var(--border);
  position: relative;
}
.login-container::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 18px;
  border-top: 3px solid var(--kal-coral);
  pointer-events: none;
}

.login-header { text-align: center; margin-bottom: 2rem; }
.login-header h1 {
  font-size: var(--fs-xl); color: var(--ink-700);
  margin-bottom: 1.25rem; font-weight: 500;
  letter-spacing: 0.01em;
}
.login-header img { max-width: 180px; margin-bottom: 0.25rem; }

.login-form { display: flex; flex-direction: column; gap: 1rem; }
.login-version { text-align: center; margin-top: 1.5rem; font-size: var(--fs-sm); color: var(--ink-500); }

/* "or" divider between local + SSO sign-in. */
.login-or {
  display: flex; align-items: center; gap: 0.75rem;
  margin: 1.25rem 0;
  color: var(--ink-500); font-size: var(--fs-sm);
  text-transform: uppercase; letter-spacing: 0.12em;
}
.login-or::before, .login-or::after {
  content: ""; flex: 1; height: 1px; background: var(--ink-200, #e5e1d8);
}

/* Microsoft sign-in button — neutral white with the four-square logo, per
   Microsoft brand guidance. Stands apart from .btn-primary so users see
   it as a secondary path, not the default. */
.btn-microsoft {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 0.6rem;
  background: #ffffff;
  color: #2f2f2f;
  border: 1px solid #d4d2d0;
  font-weight: 600;
  text-decoration: none;
}
.btn-microsoft:hover { background: #f7f6f4; border-color: #b8b6b3; }
.btn-microsoft .ms-logo { flex-shrink: 0; }

/* ═══════════════════════════════════
   FORMS
   ═══════════════════════════════════ */

.form-group { display: flex; flex-direction: column; gap: 0.35rem; margin-bottom: 0.85rem; }
.form-group label {
  font-weight: 700;
  font-size: var(--fs-sm);
  color: var(--ink-500);
  text-transform: uppercase;
  letter-spacing: 0.09em;
}

.form-group input,
.form-group select,
.form-group textarea {
  padding: 0.6rem 0.85rem;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  font-size: var(--fs-lg);
  font-family: inherit;
  transition: border 0.15s, box-shadow 0.15s;
  background: var(--paper);
  color: var(--ink-900);
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
  outline: none;
  border-color: var(--kal-coral);
  box-shadow: 0 0 0 3px var(--kal-coral-wash);
}

.form-card {
  max-width: 900px;
  margin: 0 auto;
  background: var(--paper);
  padding: 1.75rem 1.75rem 1.5rem;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  border: 1px solid var(--border);
}
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }

/* Horizontal filter bar — form-groups laid out in a row, bottom-aligned.
   Use on list-page filter forms (audit, future pages). Form-groups inside
   inherit the standard label + input styling from .form-group above. */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  align-items: flex-end;
  padding: 1rem 1.25rem;
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  margin-bottom: 1rem;
}
.filter-bar .form-group { margin-bottom: 0; min-width: 160px; }
.filter-bar .form-group.grow { flex: 1; min-width: 220px; }
.filter-bar .form-actions {
  display: flex;
  gap: 0.5rem;
  margin-left: auto;
}

.radio-group { display: flex; gap: 1.5rem; }
.radio-group label {
  font-weight: 400; font-size: var(--fs-base);
  display: flex; align-items: center; gap: 0.3rem;
  text-transform: none; letter-spacing: 0; color: var(--ink-800);
}

/* ═══════════════════════════════════
   BUTTONS
   ═══════════════════════════════════ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  padding: 0.5rem 1.1rem;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  font-size: var(--fs-base);
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: all 0.15s;
  background: var(--paper);
  color: var(--ink-800);
  letter-spacing: 0.01em;
}
.btn:hover { background: var(--kal-coral-wash); color: var(--kal-coral); border-color: var(--kal-coral-soft); }

.btn-primary {
  background: var(--kal-coral);
  color: var(--white);
  border-color: var(--kal-coral);
  box-shadow: 0 4px 12px rgba(217, 79, 58, 0.28), inset 0 1px 0 rgba(255,255,255,0.2);
}
.btn-primary:hover {
  background: var(--kal-coral-deep);
  color: var(--white);
  border-color: var(--kal-coral-deep);
}

.btn-block { width: 100%; }
.btn-sm { padding: 0.35rem 0.85rem; font-size: var(--fs-sm); }

.btn-danger-outline {
  color: var(--kal-coral);
  border-color: var(--kal-coral-soft);
  background: transparent;
}
.btn-danger-outline:hover { background: var(--kal-coral-wash); color: var(--kal-coral-deep); border-color: var(--kal-coral); }

.btn-success {
  background: var(--kal-green);
  color: var(--white);
  border-color: var(--kal-green);
  box-shadow: 0 4px 12px rgba(74, 159, 95, 0.28), inset 0 1px 0 rgba(255,255,255,0.2);
}
.btn-success:hover {
  background: var(--kal-green-deep);
  color: var(--white);
  border-color: var(--kal-green-deep);
}

/* ═══════════════════════════════════
   ALERTS
   ═══════════════════════════════════ */

.alert { padding: 0.75rem 1rem; border-radius: 10px; margin-bottom: 1rem; font-size: var(--fs-base); border: 1px solid transparent; }
.alert-error { background: var(--kal-coral-wash); color: var(--kal-coral-deep); border-color: var(--kal-coral-soft); }
.alert-success { background: var(--kal-green-tint); color: var(--kal-green-deep); border-color: var(--kal-green-soft); }

/* Bounced-remittance banner on /financial/bills. Sticky list of supplier
   remittance bounces that stays visible until each row is marked resolved. */
.bounce-banner {
  background: var(--kal-coral-wash);
  border: 1px solid var(--kal-coral-soft);
  border-left: 4px solid var(--kal-coral);
  border-radius: 10px;
  padding: 0.9rem 1.1rem;
  margin: 0 0 1.1rem;
  color: var(--ink-700);
}
.bounce-banner-header { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.75rem; margin-bottom: 0.65rem; }
.bounce-banner-header strong { color: var(--kal-coral-deep); font-size: var(--fs-base); }
.bounce-banner-hint { color: var(--ink-500); font-size: var(--fs-sm); }
.bounce-banner-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.55rem; }
.bounce-banner-row {
  background: var(--paper);
  border: 1px solid var(--kal-coral-soft);
  border-radius: 8px;
  padding: 0.6rem 0.8rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.9rem;
  align-items: center;
  justify-content: space-between;
  transition: opacity 0.25s ease, transform 0.25s ease, max-height 0.3s ease, padding 0.3s ease, margin 0.3s ease;
}
.bounce-banner-row.is-dismissing {
  opacity: 0;
  transform: translateX(8px);
  max-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  margin-top: 0;
  margin-bottom: 0;
  overflow: hidden;
}
.bounce-banner-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; font-size: var(--fs-sm); flex: 1 1 auto; min-width: 0; }
.bounce-banner-sep { color: var(--ink-300); }
.bounce-banner-supplier { font-weight: 600; }
.bounce-banner-email,
.bounce-banner-batch,
.bounce-banner-when { color: var(--ink-500); }
.bounce-banner-detail { width: 100%; font-size: var(--fs-sm); color: var(--ink-500); margin-top: 0.25rem; word-break: break-word; }
.bounce-banner-actions { margin: 0; }

/* ═══════════════════════════════════
   TABLES
   ═══════════════════════════════════ */

.data-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: 0 14px 14px 14px;   /* top-left square to meet folder tabs */
  overflow: hidden;
  box-shadow: 0 8px 24px rgba(45, 35, 25, 0.06);
  font-size: var(--fs-base);
}
.data-table thead th {
  background: var(--ink-50);
  color: var(--ink-500);
  padding: 0.65rem 0.85rem;
  text-align: left;
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  border-bottom: 1px solid var(--border);
}

/* Sortable column headers — wired by public/js/list-sort.js. The .sortable
   class is added at runtime to any <th data-sort-key="…">. The arrow
   indicator is a pseudo-element so the header text stays selectable
   and the click target stays the whole cell. */
.data-table thead th.sortable {
  cursor: pointer;
  user-select: none;
  position: relative;
  padding-right: 1.6em;
}
.data-table thead th.sortable:hover {
  background: var(--ink-100, #e9e6df);
  color: var(--ink-700, #2d2722);
}
.data-table thead th.sortable:focus-visible {
  outline: 2px solid var(--kal-coral, #DE5A41);
  outline-offset: -2px;
}
.data-table thead th.sortable::after {
  content: '\2195'; /* ↕ — neutral hint for inactive sortable headers */
  position: absolute;
  right: 0.55em;
  top: 50%;
  transform: translateY(-50%);
  font-size: 0.85em;
  opacity: 0.35;
}
.data-table thead th.sortable-active {
  color: var(--kal-coral-deep, #c14b34);
}
.data-table thead th.sortable-active::after { opacity: 0.95; }
.data-table thead th.sortable-asc::after  { content: '\25B2'; } /* ▲ */
.data-table thead th.sortable-desc::after { content: '\25BC'; } /* ▼ */

/* Clear-sort chip — auto-injected by public/js/list-sort.js into the
   page-toolbar-meta when ?sort= is in the URL. Only visible when a
   non-default sort is active; clicking removes sort+dir+page params. */
.clear-sort-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.25em;
  margin-left: 0.6rem;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  background: var(--ink-100, #efeae1);
  color: var(--ink-500, #5a4f44);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-decoration: none;
  border: 1px solid transparent;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.clear-sort-chip:hover,
.clear-sort-chip:focus-visible {
  background: var(--kal-coral, #DE5A41);
  color: #fff;
  outline: none;
  border-color: var(--kal-coral-deep, #c14b34);
}
.data-table tbody td {
  padding: 0.7rem 0.85rem;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.data-table tbody tr:last-child td { border-bottom: none; }
.data-table tbody tr:hover td { background: var(--kal-coral-wash); }
.data-table.compact td,
.data-table.compact th { padding: 0.4rem 0.65rem; font-size: var(--fs-md); }

/* Footer (Average / Total) row. Without this, browsers fall back to the
   default `<th>` styling -- center-aligned + different padding -- and
   the columns visibly drift out of alignment with the data rows above.
   Matches the tbody td shape (left-aligned, same padding, same
   vertical-align) plus a stronger top border + a slightly muted
   background so it reads as a summary, and a touch more bottom padding
   so the row has breathing space at the table's edge. */
.data-table tfoot th,
.data-table tfoot td {
  padding: 0.85rem 0.85rem 1rem;
  text-align: left;
  font-weight: 700;
  vertical-align: top;
  border-top: 2px solid var(--border);
  background: var(--paper-50, #fbf6ee);
}

/* ═══════════════════════════════════
   FILTER TABS (folder-style)
   ═══════════════════════════════════ */

.filter-tabs {
  display: flex;
  align-items: flex-end;
  gap: 0;
  margin: 1rem 0 0;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--border);
}
.filter-tab {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.65rem 1.1rem 0.7rem;
  font-size: var(--fs-base);
  font-weight: 500;
  color: var(--ink-500);
  background: transparent;
  border: none;
  border-radius: 12px 12px 0 0;
  border-top: 3px solid transparent;
  border-left: 1px solid transparent;
  border-right: 1px solid transparent;
  transition: color 0.12s, background 0.12s;
  position: relative;
  top: 1px;
  cursor: pointer;
}
.filter-tab:hover { color: var(--kal-coral); background: var(--kal-coral-wash); }
.filter-tab.active {
  background: var(--paper);
  color: var(--ink-900);
  font-weight: 600;
  border-top-color: var(--kal-coral);
  border-left-color: var(--border);
  border-right-color: var(--border);
}
.filter-tab.clear {
  border: none !important;
  background: transparent !important;
  color: var(--ink-400);
  font-weight: 400;
  font-size: var(--fs-md);
  margin-left: auto;
  padding: 0.6rem 0.5rem;
  align-self: center;
  top: 0;
}
.filter-tab.clear:hover { color: var(--kal-coral); background: transparent !important; }

.filter-tab-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  background: var(--ink-100);
  color: var(--ink-500);
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.02em;
}

/* ═══════════════════════════════════
   GROUP SECTIONS (grouped tables — notebook panel)
   ═══════════════════════════════════ */

.group-section { margin-bottom: 1.5rem; }
/* PORTAL-WIDE rule: filter-tabs must always touch whatever sits below
   them — no gap, no float. Tabs are file-folder tabs hanging off the
   panel/table beneath; if a margin appears between them and the next
   element they look untethered. Per-page templates have repeatedly
   re-introduced this gap via inline `style="margin-bottom: 1rem"` on
   the tab strip OR `margin-top` on the next element. The rule below
   short-circuits both: any element that is the immediate sibling of
   .filter-tabs gets margin-top: 0. The earlier .filter-tabs +
   .group-section rule is now subsumed by this; the rounded-corner
   override still applies. */
.filter-tabs + * { margin-top: 0; }
.filter-tabs + .group-section > .group-header { border-radius: 0 12px 0 0; }

/* Audit-page headline pill row — sits at the top of the page above the
   filter-bar form. The filter-tabs strip lives further down (just above
   each tab's table) so this row is just an ordinary horizontal pill
   row, no panel styling. */
.audit-headline {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.group-header {
  padding: 0.75rem 1.1rem;
  border-radius: 12px 12px 0 0;
  color: var(--white);
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: var(--fs-base);
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  border: 1px solid transparent;
}
.centre-header {
  background: linear-gradient(90deg, var(--kal-coral), var(--kal-coral-deep));
  border-color: var(--kal-coral-deep);
  box-shadow: 0 4px 10px rgba(217, 79, 58, 0.18);
}
.centre-header strong { font-weight: 700; letter-spacing: 0.04em; }

/* Centre header stats row — count, total, GST pills. Given fixed
   min-widths so each sits in a stable horizontal slot across every
   centre — scanning vertically down the list lines the values up
   even when some centres have a "Pushed to QBO" chip on the right
   and others have a "Push to QBO" button. */
.centre-header-stats {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-left: 1rem;
}
.centre-header-stat-count {
  min-width: 140px;
  text-align: center;
  justify-content: center;
}
.centre-header-stat-total,
.centre-header-stat-gst {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
  justify-content: space-between;
  font-variant-numeric: tabular-nums;
}
.centre-header-stat-total { min-width: 160px; }
.centre-header-stat-gst   { min-width: 140px; }
.centre-header-stat-label {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  opacity: 0.75;
}
.centre-header-stat-total strong,
.centre-header-stat-gst strong { font-weight: 700; }
.centre-header-code { min-width: 48px; display: inline-block; }

/* Pushed-to-QBO pill rendered as an inline <form> so admins can
   re-push (after deleting/voiding the original Bill in QBO) without
   touching the DB. The whole pill reads "Pushed to QBO · Bill …" +
   a subtle ↻ icon; the pill itself is also Ctrl/Cmd-clickable as a
   power-user shortcut. The visual style matches `.meta-pill.success`
   so it reads the same as before when nothing's being hovered. */
.qbo-pushed-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  cursor: pointer;
  padding-right: 0.35rem;  /* tighter than default — button has its own padding */
}
.qbo-pushed-pill:hover { filter: brightness(1.05); }
.qbo-pushed-label { pointer-events: none; }
.qbo-pushed-repush {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.3);
  color: inherit;
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s, transform 0.3s;
}
.qbo-pushed-repush:hover { background: rgba(255, 255, 255, 0.6); }
.qbo-pushed-repush:active { transform: rotate(180deg); }
.week-header {
  background: var(--ink-800);
  border-color: var(--ink-800);
  margin: 0.35rem 0;
  font-size: var(--fs-md);
}
.count-badge {
  margin-left: auto;
  background: rgba(255,255,255,0.18);
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: 0.03em;
}
.subgroup { margin-left: 0.75rem; }

/* When a group-section contains a data-table, remove the table's top-left
   radius so it joins the centre-header cleanly. */
.group-section .data-table { border-radius: 0 0 14px 14px; }

/* Collapse icon */
details summary { list-style: none; }
details summary::-webkit-details-marker { display: none; }
.collapse-icon::before {
  content: '▾';
  display: inline-block;
  transition: transform 0.2s;
  margin-right: 0.2rem;
  font-size: var(--fs-sm);
  opacity: 0.85;
}
details:not([open]) .collapse-icon::before { transform: rotate(-90deg); }

/* ═══════════════════════════════════
   TOOLBAR
   ═══════════════════════════════════ */

.toolbar { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 1rem; }

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

.page-toolbar-actions,
.page-toolbar-meta {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* ═══════════════════════════════════
   LIST SHELL — summary/detail rows
   ═══════════════════════════════════ */

.list-shell-table { table-layout: fixed; }
.filter-only-col { display: none; width: 0 !important; padding: 0 !important; border: 0 !important; }

.summary-row td {
  vertical-align: top;
  padding-top: 0.75rem;
  padding-bottom: 0.75rem;
}

/* Row-level clickable trigger (e.g. click anywhere on a list row to open
   the edit overlay). Pairs with `data-overlay-url` + `data-overlay-href`
   on the <tr>. */
.row-clickable { cursor: pointer; }
.row-clickable:hover { background: var(--surface-200, #f1ece4); }
.row-clickable td { vertical-align: top; padding-top: 0.75rem; padding-bottom: 0.75rem; }

.summary-main { display: flex; flex-direction: column; gap: 0.4rem; }
.summary-title { font-weight: 700; color: var(--ink-900); font-size: var(--fs-lg); }
.summary-subtitle { color: var(--ink-700); font-size: var(--fs-md); }
/* Stacked variant — Total on one line, GST below it, no bullet
   separator. Used on the petty-cash list summary so both figures
   are glance-readable. */
.summary-subtitle-stack { display: flex; flex-direction: column; gap: 0.1rem; }
.summary-subtitle-stack .summary-subtitle-secondary {
  color: var(--ink-500);
  font-size: var(--fs-sm);
}
.summary-preview { color: var(--ink-700); font-size: var(--fs-base); line-height: 1.55; }

/* Coral-wash "Note" callout used in maintenance list summaries.
   Echoes V2's inline update note — left-border accent + tiny label pill. */
.summary-note {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.35rem 0.6rem 0.35rem 0.55rem;
  background: var(--kal-coral-wash);
  border-left: 3px solid var(--kal-coral);
  border-radius: 0 6px 6px 0;
  color: var(--ink-700);
  font-size: var(--fs-md);
  line-height: 1.4;
}
.summary-note-label {
  flex-shrink: 0;
  font-size: var(--fs-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--kal-coral-deep);
}
.summary-note-body { word-break: break-word; }

.summary-meta {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  flex-wrap: wrap;
}

/* Meta pills — chip style used across list rows */
.meta-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  background: var(--ink-100);
  color: var(--ink-700);
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: 0.02em;
  border: 1px solid transparent;
}

.meta-pill.success {
  background: var(--kal-green);
  color: var(--white);
  border-color: var(--kal-green);
}
.meta-pill.success::before {
  content: '✓'; font-weight: 700; font-size: var(--fs-xs);
  margin-right: 0.05rem;
}

.meta-pill.warning { background: var(--kal-amber-tint); color: #8a5c1b; border-color: #e7c48a; }

/* "Getting there" tier — sits visually between warning (orange) and success
   (bright filled green). Used by occupancy week % between 70 and 90 to mean
   "good but not at target". Soft mint background + dark green text reads as
   the same colour family as success but visibly less complete. */
.meta-pill.progress { background: var(--kal-green-tint); color: var(--kal-green-deep); border-color: var(--kal-green-soft); }

.meta-pill.danger { background: var(--kal-coral-tint); color: var(--kal-coral-deep); border-color: var(--kal-coral-soft); }

/* Maintenance list pills — uniform width so Status / Delegation / Photos
   stack neatly regardless of label length (widest common label is
   "Owner (Agent)" ≈ 110px). */
.maintenance-table .summary-meta .meta-pill,
.maintenance-table .pill-paperclip {
  min-width: 110px;
  justify-content: center;
}

/* Paperclip-prefixed pill — inline SVG replaces the decorative ::before. */
.meta-pill.pill-paperclip {
  justify-content: center;
}
.meta-pill.pill-paperclip::before { content: none; }
.meta-pill.pill-paperclip svg { flex: 0 0 auto; opacity: 0.95; }

/* ═══════════════════════════════════
   Owner Reports — at-a-glance metrics
   ═══════════════════════════════════ */

/* Per-centre summary card — rendered above each centre's type
   groups. Shows the latest month's headline numbers + a 6-month
   profit/loss sparkline. Sits inside the .group-section accordion
   below the centre header. */
.centre-summary-card {
  margin: 10px 12px 14px 12px;
  padding: 14px 16px;
  background: #fff;
  border: 1px solid #e6dccb;
  border-radius: 8px;
  box-shadow: 0 1px 2px rgba(45, 35, 25, 0.04);
}
.csc-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid #f0e8d9;
}
.csc-header-label {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--ink-500);
}
.csc-header-period {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink-700);
}
.csc-pills {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
}
.csc-pill {
  padding: 8px 10px;
  background: #fbf7ee;
  border: 1px solid #ebe1cc;
  border-radius: 6px;
}
.csc-pill-label {
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--ink-500);
  margin-bottom: 2px;
}
.csc-pill-value {
  font-size: var(--fs-lg);
  font-weight: 700;
  color: var(--ink-700);
  font-variant-numeric: tabular-nums;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
}
.csc-pill-sub {
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--ink-500);
}
.csc-pill-trend {
  font-size: var(--fs-md);
  margin-left: 2px;
}
/* P/L pill colours when positive / negative. Mint background +
   green text for profit; coral wash + coral text for loss. */
.csc-pill--pl.csc-pill--positive {
  background: var(--kal-green-tint, #e8f4ec);
  border-color: var(--kal-green-soft, #c1e0cc);
}
.csc-pill--pl.csc-pill--positive .csc-pill-value {
  color: var(--kal-green-deep, #2d6e44);
}
.csc-pill--pl.csc-pill--negative {
  background: var(--kal-coral-tint, #fbe7e3);
  border-color: var(--kal-coral-soft, #f0c0b8);
}
.csc-pill--pl.csc-pill--negative .csc-pill-value {
  color: var(--kal-coral-deep, #b03d2b);
}

/* Sparkline row — sits at the bottom of the summary card. */
.csc-sparkline-row {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid #f0e8d9;
}
.csc-sparkline-label {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 600;
  color: var(--ink-500);
}
.csc-sparkline-range {
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  color: var(--ink-400, #8a7e6b);
}
.csc-sparkline {
  flex: 0 0 auto;
  width: 200px;
  height: 48px;
  color: var(--kal-coral, #DE5A41);
}

/* 2×4 stats grid rendered as a <tr> IMMEDIATELY BELOW its Monthly
   Financial summary row. Open by default (the Stats button on the
   row above toggles closed for a denser view). Same chip shape as
   .csc-pills above for visual consistency. The <td> uses colspan=5
   to span the row, and a fbf7ee tint with no top border makes the
   row + stats grid read as one card. */
.rp-stats-cell {
  padding: 8px 14px 14px 14px !important;
  background: #fbf7ee;
  border-bottom: 1px solid var(--border);
}
/* Suppress the summary row's bottom border when a stats grid sits
   below it — visually glues the two together so it's obvious which
   month the chips belong to. */
.reports-table tbody tr.rp-row--has-stats td {
  border-bottom: none;
}
.report-stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 10px;
}
.rsg-chip {
  padding: 8px 10px;
  background: #fff;
  border: 1px solid #ebe1cc;
  border-radius: 6px;
}
.rsg-label {
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--ink-500);
  margin-bottom: 2px;
}
.rsg-value {
  font-size: var(--fs-md);
  font-weight: 700;
  color: var(--ink-700);
  font-variant-numeric: tabular-nums;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.rsg-sub {
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--ink-500);
}
.rsg-chip--pos { border-color: var(--kal-green-soft, #c1e0cc); background: var(--kal-green-tint, #e8f4ec); }
.rsg-chip--pos .rsg-value { color: var(--kal-green-deep, #2d6e44); }
.rsg-chip--neg { border-color: var(--kal-coral-soft, #f0c0b8); background: var(--kal-coral-tint, #fbe7e3); }
.rsg-chip--neg .rsg-value { color: var(--kal-coral-deep, #b03d2b); }

/* Stats toggle button — chevron rotates on open. */
.rp-stats-toggle.is-open span { transform: rotate(180deg); display: inline-block; }
.rp-stats-toggle span { transition: transform 0.15s ease; }

/* Owner Reports — type-indicator pills. BAS = "document" icon on a
   desaturated blue (matches the tax/government feel of a lodgement
   form). Monthly Financial = "bar chart" icon on the existing success
   green palette (carries the finance / monthly-results meaning).
   The ::before { content:none } overrides any tick from other variants
   so the SVG is the only prefix. */
.meta-pill.pill-report-bas {
  background: #e3edf7;
  color: #1f4d80;
  border-color: #c2d6ea;
}
.meta-pill.pill-report-mfr {
  background: var(--kal-green-tint);
  color: var(--kal-green-deep);
  border-color: var(--kal-green-soft);
}
.meta-pill.pill-report-bas::before,
.meta-pill.pill-report-mfr::before { content: none; }
.meta-pill.pill-report-bas svg,
.meta-pill.pill-report-mfr svg {
  flex: 0 0 auto;
  opacity: 0.95;
}

/* Anchor rendered as a meta-pill — no underline, stays clickable. */
a.meta-pill.file-pill {
  text-decoration: none;
  cursor: pointer;
}
a.meta-pill.file-pill:hover { filter: brightness(0.95); }

/* Removable filter chip — label + a round red × button for dropping just
   this one filter. Used on every list page's active-filter strip. The ×
   is an anchor that links back to the list URL minus this filter's
   af_<key> params, so there's no JS dependency. */
.meta-pill-removable {
  padding-right: 0.3rem;
}
.meta-pill-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.15rem;
  height: 1.15rem;
  border-radius: 999px;
  background: var(--kal-coral, #DE5A41);
  color: var(--white, #fff);
  text-decoration: none;
  margin-left: 0.15rem;
  padding: 0;
  transition: background 0.12s, transform 0.12s;
  cursor: pointer;
}
.meta-pill-remove svg { width: 0.7rem; height: 0.7rem; display: block; }
.meta-pill-remove:hover,
.meta-pill-remove:focus-visible {
  background: var(--kal-coral-deep, #a53a28);
  transform: scale(1.08);
  color: var(--white, #fff);
  text-decoration: none;
  outline: none;
}

/* Banking totals cell — primary amount + method breakdown inline, wraps cleanly. */
.banking-totals {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 12px;
  font-variant-numeric: tabular-nums;
}
.banking-total {
  font-weight: 700;
  color: var(--ink-900);
  white-space: nowrap;
}
.banking-breakdown {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 2px 10px;
  color: var(--ink-700);
  font-size: var(--fs-md);
}
.banking-breakdown .bk-seg {
  white-space: nowrap;
}

.detail-toggle { min-width: 60px; }
.detail-toggle.btn-icon { min-width: 0; }

.maintenance-action-stack {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
}

.maintenance-actions {
  padding-left: 0.55rem !important;
  padding-right: 0.55rem !important;
  text-align: right;
}
.maintenance-actions .btn-icon { width: 32px; height: 32px; padding: 0; flex: 0 0 32px; }

/* Circular icon-only button (notebook style) */
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px; height: 32px;
  padding: 0;
  border-radius: 999px;
  line-height: 0;
}
.btn-icon svg { display: block; }
.btn-icon.is-open { background: var(--kal-coral); border-color: var(--kal-coral); color: var(--white); }

/* Notify-bell "already sent" state — coral active state dimmed to a
   muted cream/ink so the admin can see at a glance which rows have
   already been chased. Click still works (debts-notify.js prompts
   "already notified, resend?"); the muted styling is the visual
   signal, not a disabled state. Hover restores the coral so the
   admin gets clear "yes this is still clickable" feedback. */
.btn-icon.btn-notified {
  background: var(--cream);
  color: var(--ink-500);
  border-color: var(--ink-500);
  opacity: 0.55;
  box-shadow: none;
}
.btn-icon.btn-notified:hover,
.btn-icon.btn-notified:focus-visible {
  background: var(--kal-coral);
  color: var(--white);
  border-color: var(--kal-coral);
  opacity: 1;
  box-shadow: 0 4px 12px rgba(217, 79, 58, 0.28);
}

/* Dark primary "View" button used in maintenance list */
.btn-dark {
  background: var(--ink-900);
  color: var(--white);
  border-color: var(--ink-900);
  box-shadow: 0 2px 6px rgba(29, 24, 19, 0.22);
}
.btn-dark:hover,
.btn-dark:focus-visible {
  background: var(--kal-coral);
  color: var(--white);
  border-color: var(--kal-coral);
  box-shadow: 0 4px 12px rgba(217, 79, 58, 0.28);
}

/* Detail row panel */
.detail-row > td { padding: 0 !important; background: var(--kal-coral-wash); }

/* Expandable detail rows must span the FULL table width regardless of
   table-layout: fixed column math. Forcing display:block + width:100% takes
   the row out of the column flow so the single colspan cell can't be squeezed
   when a hidden .filter-only-col throws off the computed column count.
   Previously ONLY .maintenance-table carried this, so every new list page hit
   the "detail row not full width" bug on first build — promoting it to every
   .list-shell-table fixes it once and for all future pages. See CLAUDE.md →
   "Hidden table columns silently ruin table-layout: fixed layouts". */
.list-shell-table .detail-row { display: block; width: 100%; }
.list-shell-table .detail-row[hidden] { display: none !important; }
.list-shell-table .detail-row > td { display: block; width: 100%; box-sizing: border-box; }

.detail-panel {
  border-top: 1px dashed var(--border-strong);
  padding: 1rem 1.1rem 1.1rem;
  width: 100%; min-width: 0; max-width: 100%;
  box-sizing: border-box;
  background: linear-gradient(180deg, var(--kal-coral-wash) 0%, var(--paper) 60%);
}
.detail-panel-body { width: 100%; min-width: 0; max-width: 100%; }

.detail-panel-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
  gap: 0.85rem;
  width: 100%; min-width: 0; max-width: 100%;
}

.maintenance-detail-grid { grid-template-columns: 1.05fr 1fr 1fr 1.2fr 1.2fr; }

@media (max-width: 1600px) { .maintenance-detail-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 1050px) { .maintenance-detail-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 760px)  { .maintenance-detail-grid { grid-template-columns: 1fr; } }

.detail-panel-grid > * { min-width: 0; }

.detail-card {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.9rem 1rem;
  box-shadow: var(--shadow-sm);
  min-width: 0;
  overflow-wrap: anywhere;
}
.detail-card h4 {
  margin: 0 0 0.45rem;
  font-size: var(--fs-xs);
  color: var(--ink-500);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 700;
}
.detail-card p,
.detail-card ul,
.detail-card div {
  font-size: var(--fs-base);
  min-width: 0;
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: break-word;
}
.detail-card ul { padding-left: 1rem; }
.detail-card .html-content,
.detail-card .html-content * {
  max-width: 100%;
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: break-word;
}
.detail-card .html-content pre { white-space: pre-wrap; }

.detail-panel-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-top: 0.85rem;
}

.detail-loading,
.detail-error,
.detail-empty {
  color: var(--ink-500);
  font-size: var(--fs-base);
}
.detail-error { color: var(--kal-coral-deep); }

.file-list {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.file-chip {
  display: inline-flex;
  align-items: center;
  padding: 0.35rem 0.6rem;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--paper);
  color: var(--ink-700);
  font-size: var(--fs-sm);
  font-weight: 500;
  text-decoration: none;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.file-chip:hover { border-color: var(--border-strong); color: var(--kal-coral-deep); }

.thumb-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
  gap: 0.5rem;
}
.thumb-list a { display: block; }
.thumb-list img {
  width: 100%;
  height: 88px;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid var(--border);
  display: block;
}

.status-dot {
  width: 8px; height: 8px;
  border-radius: 999px;
  display: inline-block;
  margin-right: 0.35rem;
  background: var(--ink-400);
}
.status-dot.success { background: var(--kal-green); }
.status-dot.warning { background: var(--kal-amber); }
.status-dot.danger { background: var(--kal-coral); }

.inline-form { display: inline; }

.list-empty {
  background: var(--paper);
  border: 1px dashed var(--border-strong);
  border-radius: 14px;
  padding: 1.5rem;
  color: var(--ink-700);
  text-align: center;
}

/* ═══════════════════════════════════
   OVERLAY (iframe)
   ═══════════════════════════════════ */

.page-overlay { position: fixed; inset: 0; z-index: 1200; }
.page-overlay-backdrop {
  position: absolute; inset: 0;
  background: rgba(29, 24, 19, 0.55);
  backdrop-filter: blur(3px);
}
.page-overlay-dialog {
  position: relative;
  z-index: 1;
  /* Widened from 1240px so full-width forms with a side preview pane
     (e.g. the petty-cash form with its receipt preview) have breathing
     room on standard 1920×1080 monitors without shrinking the form
     inputs. On smaller viewports the calc() clamps down automatically. */
  width: min(1760px, calc(100vw - 1rem));
  height: min(92vh, calc(100vh - 1rem));
  margin: 0.5rem auto;
  background: var(--paper);
  border-radius: 18px;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  border: 1px solid var(--border);
}
.page-overlay-dialog--compact {
  width: min(820px, calc(100vw - 1rem));
  height: min(84vh, 760px);
}
.page-overlay-close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  z-index: 2;
  width: 2.2rem;
  height: 2.2rem;
  display: flex; align-items: center; justify-content: center;
  border: 0;
  border-radius: 999px;
  background: var(--kal-coral);
  color: var(--white);
  cursor: pointer;
  padding: 0;
  box-shadow: 0 4px 12px rgba(217, 79, 58, 0.3);
}
.page-overlay-close svg { width: 1.1rem; height: 1.1rem; display: block; }
.page-overlay-close:hover { background: var(--kal-coral-deep); }

.page-overlay-frame {
  width: 100%; height: 100%;
  border: 0;
  background: var(--cream);
}

.page-overlay-loading {
  position: absolute; inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(255, 250, 242, 0.75);
  backdrop-filter: blur(1px);
  z-index: 1;
}
.page-overlay.is-loading .page-overlay-loading { display: flex; }
.page-overlay.is-loading .page-overlay-frame { opacity: 0; }

body.overlay-open { overflow: hidden; }
.overlay-frame-body { background: transparent; }
/* Strip the site-wide 1600px cap on `.main-content` inside the overlay
   iframe — the dialog itself is already capped at 1760px and its own
   chrome provides the outer framing, so an inner cap just wastes width
   on full-width forms (notably petty-cash with its side preview). */
.overlay-frame-body .main-content { padding: 1.25rem 1.25rem 1rem; max-width: none; }

/* ═══════════════════════════════════
   TABLE TOOLS (search, filters, export)
   ═══════════════════════════════════ */

.table-tools { margin-bottom: 0.75rem; }
.table-tools-bar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}
.page-toolbar .table-tools { margin-bottom: 0; }

.search-input {
  padding: 0.4rem 0.9rem;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  font-size: var(--fs-base);
  font-family: inherit;
  width: 260px;
  transition: border-color 0.15s, box-shadow 0.15s;
  background: var(--paper);
  color: var(--ink-900);
}
.search-input:focus {
  outline: none;
  border-color: var(--kal-coral);
  box-shadow: 0 0 0 3px var(--kal-coral-wash);
}
.search-input::placeholder { color: var(--ink-400); }

/* Filter modal overlay */
.filter-modal-overlay {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(29, 24, 19, 0.4);
  display: flex; align-items: center; justify-content: center;
  padding: 1rem;
}
.filter-modal {
  background: var(--paper);
  border-radius: 16px;
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-width: 700px;
  max-height: 80vh;
  overflow-y: auto;
  padding: 1.5rem;
  border: 1px solid var(--border);
}
.filter-modal-header {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 1rem;
}
.filter-modal-header h3 { margin: 0; font-size: var(--fs-2xl); }
.filter-modal-close {
  width: 36px; height: 36px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--kal-coral);
  color: var(--white);
  border: none;
  cursor: pointer;
  padding: 0;
}
.filter-modal-close svg { width: 18px; height: 18px; display: block; }
.filter-modal-close:hover { background: var(--kal-coral-deep); }

.filter-mode-bar {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 1rem;
  padding: 0.5rem 0.75rem;
  background: var(--ink-50);
  border-radius: 10px;
}
.filter-mode-label { font-size: var(--fs-md); font-weight: 600; color: var(--ink-700); margin-right: 0.25rem; }
.filter-mode-btn { font-size: var(--fs-sm); }
.filter-mode-btn.active { background: var(--kal-coral); color: var(--white); border-color: var(--kal-coral); }

.filter-rules { margin-bottom: 1rem; }
.filter-rule-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
  padding: 0.5rem;
  background: var(--ink-50);
  border-radius: 8px;
  border: 1px solid var(--border);
}
.filter-rule-field,
.filter-rule-operator {
  padding: 0.4rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: var(--fs-md);
  font-family: inherit;
  background: var(--paper);
}
.filter-rule-field { min-width: 150px; }
.filter-rule-operator { min-width: 130px; }
.filter-rule-value {
  flex: 1;
  padding: 0.4rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: var(--fs-md);
  font-family: inherit;
  min-width: 100px;
}
.filter-rule-delete {
  width: 32px; height: 32px;
  padding: 0;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.filter-rule-delete svg { width: 14px; height: 14px; display: block; }

/* Small × button sitting inside the search input group on list pages. */
.search-clear {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.35rem 0.55rem;
}
.search-clear svg { width: 14px; height: 14px; display: block; }

.filter-modal-footer {
  display: flex;
  justify-content: space-between;
  margin-top: 1.25rem;
  padding-top: 1rem;
  border-top: 1px dashed var(--border);
}

.bulk-update-info {
  background: var(--kal-amber-tint);
  border: 1px solid #e7c48a;
  border-radius: 8px;
  padding: 0.6rem 0.75rem;
  font-size: var(--fs-md);
  color: #8a5c1b;
  margin-bottom: 1rem;
}
.bulk-arrow { font-size: var(--fs-xl); font-weight: 700; color: var(--ink-400); padding: 0 0.25rem; }

.filter-active-badge {
  background: var(--kal-coral);
  color: var(--white);
  font-size: var(--fs-xs);
  font-weight: 700;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
}

/* Dark "X records" pill — V2 style */
.record-count {
  margin-left: auto;
  font-size: var(--fs-sm);
  background: var(--ink-900);
  color: var(--white);
  padding: 0.3rem 0.85rem;
  border-radius: 999px;
  font-weight: 600;
  letter-spacing: 0.02em;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}
.record-count::before {
  content: '';
  width: 8px; height: 8px;
  border-radius: 999px;
  background: var(--kal-coral-soft);
}

/* ═══════════════════════════════════
   NOTES
   ═══════════════════════════════════ */

.notes-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; }
.notes-column-header {
  padding: 0.7rem 1.1rem;
  color: var(--white);
  border-radius: 12px 12px 0 0;
  font-weight: 700;
  font-size: var(--fs-base);
  letter-spacing: 0.03em;
}
.notes-column-header.issues { background: var(--kal-coral); }
.notes-column-header.feedback { background: var(--ink-800); }
.note-card {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: 0 0 12px 12px;
  padding: 1rem 1.1rem;
  margin-bottom: 0.75rem;
  box-shadow: var(--shadow-sm);
}
.note-centre { font-weight: 700; font-size: var(--fs-base); color: var(--kal-coral); }
.note-meta { display: flex; gap: 2rem; font-size: var(--fs-sm); color: var(--ink-500); margin: 0.4rem 0; }
.note-content { font-size: var(--fs-base); line-height: 1.6; margin-top: 0.5rem; max-height: 240px; overflow-y: auto; }

/* ═══════════════════════════════════
   CALENDAR
   ═══════════════════════════════════ */

.calendar-header { display: flex; align-items: center; gap: 1rem; margin-bottom: 1rem; }
.calendar-nav { display: flex; gap: 0.25rem; }

/* ═══════════════════════════════════
   KINDY FUNDING
   ═══════════════════════════════════ */

.kindy-funding-header { text-align: center; margin-bottom: 2rem; }
.kindy-funding-header h2 { margin-bottom: 0.5rem; }
.kindy-funding-header p { margin: 0.25rem 0; font-size: var(--fs-base); color: var(--ink-700); }

/* ═══════════════════════════════════
   MISC
   ═══════════════════════════════════ */

.empty-state {
  text-align: center;
  padding: 3rem 1rem;
  color: var(--ink-500);
  background: var(--paper);
  border: 1px dashed var(--border-strong);
  border-radius: 14px;
  font-size: var(--fs-base);
}

.col-date { min-width: 110px; }

/* Petty-cash read-only detail overlay (views/partials/details/petty-cash.ejs).
   Stacks two full-width cards: transaction-meta + notes + receipt on
   top, amounts table / single-line summary below. No grid splits —
   the amounts block is the visual weight, the meta block stays
   compact at the top. */
.pc-detail-overlay {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  width: 100%;
  min-width: 0;
}
.pc-detail-overlay > .detail-card {
  width: 100%;
}
.pc-detail-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
}
.pc-detail-header h4 {
  margin: 0;
}
.pc-meta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.5rem;
  margin-bottom: 0.2rem;
}
.pc-meta-row > div {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.pc-meta-label {
  font-size: var(--fs-xs);
  color: var(--ink-500);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 700;
  margin-bottom: 0.1rem;
}
.pc-meta-value {
  font-size: var(--fs-base);
  overflow-wrap: anywhere;
}
.pc-detail-section {
  margin-top: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.pc-detail-section .html-content {
  font-size: var(--fs-base);
  overflow-wrap: anywhere;
}
.pc-detail-section .thumb-list { margin: 0; }
.pc-amounts-card h4 { margin-bottom: 0.6rem; }
.pc-amounts-table { margin: 0; }
.pc-amounts-single {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 2rem;
}
.pc-amounts-single > div {
  display: flex;
  flex-direction: column;
}
.pc-amount-value {
  font-size: var(--fs-lg, 1.1rem);
  font-weight: 600;
}

/* Petty-cash list layout.
   CRITICAL: every visible column has an EXPLICIT width (pixels or
   percentage) — NO `width: auto` allowed. Confirmed by the diagnostic
   output: when Preview was `width: auto`, the browser treated the 3
   hidden `.filter-only-col` columns as ALSO auto and shared the
   leftover ~396px equally between all 4 "auto" columns, giving
   Preview only ~99px and leaving a ~298px gap on the right.
   The <colgroup> attempt (commit 057e8e0) collapsed the table
   entirely in the browser — browser-specific handling of 0-width
   cols under table-layout: fixed is not reliable.
   Fix: Preview gets an explicit 32% so there is NO auto pool. The
   widths intentionally sum to >100% (275px fixed + 79%) so the
   browser scales percentages proportionally to fit the table width;
   hidden cols are forced to 0 by `.filter-only-col { width: 0
   !important }`. No ambiguity, no auto-sharing. */
.petty-cash-table {
  table-layout: fixed;
  width: 100% !important;
  min-width: 100%;
}
/* All-percentage widths summing to exactly 100%. Fixed-px widths were
   leaving a right-side gap at screen widths above ~1559px because the
   sum (275px + 79%) fell BELOW 100% of the table width. Pure
   percentages always fill to 100% regardless of screen size.
   min-width on the narrow columns keeps them usable on small screens. */
.petty-cash-table .col-date    { width: 6%;  min-width: 60px; }
.petty-cash-table .col-trans   { width: 23%; }
.petty-cash-table .col-total   { width: 9%;  min-width: 80px; }
.petty-cash-table .col-status  { width: 26%; }
.petty-cash-table .col-preview { width: 27%; }
.petty-cash-table .col-actions { width: 9%;  min-width: 108px; text-align: right; white-space: nowrap; }

/* Status cell pills — `.summary-meta` is display:flex + flex-wrap,
   so if the 3 pills (Pending / Receipt #NNN / paperclip "Receipt")
   don't all fit on one line, they stack and the row grows to ~100px
   tall. The wider .col-status above gives them the room they need.
   Long receipt numbers (e.g. Temu order IDs like
   PO-012-06642009928313899 = 25+ chars) would otherwise make a single
   pill wrap internally to 2 lines; clamp + ellipsis keeps the pill
   single-line. The full number is still visible in the detail panel
   on expand. */
.petty-cash-table .summary-meta .meta-pill {
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Tbody Actions cell inherits the column width from fixed-layout; still
   right-align + nowrap so the icons hug the right edge even when the
   row content wraps onto two lines. */
.petty-cash-table tbody td.maintenance-actions { text-align: right; white-space: nowrap; }

/* Whole row opens the edit overlay on click (see overlay.js
   row-level `data-overlay-url` handling). cursor + subtle hover
   tint make it obvious the row is interactive without changing
   the existing grouped layout. */
.petty-cash-table tr.pc-clickable { cursor: pointer; }
.petty-cash-table tr.pc-clickable:hover td:not(.filter-only-col) {
  background: rgba(222, 90, 65, 0.05);
}

.petty-cash-table .date-cell-stacked { line-height: 1.05; }
.petty-cash-table .date-cell-stacked .date-main { font-size: var(--fs-md); }
.petty-cash-table .date-cell-stacked .date-year { font-size: var(--fs-xs); }

/* ── Terminated Enrolments table ───────────────────────────────────────
   Same hidden-column gotcha as .petty-cash-table — the `Centre` th is
   `display:none` (filter-only-col) and would silently steal width from
   the visible columns under `table-layout: fixed`. Pin every visible
   column with explicit widths summing to 100% so the hidden col gets
   nothing left over to claim. See CLAUDE.md → "Hidden table columns
   silently ruin table-layout: fixed layouts" for the long version. */
.terminated-table {
  table-layout: fixed;
  width: 100% !important;
  min-width: 100%;
}
.terminated-table .col-child   { width: 22%; min-width: 200px; }
.terminated-table .col-started { width: 11%; min-width: 95px; }
.terminated-table .col-ended   { width: 13%; min-width: 110px; }
.terminated-table .col-days    { width: 10%; min-width: 80px; }
.terminated-table .col-room    { width: 14%; min-width: 110px; }
.terminated-table .col-reason  { width: 22%; }
.terminated-table .col-actions { width: 8%;  min-width: 72px; text-align: right; white-space: nowrap; }
.terminated-table tbody td.maintenance-actions { text-align: right; white-space: nowrap; }

/* New Enrolments table — hidden .filter-only-col Centre + 8 visible columns.
   Every visible column gets an explicit width; widths intentionally sum to
   >100% so the browser scales them to fit and the hidden column can't claim
   leftover space (see the hidden-column gotcha in CLAUDE.md). */
.new-enrolments-table {
  table-layout: fixed;
  width: 100% !important;
  min-width: 100%;
}
.new-enrolments-table .col-child   { width: 20%; min-width: 180px; }
.new-enrolments-table .col-started { width: 12%; min-width: 110px; }
.new-enrolments-table .col-days    { width: 9%;  min-width: 80px; }
.new-enrolments-table .col-session { width: 13%; min-width: 100px; }
.new-enrolments-table .col-room    { width: 14%; min-width: 110px; }
.new-enrolments-table .col-type    { width: 13%; min-width: 100px; }
.new-enrolments-table .col-issues  { width: 22%; min-width: 150px; }
.new-enrolments-table .col-actions { width: 9%;  min-width: 72px; text-align: right; white-space: nowrap; }
.new-enrolments-table tbody td.maintenance-actions { text-align: right; white-space: nowrap; }

/* ── Utilisation tables (By-Week + By-Room) ────────────────────────────
   Both tables hide the `Centre` column via `filter-only-col` so the
   advanced-filter UI can target it without it being visible. Same gotcha
   as petty-cash + terminated: under `table-layout: fixed`, a hidden col
   with `width: auto` silently steals width from visible cols. Pin every
   visible col with an explicit % so the hidden one is left with nothing
   to claim. See CLAUDE.md → "Hidden table columns silently ruin
   table-layout: fixed layouts" for the long version + diagnostic.

   The two tables have different column shapes (week-down vs room-down),
   so they need separate width sets. Both sum to 100%. */
/* By-Week table: 10 visible columns + 1 filter-only Centre column.
   Widths intentionally sum to ~113% so percentages get scaled DOWN to
   fit the container — the only reliable way under `table-layout: fixed`
   when one column is `display:none`. NEVER let this sum drop below
   100%; see CLAUDE.md "Hidden table columns silently ruin table-layout:
   fixed layouts" for the long version. */
.utilisation-week-table {
  table-layout: fixed;
  width: 100% !important;
  min-width: 100%;
}
.utilisation-week-table .col-week     { width: 11%; min-width: 90px; }
.utilisation-week-table .col-rooms    { width: 6%;  min-width: 50px; }
.utilisation-week-table .col-bookings { width: 9%;  min-width: 75px; }
.utilisation-week-table .col-places   { width: 9%;  min-width: 75px; }
.utilisation-week-table .col-spare    { width: 8%;  min-width: 65px; }
.utilisation-week-table .col-peak     { width: 16%; min-width: 110px; }
.utilisation-week-table .col-trend    { width: 11%; min-width: 85px; }
.utilisation-week-table .col-yoy      { width: 11%; min-width: 85px; }
.utilisation-week-table .col-pct      { width: 14%; min-width: 90px; }
.utilisation-week-table .col-actions  { width: 11%; min-width: 80px; text-align: right; white-space: nowrap; }
.utilisation-week-table tbody td.maintenance-actions { text-align: right; white-space: nowrap; }
/* Sum of visible cols: 11+6+9+9+8+16+11+11+14+11 = 106% (>100% target) */

/* By-Room table: 9 visible columns + 1 filter-only Centre column.
   Same >100% rule applies. The trend-style cols (vs Centre + Rank) sit
   between Best and the headline Avg week %; full room-level trends
   (4w / vs LY) live in the expanded detail box, not on the row. */
.utilisation-room-table {
  table-layout: fixed;
  width: 100% !important;
  min-width: 100%;
}
.utilisation-room-table .col-room      { width: 24%; min-width: 180px; }
.utilisation-room-table .col-weeks     { width: 6%;  min-width: 55px; }
.utilisation-room-table .col-places    { width: 9%;  min-width: 80px; }
.utilisation-room-table .col-latest    { width: 10%; min-width: 90px; }
.utilisation-room-table .col-best      { width: 10%; min-width: 90px; }
.utilisation-room-table .col-vs-centre { width: 14%; min-width: 110px; }
.utilisation-room-table .col-rank      { width: 10%; min-width: 80px; }
.utilisation-room-table .col-pct       { width: 13%; min-width: 90px; }
.utilisation-room-table .col-actions   { width: 10%; min-width: 80px; text-align: right; white-space: nowrap; }
.utilisation-room-table tbody td.maintenance-actions { text-align: right; white-space: nowrap; }
/* Sum of visible cols: 24+6+9+10+10+14+10+13+10 = 106% (>100% target) */

/* Footer summary row inside each centre group. Subtle separator + a
   slightly muted background so it reads as "summary, not data". */
.utilisation-week-table tr.totals-row td,
.utilisation-room-table tr.totals-row td {
  background: #fff7f4;
  border-top: 2px solid rgba(222, 90, 65, 0.35);
  font-size: var(--fs-sm);
}

/* ── Trend deltas (WoW, YoY, 4-week) ──────────────────────────────────
   Used by all three trend columns on the utilisation page. Green for
   improvement, red for decline, muted dash for "no reference" or
   near-zero. Inline-flex keeps the arrow + magnitude on one line and
   prevents the cell from wrapping awkwardly when space is tight. */
.trend {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  font-size: var(--fs-sm);
  font-weight: 600;
  white-space: nowrap;
}
.trend-up   { color: #15803d; }   /* green-700 */
.trend-down { color: #b91c1c; }   /* red-700 */
.trend-flat { color: var(--ink-500, #888); font-weight: 500; }

/* ── View-mode segmented control (By Week / By Room) ──────────────────
   Sits inside `.page-toolbar-actions` to the LEFT of the search +
   advanced-filter UI. Active button picks up the brand coral; inactive
   stays neutral on a subtle background so the pair reads as a single
   unit. */
.view-toggle {
  display: inline-flex;
  border: 1px solid var(--paper-300, #e5d8c8);
  background: var(--paper-50, #fbf6ee);
  border-radius: 999px;
  padding: 2px;
  gap: 2px;
}
.view-toggle-btn {
  display: inline-block;
  padding: 0.4rem 0.95rem;
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink-700, #4a4030);
  text-decoration: none;
  border-radius: 999px;
  transition: background 0.12s, color 0.12s;
}
.view-toggle-btn:hover { background: rgba(222, 90, 65, 0.08); }
.view-toggle-btn.active {
  background: var(--kal-coral, #DE5A41);
  color: #fff;
  cursor: default;
}
.view-toggle-btn.active:hover { background: var(--kal-coral, #DE5A41); }

/* Per-centre summary footer (month-scoped tabs only — Last Month /
   This Month / Last Month to Today). Implemented as a single
   full-span <td> with flex/grid inside so the layout is independent
   of the main-table's 9-column widths. The previous tfoot used
   colspan and inherited column widths, which put the GST value way
   too far right and caused the "GST $X.XX" label to wrap. */
.pc-foot .pc-foot-cell {
  background: #fff3ef;
  border-top: 2px solid var(--kal-coral);
  padding: 0;
}
.pc-foot-summary {
  display: flex;
  align-items: baseline;
  gap: 2rem;
  padding: 0.85rem 1rem;
  flex-wrap: wrap;
}
.pc-foot-summary-label {
  flex: 1 1 auto;
  font-weight: 600;
  color: var(--ink-900);
  font-size: var(--fs-base);
  min-width: 200px;
}
.pc-foot-summary-label strong {
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-900);
}
.pc-foot-summary-total,
.pc-foot-summary-gst {
  display: inline-flex;
  align-items: baseline;
  gap: 0.45rem;
  white-space: nowrap;
}
.pc-foot-summary-total strong,
.pc-foot-summary-gst strong {
  font-size: var(--fs-lg);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink-900);
}
.pc-foot-mini-label {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-500);
  font-weight: 600;
}

/* Category breakdown — CSS grid, 3 columns: name | amount | GST.
   The grid template uses the SAME proportions as a typical table
   (name takes remainder, amount + GST fixed) so values sit under the
   summary totals above. */
.pc-foot-cat {
  background: var(--bg-cream);
  border-top: 1px dashed var(--ink-200);
}
.pc-foot-cat-row {
  display: grid;
  grid-template-columns: 1fr 140px 120px;
  gap: 1rem;
  padding: 0.45rem 1rem;
  font-size: var(--fs-sm);
  color: var(--ink-800);
  align-items: baseline;
}
.pc-foot-cat-row + .pc-foot-cat-row {
  border-top: 1px solid var(--ink-100);
}
.pc-foot-cat-head {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-500);
  font-weight: 700;
  background: var(--ink-50);
}
.pc-foot-cat-name { font-weight: 600; }
.pc-foot-cat-count {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 0.05rem 0.45rem;
  border-radius: 10px;
  background: var(--ink-100);
  color: var(--ink-600);
  font-size: var(--fs-xs);
  font-weight: 500;
}

/* Receipt viewer overlay — full-viewport image/PDF preview opened by
   clicking the Receipt pill on the list. Fixed positioning ignores the
   host layout's padding so the file fills the iframe completely. */
.receipt-viewer {
  position: fixed;
  inset: 0;
  background: #111;
  overflow: hidden;
  z-index: 1;
}
.receipt-viewer-pdf {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}
.receipt-viewer-image {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 0.5rem;
  box-sizing: border-box;
}
.receipt-viewer-image img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
/* Fallback escape-hatch link surfaced only over the PDF viewer —
   sits top-right so the embedded PDF still gets almost the full
   viewport while users whose browsers/extensions refuse to render
   PDFs in iframes can one-click to a native tab. */
.receipt-viewer-open {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  padding: 0.4rem 0.9rem;
  background: rgba(255, 255, 255, 0.92);
  color: var(--kal-coral-deep);
  font-weight: 600;
  font-size: var(--fs-sm);
  text-decoration: none;
  border-radius: 999px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
  z-index: 2;
}
.receipt-viewer-open:hover { background: #fff; }

/* ═══════════════════════════════════
   QBO push dialog (petty-cash list)
   ═══════════════════════════════════
   Simple modal used by the AJAX "Push to QBO" flow — three states:
   confirm, pushing, result (success or failure). The <pre> block
   surfaces the server-side error text verbatim so the user can
   actually read WHY a push failed (previously buried in a tooltip
   on a tiny red pill). */
.qbo-dialog {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: center;
}
.qbo-dialog[hidden] { display: none; }
body.qbo-dialog-open { overflow: hidden; }
.qbo-dialog-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(45, 35, 25, 0.55);
}
.qbo-dialog-panel {
  position: relative;
  background: var(--paper);
  border-radius: 14px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
  padding: 1.5rem 1.75rem;
  width: min(560px, calc(100vw - 2rem));
  max-height: calc(100vh - 3rem);
  overflow: auto;
  text-align: left;
}
.qbo-dialog-title {
  margin: 0 0 0.75rem;
  font-size: var(--fs-xl);
  color: var(--ink-900);
}
.qbo-dialog-body p { margin: 0 0 0.75rem; color: var(--ink-800); }
.qbo-dialog-body .qbo-dialog-error {
  background: #fdf3f0;
  border: 1px solid var(--kal-coral-soft);
  border-left: 4px solid var(--kal-coral-deep);
  padding: 0.75rem 0.9rem;
  border-radius: 6px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--fs-sm);
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--ink-900);
  margin: 0 0 0.5rem;
}
.qbo-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 1rem;
}
.qbo-dialog-actions:empty { display: none; }
.qbo-dialog-spinner {
  width: 36px;
  height: 36px;
  margin: 0.75rem auto 0;
  border-radius: 50%;
  border: 3px solid var(--ink-100);
  border-top-color: var(--kal-coral);
  animation: qbo-spin 0.8s linear infinite;
}
@keyframes qbo-spin { to { transform: rotate(360deg); } }
.no-wrap { white-space: nowrap; }
.html-content { line-height: 1.55; word-break: break-word; color: var(--ink-700); }
.html-content p { margin: 0 0 0.25rem; }
.html-content strong { font-weight: 700; color: var(--ink-900); }

.page-full-width { max-width: 100%; }

/* ═══════════════════════════════════
   MAINTENANCE TABLE (page-specific tweaks)
   ═══════════════════════════════════ */

.maintenance-table { table-layout: fixed; width: 100% !important; min-width: 100%; }
.maintenance-table td { vertical-align: top; white-space: normal; word-wrap: break-word; }
.maintenance-table .detail-row { display: block; width: 100%; }
.maintenance-table .detail-row[hidden] { display: none !important; }
.maintenance-table .detail-row > td { display: block; width: 100%; box-sizing: border-box; }
.maintenance-table .col-date { width: 112px; }
.maintenance-table .col-delegation { width: 130px; }
.maintenance-table .col-location { width: 160px; font-size: var(--fs-base); }
.maintenance-table .col-desc { width: 22%; }
.maintenance-table .col-prev { width: 70px; }
.maintenance-table .col-progress { width: 22%; }
.maintenance-table .col-after { width: 12%; }
.maintenance-table .col-img { width: 110px; text-align: center; }
.maintenance-table .col-actions { width: 104px; text-align: right; white-space: nowrap; }

.debt-insights-panel {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 1rem;
  margin-bottom: 1.25rem;
  padding: 1rem 1.15rem;
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}
.debt-insights-summary { display: flex; flex-direction: column; gap: 0.85rem; }
.debt-insight-stat { display: flex; flex-direction: column; gap: 0.15rem; }
.debt-insight-value {
  font-size: var(--fs-2xl);
  font-weight: 700;
  color: var(--ink-900);
  font-variant-numeric: tabular-nums;
}
.debt-insight-label {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-700);
}
.debt-insight-hint { font-size: var(--fs-sm); color: var(--ink-700); }
.debt-aging-bars {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 0.5rem;
  margin-top: 0.35rem;
}
.debt-aging-item {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.45rem 0.5rem;
  background: var(--cream, #fbf7f3);
  border-radius: var(--radius-md, 8px);
  border: 1px solid var(--border);
}
.debt-aging-item-label { font-size: var(--fs-xs); font-weight: 600; color: var(--ink-700); }
.debt-aging-item-value { font-size: var(--fs-sm); font-weight: 700; font-variant-numeric: tabular-nums; }
.debt-top-list {
  list-style: none;
  margin: 0.35rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.debt-top-list li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.75rem;
  font-size: var(--fs-sm);
  border-bottom: 1px dashed var(--border);
  padding-bottom: 0.35rem;
}
.debt-top-list li:last-child { border-bottom: none; padding-bottom: 0; }
.debt-top-family { color: var(--ink-900); }
.debt-top-amount { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
@media (max-width: 900px) {
  .debt-insights-panel { grid-template-columns: 1fr; }
  .debt-aging-bars { grid-template-columns: repeat(2, 1fr); }
}

.debts-table { table-layout: fixed; width: 100% !important; min-width: 100%; }
.debts-table td { vertical-align: top; white-space: normal; word-wrap: break-word; }
.debts-table .col-family  { width: 22%; }
.debts-table .col-total   { width: 140px; white-space: nowrap; }
.debts-table .col-status  { width: 200px; }
.debts-table .col-preview { width: auto; }
.debts-table .col-actions { width: 136px; text-align: right; white-space: nowrap; }

.maintenance-table tbody td:first-child {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* Split-date cell — big dd/mm + muted yyyy */
.date-cell-stacked { display: flex; flex-direction: column; line-height: 1.1; }
.date-cell-stacked .date-main {
  font-size: var(--fs-lg);
  font-weight: 700;
  color: var(--ink-900);
  font-variant-numeric: tabular-nums;
}
.date-cell-stacked .date-year {
  font-size: var(--fs-sm);
  color: var(--ink-500);
  font-weight: 500;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}
/* Overdue tints the stacked date coral without forcing a single-line block */
.date-cell-stacked.is-overdue .date-main { color: var(--kal-coral-deep); }
.date-cell-stacked.is-overdue .date-year { color: var(--kal-coral); }

.maintenance-location { line-height: 1.4; font-weight: 600; color: var(--ink-900); }

/* Dark asset-count pill (V2) */
.asset-count-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.2rem 0.65rem;
  background: var(--ink-900);
  color: var(--white);
  border-radius: 999px;
  font-size: var(--fs-sm);
  font-weight: 700;
}
.asset-count-pill::before {
  content: '📎';   /* simple paperclip glyph — no extra SVG asset */
  font-size: var(--fs-xs);
  opacity: 0.95;
}

/* Insurance table */
.insurance-table { table-layout: fixed; width: 100%; }
.insurance-table td { vertical-align: top; white-space: normal; word-wrap: break-word; }
.insurance-table .col-centre { width: 60px; }
.insurance-table .col-type { width: 80px; }
.insurance-table .col-date { width: 95px; }
.insurance-table .col-claim { width: 110px; }
.insurance-table .col-injury { width: 12%; }
.insurance-table .col-staff { width: 10%; }
.insurance-table .col-desc { width: auto; }
.insurance-table .col-actions { width: 80px; text-align: center; white-space: nowrap; }

/* Quill — restyle to sit on paper */
.quill-editor {
  background: var(--paper);
  border-radius: 0 0 8px 8px;
  font-family: inherit;
  font-size: var(--fs-lg);
}
.quill-editor .ql-editor { min-height: 120px; color: var(--ink-900); }
.quill-sm .ql-editor { min-height: 60px; }
.ql-toolbar.ql-snow { border-radius: 8px 8px 0 0; border-color: var(--border-strong); background: var(--ink-50); }
.ql-container.ql-snow { border-color: var(--border-strong); }

.maint-summary {
  background: var(--ink-50);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1rem 1.1rem;
}
.maint-summary-row { display: flex; gap: 2rem; flex-wrap: wrap; margin-bottom: 0.75rem; font-size: var(--fs-base); }
.maint-summary-desc { font-size: var(--fs-base); }
.maint-summary-desc .html-content {
  margin-top: 0.25rem;
  padding: 0.6rem 0.75rem;
  background: var(--paper);
  border-radius: 8px;
  border: 1px solid var(--border);
}

.overdue-date {
  background: var(--kal-coral) !important;
  color: var(--white) !important;
  font-weight: 700;
  border-radius: 8px;
  padding: 0.3rem 0.55rem;
}

/* Image thumbnails */
.img-cell { white-space: normal; vertical-align: top; }
.img-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3px;
  height: 100%;
}
.thumb {
  width: 100%; height: 100%; min-height: 40px;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid var(--border);
  cursor: pointer;
  transition: transform 0.15s;
  display: block;
}
.thumb:hover { transform: scale(2); z-index: 10; position: relative; }
.img-grid.single { grid-template-columns: 1fr; }

.currency { text-align: right; font-variant-numeric: tabular-nums; }
/* Header cells also right-align so column labels sit above their values. */
.data-table thead th.currency { text-align: right; }
/* `.currency.money-col` — narrow, decimal-aligned currency column with a
   centred header. Width is fixed to fit `$XXX,XXX.XX` at tabular-nums. */
.data-table th.currency.money-col { text-align: center; }
.data-table .currency.money-col { width: 9rem; white-space: nowrap; }
.currency.negative { color: var(--kal-coral-deep); }
.currency.is-reverse { color: var(--kal-coral-deep); font-weight: 600; }
.total-row td { background: var(--ink-50); border-top: 2px solid var(--border); font-weight: 700; }

/* Reverse (refund / reimburse) rows in the petty cash list: tinted
   background + coral left border so they're visually unmistakable as
   money flowing IN, not OUT. Hover intensifies slightly. */
.summary-row.is-reverse-row td {
  background: #fef3f0;
  border-left: none;
}
.summary-row.is-reverse-row td:first-child {
  border-left: 3px solid var(--kal-coral-deep);
}
.summary-row.is-reverse-row:hover td { background: #fde6e0; }
.summary-row.is-reverse-row .summary-subtitle { color: var(--kal-coral-deep); }
/* Refund pill — coral background, distinct from the amber "pending"
   pill so admins don't confuse "refund row" with "needs verification". */
.meta-pill.refund-pill {
  background: #fde6e0;
  color: var(--kal-coral-deep);
  border-color: var(--kal-coral-deep);
  margin-left: 0.4rem;
  font-weight: 600;
  letter-spacing: 0.03em;
}

/* Multi-category receipt lines: left-edge border ties sibling rows
   together visually without changing the row structure. Reduces the
   between-row gap so a 3-line receipt reads as one unit. The pill
   in the category cell labels each line's position (1/3 etc.). */
.summary-row.is-group-member td {
  border-left: none;
}
.summary-row.is-group-member td:first-child {
  border-left: 3px solid var(--kal-coral);
}
.summary-row.is-group-member:not(.is-group-first) td { padding-top: 0.4rem; }
.summary-row.is-group-member:not(.is-group-last) td { padding-bottom: 0.4rem; border-bottom-color: transparent; }
/* Multi-line receipts render as a two-tier structure:
     - one .pc-group-header row at the top of the group (supplier
       name, group pill, receipt total, status, notes, actions)
     - one .pc-line-row per DB line below it (description + per-line
       amount only; receipt-level cells stay blank)
   Both rows share the coral left stripe + subtle tint so the group
   visually reads as one card. The header sits flush to the lines
   beneath; the lines are slightly indented + use the smaller
   .summary-note badge style for their description. */
.summary-row.is-group-member { background: rgba(222, 90, 65, 0.025); }
/* Header row carries the bulk of the visual weight — supplier name
   in the default bold .summary-title, receipt total prominent. No
   special CSS needed beyond what .summary-title already provides. */
.summary-row.pc-group-header { /* baseline already covered by .is-group-member tint + .summary-title bold */ }
/* Multi-line line rows — slight left indent on the Transaction cell
   so they visually nest under the header above them. :nth-child(5)
   is the Transaction column (1=Centre filter-only, 2=Date,
   3=Category filter-only, 4=Supplier filter-only, 5=Transaction,
   6=Amount, 7=Status, 8=Preview, 9=Actions). */
.summary-row.pc-line-row > td:nth-child(5) {
  padding-left: 1.5rem;
}
.meta-pill.group-pill {
  background: #fff7ed;
  color: #9a3412;
  border-color: #fdba74;
  margin-left: 0.4rem;
  font-weight: 500;
}

.completed-row td { background: var(--kal-green-tint) !important; }
.completed-row:hover td { background: #d5ead9 !important; }

.warning-icon {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--kal-amber);
  color: var(--ink-900);
  border-radius: 50%;
  width: 18px; height: 18px;
  font-size: var(--fs-2xs); font-weight: 700;
  margin-right: 4px;
}
.text-muted { color: var(--ink-500); }

/* ═══════════════════════════════════
   USER MANAGEMENT
   ═══════════════════════════════════ */

.role-badge {
  display: inline-block;
  padding: 0.18rem 0.55rem;
  border-radius: 999px;
  font-size: var(--fs-sm);
  font-weight: 700;
  text-transform: capitalize;
  letter-spacing: 0.03em;
}
.role-admin { background: var(--kal-coral-tint); color: var(--kal-coral-deep); }
.role-owner { background: var(--kal-amber-tint); color: #8a5c1b; }
.role-head_office { background: #ede0f3; color: #5b2a84; }
.role-centre { background: #d9ecf5; color: #0f4b6b; }
.role-marketing { background: #fbe1c7; color: #8a441a; }
.role-maintenance { background: var(--ink-100); color: var(--ink-700); }

.status-badge {
  display: inline-block;
  padding: 0.18rem 0.55rem;
  border-radius: 999px;
  font-size: var(--fs-sm);
  font-weight: 700;
  text-transform: capitalize;
  letter-spacing: 0.03em;
}
.status-active { background: var(--kal-green-tint); color: var(--kal-green-deep); }
.status-inactive { background: var(--kal-coral-tint); color: var(--kal-coral-deep); }

.action-cell { white-space: nowrap; }
.action-cell form { display: inline; }

.centre-checkboxes {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 0.35rem;
}
.checkbox-label {
  display: flex; align-items: center;
  gap: 0.45rem;
  font-size: var(--fs-base);
  padding: 0.35rem 0.55rem;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.1s;
}
.checkbox-label:hover { background: var(--kal-coral-wash); }

.form-hint {
  font-size: var(--fs-sm);
  color: var(--ink-500);
  margin-bottom: 0.5rem;
}

.form-hint-banner {
  padding: 0.75rem 1rem;
  background: var(--kal-coral-wash);
  border-left: 3px solid var(--kal-coral);
  color: var(--ink-800);
  font-size: var(--fs-base);
  border-radius: 8px;
  margin-bottom: 1rem;
}

.form-group input:disabled,
.form-group select:disabled,
.form-group textarea:disabled {
  background: var(--ink-50);
  color: var(--ink-700);
  cursor: not-allowed;
  opacity: 1;
}

.form-readonly-box {
  padding: 0.6rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--ink-50);
  color: var(--ink-800);
  font-size: var(--fs-lg);
  min-height: 2.4rem;
}
.form-readonly-box .thumb-list { margin: 0; }

/* ─── Maintenance audit log ─── */
.maintenance-audit-card { margin-top: 1rem; }
.audit-list { list-style: none; padding: 0; margin: 0.5rem 0 0; }
.audit-entry { padding: 0.75rem 0; border-top: 1px dashed var(--border); }
.audit-entry:first-child { border-top: none; padding-top: 0; }
.audit-header {
  display: flex; align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  font-size: var(--fs-base);
  margin-bottom: 0.4rem;
}
.audit-header .meta-pill { font-size: var(--fs-sm); }
.audit-summary { font-size: var(--fs-base); }
.audit-changes { list-style: none; padding: 0; margin: 0; }
.audit-change { padding: 0.4rem 0; font-size: var(--fs-base); }
.audit-change + .audit-change { border-top: 1px dashed var(--border); }
.audit-diff { margin-top: 0.2rem; }
.audit-from, .audit-to {
  display: block;
  padding: 0.15rem 0.45rem;
  border-radius: 6px;
  text-decoration: none;
  font-family: inherit;
}
.audit-from {
  background: rgba(217, 79, 58, 0.1);
  color: var(--kal-coral-deep);
  text-decoration: line-through;
}
.audit-to {
  background: rgba(74, 159, 95, 0.12);
  color: var(--kal-green-deep);
}

/* ─── Combobox ─── */
.combobox { position: relative; }
.combobox > input { width: 100%; }
.combobox-list {
  position: absolute;
  top: calc(100% + 2px);
  left: 0; right: 0;
  z-index: 20;
  margin: 0;
  padding: 0.3rem 0;
  list-style: none;
  background: var(--paper);
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  box-shadow: var(--shadow);
  max-height: 240px;
  overflow-y: auto;
}
.combobox-option {
  padding: 0.5rem 0.85rem;
  font-size: var(--fs-base);
  color: var(--ink-800);
  cursor: pointer;
  transition: background 0.1s;
}
.combobox-option:hover,
.combobox-option.is-active {
  background: var(--kal-coral-wash);
  color: var(--kal-coral-deep);
}

/* ═══════════════════════════════════
   PAGINATION
   ═══════════════════════════════════ */

.pagination-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
  padding: 0.85rem 0;
  margin: 1rem 0 1.25rem;
  border-top: 1px dashed var(--border);
}
.pagination-info {
  font-size: var(--fs-md);
  color: var(--ink-500);
}
.pagination-info strong { color: var(--ink-900); font-weight: 600; }
.pagination-controls { display: flex; gap: 0.25rem; align-items: center; }
.pagination-controls .btn.btn-sm {
  min-width: 36px;
  height: 36px;
  padding: 0 0.65rem;
  border-radius: 999px;
  background: var(--paper);
  border: 1px solid var(--border);
  color: var(--ink-800);
  font-weight: 500;
}
.pagination-controls .btn.btn-sm.btn-primary {
  background: var(--kal-coral);
  color: var(--white);
  border-color: var(--kal-coral);
  font-weight: 700;
  box-shadow: 0 4px 10px rgba(217, 79, 58, 0.25);
}
.pagination-size {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  font-size: var(--fs-md);
  color: var(--ink-500);
}
.pagination-size .btn.btn-sm {
  width: 36px;
  height: 36px;
  padding: 0;
  border-radius: 999px;
  background: var(--paper);
  border: 1px solid var(--border);
  color: var(--ink-800);
  font-weight: 500;
}
.pagination-size .btn.btn-sm.btn-primary {
  background: var(--kal-coral);
  color: var(--white);
  border-color: var(--kal-coral);
  font-weight: 700;
}

/* ═══════════════════════════════════
   ERROR PAGE
   ═══════════════════════════════════ */

.error-page { text-align: center; padding: 4rem 1rem; }
.error-page h1 { font-size: var(--fs-err); margin-bottom: 0.5rem; color: var(--ink-500); letter-spacing: -0.02em; }
.error-page p { margin-bottom: 2rem; color: var(--ink-700); }

/* ═══════════════════════════════════
   FOOTER
   ═══════════════════════════════════ */

.footer {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  padding: 1.5rem;
  margin-top: 2rem;
  border-top: 1px dashed var(--border-strong);
}
.footer-logo { height: 22px; width: auto; opacity: 0.4; }
.version { font-size: var(--fs-sm); color: var(--ink-500); font-variant-numeric: tabular-nums; }

/* ═══════════════════════════════════
   INCOME PIVOT (months-as-columns table on /financial/income)
   Metric label in the sticky first column; one column per month of data.
   Horizontal scroll kicks in when month count exceeds viewport width.
   ═══════════════════════════════════ */

.income-pivot-scroll { overflow-x: auto; }
.income-pivot { width: 100%; table-layout: auto; }
.income-pivot thead th,
.income-pivot tbody td { white-space: nowrap; }
.income-pivot .income-pivot-label {
  position: sticky; left: 0;
  background: var(--paper);
  z-index: 1;
  text-align: left;
  font-weight: 600;
  color: var(--ink-700);
}
.income-pivot thead th.income-pivot-label {
  background: var(--ink-50);
}
.income-pivot tr.total-row .income-pivot-label {
  background: var(--ink-50);
}
.income-pivot .income-pivot-month {
  text-align: right;
  vertical-align: bottom;
  padding-top: 0.9rem;
  padding-bottom: 0.5rem;
  color: var(--ink-800);
  font-weight: 600;
}
.income-pivot .income-pivot-month-name {
  display: block;
  font-size: var(--fs-sm);
  letter-spacing: 0.02em;
}
.income-pivot .income-pivot-month .meta-pill {
  display: inline-block;
  margin-top: 0.25rem;
  font-size: var(--fs-xs);
}
.income-pivot .income-pivot-month.is-current {
  color: var(--kal-coral-deep);
}
.income-pivot tbody td.currency {
  padding-left: 1rem;
}

/* ═══════════════════════════════════
   KAL CHART (shared list-page line-chart primitive)
   Used by Debts (weekly) and Income (monthly). Driven by public/js/kal-chart.js.
   ═══════════════════════════════════ */

.kal-chart-card {
  background: var(--paper);
  border: 1px solid var(--border-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 1rem 1.25rem 1.25rem;
  margin: 0 0 1rem;
}
.kal-chart-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
}
.kal-chart-title {
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--ink-900);
  margin: 0;
}
.kal-chart-range {
  font-size: var(--fs-sm);
  color: var(--ink-700);
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.kal-chart-range select {
  border: 1px solid var(--border-light);
  background: #fff;
  border-radius: var(--radius-sm);
  padding: 0.25rem 0.5rem;
  font: inherit;
  color: var(--ink-800);
  cursor: pointer;
}
.kal-chart-canvas-wrap {
  position: relative;
  height: 360px;
  width: 100%;
}
.kal-chart-canvas-wrap canvas { display: block; width: 100% !important; height: 100% !important; }
.kal-chart-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--ink-500);
  font-size: var(--fs-sm);
}
.kal-chart-empty[hidden] { display: none; }
.kal-chart-legend-tools {
  display: flex;
  gap: 0.4rem;
  margin-top: 0.9rem;
}
.kal-chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.4rem;
}
.kal-chart-legend-pill {
  --pill-color: var(--ink-400);
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.2rem 0.6rem;
  background: #fff;
  border: 1px solid var(--border-light);
  border-bottom: 2px solid var(--pill-color);
  border-radius: 999px;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--ink-800);
  cursor: pointer;
  transition: opacity 0.12s, background 0.12s;
}
.kal-chart-legend-pill:hover { background: var(--ink-50); }
.kal-chart-legend-pill .legend-dot {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--pill-color);
  display: inline-block;
}
.kal-chart-legend-pill.is-hidden {
  opacity: 0.4;
  border-bottom-color: var(--ink-300);
  text-decoration: line-through;
}
.kal-chart-legend-pill.is-hidden .legend-dot { background: var(--ink-300); }

/* ═══════════════════════════════════
   RESPONSIVE
   ═══════════════════════════════════ */

/* ═══════════════════════════════════
   IMPERSONATION BANNER
   ═══════════════════════════════════ */

.impersonation-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  background: #c0392b;
  color: #fff;
  padding: 0.65rem 1.5rem;
  font-size: var(--fs-body);
  font-weight: 600;
  border-bottom: 2px solid #922b1d;
  box-shadow: 0 1px 6px rgba(0,0,0,0.15);
  letter-spacing: 0.01em;
}

.impersonation-banner strong {
  font-weight: 700;
  letter-spacing: 0.02em;
}

.impersonation-banner-text {
  flex: 1;
  line-height: 1.3;
}

.impersonation-banner-sub {
  font-weight: 400;
  opacity: 0.92;
  margin-left: 0.35rem;
}

.impersonation-banner-form {
  flex: 0 0 auto;
  margin: 0;
}

.impersonation-banner-btn,
.impersonation-banner .btn.btn-sm {
  background: #fff;
  color: #c0392b;
  border: 1px solid #fff;
  font-weight: 700;
  padding: 0.35rem 0.9rem;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.impersonation-banner-btn:hover,
.impersonation-banner .btn.btn-sm:hover {
  background: #f5ead7;
  color: #922b1d;
}

@media (max-width: 640px) {
  .impersonation-banner {
    flex-direction: column;
    align-items: stretch;
    text-align: center;
    padding: 0.6rem 0.9rem;
    gap: 0.5rem;
  }
  .impersonation-banner-form { display: flex; justify-content: center; }
}

@media (max-width: 768px) {
  .dashboard-grid { grid-template-columns: 1fr; }
  .notes-grid { grid-template-columns: 1fr; }
  .form-row { grid-template-columns: 1fr; }
  .top-nav { flex-wrap: wrap; height: auto; padding: 0.5rem 0.75rem; gap: 0.25rem; }
  .nav-items { flex-wrap: wrap; justify-content: center; }
  .nav-brand { margin-right: 0.5rem; }
  .nav-user-menu { margin-left: auto; }
  /* Nav height is variable on mobile (wraps). Drop sticky on the
     centre bar to avoid mis-aligned pinning under a taller nav. */
  .centre-bar { position: static; top: auto; }
  .welcome-banner h1 { font-size: var(--fs-3xl); }
  .main-content { padding: 1.25rem 1rem 2rem; }
  .page-title-header h2 { font-size: var(--fs-5xl); }
}

/* ═══════════════════════════════════
   AJAX live-update primitives
   (toast notifier, inline field errors,
    row flash + remove animations)
   ═══════════════════════════════════ */

/* Toast stack — fixed bottom-right corner of the viewport. */
#kal-toast-stack {
  position: fixed;
  bottom: 1.5rem;
  right: 1.5rem;
  z-index: 10000;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  pointer-events: none;
  max-width: min(90vw, 360px);
}

.kal-toast {
  pointer-events: auto;
  background: var(--paper);
  color: var(--ink-900);
  padding: 0.75rem 1rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  border-left: 4px solid var(--ink-500);
  box-shadow: 0 6px 16px rgba(29, 24, 19, 0.15);
  font-size: var(--fs-md);
  line-height: 1.4;
  cursor: pointer;
  opacity: 0;
  transform: translateX(20px);
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.kal-toast.is-visible { opacity: 1; transform: translateX(0); }
.kal-toast.is-leaving { opacity: 0; transform: translateX(20px); }

.kal-toast--success { border-left-color: var(--kal-green); }
.kal-toast--error   { border-left-color: var(--kal-coral-deep); }
.kal-toast--warning { border-left-color: var(--kal-amber); }
.kal-toast--info    { border-left-color: var(--ink-500); }

/* Inline form-field error messages painted by list-live.js on 422. */
.form-group.has-error input,
.form-group.has-error select,
.form-group.has-error textarea,
.form-group.has-error .ql-container {
  border-color: var(--kal-coral-deep) !important;
  background: var(--kal-coral-wash);
}
.form-error {
  display: block;
  margin-top: 0.25rem;
  color: var(--kal-coral-deep);
  font-size: var(--fs-sm);
  font-weight: 500;
}

/* Row flash on update — coral wash that fades back to normal. */
@keyframes kal-row-flash {
  0%   { background-color: var(--kal-coral-tint); }
  100% { background-color: transparent; }
}
.summary-row.is-flashing > td,
tr.is-flashing > td {
  animation: kal-row-flash 1.2s ease-out;
}

/* Row remove — fade out before the JS strips the element. */
.summary-row.is-removing,
tr.is-removing {
  opacity: 0;
  transition: opacity 0.2s ease;
}

/* Busy form — dim the controls while the fetch is in flight. */
form.is-busy { opacity: 0.7; pointer-events: none; }
form.is-busy button[disabled] { cursor: progress; }


/* ═══════════════════════════════════
   BILLS DASHBOARD (/financial/bills-{inc,exc}-kal)
   ═══════════════════════════════════ */

.bills-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 0.75rem;
  margin: 0.5rem 0 1rem;
}
.bills-summary { display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center; }
.bills-summary .meta-pill strong { font-weight: 700; }
.bills-toolbar .form-actions { display: flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; }

.bills-search {
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--ink-200, #e5e1d8);
  border-radius: 6px;
  font-size: var(--fs-sm);
  min-width: 240px;
}
.bills-search:focus { outline: 2px solid var(--kal-coral); outline-offset: -1px; }
.bills-method-filter {
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--ink-200, #e5e1d8);
  border-radius: 6px;
  background: #fff;
  font-size: var(--fs-sm);
}
.bills-bulk-select {
  white-space: nowrap;
}

.bills-centre-group { margin-bottom: 0.75rem; }
/* Centre summary sits inside the coral .centre-header gradient; var(--ink-500)
   grey-on-coral was unreadable. Use translucent white so the meta line still
   reads as secondary but holds enough contrast against the orange. */
.bills-centre-group .centre-meta {
  margin-left: 0.75rem;
  color: rgba(255, 255, 255, 0.92);
  font-weight: 500;
  font-size: var(--fs-sm);
}
.bills-centre-group .centre-meta strong {
  color: #fff;
  font-weight: 700;
}
.bills-centre-group .centre-code { font-weight: 700; }

.bills-method-group {
  margin: 0.5rem 0 0.5rem 0.5rem;
  border-left: 3px solid var(--kal-coral, #DE5A41);
  padding-left: 0.75rem;
}
.bills-method-group > summary {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.75rem;
  list-style: none;
  cursor: pointer;
  padding: 0.4rem 0;
  font-size: var(--fs-md);
}
.bills-method-group > summary::-webkit-details-marker { display: none; }
.bills-method-title {
  min-width: 0;
}
.bills-method-meta { margin-left: 0.6rem; color: var(--ink-500); font-size: var(--fs-sm); }
.bills-section-select {
  flex: 0 0 auto;
  min-height: 30px;
  min-width: 86px;
  padding: 0.3rem 0.7rem;
}

.bills-table-wrap { overflow-x: auto; }
.bills-table { width: 100%; }
.bills-table .num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.bills-table tbody tr.bills-row[hidden] { display: none; }
.bills-select-col,
.bills-doc-col,
.bills-select-cell,
.bills-doc-cell {
  width: 42px;
  text-align: center;
  white-space: nowrap;
}
.bills-select-cell input[type="checkbox"] {
  width: 18px;
  height: 18px;
  accent-color: var(--kal-coral, #DE5A41);
  cursor: pointer;
}
.bills-select-cell input[type="checkbox"]:disabled {
  cursor: not-allowed;
}
.bills-row--blocked {
  color: var(--ink-500, #888);
}
.bills-row--needs-fix {
  outline: 3px solid var(--kal-coral, #DE5A41);
  outline-offset: -3px;
  background: var(--kal-coral-wash, #fff4f1);
}
.bills-pay-block {
  margin-top: 0.2rem;
  color: var(--kal-coral-deep, #b83221);
  font-size: var(--fs-xs, 0.78rem);
  font-weight: 600;
}
.bills-invoice-btn {
  width: 30px;
  height: 30px;
}
.bills-bank-cell {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem;
  min-width: 170px;
}
.bills-bank-cell > span {
  min-width: 0;
  overflow-wrap: anywhere;
}
.bills-batch-bar {
  position: sticky;
  top: var(--bills-batch-top, 0.5rem);
  z-index: 98;
  display: grid;
  grid-template-columns: minmax(180px, 1fr) auto auto;
  align-items: center;
  gap: 0.75rem;
  margin: 0 0 1rem;
  padding: 0.75rem;
  background: rgba(255, 255, 255, 0.96);
  border: 1px solid var(--ink-200, #e5e1d8);
  border-left: 4px solid var(--kal-coral, #DE5A41);
  border-radius: 8px;
  box-shadow: 0 10px 30px rgba(29, 24, 19, 0.12);
  backdrop-filter: blur(6px);
}
.bills-batch-bar[hidden] { display: none; }
.bills-batch-bar.is-empty {
  box-shadow: none;
  border-left-color: var(--ink-200, #e5e1d8);
}
.bills-batch-summary {
  display: grid;
  gap: 0.15rem;
  text-align: left;
}
.bills-batch-summary span {
  color: var(--ink-500, #777);
  font-size: var(--fs-sm);
}
.bills-batch-total {
  display: grid;
  gap: 0.1rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.bills-batch-total span {
  color: var(--ink-500, #777);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.bills-batch-total strong {
  font-size: var(--fs-lg, 1.1rem);
}

.bills-line-inline { color: var(--ink-700); font-size: var(--fs-sm); }
.bills-line-detail { font-size: var(--fs-sm); }
.bills-line-detail summary { cursor: pointer; color: var(--kal-coral); }
.bills-line-detail ul { margin: 0.4rem 0 0.2rem 1.1rem; padding: 0; }
.bills-line-detail li { padding: 0.2rem 0; }
.bills-line-desc { color: var(--ink-500); font-size: 0.92em; }

.bills-modal[hidden] {
  display: none;
}
.bills-modal {
  position: fixed;
  inset: 0;
  z-index: 2500;
  display: grid;
  place-items: center;
  padding: 1rem;
}
.bills-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(31, 26, 20, 0.42);
}
.bills-modal-panel {
  position: relative;
  z-index: 1;
  width: min(720px, 100%);
  max-height: min(760px, calc(100vh - 2rem));
  overflow: auto;
  background: #fff;
  border: 1px solid var(--ink-200, #e5e1d8);
  border-radius: 8px;
  box-shadow: 0 24px 70px rgba(29, 24, 19, 0.28);
  padding: 1rem;
}
.bills-modal-panel--wide {
  width: min(860px, 100%);
}
.bills-modal-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.85rem;
}
.bills-modal-head h3 {
  margin: 0;
  color: var(--kal-coral, #DE5A41);
}
.bills-modal-head p {
  margin: 0.25rem 0 0;
  color: var(--ink-500, #777);
  font-size: var(--fs-sm);
}
.bills-date-table input[type="date"] {
  min-width: 150px;
  padding: 0.4rem 0.55rem;
  border: 1px solid var(--ink-200, #e5e1d8);
  border-radius: 6px;
}
.bills-summary-preview {
  overflow-x: auto;
  padding: 0.75rem;
  border: 1px solid var(--ink-200, #e5e1d8);
  border-radius: 8px;
  background: var(--paper, #fdf9f5);
}
.bills-modal-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-top: 1rem;
}

@media (max-width: 720px) {
  .bills-batch-bar {
    grid-template-columns: 1fr;
    align-items: stretch;
  }
  .bills-batch-total {
    text-align: left;
  }
  .bills-batch-bar .btn {
    width: 100%;
  }
}

/* ─── PayGen live console (CI-log style) ─────────────────────────────
   Used by /payroll/paygen — the SSE stream renders one line per step
   as the run progresses so the user can see exactly which stage
   is active (FoundU pull, ABR lookup, SharePoint uploads, QBO post,
   ROB Excel writeback). Lives next to the existing alert/banner
   styles; level modifiers map onto the same palette as .meta-pill.
─────────────────────────────────────────────────────────────────── */
.paygen-console {
  margin: 1rem 0;
  background: var(--paper, #fdf9f5);
  border: 1px solid var(--ink-200, #e2dcd4);
  border-radius: var(--radius);
  overflow: hidden;
  font-size: var(--fs-sm);
  max-width: 1100px;
}
.paygen-console-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.5rem 0.9rem;
  background: linear-gradient(180deg, #fff 0%, var(--paper, #fdf9f5) 100%);
  border-bottom: 1px solid var(--ink-200, #e2dcd4);
}
.paygen-console-title {
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-size: var(--fs-xs);
  color: var(--ink-700, #4a4a4a);
}
.paygen-console-status {
  font-size: var(--fs-xs);
  color: var(--ink-500, #888);
  font-variant-numeric: tabular-nums;
}
.paygen-console-status.ok    { color: var(--success, #2e7d32); }
.paygen-console-status.warn  { color: #b56300; }
.paygen-console-status.error { color: #c62828; }

.paygen-console-body {
  margin: 0;
  padding: 0.7rem 0.9rem;
  background: #1f1f23;
  color: #e9e9ec;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  font-size: var(--fs-sm);
  line-height: 1.5;
  max-height: 360px;
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-word;
}
.paygen-log-line {
  display: block;
  padding: 0.05rem 0;
}
.paygen-log-line.info  { color: #d4d4d8; }
.paygen-log-line.ok    { color: #6ddc94; }
.paygen-log-line.warn  { color: #ffb84d; }
.paygen-log-line.error { color: #ff7a7a; font-weight: 600; }

.paygen-console-body::-webkit-scrollbar { width: 10px; }
.paygen-console-body::-webkit-scrollbar-track { background: #2a2a30; }
.paygen-console-body::-webkit-scrollbar-thumb { background: #45454d; border-radius: 5px; }
.paygen-console-body::-webkit-scrollbar-thumb:hover { background: #5b5b66; }

/* ─── PayGen duplicate-DocNumber modal ────────────────────────────────
   Used by /payroll/paygen — shown when QBO already has a Bill at
   the resolved DocNumber. User must explicitly choose Skip / Delete-
   and-re-post / Cancel. Backdrop click does not dismiss.
─────────────────────────────────────────────────────────────────── */
.paygen-modal {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
}
.paygen-modal[hidden] { display: none; }
.paygen-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20, 20, 22, 0.55);
}
.paygen-modal-card {
  position: relative;
  z-index: 1;
  background: var(--paper, #fff);
  border: 1px solid var(--ink-200, #e2dcd4);
  border-radius: var(--radius-lg);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
  padding: 1.4rem 1.6rem;
  max-width: 540px;
  width: calc(100% - 2rem);
  font-size: var(--fs-sm);
}
.paygen-modal-card h3 {
  margin: 0 0 0.5rem;
  color: var(--kal-coral, #DE5A41);
  font-size: 1.1rem;
}
.paygen-modal-card p { margin: 0 0 0.6rem; }
.paygen-dup-meta {
  list-style: none;
  margin: 0 0 1rem;
  padding: 0.6rem 0.8rem;
  background: rgba(222, 90, 65, 0.06);
  border-radius: var(--radius-sm);
  font-variant-numeric: tabular-nums;
}
.paygen-dup-meta li { padding: 0.15rem 0; }
.paygen-dup-meta li.paygen-dup-warn {
  margin-top: 0.3rem;
  padding-top: 0.3rem;
  border-top: 1px dashed var(--ink-200, #e2dcd4);
  color: #b56300;
}
.paygen-modal-actions {
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
  flex-wrap: wrap;
}

/* ─── Staff Advertising ─────────────────────────────────────────────── */
.staff-ad-detail-page {
  width: min(100%, 1280px);
  margin: 0 auto;
  text-align: left;
}
.staff-ad-detail-page .page-title-header {
  margin-bottom: 1rem;
}
.staff-ad-detail-page h2,
.staff-ad-detail-page h3,
.staff-ad-detail-page h4,
.staff-ad-detail-page p {
  text-align: left;
}
/* The .main-content parent applies `text-align: center` by default and
   only resets a small allow-list of children (form, p, ul, ol …). The
   staff-ad section/grid containers aren't in that list, so without this
   reset their inline content centres inside each grid cell — which the
   user perceives as "stacked / narrow / broken". Force left-align on
   every staff-ad container so grid cells render naturally. */
.staff-ad-detail-page,
.staff-ad-detail-page .staff-ad-summary,
.staff-ad-detail-page .staff-ad-summary-main,
.staff-ad-detail-page .staff-ad-summary-meta,
.staff-ad-detail-page .staff-ad-panel,
.staff-ad-detail-page .staff-ad-panel-heading,
.staff-ad-detail-page .staff-ad-facts,
.staff-ad-detail-page .staff-ad-fact,
.staff-ad-detail-page .staff-ad-copy-grid,
.staff-ad-detail-page .staff-ad-copy-block,
.staff-ad-detail-page .staff-ad-body-block,
.staff-ad-detail-page .staff-ad-copy-actions,
.staff-ad-detail-page .form-row,
.staff-ad-detail-page .form-group,
.staff-ad-detail-page .form-actions {
  text-align: left;
}
.staff-ad-back-link {
  margin: 0 0 1rem;
}

.staff-ad-summary,
.staff-ad-panel,
.staff-config-section {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}

.staff-ad-summary {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(24rem, auto);
  align-items: stretch;
  gap: 1rem;
  padding: 1.25rem 1.5rem;
  margin-bottom: 1rem;
}
.staff-ad-summary-main {
  min-width: 0;
}
.staff-ad-summary h3 {
  margin: 0.45rem 0 0.2rem;
  color: var(--ink-900);
  font-size: var(--fs-3xl);
}
.staff-ad-summary p,
.staff-ad-summary-meta p {
  margin: 0.2rem 0;
  color: var(--ink-600);
}
.staff-ad-summary-meta {
  display: grid;
  grid-template-columns: repeat(3, minmax(8rem, 1fr));
  gap: 0.7rem;
  min-width: 0;
  text-align: left;
}
.staff-ad-summary-meta > div,
.staff-ad-fact {
  min-width: 0;
  padding: 0.7rem 0.8rem;
  background: rgba(255, 255, 255, 0.58);
  border: 1px solid var(--ink-100);
  border-radius: var(--radius-sm);
}
.staff-ad-summary-meta span,
.staff-ad-fact span {
  display: block;
  margin-bottom: 0.18rem;
  color: var(--ink-500);
  font-size: var(--fs-xs);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.staff-ad-summary-meta strong,
.staff-ad-fact strong {
  display: block;
  min-width: 0;
  color: var(--ink-900);
  font-weight: 700;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}
.staff-ad-summary-meta small {
  display: block;
  margin-top: 0.12rem;
  color: var(--ink-500);
}

.staff-ad-panel {
  width: 100%;
  max-width: none;
  padding: 1.25rem 1.5rem;
  margin-bottom: 1rem;
}
.staff-ad-panel-heading,
.staff-config-heading,
.staff-ad-copy-actions {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1rem;
}
.staff-ad-panel-heading {
  padding-bottom: 0.9rem;
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--border);
}
.staff-ad-panel-heading h3,
.staff-config-heading h3 {
  margin: 0;
  color: var(--kal-coral);
  text-align: left;
}
.staff-ad-panel-heading p,
.staff-config-heading p {
  margin: 0.25rem 0 0;
  color: var(--ink-600);
}

.staff-ad-facts {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.75rem;
}
.staff-ad-fact-wide {
  grid-column: span 2;
}
.staff-ad-fact-full {
  grid-column: 1 / -1;
}
.staff-ad-facts-billing {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.staff-ad-detail-list {
  display: grid;
  grid-template-columns: minmax(10rem, 14rem) 1fr;
  gap: 0.55rem 1rem;
  margin: 0;
}
.staff-ad-detail-list dt {
  font-weight: 700;
  color: var(--ink-600);
}
.staff-ad-detail-list dd {
  margin: 0;
  color: var(--ink-900);
  white-space: pre-wrap;
}

.staff-ad-copy-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}
.staff-ad-copy-grid-fields {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.staff-ad-copy-block {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}
.staff-ad-copy-actions {
  align-items: center;
}
.staff-ad-copy-actions label {
  font-weight: 700;
  font-size: var(--fs-sm);
  color: var(--ink-500);
  text-transform: uppercase;
  letter-spacing: 0.09em;
}
.staff-ad-copy-block textarea,
.staff-config-section textarea {
  width: 100%;
  box-sizing: border-box;
  resize: vertical;
}
.staff-ad-copy-block textarea {
  min-height: 6.5rem;
  font-family: var(--font-body);
  font-size: var(--fs-base);
  line-height: 1.45;
}
.staff-ad-body-block {
  margin-top: 1rem;
}

/* Key Selling Points — three separate single-line inputs, each with its
   own Copy button + a small "<used>/<max>" character counter. Mirrors
   the SEEK posting form which has three discrete per-bullet input boxes
   with an 80-char hard cap. The 80 cap is enforced server-side too via
   normaliseSellingPoints() in services/staffAdvertising.js. */
.staff-ad-selling-points .staff-ad-section-label {
  font-weight: 700;
  font-size: var(--fs-sm);
  color: var(--ink-500);
  text-transform: uppercase;
  letter-spacing: 0.09em;
}
.staff-ad-selling-point-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.staff-ad-selling-point-row input[type="text"] {
  flex: 1 1 auto;
  min-width: 0;
  width: auto;
  font-family: var(--font-body);
  font-size: var(--fs-base);
}
.staff-ad-char-counter {
  flex: 0 0 auto;
  font-size: var(--fs-xs);
  color: var(--ink-400);
  font-variant-numeric: tabular-nums;
  min-width: 3.25rem;
  text-align: right;
}
.staff-ad-char-counter.at-limit {
  color: var(--kal-coral);
  font-weight: 600;
}
/* Full job ad body — Quill editor with restricted toolbar. Manually
   instantiated by views/pages/staff-advertising/detail.ejs (see
   views/CLAUDE.md → Rich text → restricted-toolbar pattern). The
   bespoke contenteditable + hand-rolled toolbar this replaces had a
   parallel hidden textarea that wasn't actually hidden — Quill writes
   into <input type="hidden"> instead and never has that problem. */
.staff-ad-quill {
  background: #fff;
  border-radius: var(--radius-sm);
  text-align: left;
}
.staff-ad-quill .ql-toolbar.ql-snow {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  background: var(--ink-50);
}
.staff-ad-quill .ql-container.ql-snow {
  min-height: 28rem;
  max-height: 60vh;
  overflow-y: auto;
  border: 1px solid var(--border-strong);
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.58;
}
.staff-ad-quill .ql-editor {
  min-height: 26rem;
  padding: 1rem 1.1rem;
  color: var(--ink-900);
}
.staff-ad-quill .ql-editor h3,
.staff-ad-quill .ql-editor h4 {
  margin: 1rem 0 0.5rem;
  color: var(--ink-900);
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 800;
}
.staff-ad-quill .ql-editor ul,
.staff-ad-quill .ql-editor ol {
  margin: 0.5rem 0 0.9rem 0.5rem;
}
.staff-ad-quill .ql-editor p {
  margin: 0 0 0.75rem;
}

.staff-config-form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.staff-cache-toolbar,
.staff-cache-note {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
.staff-cache-toolbar {
  padding: 0.85rem 1rem;
  margin-bottom: 1rem;
}
.staff-cache-toolbar .form-hint {
  display: block;
  margin-top: 0.15rem;
}
.staff-cache-note {
  margin: -0.2rem 0 1rem;
  padding: 0.65rem 0.8rem;
  color: var(--ink-600);
  font-size: var(--fs-sm);
  box-shadow: none;
}
.staff-cache-note span {
  color: var(--ink-500);
  margin-left: 0.4rem;
}
.staff-config-section {
  padding: 1.25rem 1.5rem;
}
.staff-config-heading {
  margin-bottom: 1rem;
  padding-bottom: 0.8rem;
  border-bottom: 1px solid var(--border);
}
.sticky-actions {
  position: sticky;
  bottom: 0;
  padding: 0.8rem 0;
  background: linear-gradient(to top, var(--cream), rgba(251, 247, 243, 0.88));
}

@media (max-width: 760px) {
  .staff-ad-summary,
  .staff-ad-panel-heading,
  .staff-config-heading,
  .staff-cache-toolbar,
  .staff-cache-note {
    flex-direction: column;
  }
  .staff-ad-summary-meta {
    text-align: left;
    min-width: 0;
    grid-template-columns: 1fr;
  }
  .staff-ad-summary {
    grid-template-columns: 1fr;
  }
  .staff-ad-facts,
  .staff-ad-facts-billing {
    grid-template-columns: 1fr;
  }
  .staff-ad-fact-wide,
  .staff-ad-fact-full {
    grid-column: auto;
  }
  .staff-ad-detail-list {
    grid-template-columns: 1fr;
  }
  .staff-ad-detail-list dt {
    margin-top: 0.4rem;
  }
  .staff-ad-copy-grid {
    grid-template-columns: 1fr;
  }
  .staff-ad-quill .ql-container.ql-snow {
    min-height: 22rem;
  }
  .staff-ad-quill .ql-editor {
    min-height: 20rem;
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   Wages page — toolbar + period navigator
   ═══════════════════════════════════════════════════════════════════════ */

/* Top filter bar — VIEW BY + HISTORY + a non-interactive "Showing N"
   summary that visually confirms a period-type switch took effect. */
.filter-bar.wages-toolbar {
  align-items: flex-end;
  gap: 1.1rem;
  max-width: 880px;
}
.wages-toolbar .form-group {
  margin-bottom: 0;
}
.wages-toolbar .form-group select {
  min-width: 13rem;
}
.wages-toolbar-summary {
  /* Visually styled like a form-group but inert — the label sits
     above a coral pill + caption, matching the rest of the toolbar's
     uppercase-label rhythm without offering a control to interact
     with. Gives switching periods a clear visible signal. */
  min-width: 11rem;
}
.wages-toolbar-summary-row {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.55rem 0.2rem;
}
.wages-count-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.2rem;
  height: 2.2rem;
  padding: 0 0.55rem;
  border-radius: 999px;
  background: var(--brand-500, #DE5A41);
  color: #fff;
  font-weight: 700;
  font-size: 1rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  line-height: 1;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08);
}
.wages-count-detail {
  color: var(--ink-700, #2a2a2a);
  font-size: 0.95rem;
  line-height: 1.25;
}
.wages-count-detail small {
  display: block;
  color: var(--ink-400, #7a7a7a);
  font-size: 0.78rem;
  margin-top: 0.1rem;
}

/* Staffing-curve card — intraday children/required/rostered chart
   shown per-centre (in the centre details header) and per-room
   (lazy-loaded inline detail panel). */
.staffing-curve-card {
  background: var(--paper, #fff8f1);
  border: 1px solid var(--ink-50, #e8dccb);
  border-radius: 10px;
  padding: 0.9rem 1rem 0.7rem;
  margin: 0.6rem 0 0.9rem;
}
.staffing-curve-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.8rem;
  margin-bottom: 0.6rem;
  flex-wrap: wrap;
}
.staffing-curve-title {
  font-weight: 600;
  color: var(--ink-700, #2a2a2a);
  font-size: 0.95rem;
}
.staffing-curve-title small {
  display: inline-block;
  margin-left: 0.4rem;
  color: var(--ink-400, #7a7a7a);
  font-weight: 400;
  font-size: 0.82rem;
}
.staffing-curve-days {
  display: inline-flex;
  gap: 0.3rem;
  flex-wrap: wrap;
}
.staffing-curve-days button {
  appearance: none;
  border: 1px solid var(--ink-100, #d6c8b3);
  background: #fff;
  color: var(--ink-500, #4a4a4a);
  font-size: 0.78rem;
  font-weight: 500;
  padding: 0.32rem 0.6rem;
  border-radius: 999px;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
  font-variant-numeric: tabular-nums;
}
.staffing-curve-days button:hover {
  border-color: var(--brand-500, #DE5A41);
  color: var(--brand-500, #DE5A41);
}
.staffing-curve-days button.is-active {
  background: var(--brand-500, #DE5A41);
  border-color: var(--brand-500, #DE5A41);
  color: #fff;
}
.staffing-curve-canvas-wrap {
  position: relative;
  height: 240px;
}
.staffing-curve-empty {
  text-align: center;
  color: var(--ink-400, #7a7a7a);
  font-style: italic;
  padding: 2.2rem 0.5rem;
  font-size: 0.9rem;
}

/* The period navigator strip above the per-room table. Prev / current /
   next buttons, an optional Today shortcut, and a grouped Jump-to
   dropdown that opens "Upcoming / Current / Past" optgroups.
   Reuses .filter-bar for the bar chrome (paper background, rounded
   border) but with custom flex behaviour so the current-period block
   gets the centre-stage. */
.filter-bar.period-nav-bar {
  margin-top: 0.6rem;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.period-nav-btn {
  min-width: 7.5rem;
}
.period-nav-btn.disabled {
  opacity: 0.4;
  pointer-events: none;
  cursor: default;
}
.period-nav-current {
  flex: 1;
  text-align: center;
  padding: 0.2rem 0.5rem;
  min-width: 14rem;
}
.period-nav-label {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--ink-700, #2a2a2a);
}
.period-nav-dates {
  color: var(--ink-400, #7a7a7a);
  font-size: 0.85em;
  font-variant-numeric: tabular-nums;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  justify-content: center;
}
/* The Jump-to form sits beside the prev/next/today buttons. Trim the
   default .form-group bottom margin so the row doesn't grow taller
   than the buttons. */
.period-jump-form {
  display: inline-flex;
  align-items: flex-end;
  gap: 0.5rem;
  margin: 0;
}
.period-jump-form .form-group {
  margin-bottom: 0;
  min-width: 18rem;
}
.period-jump-form select {
  font-variant-numeric: tabular-nums;
}
