/* ============================================================================
   ChurchCRM wearing the Sparkler CMS dashboard design system.
   DRAFT — previewed through proxy.mjs, nothing deployed.

   Tokens read out of cms/client/sparkler/app.dc.html — the SHIPPED dashboard, not
   the Phase-0 mockup (which is still on Poppins and an older blue). This is what

   Delmy's / DT Construction / every CMS tenant actually logs into:

       --ink #0f172a   --paper #f6f7fb  --panel #fff    --line #e2e8f0
       --muted #475569 --soft #8591a2
       --blue #2563eb  --purple #6568fc --green #166534
       --grad linear-gradient(135deg,#2563eb,#6568fc)     font Plus Jakarta Sans
       --shadow-sm 0 1px 2px rgba(20,30,60,.05), 0 4px 14px rgba(20,30,60,.04)
       --r 14px        sidebar: #0f172a bg, #aab2c5 text

   Earlier passes went the wrong way — stripping colour, deleting cards, going
   monochrome. This system does the opposite: a DARK sidebar against a light
   canvas, white cards that genuinely lift, and saturated gradient tiles doing
   the accent work. That contrast is what reads as current.

   Positions untouched: nothing moved, reordered or hidden.
   ============================================================================ */

@font-face {
  font-family: 'Plus Jakarta Sans'; font-style: normal; font-weight: 400 800; font-display: swap;
  src: url('pjs-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Plus Jakarta Sans'; font-style: normal; font-weight: 400 800; font-display: swap;
  src: url('pjs-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --ink:    #0f172a;
  --paper:  #f6f7fb;
  --panel:  #ffffff;
  --line:   #e2e8f0;
  --muted:  #475569;
  --soft:   #8591a2;
  --blue:   #2563eb;
  --purple: #6568fc;
  --green:  #166534;
  --grad:   linear-gradient(135deg, #2563eb, #6568fc);
  --shadow:    0 10px 34px rgba(20, 30, 60, .08);
  --shadow-sm: 0 1px 2px rgba(20, 30, 60, .05), 0 4px 14px rgba(20, 30, 60, .04);
  --r: 16px;

  --tblr-font-sans-serif: 'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif !important;
  --tblr-body-bg:      var(--paper) !important;
  --tblr-body-color:   var(--muted) !important;
  --tblr-border-color: var(--line) !important;
  --tblr-border-color-translucent: var(--line) !important;
  --tblr-primary:      var(--blue) !important;
  --tblr-primary-rgb:  37, 99, 235 !important;
  --tblr-border-radius-sm: 9px  !important;
  --tblr-border-radius:    10px !important;
  --tblr-border-radius-lg: 14px !important;
  --tblr-border-radius-xl: 18px !important;
}

body {
  font-family: var(--tblr-font-sans-serif);
  background: var(--paper) !important;
  color: var(--muted);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ── Sidebar: dark panel, the single biggest shift ───────────────────────── */
.navbar-vertical {
  background: #0d1424 !important;
  border-right: 0 !important;
  padding: 14px 10px;
}
.navbar-vertical .navbar-brand,
.navbar-vertical .navbar-brand * { color: #fff !important; }
.navbar-vertical .nav-link {
  color: #cbd5e1 !important;
  border-radius: 9px;
  margin: 0 5px;
  padding: .34rem .7rem !important;
  font-size: .9rem;
  font-weight: 500;
  letter-spacing: -0.006em;
}
.navbar-vertical .nav-link .nav-link-icon { opacity: .8; }
.navbar-vertical .nav-link:hover { background: rgba(255,255,255,.06) !important; color: #fff !important; }
/* Active item is the brand gradient — exactly how the dashboard marks it. */
.navbar-vertical .nav-link.active,
.navbar-vertical .nav-item.active > .nav-link,
.navbar-vertical .nav-item.show > .nav-link {
  background: rgba(255, 255, 255, .09) !important;
  color: #fff !important;
  font-weight: 600;
  box-shadow: none;
}
.navbar-vertical .nav-link.active .nav-link-icon { opacity: 1; }
.navbar-vertical .nav-link.active::before,
.navbar-vertical .nav-item.active > .nav-link::before { display: none !important; }
.navbar-vertical .dropdown-menu { background: #171a22; border-color: rgba(255,255,255,.08); }
.navbar-vertical .dropdown-item { color: #aab2c5; }
.navbar-vertical .dropdown-item:hover { background: rgba(255,255,255,.06); color: #fff; }
.navbar-vertical hr, .navbar-vertical .hr { border-color: rgba(255,255,255,.08) !important; }

/* ── Top bar ─────────────────────────────────────────────────────────────── */
.navbar:not(.navbar-vertical) {
  background: var(--panel) !important;
  border-bottom: 1px solid var(--line) !important;
  box-shadow: none !important;
}

/* ── Cards: white, lifted, generous ──────────────────────────────────────── */
.card {
  background: var(--panel) !important;
  border: 1px solid var(--line) !important;
  border-radius: var(--r) !important;
  box-shadow: 0 1px 2px rgba(20, 30, 60, .04) !important;
}
.card-header {
  border-bottom: 0 !important;              /* the shipped dashboard has no rule under a card title */
  padding: 1.3rem 1.35rem .35rem !important;
  background: transparent !important;
}
.card-body { padding: 1.35rem !important; }
.card-title, .card-header h3 {
  font-size: 1rem !important;
  font-weight: 600 !important;
  color: var(--ink) !important;
  letter-spacing: -0.01em;
  margin: 0;
}

/* ── Type ────────────────────────────────────────────────────────────────── */
h1,h2,h3,h4,.h1,.h2,.h3,.h4 { color: var(--ink); font-weight: 600; letter-spacing: -0.02em; }
.page-title { font-size: 2.05rem !important; font-weight: 700 !important; color: var(--ink) !important; letter-spacing: -0.028em; }
.page-pretitle, .subheader {
  font-size: .68rem !important; font-weight: 600 !important; letter-spacing: .1em;
  text-transform: uppercase; color: var(--soft) !important;
}
.text-muted, .text-secondary, small, .small { color: var(--soft) !important; }
td, th, .badge { font-variant-numeric: tabular-nums; }

/* ── Icon tiles: saturated gradients, not flat circles ───────────────────── */
/* ChurchCRM assigns these tiles semantic .bg-* classes almost at random — the
   four stat tiles land on slate / green / orange / blue with no relationship to
   what they count, which reads as decoration rather than meaning. One brand
   tile instead: calm, deliberate, and it stops the dashboard looking like a
   colour test. Colour is then free to mean something where it genuinely does
   (status badges, alerts). */
.avatar.bg-success, .avatar.bg-green, .avatar.bg-warning, .avatar.bg-orange,
.avatar.bg-yellow,  .avatar.bg-danger, .avatar.bg-red, .avatar.bg-secondary,
.avatar.bg-dark,    .avatar.bg-purple, .avatar.bg-pink, .avatar.bg-primary,
.avatar.bg-azure,   .avatar.bg-blue,  .avatar.bg-info, .avatar.bg-cyan,
.avatar.bg-teal,    .avatar.bg-lime {
  background: var(--grad) !important;
}

.avatar[class*="bg-"] {
  border-radius: 13px !important;
  width: 2.75rem !important;
  height: 2.75rem !important;
  color: #fff !important;
  box-shadow: 0 2px 6px rgba(37, 99, 235, .18);
}
.avatar[class*="bg-"] > i, .avatar[class*="bg-"] > svg { color: #fff !important; font-size: 1.15rem; }

/* ── Stat blocks: the number leads ───────────────────────────────────────── */
/* Markup is generic (<div class="fw-medium text-body">936</div>), so matched by
   SHAPE via :has() rather than by class, which would catch every .fw-medium. */
.col:has(> .fw-medium.text-body + .text-body-secondary) > .fw-medium.text-body {
  font-size: 1.85rem !important; font-weight: 700 !important; line-height: 1.1;
  letter-spacing: -0.03em; color: var(--ink) !important;
}
.col:has(> .fw-medium.text-body + .text-body-secondary) > .text-body-secondary {
  font-size: .78rem !important; font-weight: 500 !important; color: var(--soft) !important;
}

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.btn { border-radius: 10px; font-weight: 600; font-size: .875rem; padding: .55rem 1rem; box-shadow: none; }
.btn-primary {
  background: var(--blue) !important;
  border: 1px solid var(--blue) !important;
  color: #fff !important;
  box-shadow: none !important;
}
.btn-primary:hover { background: #1d4fd8 !important; border-color: #1d4fd8 !important; }
.btn-outline-primary, .btn-outline-secondary, .btn-white, .btn-default {
  background: var(--panel); border: 1px solid var(--line); color: var(--ink) !important;
}
.btn-outline-primary:hover, .btn-outline-secondary:hover, .btn-white:hover, .btn-default:hover {
  background: #fbfcff; border-color: #dfe4ee; color: var(--ink) !important;
}

/* ── Badges: soft tint pills ─────────────────────────────────────────────── */
.badge {
  border-radius: 999px; font-weight: 600; font-size: .72rem; padding: .34em .72em;
  background: #eff2ff !important; color: var(--blue) !important;
}
.badge.bg-success, .badge.bg-green  { background: #e6f6ed !important; color: #1f8a55 !important; }
.badge.bg-warning, .badge.bg-orange { background: #fdf1de !important; color: #b06d13 !important; }
.badge.bg-danger,  .badge.bg-red    { background: #fdeaea !important; color: #c2403c !important; }

/* ── Inputs ──────────────────────────────────────────────────────────────── */
.form-control, .form-select {
  border-radius: 10px; border-color: var(--line); background: #fbfcff;
  padding: .58rem .85rem; font-size: .9rem; color: var(--ink); box-shadow: none;
}
.form-control:focus, .form-select:focus {
  background: #fff; border-color: var(--blue);
  box-shadow: 0 0 0 4px rgba(37, 99, 235, .12);
}
.form-label { font-size: .8rem; font-weight: 600; color: var(--ink); }

/* ── Tables ──────────────────────────────────────────────────────────────── */
.table thead th {
  text-transform: uppercase; font-size: .67rem; letter-spacing: .09em; font-weight: 600;
  color: var(--soft); background: transparent !important;
  border-bottom: 1px solid var(--line) !important; padding: .75rem 1rem;
}
.table td, .table tbody th {
  padding: .85rem 1rem; color: var(--muted); vertical-align: middle;
  border-bottom: 1px solid #f2f4f9 !important;
}
.table-hover > tbody > tr:hover > * { background: #f7f9fd !important; }

/* ── Progress ────────────────────────────────────────────────────────────── */
.progress { height: .45rem; border-radius: 999px; background: #eef1f7; }
.progress-bar { border-radius: 999px; background: var(--grad) !important; }

/* ── Floating surfaces ───────────────────────────────────────────────────── */
.dropdown-menu, .modal-content {
  border-radius: var(--r); border: 1px solid var(--line); box-shadow: var(--shadow);
}
.dropdown-menu { padding: .35rem; }
.dropdown-item { border-radius: 9px; padding: .5rem .65rem; font-size: .875rem; }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: #d4dde9; border-radius: 99px; border: 3px solid var(--paper); background-clip: content-box; }

/* Sidebar group labels — WEBSITE / LEADS & GROWTH / REVENUE / ACCOUNT in the
   shipped dashboard. Tabler has no direct equivalent, so anything acting as a
   heading inside the dark panel gets the same treatment rather than inheriting
   nav-item styling. */
.navbar-vertical .navbar-heading,
.navbar-vertical .nav-header,
.navbar-vertical h6 {
  color: #64748b !important;
  font-size: .68rem !important;
  font-weight: 700 !important;
  letter-spacing: .11em;
  text-transform: uppercase;
  padding: 1.1rem .95rem .35rem !important;
  margin: 0;
}

/* Sidebar count badges: small, soft-blue, like the shipped "3" / "5". */
.navbar-vertical .badge {
  background: rgba(59, 130, 246, .18) !important;
  color: #93c5fd !important;
  font-size: .68rem !important;
  font-weight: 600;
  padding: .18em .5em;
}

/* Tighter vertical rhythm in the sidebar — the shipped dashboard stacks its nav
   rows close together and lets the group labels do the separating, rather than
   spacing every item apart. Tabler adds margins at the nav-item level too, so
   those have to be zeroed or the row gap survives. */
.navbar-vertical .navbar-nav { gap: 0 !important; }
.navbar-vertical .navbar-nav > .nav-item { margin: 0 !important; }
.navbar-vertical .nav-item + .nav-item { margin-top: 0 !important; }
.navbar-vertical .nav-link { line-height: 1.35; }
.navbar-vertical .nav-link .nav-link-icon { margin-inline-end: .6rem; }
/* Collapsed sub-menus (People > Dashboard / Add New Person / …) tighten too. */
.navbar-vertical .dropdown-menu .dropdown-item { padding-block: .28rem !important; }
.navbar-vertical .nav-item .nav-item .nav-link { padding-block: .28rem !important; }

/* ── Spacing between card blocks ─────────────────────────────────────────── */
/* Tabler leaves stacked cards flush; the shipped dashboard sets every block
   apart with real space. Applied as margin on the card and a gutter on the row
   so it works for both stacked and side-by-side columns. */
.card { margin-bottom: 1.5rem !important; }
.page-body .row { row-gap: 1.5rem; }
/* No :last-child exception here. Zeroing the last card in a column looks right
   inside that column and then removes the gap before the NEXT row — which is
   exactly how "Deposit Tracking" ended up flush against the two cards above it.
   A uniform bottom margin costs a little space at the foot of a column and
   guarantees every block is separated. */
.card + .card { margin-top: 0 !important; }
/* Rows that are siblings need the gap too — row-gap only separates items INSIDE
   one row, not one .row from the next. */
.page-body .row + .row { margin-top: 0; }

/* ── No accent bar beside the active sidebar item ────────────────────────── */
/* Tabler marks the current page with a left rule. The background pill already
   says which item is active, so remove every way that bar can be drawn rather
   than chasing whichever one this build uses. */
.navbar-vertical .nav-item,
.navbar-vertical .nav-item.active,
.navbar-vertical .nav-link,
.navbar-vertical .nav-link.active,
.navbar-vertical .navbar-nav,
.navbar-vertical .navbar-nav > li {
  border-left: 0 !important;
  border-inline-start: 0 !important;
  box-shadow: none !important;
}
.navbar-vertical .nav-item::before,  .navbar-vertical .nav-item::after,
.navbar-vertical .nav-link::before,  .navbar-vertical .nav-link::after,
.navbar-vertical .nav-item.active::before, .navbar-vertical .nav-link.active::before {
  display: none !important;
  content: none !important;
}

/* ── Design-system consistency ───────────────────────────────────────────── */
/* Cards sitting in the same row end at the same baseline. Bootstrap columns are
   equal-height already; the CARD inside them is not, so it has to be told to
   fill its column. Without this, a short card next to a tall one leaves a
   ragged edge — the thing that most makes a dashboard look assembled rather
   than designed. */
/* Scoped with :has() to rows that actually hold cards. The first version hit
   EVERY .row under .page-body, including the form rows inside a card — turning
   those columns into flex containers changed how their fields sized, which is
   why some columns stopped lining up with the content under them. */
.page-body .row:has(> [class*="col-"] > .card) { align-items: stretch; }
.page-body .row:has(> [class*="col-"] > .card) > [class*="col-"] { display: flex; flex-direction: column; }
.page-body .row:has(> [class*="col-"] > .card) > [class*="col-"] > .card { flex: 1 1 auto; }

/* One control height across the product, so buttons and inputs sitting side by
   side line up instead of missing each other by a pixel or two. */
.btn:not(.btn-sm):not(.btn-lg):not(.btn-icon) { min-height: 38px; }
.form-control:not(.form-control-sm):not(.form-control-lg),
.form-select:not(.form-select-sm):not(.form-select-lg) { min-height: 38px; }

/* One icon-tile size everywhere they appear. */
.avatar[class*="bg-"] { flex: none; }

/* Figures line up in columns: tabular numerals plus consistent alignment for
   the count/percentage columns that read as data rather than labels. */
.table td .text-end, .table th.text-end, .table td.text-end { font-variant-numeric: tabular-nums; }

/* Equal gutters between every dashboard block, horizontal and vertical. */
.page-body .row { --tblr-gutter-x: 1.5rem; }

/* ── Sidebar: resizable + collapsible (drives theme.js) ──────────────────── */
:root { --vq-sidebar-w: 252px; }

.navbar-vertical {
  width: var(--vq-sidebar-w) !important;
  min-width: var(--vq-sidebar-w) !important;
  max-width: var(--vq-sidebar-w) !important;
  transition: width .16s ease, min-width .16s ease, max-width .16s ease;
  position: relative;
  overflow: visible !important;
}
/* Tabler offsets the page by a fixed sidebar width; follow the live value. */
.page-wrapper { margin-inline-start: var(--vq-sidebar-w) !important; transition: margin .16s ease; }

/* Drag handle — a hit area on the right edge, invisible until approached. */
.vq-grip {
  position: absolute; top: 0; right: -3px; bottom: 0; width: 6px;
  cursor: col-resize; z-index: 40; background: transparent;
}
.vq-grip:hover { background: rgba(37, 99, 235, .55); }

/* Collapse toggle, pinned bottom-left of the panel. */
.vq-collapse {
  position: absolute; bottom: 12px; right: 12px; z-index: 41;
  width: 28px; height: 28px; display: flex; align-items: center; justify-content: center;
  border-radius: 8px; border: 1px solid rgba(255,255,255,.12);
  background: rgba(255,255,255,.06); color: #cbd5e1; cursor: pointer;
  transition: background .14s ease, transform .16s ease;
}
.vq-collapse:hover { background: rgba(255,255,255,.14); color: #fff; }

/* Collapsed: icons only. Nothing is removed — labels are hidden, so every item
   stays in the same order and the same place. */
.vq-sidebar-collapsed .vq-collapse svg { transform: rotate(180deg); }
.vq-sidebar-collapsed .navbar-vertical .nav-link-title,
.vq-sidebar-collapsed .navbar-vertical .navbar-brand span,
.vq-sidebar-collapsed .navbar-vertical .badge,
.vq-sidebar-collapsed .navbar-vertical .nav-link-toggle,
.vq-sidebar-collapsed .navbar-vertical .navbar-heading { display: none !important; }
.vq-sidebar-collapsed .navbar-vertical .nav-link {
  justify-content: center; padding-inline: 0 !important;
}
.vq-sidebar-collapsed .navbar-vertical .nav-link .nav-link-icon { margin-inline-end: 0 !important; }
.vq-sidebar-collapsed .navbar-vertical .dropdown-menu { display: none !important; }

/* Sub-menus (People > Dashboard / Add New Person / …) sit as tight as the
   top-level rows — Tabler pads the nested list as well as its items, so both
   the container and the rows have to come in or the group still reads loose. */
.navbar-vertical .navbar-nav .navbar-nav,
.navbar-vertical .nav-item .dropdown-menu {
  padding-block: 1px !important;
  margin-block: 0 !important;
}
.navbar-vertical .navbar-nav .navbar-nav > .nav-item > .nav-link {
  padding-block: .28rem !important;
  min-height: 0;
}
.navbar-vertical .nav-link { min-height: 0; }

/* ── Sub-menu rows: kill the 40px floor ──────────────────────────────────── */
/* The expanded items were not loose because of padding — Tabler sets
   min-height:40px on .nav-link, so tightening the padding changed nothing and
   every row stayed 40px apart. Height has to come from the padding instead. */
.navbar-vertical .navbar-nav .nav-link,
.navbar-vertical .navbar-nav .nav-link.flex-fill,
.navbar-vertical .navbar-nav .nav-item > .d-flex,
.navbar-vertical .navbar-nav .nav-item {
  min-height: 0 !important;
}
.navbar-vertical .navbar-nav .navbar-nav .nav-link { padding-block: .26rem !important; }
.navbar-vertical .navbar-nav.ps-3 { padding-block: 2px !important; }

/* ============================================================================
   VERBATIM SPEC — values copied out of the inline styles in app.dc.html rather
   than eyeballed. Everything below overrides the approximations above.

     sidebar panel   background:#0f172a; color:#a5b3c7; padding:16px 12px; gap:2px
     sidebar item    gap:10px; padding:6px 10px; border-radius:9px; font-weight:600
     group label     font:700 10px; letter-spacing:.07em; uppercase; color:#96a4b7;
                     padding:0 8px; margin-bottom:8px
     card            background:#fff; border:1px solid #e2e8f0; border-radius:18px;
                     padding:20px
     icon tile       42px; border-radius:12px; grid + place-items:center; color:#fff
     primary button  border-radius:10px; padding:9px 15px; font:700 13px
     quiet button    border:1px solid #e2e8f0; background:#fff; border-radius:9px;
                     padding:8px 14px; font:700 12px; color:#475569
   ============================================================================ */

.navbar-vertical {
  background: #0f172a !important;
  color: #a5b3c7 !important;
  padding: 16px 12px !important;
}
.navbar-vertical .navbar-nav { gap: 2px !important; }
.navbar-vertical .nav-link {
  gap: 10px;
  padding: 6px 10px !important;
  border-radius: 9px;
  font-weight: 600;
  font-size: 13.5px;
  color: #a5b3c7 !important;
  margin: 0 !important;
}
.navbar-vertical .nav-link .nav-link-icon { margin-inline-end: 0 !important; opacity: .85; }
.navbar-vertical .navbar-nav .navbar-nav .nav-link { padding: 6px 10px !important; }
.navbar-vertical .navbar-nav.ps-3 { padding-block: 0 !important; }
.navbar-vertical .nav-item + .nav-item { margin-top: 0 !important; }

.navbar-vertical .navbar-heading,
.navbar-vertical .nav-header,
.navbar-vertical h6 {
  font-size: 10px !important;
  font-weight: 700 !important;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: #96a4b7 !important;
  padding: 0 8px !important;
  margin: 14px 0 8px !important;
}

.card {
  background: #fff !important;
  border: 1px solid #e2e8f0 !important;
  border-radius: 18px !important;
  box-shadow: none !important;
}
.card-body   { padding: 20px !important; }
.card-header { padding: 20px 20px 0 !important; }
.card-footer { padding: 0 20px 20px !important; }

.avatar[class*="bg-"] {
  width: 42px !important;
  height: 42px !important;
  border-radius: 12px !important;
  display: grid !important;
  place-items: center !important;
  color: #fff !important;
  box-shadow: none !important;
}

.btn-primary {
  border-radius: 10px !important;
  padding: 9px 15px !important;
  font: 700 13px/1.2 'Plus Jakarta Sans', system-ui, sans-serif !important;
  min-height: 0 !important;
  white-space: nowrap;
}
.btn:not(.btn-primary):not(.btn-icon) {
  border: 1px solid #e2e8f0 !important;
  background: #fff !important;
  border-radius: 9px !important;
  padding: 8px 14px !important;
  font: 700 12.5px/1.2 'Plus Jakarta Sans', system-ui, sans-serif !important;
  color: #475569 !important;
  min-height: 0 !important;
  white-space: nowrap;
}
/* Icon-only buttons square off at the quiet button's height rather than
   inheriting a text button's horizontal padding. */
.btn-icon {
  width: 33px !important; height: 33px !important; padding: 0 !important;
  border-radius: 9px !important; min-height: 0 !important;
}

/* ── Card status bars ────────────────────────────────────────────────────── */
/* Tabler paints a 2px coloured rule along a card edge via .card-status-*;
   ChurchCRM uses it 66 times, mostly bg-primary/success/info picked per view
   with no consistent meaning. The colour says nothing, so it goes. */
.card-status-top, .card-status-bottom, .card-status-start, .card-status-end,
.card > .progress:first-child { display: none !important; }

/* ── Tables inside cards line up with the card's own 20px inset ──────────── */
/* Two problems, one cause: Tabler pads the first cell to the card inset but
   leaves header cells on the table's own padding, so a right-aligned column
   header sat ~4px off its numbers, and edge cells sat 16px in against a 20px
   card. Header and body now share one padding, and the outer columns take the
   card's 20px. */
.card .table > :not(caption) > * > * { padding-left: 16px !important; padding-right: 16px !important; }
.card .table > :not(caption) > * > *:first-child { padding-left: 20px !important; }
.card .table > :not(caption) > * > *:last-child  { padding-right: 20px !important; }
.card .list-group-flush > .list-group-item,
.card > .card-body > .list-group > .list-group-item { padding-inline: 20px !important; }
/* A full-bleed table sitting straight under a card header needs the header's
   bottom inset back, or the first row crowds the title. */
.card > .table:first-child, .card > .table-responsive:first-child { margin-top: 4px; }

/* ── Action rows are content-width, not stretched ───────────────────────── */
/* PersonEditor puts .flex-grow-1 on Save / Save and Add, so a two-button row
   spans the whole form. Buttons size to their label and the row packs left. */
.btn.flex-grow-1, .btn.w-100, .btn.btn-block { flex-grow: 0 !important; width: auto !important; }
.d-flex.gap-2 > .btn, .d-flex.gap-3 > .btn { flex: none !important; }

/* ============================================================================
   PASS 2 — avatars, collapsed sidebar, DataTables chrome, card headers
   ============================================================================ */

/* ── Person avatars ──────────────────────────────────────────────────────── */
/* ChurchCRM picks an initials colour from a fixed eight-swatch palette
   (#667eea #764ba2 #f093fb #4facfe #00f2fe #43e97b #fa709a #fee140) hashed off
   the person's name and written INLINE, so it is only reachable by attribute.
   Those swatches are the loudest thing on the dashboard and the colour carries
   no meaning — two people are never related because they hash alike. Sparkler
   uses one soft chip for every set of initials; same here. */
.avatar[style*="background-color"] {
  background-color: #e7efff !important;
  background-image: none !important;
  color: #2563eb !important;
  box-shadow: none !important;
}
.avatar[style*="background-color"] .avatar-title { color: #2563eb !important; font-weight: 700; }
.avatar.avatar-sm { width: 34px !important; height: 34px !important; font-size: 12px !important; }

/* ── Collapsed sidebar ───────────────────────────────────────────────────── */
/* The markup is <li><div class="d-flex"><a class="nav-link flex-fill">…</a>
   <span class="nav-link-arrow">chevron</span></div>…</li>. The first pass hid
   ".nav-link-toggle", which does not exist in this build — so the chevrons
   survived, hung off the right edge and got clipped, and flex-fill kept the
   icons pinned left instead of centred. */
.vq-sidebar-collapsed .navbar-vertical .nav-link-arrow,
.vq-sidebar-collapsed .navbar-vertical .navbar-brand-text,
/* :not(.navbar-collapse) matters — the whole nav list lives in a
   div.collapse.navbar-collapse, so a bare .collapse rule hides the sidebar's
   entire contents and leaves a dark empty strip. */
.vq-sidebar-collapsed .navbar-vertical .collapse:not(.navbar-collapse),
.vq-sidebar-collapsed .navbar-vertical .collapsing:not(.navbar-collapse) { display: none !important; }
.vq-sidebar-collapsed .navbar-vertical .nav-item > .d-flex { justify-content: center; }
.vq-sidebar-collapsed .navbar-vertical .nav-link {
  flex: none !important;
  width: 44px; height: 40px;
  padding: 0 !important;
  margin: 0 auto;
  justify-content: center;
  border-radius: 11px;
}
.vq-sidebar-collapsed .navbar-vertical .navbar-brand { justify-content: center; padding-inline: 0 !important; }
.vq-sidebar-collapsed .navbar-vertical { padding-inline: 12px !important; }
/* The grip stays reachable while collapsed, so the sidebar can be dragged back
   out as well as reopened from the toggle. */
.vq-sidebar-collapsed .vq-grip { right: -4px; width: 8px; }

/* ── Card header ─────────────────────────────────────────────────────────── */
/* "<i class='fa-solid fa-home'></i> Families" — the single space collapses
   against the glyph box, so the icon reads as touching the title. */
.card-title > i:first-child,
.card-header > i:first-child,
.page-title > i:first-child { margin-right: 9px; }

/* Tabs sitting in a card header rode over the card's own top border. Segmented
   pills inside the header instead — no border to cross. */
.card .nav-tabs, .card .nav-tabs .nav-item { border: 0 !important; }
.card .nav-tabs { gap: 4px; margin: 0 !important; }
.card .nav-tabs .nav-link {
  border: 0 !important; border-radius: 9px !important;
  padding: 6px 12px !important; font-size: 13px; font-weight: 600;
  color: #64748b !important; background: transparent !important;
}
.card .nav-tabs .nav-link:hover { background: #f1f5f9 !important; color: var(--ink) !important; }
.card .nav-tabs .nav-link.active { background: #e7efff !important; color: #2563eb !important; }

/* ── DataTables chrome ───────────────────────────────────────────────────── */
/* DataTables 2 pins .dt-column-order to the right edge of the header cell, so
   on a wide column its two solid triangles float halfway to the NEXT heading
   and read as a column of their own. Muted by default, brand-blue only on the
   column actually sorted. */
.dt-column-order::before, .dt-column-order::after {
  opacity: .3 !important; font-size: .62em !important; color: var(--soft) !important;
}
th.dt-ordering-asc  .dt-column-order::before,
th.dt-ordering-desc .dt-column-order::after { opacity: 1 !important; color: var(--blue) !important; }
.dt-column-header { gap: 6px; }

.dt-search label, .dt-length label {
  display: flex; align-items: center; gap: 8px; margin: 0;
  font-size: 12px; font-weight: 600; color: var(--soft);
  text-transform: uppercase; letter-spacing: .06em;
}
.dt-search input, .dt-length select {
  border-radius: 9px !important; border: 1px solid var(--line) !important;
  background: #fbfcff !important; font-size: 13px !important; color: var(--ink) !important;
}
.dt-info { font-size: 12.5px; color: var(--soft); }
.dt-paging .page-link {
  border: 0 !important; border-radius: 9px !important;
  font-weight: 700; font-size: 12.5px; color: var(--muted) !important; min-width: 32px; text-align: center;
}
.dt-paging .page-item.active .page-link { background: var(--blue) !important; color: #fff !important; }
.dt-paging .page-item.disabled .page-link { opacity: .35; }

/* ── Listing tables: nothing overflows its column ────────────────────────── */
/* DataTables hands out percentage widths that leave a long name or a formatted
   phone number spilling past its cell. Cells wrap, long unbroken tokens break,
   and the two columns that carry the most characters get a floor width so the
   layout algorithm cannot squeeze them below readable. */
/* break-word, NOT anywhere: `anywhere` also shrinks a cell's min-content width
   to about one character, and with table-layout:auto the browser then happily
   squeezed Name to 186px and Phone to 124px — it was the wrapping, not the
   cure. break-word only breaks a token that genuinely cannot fit. */
.card .table td { white-space: normal; overflow-wrap: break-word; }
/* Name and phone stay on one line. Tagged by theme.js rather than matched with
   :has(): Chrome re-evaluates a :has() rule on every DOM mutation in its scope,
   and with `.table:has(...)` on a page DataTables builds row by row that took
   /people/list from 2.7s to 23.5s. Measured — neutering these seven rules alone
   brought it back to 3.6s. The JS tags once per draw instead.
   Previously: matched by what the cell CONTAINS rather
   than by index — column order differs per listing. No min-width: the auto
   layout already gives these columns what they need once `anywhere` is gone,
   and a hard floor pushed the table wide enough that DataTables Responsive
   collapsed the Actions column into a child row. */
.card .table td.vq-nowrap-cell { white-space: nowrap !important; }

/* ── Sidebar scrolls when the open sub-menus outrun the viewport ─────────── */
/* overflow:visible was set on the panel so the drag grip could hang past its
   right edge — and that also removed the only scroll container, so with two or
   three groups expanded the bottom of the nav simply could not be reached. The
   panel keeps its visible overflow; the nav list inside it does the scrolling. */
.navbar-vertical { display: flex !important; flex-direction: column; }
.navbar-vertical > .container-fluid {
  display: flex; flex-direction: column;
  flex: 1 1 auto; min-height: 0;
}
.navbar-vertical .navbar-collapse {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overflow-x: hidden;
  /* clears the collapse toggle pinned at the bottom of the panel */
  padding-bottom: 46px;
}
.navbar-vertical .navbar-collapse::-webkit-scrollbar { width: 8px; }
.navbar-vertical .navbar-collapse::-webkit-scrollbar-thumb {
  background: rgba(255,255,255,.16); border-radius: 99px;
  border: 2px solid transparent; background-clip: content-box;
}
.navbar-vertical .navbar-collapse::-webkit-scrollbar-track { background: transparent; }

/* ── DataTables chrome, second pass ──────────────────────────────────────── */
/* The label and the input are SIBLINGS inside .dt-search, so flexing the label
   did nothing and the field dropped onto its own line. Flex the wrapper. */
.dt-search, .dt-length { display: flex; align-items: center; gap: 8px; }
.dt-search label, .dt-length label { display: inline-flex; align-items: center; gap: 8px; margin: 0; }
.dt-search input { min-width: 220px; }

/* Header cells never wrap — "Actions" was breaking to "ACTI / ONS" once body
   cells were allowed to wrap. Only the data wraps. */
.card .table th, .card .table thead th { white-space: nowrap !important; }

/* Pull the sort control up against its own column title. DataTables absolutely
   positions it at the cell's right edge, which on a wide column parks it
   halfway to the next heading and reads as a column of arrows. */
.dt-column-header { display: flex !important; align-items: center; gap: 6px; }
/* relative, NOT static: DataTables draws the two triangles as absolutely
   positioned ::before/::after. With the box set to static they resolved
   against the nearest positioned ancestor instead — the .card — and all eight
   columns' arrows stacked into one stray glyph at the card's left edge. */
.dt-column-order {
  position: relative !important;
  inset: auto !important;
  width: 10px !important; height: 1em;
  flex: none; display: inline-block;
}
/* DataTables lets the title box flex to fill the cell, which parked the sort
   control at the far end of a wide column — the pairs of arrows sitting
   halfway between two headings. !important because its own rule is more
   specific than a bare class. */
.dt-column-title { flex: 0 0 auto !important; }
.dt-column-header { justify-content: flex-start !important; }
.dt-column-header:has(.dt-column-title) { width: auto; }
th.text-end .dt-column-header, th.dt-right .dt-column-header { justify-content: flex-end; }

/* ── DataTables sits inside the card's own inset ─────────────────────────── */
/* The DataTables container is dropped into a bare, unpadded div in the card,
   and its layout rows carry Bootstrap's negative gutter — so Search, the info
   line and the pager all rendered hard against the card border while the table
   text sat 20px in. Rows get the card's inset; the table itself stays
   full-bleed because its cells already carry that 20px. */
.card .dt-container > .row { margin-inline: 0 !important; padding-inline: 20px; }
.card .dt-container > .row > [class*="col-"] { padding-inline: 0 !important; }
.card .dt-container > .row.dt-layout-table { padding-inline: 0; }

/* Vertical rhythm: mt-2 (8px) put the search row against the card title and
   the pager against the last data row. */
.card .dt-container > .row:first-child { margin-top: 4px !important; margin-bottom: 14px !important; }
.card .dt-container > .row:last-of-type { margin-top: 14px !important; }
.card .dt-container > .row.dt-layout-table { margin-top: 0 !important; }

/* ── Page title and the cards under it share one left edge ───────────────── */
/* Some views (PropertyList, the custom-field editors) wrap their content in a
   second .container-fluid inside the page's .container-xl. That nested
   container adds its own 16px gutter, so the card sat 16px right of the page
   title while other views lined up. */
.page-body .container-xl .container-fluid,
.page-body .container-xl .container { padding-inline: 0 !important; }

/* ── Calendar fits the window ────────────────────────────────────────────── */
/* This build of FullCalendar ships hashed class names (fc-forma-b7K …), so the
   documented v6 hooks do not exist. What is stable is the ARIA structure —
   role=grid / rowgroup / row — plus the fc- class prefix, which every build
   keeps. The month grid is pinned to what is left of the viewport and the six
   week rows share it instead of each taking their inline flex-basis:130px. */
.page-body [class*="fc-"][role="grid"] {
  height: calc(100vh - 465px) !important;
  min-height: 400px;
}
/* The chain grid → body → rowgroup has to be flex columns that pass the height
   down, or the week rows — freed from their inline flex-basis — collapse to
   1px. The header rowgroup is left alone: only the group whose rows carry an
   inline flex-basis is the week grid. */
.page-body [class*="fc-"][role="grid"] { display: flex; flex-direction: column; }
.page-body [class*="fc-"][role="grid"] > * { flex: 0 0 auto; min-height: 0; }
.page-body [class*="fc-"][role="grid"] > *:has([role="rowgroup"] > [role="row"][style*="flex-basis"]),
.page-body [class*="fc-"] [role="rowgroup"]:has(> [role="row"][style*="flex-basis"]) {
  flex: 1 1 auto !important; min-height: 0; display: flex; flex-direction: column;
}
.page-body [class*="fc-"] [role="rowgroup"] > [role="row"][style*="flex-basis"] {
  flex: 1 1 0 !important;
  min-height: 0 !important;
}
/* Day cells clip a busy day rather than pushing the grid taller. */
.page-body [class*="fc-"] [role="gridcell"] { overflow: hidden; }

/* Toolbar in the product's own type rather than FullCalendar's defaults. */
.page-body [class*="fc-"] [role="heading"] { font-size: 1.05rem !important; font-weight: 700; color: var(--ink); }
.page-body [class*="fc-"] button:not(.btn) {
  border-radius: 9px !important; border: 1px solid var(--line) !important;
  background: #fff !important; color: var(--muted) !important;
  font: 700 12.5px/1.2 'Plus Jakarta Sans', system-ui, sans-serif !important;
  padding: 8px 14px !important; box-shadow: none !important;
}
.page-body [class*="fc-"] button[aria-selected="true"],
.page-body [class*="fc-"] button[aria-pressed="true"] {
  background: #e7efff !important; color: var(--blue) !important; border-color: #cddcfb !important;
}

/* ============================================================================
   PASS 3 — design-rule enforcement, applied globally
   The 8px grid: 8px between controls in a row, 16px between groups, 24px
   between sections. Labels 6px above their field. Nothing paints over a card
   corner. Nothing in the dark sidebar drops below readable contrast.
   ============================================================================ */

/* ── Form labels sit clear of their field ────────────────────────────────── */
.form-label, label.form-label, .form-group > label, .mb-3 > label:not(.form-check-label) {
  margin-bottom: 6px !important;
  display: block;
}
.form-group, .mb-3 { margin-bottom: 16px !important; }
.form-check { margin-top: 4px; }

/* ── Card corners stay intact ────────────────────────────────────────────── */
/* A full-bleed table, footer or list painted a square background over the
   card's 18px corner, so the grey border vanished at the bottom of the card.
   Outer children inherit the radius instead of clipping the card, which would
   also clip the ⋮ action menus. */
.card > :first-child { border-start-start-radius: inherit; border-start-end-radius: inherit; }
.card > :last-child  { border-end-start-radius: inherit;   border-end-end-radius: inherit; }
.card > .table-responsive, .card > .table-responsive > .table,
.card > .table, .card > .list-group, .card > .card-footer, .card > .dt-container,
.card > .card-body:last-child { border-end-start-radius: inherit; border-end-end-radius: inherit; }
.card .table > tbody > tr:last-child > td:first-child,
.card .list-group-flush > .list-group-item:last-child { border-end-start-radius: 17px; }
.card .table > tbody > tr:last-child > td:last-child { border-end-end-radius: 17px; }
/* The last row's own rule doubled the card border at the foot. */
.card .table > tbody > tr:last-child > td,
.card .table > tbody > tr:last-child > th { border-bottom: 0 !important; }
.card .list-group-flush > .list-group-item:last-child { border-bottom: 0 !important; }
.card-footer { background: transparent !important; border-top: 1px solid var(--line) !important; }

/* ── Sidebar count badges: every variant readable on the dark panel ──────── */
/* The Calendar row carries three badges in three Tabler colours; the
   secondary one inherited the page's muted grey and disappeared into the
   panel. One treatment for all of them. */
.navbar-vertical .badge, .navbar-vertical .badge *,
.navbar-vertical .badge.bg-secondary, .navbar-vertical .badge.text-secondary,
.navbar-vertical .badge.bg-secondary-lt, .navbar-vertical .badge[class*="bg-"] {
  background: rgba(59, 130, 246, .2) !important;
  color: #bfdbfe !important;
  font-weight: 700 !important;
  min-width: 20px; text-align: center;
}
.navbar-vertical .badge + .badge { margin-left: 4px; }

/* ── Button rows: 8px between buttons, always ────────────────────────────── */
.btn-list, .btn-group-flex, .card-actions, .page-title-actions,
.d-flex:has(> .btn + .btn), .btn-toolbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.btn-list > .btn, .btn-list > .dropdown { margin: 0 !important; }
.btn + .btn:not(.btn-group > .btn) { margin-left: 8px; }
.d-flex:has(> .btn + .btn) > .btn + .btn { margin-left: 0; }

/* ── Calendar toolbar and sizing ─────────────────────────────────────────── */
/* Month / Week / Day / List sat flush; prev / next / today too. And the grid
   can take more room than the strict fit gave it. */
.page-body [class*="fc-"] [role="tablist"],
.page-body [class*="fc-"] [role="toolbar"] > *,
.page-body [class*="fc-"] .crm-fc-head > * { display: flex; gap: 8px; align-items: center; }
.page-body [class*="fc-"] .crm-fc-head { gap: 16px; flex-wrap: wrap; row-gap: 12px; margin-bottom: 16px; }
.page-body [class*="fc-"][role="grid"] {
  height: max(600px, calc(100vh - 465px)) !important;
}
.page-body [class*="fc-"] [role="gridcell"] { padding: 4px; }

/* ── Grids of equal cards centre and space evenly ────────────────────────── */
.page-body .row.row-cards, .page-body .row.g-3, .page-body .row.g-4 { --tblr-gutter-x: 24px; --tblr-gutter-y: 24px; }
.page-body .row > [class*="col-"] > .card:only-child { height: 100%; }
/* .mb-3 is also on cards and rows; the 16px form-group rule above must not
   pull those down from the 24px section gap. */
.card.mb-3, .row.mb-3, .page-body > .mb-3 { margin-bottom: 1.5rem !important; }

/* ── Dashboard Birthdays: name starts at the card edge ───────────────────── */
/* MainDashboard.js gives the Birthdays table a leading 40px column that renders
   an empty string (a photo slot that is never filled — the avatar is drawn
   inside the Name cell instead). Empty column + its 20px edge padding pushed
   every name ~90px in from the card. */
#PersonBirthdayDashboardItem th:first-child,
#PersonBirthdayDashboardItem td:first-child { display: none; }
#PersonBirthdayDashboardItem th:nth-child(2),
#PersonBirthdayDashboardItem td:nth-child(2) { padding-left: 20px !important; }

/* ── Full-bleed card bodies stay full-bleed ──────────────────────────────── */
/* Tabler marks a card body that holds a table with .p-0 so the table can run
   edge to edge and let its cells carry the inset. The blanket
   `.card-body { padding: 20px !important }` beat that utility, so every such
   table was indented 20px on top of its own 20px cell padding — the Birthdays
   names on the dashboard sat 40px right of the card title. */
.card-body.p-0 { padding: 0 !important; }
.card-body.px-0 { padding-inline: 0 !important; }
.card-body.py-0 { padding-block: 0 !important; }

/* DataTables built with the legacy `dom` option wraps the table in a plain
   .row (no dt-layout-table class), so the 20px row inset meant for the
   search/pager rows was landing on the table as well. */
.card .dt-container > .row:has(> [class*="col-"] > table),
.card .dt-container > .row:has(> [class*="col-"] > .table-responsive) { padding-inline: 0 !important; }

/* ── AUDIT: GROUPS+EVENTS ── */
/* Groups, Sunday School, Events and the Calendar. Measured at 1440×1000
   through the preview proxy; each rule names the page and the defect. */

/* ── Card footers (group view About/Properties, event check-in) ──────────── */
/* The verbatim-spec footer had 0 top padding, so once the footer grew a
   border-top the Email Export line and the Assign row sat 2–6px under the
   rule. 16px above, the same as any group gap. */
.card-footer { padding: 16px 20px 20px !important; }
/* Group view Properties footer: a .form-select-sm next to a btn-sm primary
   was 41px against 35px — Tabler's -sm select still took the full-size input
   padding. Match the button beside it. */
.card-footer .d-flex > .form-select-sm,
.card-footer .d-flex > .form-control-sm {
  height: 35px; min-height: 35px !important; padding-block: 0 !important;
  font-size: 13px !important; line-height: 33px;
}

/* ── Card headers that are an <h5> (groups dashboard "Add New Group",
      "Groups"; group types "Add New Group Type", "Existing Options") ────── */
/* These views skip .card-title and drop a bare h5 in the header, so the title
   rendered at 13px/500 with the icon glyph touching the text. Same type as
   every other card title, icon 9px off the word. */
.card-header > h5, .card-header > h4 {
  font-size: 1rem !important; font-weight: 600 !important; color: var(--ink) !important;
  display: flex; align-items: center; gap: 9px; margin: 0;
}
.card-header > h5 > i, .card-header > h4 > i { margin-right: 0 !important; }

/* ── Sunday School dashboard: .table-bordered inside a card ─────────────── */
/* Both DataTables there are .table-bordered, the only listing tables in the
   product with vertical rules between cells. Horizontal rules only, like every
   other list. */
.card .table-bordered,
.card .table-bordered > :not(caption) > * > * { border-left: 0 !important; border-right: 0 !important; }
.card .table-bordered > :not(caption) > thead > * > * { border-top: 0 !important; }

/* ── Event Types: sort control on the numeric "Events" column ───────────── */
/* DataTables flips .dt-type-numeric headers to row-reverse, which parked the
   arrows BEFORE the label — the one header out of seven reading backwards.
   text-center columns also centre their header over the centred values. */
th.dt-type-numeric .dt-column-header { flex-direction: row !important; }
th.text-center .dt-column-header { justify-content: center !important; }

/* ── PropertyList (Type=g): Person / Family / Group filter ──────────────── */
/* A .btn-group of three outline buttons: touching, and the active one drew
   exactly like the others so the current tab was invisible. Pills with the
   8px control gap and the same active tint the Members tabs use. */
.btn-group:not(.dropdown):not(:has(> .dropdown-toggle)) { display: inline-flex; gap: 8px; }
.btn-group:not(:has(> .dropdown-toggle)) > .btn { border-radius: 9px !important; margin-left: 0 !important; }
.btn-group > .btn.active, .btn-group > .btn.active:hover {
  background: #e7efff !important; color: var(--blue) !important; border-color: #cddcfb !important;
}

/* ── Event editor ───────────────────────────────────────────────────────── */
/* The title input is form-control-lg.border-0.border-bottom.rounded-0.px-0:
   with the global #fbfcff input fill that became a borderless grey slab and
   its label was the only muted label on the form. A regular field, and the
   label matches its neighbours. */
.form-control.border-0.border-bottom {
  border: 1px solid var(--line) !important; border-radius: 10px !important;
  padding: .58rem .85rem !important; background: #fbfcff !important;
  font-size: 15px !important; font-weight: 600; color: var(--ink);
}
label.form-label.text-muted { color: var(--ink) !important; font-size: .8rem !important; }
/* Tom Select: the single (Event Type, 38px) and multi (Pinned Calendars, 42px)
   controls sat on either side of the 40px native fields in the same row. */
.ts-wrapper.form-select:not(.form-select-sm) { min-height: 40px !important; height: auto !important; padding: 0 !important; }
.ts-wrapper.form-select:not(.form-select-sm) > .ts-control {
  min-height: 40px !important; padding: 7px 12px !important; align-items: center;
  border: 1px solid var(--line) !important; border-radius: 10px !important; background: #fbfcff !important;
}
.ts-wrapper.multi > .ts-control > .item { margin: 0 4px 0 0 !important; }
/* Quill's placeholder is absolutely positioned; without a positioned editor it
   resolved against the card and hung 4px outside the editor's left edge. */
.ql-container { position: relative; }
.ql-editor { position: relative; }

/* ── Calendar (/event/calendars) ────────────────────────────────────────── */
/* The earlier toolbar rule targeted .crm-fc-head; the class ChurchCRM
   actually sets is .crm-fc-header-toolbar, so nothing about the toolbar had
   landed except the tablist gap. */
.crm-fc-header-toolbar {
  display: flex !important; align-items: center; gap: 16px !important;
  padding: 20px 20px 16px !important; margin: 0 !important;
}
/* Three equal sections so the month title is centred on the card, not on
   whatever is left between a 179px left group and a 263px right group. */
.crm-fc-header-toolbar > div { flex: 1 1 0 !important; display: flex; align-items: center; gap: 16px !important; min-width: 0; }
.crm-fc-header-toolbar > div:nth-child(1) { justify-content: flex-start; }
.crm-fc-header-toolbar > div:nth-child(2) { justify-content: center; }
.crm-fc-header-toolbar > div:nth-child(3) { justify-content: flex-end; }
/* prev / next were fused (a 50×38 pair beside 33px-tall buttons). 8px apart,
   square, and the same height as the quiet buttons around them. */
.crm-fc-header-toolbar > div > div { display: flex; gap: 8px; align-items: center; }
.crm-fc-header-toolbar button[aria-label="Previous Month"],
.crm-fc-header-toolbar button[aria-label="Next Month"],
.crm-fc-header-toolbar button[aria-label^="Previous"],
.crm-fc-header-toolbar button[aria-label^="Next"] {
  width: 33px !important; height: 33px !important; padding: 0 !important;
  display: inline-grid !important; place-items: center;
}
.crm-fc-header-toolbar button svg { width: 16px; height: 16px; }
.crm-fc-header-toolbar button:disabled { opacity: .55; }
.crm-fc-header-toolbar [role="heading"] {
  font-size: 18px !important; font-weight: 700 !important; color: var(--ink) !important;
  letter-spacing: -0.015em; white-space: nowrap;
}

/* The grid drew its own 1px #e0e0e0 frame inside the card border (a card
   within a card) and painted a square white background that hid the card's
   bottom corners. No frame, transparent, bottom corners rounded on the last
   row's outer cells (the only cells that paint a background there). */
.page-body [class*="fc-"][role="grid"] { border: 0 !important; background: transparent !important; border-radius: 0 !important; }
.page-body [class*="fc-"][role="grid"] > * { background: transparent !important; }
.page-body [class*="fc-"] [role="rowgroup"] > [role="row"]:last-child > [role="gridcell"]:first-child { border-end-start-radius: 17px; }
.page-body [class*="fc-"] [role="rowgroup"] > [role="row"]:last-child > [role="gridcell"]:last-child  { border-end-end-radius: 17px; }
/* Rules between cells in the product's line colour rather than FullCalendar's. */
.page-body [class*="fc-"] [role="row"],
.page-body [class*="fc-"] [role="gridcell"],
.page-body [class*="fc-"] [role="columnheader"],
.page-body [class*="fc-"][role="grid"] > * > * { border-color: var(--line) !important; }

/* Bigger: 780px gives six 124px week rows, which is a day number plus four
   event chips without clipping. The page scrolls ~130px at 1000px tall, which
   was accepted. */
.page-body [class*="fc-"][role="grid"] { height: max(780px, calc(100vh - 330px)) !important; }

/* Day-name header: 16px/400 body text became the heaviest thing on the grid.
   Same treatment as a table header. */
.page-body [class*="fc-"] [role="columnheader"],
.page-body [class*="fc-"] [role="columnheader"] * {
  font-size: 11px !important; font-weight: 700 !important; letter-spacing: .08em;
  text-transform: uppercase; color: var(--soft) !important;
}
.page-body [class*="fc-"] [role="columnheader"] > div > div { padding: 10px 8px !important; }

/* Day numbers: 14px/400 near-black → readable weight in the ink colour. */
.page-body [class*="fc-"] [role="gridcell"] > div:first-child > [aria-hidden="true"] {
  font-size: 13px !important; font-weight: 600 !important; color: var(--ink);
  padding: 6px 8px !important; font-variant-numeric: tabular-nums;
}
/* Today and weekends: subtle tints. Other-month days keep FullCalendar's grey. */
.page-body [class*="fc-"] [role="gridcell"][aria-current="date"] { background: #eef4ff !important; }
.page-body [class*="fc-"] [role="row"] > [role="gridcell"]:first-child:not([aria-current="date"]),
.page-body [class*="fc-"] [role="row"] > [role="gridcell"]:last-child:not([aria-current="date"]) { background-color: rgba(15, 23, 42, .022); }

/* Event chips. The per-calendar colour arrives as --fc-event-color (#0000FF,
   #00AA00 …) and was used raw: a 6px pure-blue bar on a saturated fill, 16px
   box with a 12px label clipped mid-word. Soft tint of the calendar colour,
   3px bar, ellipsis on the label. */
.page-body [role="gridcell"] a[style*="--fc-event-color"] {
  font-size: 12px !important; border-radius: 6px !important;
  margin: 0 4px 2px 4px !important; padding: 1px 2px !important;
  color: var(--ink) !important; min-width: 0;
}
.page-body [role="gridcell"] a[style*="--fc-event-color"][class*="fc-"]:not(:has(> div:first-child:empty)) {
  background: color-mix(in srgb, var(--fc-event-color) 12%, #fff) !important;
  border-left-width: 3px !important;
  border-left-color: color-mix(in srgb, var(--fc-event-color) 70%, #fff) !important;
}
.page-body [role="gridcell"] a[style*="--fc-event-color"] div {
  font-size: 12px !important; text-overflow: ellipsis !important; min-width: 0;
}
.page-body [role="gridcell"] a[style*="--fc-event-color"] > div:first-child:empty {
  background: color-mix(in srgb, var(--fc-event-color) 75%, #fff) !important;
  width: 8px !important; height: 8px !important; flex: none;
}
.page-body [role="gridcell"] a[style*="--fc-event-color"]:hover { filter: brightness(.97); }
/* First chip sits 4px under the day number, not flush against it. */
.page-body [class*="fc-"] [role="gridcell"] > div:first-child { padding-bottom: 2px; }

/* ── AUDIT: FINANCE+COMMS ── */
/* Finance, Fundraiser, Communication, Data/Reports, the logged-out login page
   and the 390px dashboard. Every rule names the page it was measured on. */

/* [mobile /v2/dashboard] The sidebar width and the page offset were written
   without a breakpoint, so at 390px the panel stayed 252px wide, the page was
   pushed 252px right and every card was 49–122px wide. Tabler only makes the
   sidebar vertical from xl (1200px); below that it is a top bar. */
@media (max-width: 1199.98px) {
  .navbar-vertical {
    width: auto !important; min-width: 0 !important; max-width: none !important;
    position: relative !important; padding: 10px 12px !important;
  }
  .page-wrapper { margin-inline-start: 0 !important; }
  .vq-grip, .vq-collapse { display: none !important; }
  /* the theme stacked toggler / brand / nav as a column; the top bar is a row */
  .navbar-vertical > .container-fluid {
    flex-direction: row !important; flex-wrap: wrap !important;
    align-items: center !important; justify-content: space-between !important;
    min-height: 0 !important;
  }
  .navbar-vertical .navbar-brand { padding: 0 !important; margin: 0 !important; }
  .navbar-vertical .navbar-collapse {
    flex: 1 1 100% !important; overflow: visible !important; padding-bottom: 0 !important;
  }
  .navbar-vertical .navbar-collapse.show { padding-top: 8px; }
  .page-title { font-size: 1.6rem !important; }
}

/* [all pages] The floating Add Person / Add Family buttons sat fixed over the
   bottom-right corner, covering the Deposit Statistics card and the Run button
   on the last Query Listing rows. On desktop the only dead space on screen is
   the foot of the sidebar, beside the collapse toggle — they live there now as
   quiet chips in the sidebar's own vocabulary. */
@media (min-width: 1200px) {
  #fab-container {
    right: auto !important; left: 12px !important; bottom: 12px !important;
    flex-direction: row !important; align-items: center !important; gap: 8px !important;
  }
  .vq-sidebar-collapsed #fab-container { flex-direction: column !important; bottom: 52px !important; }
  .fab-button, .fab-button.fab-family {
    width: 28px !important; height: 28px !important; border-radius: 8px !important;
    background: rgba(255,255,255,.06) !important; border: 1px solid rgba(255,255,255,.12) !important;
    color: #cbd5e1 !important; box-shadow: none !important;
  }
  .fab-button:hover, .fab-button.fab-family:hover {
    background: rgba(255,255,255,.14) !important; color: #fff !important; transform: none !important;
  }
  .fab-button .fab-icon { font-size: 12px !important; }
  /* the nav list must be able to scroll clear of the chips */
  .navbar-vertical .navbar-collapse { padding-bottom: 56px !important; }
  .vq-sidebar-collapsed .navbar-vertical .navbar-collapse { padding-bottom: 140px !important; }
}
/* [mobile] below xl the FABs stay bottom-right; the grey menu toggle and the
   green family button become brand/ink so no raw Bootstrap grey or off-brand
   green floats over the page. */
@media (max-width: 1199.98px) {
  .fab-button.fab-family { background-color: var(--blue) !important; box-shadow: 0 4px 12px rgba(37,99,235,.3) !important; }
  .fab-menu-toggle { background-color: var(--ink) !important; box-shadow: 0 4px 12px rgba(15,23,42,.3) !important; }
}

/* [/finance/deposit/search, /finance/funds] A second .container-xl nested in
   the page's .container-xl added its own 16px gutter — cards sat at x=284
   under a title at x=268. Same fix the theme already applies to nested
   .container-fluid. */
.page-body .container-xl .container-xl { padding-inline: 0 !important; }

/* [/finance/reports] Card rows were 76px apart: 24px card margin + 24px .mb-4
   on the column + 24px row-gap. Cards already carry the 24px; the column and
   row contribute nothing. */
.page-body .row:has(> [class*="col-"] > .card) { row-gap: 0 !important; --tblr-gutter-y: 0; }
.page-body .row:has(> [class*="col-"] > .card) > [class*="col-"] { margin-bottom: 0 !important; }

/* [/finance/reports] Card titles were <h5> rather than .card-title: Tabler's
   h5 is 12px, h6 is 10px — the "Membership Reports" header was white-on-white
   (bg-dark text-white with the theme's transparent header) and every icon sat
   flush against its title. Any heading in a card header is a card title. */
.card-header > :is(h1,h2,h3,h4,h5,h6) {
  font-size: 1rem !important; font-weight: 600 !important; color: var(--ink) !important;
  margin: 0; display: flex; align-items: center; gap: 9px; letter-spacing: -0.01em;
}
.card-header > :is(h1,h2,h3,h4,h5,h6) > i:first-child { margin-right: 0 !important; }
.card-header.text-white, .card-header.text-white > *, .card-header.bg-dark > * { color: var(--ink) !important; }
.card-header.bg-dark, .card-header.bg-light, .card-header[class*="bg-"] { background: transparent !important; }
h5, .h5 { font-size: .9375rem; }
h6, .h6 { font-size: .8rem; }
.card-body h6:has(> i:first-child) { display: flex; align-items: center; gap: 8px; color: var(--ink); font-weight: 700; }

/* [/finance/, /finance/reports, /finance/funds] Text floor is 12px: badges
   were 11.52px, table headers and DataTables column titles 10.72px, the
   page pretitle 10.9px. */
.badge { font-size: 12px !important; }
.table thead th, .dt-column-title { font-size: 12px !important; letter-spacing: .06em; }
.page-pretitle, .subheader { font-size: 12px !important; }

/* [/finance/reports helper text, /finance/ Fiscal Year, DataTables labels]
   --soft (#8591a2) on white is 3.6:1. #64748b is 4.8:1 and still reads as
   secondary. */
.text-muted, .text-secondary, small, .small, .page-pretitle, .subheader,
.dt-info, .dt-search label, .dt-length label, .dt-column-order,
.text-body-secondary, .form-text, .help-block, .empty-subtitle { color: #64748b !important; }
.dt-column-order::before, .dt-column-order::after { color: #64748b !important; }

/* [/finance/deposit/search] Numeric and date columns had their sort arrows
   BEFORE the title (DataTables flips them to row-reverse) while the theme
   left-packed the header — "▼ ID" against a right-aligned column. */
th.dt-type-numeric .dt-column-header, th.dt-type-date .dt-column-header {
  flex-direction: row !important; justify-content: flex-end !important;
}

/* [/finance/ "No Active Deposit"] The empty-state glyph was Bootstrap grey. */
.empty-icon, .empty-icon > i, .empty-icon > svg { color: var(--blue) !important; }
.empty-title { color: var(--ink) !important; font-weight: 600; }

/* [/finance/funds "Active", /finance/ checklist] Soft badge variants Tabler
   spells -lt were falling through to the default blue tint. Colour means
   status here, so it stays. */
.badge.bg-success-lt, .badge.bg-green-lt, .badge.bg-teal-lt  { background: #e6f6ed !important; color: #1f8a55 !important; }
.badge.bg-warning-lt, .badge.bg-orange-lt, .badge.bg-yellow-lt { background: #fdf1de !important; color: #b06d13 !important; }
.badge.bg-danger-lt, .badge.bg-red-lt { background: #fdeaea !important; color: #c2403c !important; }
.badge.bg-warning.text-dark { color: #b06d13 !important; }

/* [/v2/email/dashboard, /v2/text/dashboard, /finance/pledge/dashboard]
   Alerts were raw Bootstrap tints with a 0px gap between the copy and the
   button inside them ("newsletters" ran into "Plugin Settings"). One soft
   tint per meaning, the design radius, and 16px between text and action. */
.alert {
  border-radius: 12px !important; padding: 14px 16px !important;
  border: 1px solid var(--line) !important; background: #f8fafc !important; color: var(--ink) !important;
}
.alert-success { background: #effaf3 !important; border-color: #cdebd9 !important; }
.alert-warning { background: #fff7ec !important; border-color: #f6dfbd !important; }
.alert-danger  { background: #fdf0f0 !important; border-color: #f3cfcf !important; }
.alert-info    { background: #eef4ff !important; border-color: #cfdcf9 !important; }
.alert-secondary, .alert-light { background: #f8fafc !important; border-color: var(--line) !important; }
.alert .d-flex { gap: 12px; }
.alert .d-flex > .btn { flex: none; margin-left: auto; }
.alert .d-flex > .btn + .btn { margin-left: 0; }
.alert > i:first-child, .alert .d-flex > i:first-child { flex: none; }
.alert .text-body-secondary, .alert .text-muted, .alert small { color: #64748b !important; }

/* [/QueryView.php, /finance/pledge/dashboard] Bare <label> elements (no
   .form-label) rendered 14px/400 in body grey; the Fiscal Year label sat 17px
   above its select because the inline <form> between them added a line box. */
.card-body .mb-3 > label:first-child:not(.form-check-label),
.page-body .mb-3 > label.fw-bold {
  font-size: .8rem !important; font-weight: 600 !important; color: var(--ink) !important;
  display: block; margin-bottom: 6px !important;
}
.mb-3 > label + form.d-inline { display: block !important; }
.mb-3 > form.d-inline + small { display: block; margin-top: 6px; }
.help-block, .form-text { font-size: 12.5px; margin-top: 6px; }

/* [/ManageEnvelopes.php] The page has no card — a bare .card-body under the
   container — and a raw <table> whose header cells hold a native <select>,
   three submit buttons and an unstyled text input on one nowrap line, so the
   table ran 30px past the viewport. The body becomes a card, the header cells
   wrap, and the controls take the design's input and select styling. */
.page-body > .container-xl > .card-body {
  background: #fff; border: 1px solid var(--line); border-radius: 18px;
  padding: 20px !important; margin-bottom: 24px;
}
form[name="ManageEnvelopes"] .table { table-layout: fixed; width: 100%; }
form[name="ManageEnvelopes"] th:first-child { width: 58%; }
form[name="ManageEnvelopes"] th:last-child  { width: 42%; }
form[name="ManageEnvelopes"] th {
  white-space: normal !important; text-transform: none !important; letter-spacing: 0 !important;
  font-size: 13px !important; color: var(--muted) !important; vertical-align: middle; line-height: 1.5;
}
form[name="ManageEnvelopes"] th b { color: var(--ink); font-weight: 600; }
form[name="ManageEnvelopes"] th > .btn, form[name="ManageEnvelopes"] th > input,
form[name="ManageEnvelopes"] th > select, form[name="ManageEnvelopes"] th > .form-check-inline {
  margin: 4px 8px 4px 0 !important; vertical-align: middle;
}
form[name="ManageEnvelopes"] th > .form-check-inline { display: inline-flex; align-items: center; gap: 8px; }
form[name="ManageEnvelopes"] .form-check-inline .form-check-label { font-size: 13px; text-transform: none; }
form[name="ManageEnvelopes"] select:not(.form-select),
form[name="ManageEnvelopes"] input[type="text"]:not(.form-control) {
  appearance: none; -webkit-appearance: none;
  border: 1px solid var(--line); border-radius: 9px; background: #fbfcff; color: var(--ink);
  font: 500 13px/1.2 'Plus Jakarta Sans', system-ui, sans-serif; padding: 8px 12px; min-height: 33px;
}
form[name="ManageEnvelopes"] select:not(.form-select) {
  padding-right: 30px;
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23475569' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m6 9 6 6 6-6'/%3e%3c/svg%3e");
  background-repeat: no-repeat; background-position: right 10px center;
}
form[name="ManageEnvelopes"] input[type="text"]:not(.form-control) { width: 80px; text-align: right; }
form[name="ManageEnvelopes"] td .form-control { max-width: 160px; text-align: right; }
form[name="ManageEnvelopes"] > .btn + .btn { margin-left: 8px; }

/* [/finance/deposit/search] The card-header collapse chevron was a 12×20px
   target. */
.card-options-collapse, .card-header a[data-bs-toggle="collapse"] {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 8px; color: var(--muted);
}
.card-options-collapse:hover { background: #f1f5f9; color: var(--ink); }

/* [/session/begin] The login page was still ChurchCRM's own: a photo under a
   65% black scrim (reads as flat grey), the old #667eea→#764ba2 purple on the
   button, link and icon, #888 contact links at 3.5:1, a 2px header rule, 8px
   radii. Same canvas, card, inputs and button as every other screen. */
body.page-login { background: var(--paper) !important; }
body.page-login::before { display: none !important; }
.login-card {
  border-radius: 18px !important; border: 1px solid var(--line);
  box-shadow: 0 10px 34px rgba(20,30,60,.08) !important;
}
.login-card-header {
  background: none !important; border-bottom: 1px solid var(--line) !important;
  padding: 28px 32px 24px !important; border-radius: 0 !important;
}
.login-header-logo { margin-bottom: 16px !important; }
.login-header-logo img { max-height: 84px !important; }
.login-card-body { padding: 24px 32px 28px !important; }
.login-header-church-name { color: var(--ink) !important; font-size: 22px !important; font-weight: 700 !important; letter-spacing: -.02em !important; margin-bottom: 6px !important; }
.login-header-tagline { color: #64748b !important; font-size: 13px !important; letter-spacing: 0 !important; }
.login-form-title { margin-bottom: 24px !important; }
.login-form-title h1 { color: var(--ink) !important; font-size: 20px !important; letter-spacing: -.02em; gap: 9px !important; margin-bottom: 6px !important; }
.login-form-title h1 i { color: var(--blue) !important; font-size: 18px !important; }
.login-form-title p { color: #64748b !important; font-size: 13.5px !important; }
body.page-auth .mb-3 { margin-bottom: 16px !important; }
body.page-auth .mb-3 label {
  margin-bottom: 6px !important; font-size: 12.8px !important; font-weight: 600 !important;
  color: var(--ink) !important; letter-spacing: 0 !important;
}
body.page-auth .mb-3 > input:not([type="checkbox"]):not([type="radio"]) {
  border: 1px solid var(--line) !important; border-radius: 10px !important; background: #fbfcff !important;
  padding: 10px 14px !important; font-size: 14px !important; min-height: 41px; color: var(--ink);
}
body.page-auth .mb-3 > input:not([type="checkbox"]):not([type="radio"]):hover { background: #fbfcff !important; border-color: #dfe4ee !important; }
body.page-auth .mb-3 > input:not([type="checkbox"]):not([type="radio"]):focus {
  background: #fff !important; border-color: var(--blue) !important; box-shadow: 0 0 0 4px rgba(37,99,235,.12) !important;
}
.login-card-body .form-footer { display: flex; justify-content: space-between; align-items: center; margin: -4px 0 16px; }
.login-card-body .form-footer a { color: var(--blue) !important; font-size: 12.5px; font-weight: 600; }
.btn-sign-in {
  background: var(--blue) !important; border-radius: 10px !important; padding: 11px 16px !important;
  font: 700 14px/1.2 'Plus Jakarta Sans', system-ui, sans-serif !important; box-shadow: none !important;
  position: relative; overflow: hidden;
}
.btn-sign-in::before { display: none !important; }
.btn-sign-in:hover { background: #1d4fd8 !important; transform: none !important; box-shadow: none !important; }
.login-contact-footer { border-top-color: var(--line) !important; margin-top: 20px !important; padding-top: 16px !important; gap: 8px 16px !important; }
.login-contact-footer a { color: #64748b !important; font-size: 12.5px !important; gap: 8px !important; font-weight: 500; }
.login-contact-footer a i { color: #8591a2 !important; font-size: 12px !important; }
.login-contact-footer a:hover, .login-contact-footer a:hover i { color: var(--blue) !important; }
.auth-footer { color: #64748b !important; }
.auth-footer a { color: var(--ink) !important; }
.auth-footer-social a {
  background: #fff !important; border: 1px solid var(--line); color: #475569 !important;
  width: 36px !important; height: 36px !important; border-radius: 10px !important;
}
.auth-footer-social a:hover { background: #fbfcff !important; color: var(--blue) !important; }

/* ── Dashboard Birthdays / Anniversaries: give the name the room ─────────── */
/* DataTables auto-sized the two visible columns 156px / 211px — the DATE got
   the wider column and every name broke onto two lines beside its avatar.
   Fixed layout with the proportions the JS asked for (60 / 40) and the date
   kept on one line. */
#PersonBirthdayDashboardItem, #FamiliesWithAnniversariesDashboardItem { table-layout: fixed; width: 100% !important; }
#PersonBirthdayDashboardItem th:nth-child(2), #PersonBirthdayDashboardItem td:nth-child(2),
#FamiliesWithAnniversariesDashboardItem th:first-child, #FamiliesWithAnniversariesDashboardItem td:first-child { width: 62% !important; }
#PersonBirthdayDashboardItem th:nth-child(3), #PersonBirthdayDashboardItem td:nth-child(3),
#FamiliesWithAnniversariesDashboardItem th:nth-child(2), #FamiliesWithAnniversariesDashboardItem td:nth-child(2) {
  width: 38% !important; white-space: nowrap; text-align: right;
}
#PersonBirthdayDashboardItem td:nth-child(3) .badge, #FamiliesWithAnniversariesDashboardItem td:nth-child(2) .badge { margin-top: 4px; }
#PersonBirthdayDashboardItem td .small, #FamiliesWithAnniversariesDashboardItem td .small { margin-top: 3px; }
/* Name + avatar row: avatar never shrinks, name may wrap only when it must. */
#PersonBirthdayDashboardItem td .d-flex, #FamiliesWithAnniversariesDashboardItem td .d-flex { gap: 10px !important; }
#PersonBirthdayDashboardItem td .avatar, #FamiliesWithAnniversariesDashboardItem td .avatar { flex: none; }
#PersonBirthdayDashboardItem td a, #FamiliesWithAnniversariesDashboardItem td a { overflow-wrap: break-word; }
/* The "Loading…" / "No birthdays" cell is a colspan first-child — the rule
   hiding the empty photo column must not take it with it. */
#PersonBirthdayDashboardItem td[colspan] { display: table-cell !important; }

/* [mobile /v2/dashboard] Below xl the Add Person / Add Family floats sat over
   the Today's Events "Check-in" button (three 56px circles, bottom-right).
   Both actions already live under People in the menu, so on small screens
   only the scroll-anywhere menu toggle stays, at a 44px footprint. */
@media (max-width: 1199.98px) {
  #fab-container { right: 16px !important; bottom: 16px !important; gap: 8px !important; }
  #fab-container .fab-person, #fab-container .fab-family { display: none !important; }
  .fab-menu-toggle { width: 44px !important; height: 44px !important; font-size: 16px; }
}

/* ── AUDIT: PEOPLE ── */
/* Dashboard, People dashboard, person/family listings, editors, property and
   custom-field editors, options editors. Measured at 1440×1000 through the
   preview proxy. Each rule names the page and the defect it fixes. */

/* [/people/list Filters, /people/family Filters, every form row in a card]
   Form-group rows inside a card were 48px apart: Bootstrap's g-3 gutter
   (raised to 24px by the theme) PLUS the theme's 24px row-gap on every .row.
   The rule is 16px between groups. Rows of cards are excluded — the
   finance block already zeroes those separately. */
.card .row:not(:has(> [class*="col-"] > .card)) { row-gap: 0 !important; }
.card .row.g-3:not(:has(> [class*="col-"] > .card)),
.card .row.g-4:not(:has(> [class*="col-"] > .card)) { --tblr-gutter-y: 16px; }

/* [/people/list People table, /admin/system/options Existing Options,
   /people/family/1 Key People + Children, /FamilyEditor.php Family Members]
   These tables sit inside a padded .card-body, so the cells' own 20px edge
   inset stacked on the body's 20px: header text, search box and pager sat
   40px in while the card title sat at 20px. Inside a padded body the edge
   cells carry no inset of their own. Full-bleed bodies (.p-0/.px-0) are the
   ones that need the 20px and are left alone. */
.card-body:not(.p-0):not(.px-0) > .dt-container > .row { padding-inline: 0 !important; }
.card-body:not(.p-0):not(.px-0) .table > :not(caption) > * > *:first-child { padding-left: 0 !important; }
.card-body:not(.p-0):not(.px-0) .table > :not(caption) > * > *:last-child  { padding-right: 0 !important; }
.card-body:not(.p-0):not(.px-0) .table > tbody > tr:last-child > td:first-child,
.card-body:not(.p-0):not(.px-0) .table > tbody > tr:last-child > td:last-child { border-radius: 0; }

/* [/FamilyEditor.php Family Members] Ten input columns in a 1114px body: the
   auto layout squeezed every select to ~62px, so "Head of Household" read as
   "Heac" and "Unknown" as "Unk" — text overflowing its cell. Cells in an
   input grid take 6px gutters instead of 16px, and each control gets the
   floor width its longest option needs; the grid already sits in a
   .table-responsive, so anything narrower scrolls rather than clips. */
.card .table.vq-input-grid > :not(caption) > * > * { padding-inline: 6px !important; }
.card .table.vq-input-grid > :not(caption) > * > *:first-child { padding-left: 0 !important; }
.card .table.vq-input-grid > :not(caption) > * > *:last-child  { padding-right: 0 !important; }
.table td > .form-control-sm { min-width: 80px; }
.table td > .form-select-sm  { min-width: 92px; text-overflow: ellipsis; }
.table td > select[name^="BirthMonth"] { min-width: 108px; }
.table td > select[name^="Classification"] { min-width: 124px; }
.table td > select[name^="Role"] { min-width: 168px; }
.table td > .form-control-sm, .table td > .form-select-sm { width: 100%; }

/* [/people/family/1 Key People] The name link sits in a flex row beside the
   avatar, so the theme's nowrap rule (which matches a link that is the cell's
   direct child) did not reach it and "Rafael Candilejo" broke onto two lines
   next to a one-line badge. */
.card .table td.vq-nowrap-cell { white-space: nowrap !important; }
.card .table td.vq-nowrap-cell a[href*="/people/view/"] { white-space: nowrap; }

/* [/people/list Family Status] The one Tom Select control holding a chip was
   48px tall beside three 42px empties in the same row. Chip and control
   padding trimmed so a filled control is the same 40px as an empty one. */
.ts-wrapper.multi.has-items > .ts-control { padding-block: 3px !important; }
.ts-wrapper.multi > .ts-control > .item {
  padding: 2px 8px !important; margin: 0 4px 0 0 !important;
  line-height: 1.4 !important; font-size: 13px; border-radius: 6px;
}

/* [/people/dashboard Age Distribution] Chart axis labels were 11px; the
   floor is 12px. [/v2/dashboard Latest Families] The 34px initials chip
   used .fs-6 and rendered its initials at 10px. */
.apexcharts-xaxis-label, .apexcharts-yaxis-label, .apexcharts-datalabel,
.apexcharts-xaxis-title-text, .apexcharts-yaxis-title-text,
.page-body .card svg text { font-size: 12px !important; }
.avatar-title.fs-6, .avatar-sm .avatar-title { font-size: 12px !important; }
/* DataTables also writes a <colgroup> (36px / 193px / 138px) for the THREE
   columns. Hiding only the cells of the empty first column shifted its 36px
   <col> onto Name, which is why every name wrapped one letter per line.
   Collapse the first <col> and size the other two explicitly. */
#PersonBirthdayDashboardItem colgroup col:first-child { visibility: collapse; width: 0 !important; }
#PersonBirthdayDashboardItem colgroup col:nth-child(2) { width: 62% !important; }
#PersonBirthdayDashboardItem colgroup col:nth-child(3) { width: 38% !important; }
#FamiliesWithAnniversariesDashboardItem colgroup col:nth-child(1) { width: 62% !important; }
#FamiliesWithAnniversariesDashboardItem colgroup col:nth-child(2) { width: 38% !important; }

/* ============================================================================
   AUDIT: ADMIN — Admin Dashboard, Plugin Management, Export, Backup, Restore,
   Reset, Upgrade, Logs, Debug, System Settings, Church Info, Localization,
   System Users, Get Started. Every rule below was measured on the page it
   names; the defect it fixes is in the comment above it.
   ============================================================================ */
/* ── AUDIT: ADMIN ── */

/* Plugin Management — each plugin row is a .card whose only visible child is a
   .card-header. The header's 20px-top / 0-bottom padding pushed the title and
   buttons to the bottom edge (buttons ended 1px above the border) so the row
   read as off-centre. Any header with nothing visible after it gets symmetric
   padding; the compact plugin rows take 12px so they stay list-height. */
.card > .card-header:last-child,
.card > .card-header:has(+ [style*="display: none"]:last-child),
.card > .card-header:has(+ .collapse:not(.show):last-child) { padding-bottom: 20px !important; }
.card > .card-header.plugin-card-header.d-flex { padding: 12px 20px !important; }

/* Plugin Management — .card-tools is display:block, so its three buttons sat
   10px apart (8px margin + inline whitespace) and the two icon-only buttons
   were 31px tall next to a 33px "Enable". Flex row, 8px gap, square icons. */
.card-header > .card-tools { display: flex !important; align-items: center; gap: 8px; }
.card-header > .card-tools > .btn { margin: 0 !important; }
.btn.btn-tool:has(> i:only-child) {
  width: 33px; height: 33px; padding: 0 !important;
  display: inline-grid; place-items: center;
}

/* Plugin Management / Admin Dashboard / Debug — card titles are written as
   "<i></i> Title <badge>" with whatever margin utility the view picked (none,
   me-1, me-2, me-3) plus a literal space, so the icon-to-text gap ranged from
   3px to 20px. Flex ignores the whitespace; one 9px gap everywhere. Debug's
   collapse chevron was a float that stuck to the word instead of the edge. */
.card-header :is(h2, h3, h4, h5, h6, .card-title) {
  display: flex; align-items: center; flex-wrap: wrap; gap: 9px; margin: 0;
}
.card-header > :is(h2, h3, h4, h5, h6, .card-title) { flex: 1 1 auto; min-width: 0; }
.card-header :is(h2, h3, h4, h5, h6, .card-title) > i[class*="fa-"] { margin: 0 !important; }
.card-header :is(h2, h3, h4, h5, h6, .card-title) > .badge { margin-left: 0 !important; }
.card-header :is(h2, h3, h4, h5, h6, .card-title) > .float-end { float: none; margin-left: auto !important; }

/* Export — the feature lists use me-1 (4px) between the check and the text. */
.card li > i[class*="fa-"]:first-child { margin-right: 8px !important; }

/* Export / Backup / Restore — PASS 3 gave .card-footer a top rule but the
   footer kept "0 20px 20px", so the buttons sat 1–2px under the line. */
.card > .card-footer { padding: 16px 20px 20px !important; }

/* Plugin Management / Backup — a card nested in a card-body keeps its 24px
   bottom margin, which stacked on the body's 20px padding: 44px under the
   last plugin row against 20px above the first. */
.card > .card-body > .card:last-child,
.card > .card-body > .row:last-child > [class*="col-"] > .card:last-child { margin-bottom: 0 !important; }

/* Church Info / Localization save rows, Plugin tools, DataTables buttons —
   "Save" and "Cancel" were 10–11px apart (ms-2 + inline whitespace) and
   baseline-aligned, so the 33px quiet button sat 2px lower than the 36px
   primary. Any element holding two adjacent buttons becomes an 8px flex row. */
.page-body :is(div, form, td, p):not(.btn-group):not(.input-group):not(.dropdown):has(> .btn + .btn) {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
}
.page-body :is(div, form, td, p):not(.btn-group):not(.input-group):has(> .btn + .btn) > .btn { margin-left: 0 !important; margin-right: 0 !important; }

/* Admin Dashboard / Church Info / Get Started — grid columns carry mb-3/mb-4
   AND the theme's 24px row-gap, so wrapped rows sat 40–48px apart, and the
   theme's blanket ".mb-3 {16px !important}" also defeated mb-md-0, leaving
   Restore Database 16px shorter than Reset Database beside it. */
.page-body .row:has(> [class*="col-"].mb-3),
.page-body .row:has(> [class*="col-"].mb-4) { row-gap: 0; }
.page-body .row > [class*="col-"].mb-md-0 { margin-bottom: 0 !important; }
.page-body .row:has(> [class*="col-"] > .quick-start-card) > [class*="col-"] { margin-bottom: 24px !important; }

/* Admin Dashboard — Quick Start tiles were raw Bootstrap grey (#f8f9fa on
   #e9ecef, 8px radius), one tile was 16px taller because its title wrapped,
   and the icon squares were six unrelated colours. White tiles, one brand
   tile, equal heights. */
.page-body .row > [class*="col-"]:has(> .quick-start-card) { display: flex; }
.quick-start-card {
  flex: 1 1 auto; height: auto !important;
  background: #fff !important; border: 1px solid var(--line) !important; border-radius: 12px !important;
}
.quick-start-icon {
  background: var(--grad) !important; color: #fff !important;
  width: 42px !important; height: 42px !important; border-radius: 12px !important;
  display: grid !important; place-items: center;
}

/* Admin Dashboard — Advanced Operations boxes: 12.8px titles in orange / blue
   (2.9:1 and 3:1 on white) with a literal space after the icon. */
.page-body .border.rounded.p-3 { border-color: var(--line) !important; border-radius: 12px !important; }
.page-body .border.rounded.p-3 > h6 { color: var(--ink) !important; font-size: 14px !important; font-weight: 600; display: flex; align-items: center; gap: 8px; }
.page-body .border.rounded.p-3 > h6 > i { margin: 0 !important; }

/* Debug — Application Integrity sits alone in a two-column row and the three
   cards after it are col-lg-6 without a row, so four half-width cards of two
   different widths (566 / 578) stacked down the left with the right half
   empty. Full width, one edge. */
.page-body > .container-xl > [class*="col-"] { width: 100% !important; flex: 0 0 100%; max-width: 100%; }
.debug-grid > [class*="col-"]:only-child { flex: 0 0 100%; width: 100%; max-width: 100%; }

/* Debug / Logs — these two views print the footer OUTSIDE .page-wrapper, so it
   centred across the full window and the copyright ran under the sidebar. */
footer.footer:not(.page-wrapper footer) { margin-inline-start: var(--vq-sidebar-w); }

/* Get Started — the four path cards wore 4px coloured top stripes (Tabler
   status bars), the layout was capped at 900px leaving a 256px hole on the
   right, mb-4 + row-gap put 48px between rows, and the "PICK A PATH" label was
   11.2px in #adb5bd (2.2:1). */
.gs-wrap { max-width: none !important; }
.gs-card { border: 1px solid var(--line) !important; border-radius: 18px !important; }
.gs-wrap .row:has(> .mb-4) { row-gap: 0; }
.gs-section-label { font-size: 12px !important; color: #64748b !important; letter-spacing: .08em; }
.gs-plugin-strip { border-color: var(--line) !important; border-radius: 14px !important; }
.gs-skip { font-size: 13px !important; color: var(--muted) !important; }

/* Reset — Tabler's decorative .card-stamp (a 112px tinted icon bleeding out of
   the card's top-right corner, behind the "Recommended" badge). */
.card-stamp { display: none !important; }

/* Upgrade — the wizard body wraps its content in .p-4 inside a container that
   already carries the card's 20px, so the alert and Continue button sat 44px
   in while the title sat 20px in. */
.bs-stepper-content > .content.p-4 { padding: 20px 0 0 !important; }

/* System Users — the legend row's .border-bottom met the next card-body's own
   top rule: a 2px line. */
.card > .card-body.border-bottom + .card-body { border-top: 0 !important; }

/* Plugin Management — "Plugin Development" is a lone col-lg-4 under two
   full-width sections, leaving two thirds of the row empty. */
.page-body .row > .col-12 + .col-lg-4:last-child:has(> .card.border-info) { flex: 0 0 100%; width: 100%; max-width: 100%; }

/* Plugin Management version badges were 11.52px; every badge reads at 12px. */
.page-body .badge { font-size: 12px !important; }

/* Localization preview panels used Bootstrap's .bg-light grey. */
.card .card-body.bg-light { background: var(--paper) !important; border-radius: 12px !important; }

/* Export / Get Started / everywhere — muted text was mapped to #8591a2, which
   is 3.2:1 on white. #64748b keeps the hierarchy and passes 4.5:1. */
.page-body :is(.text-muted, .text-secondary, .text-body-secondary, small, .small, .form-hint) { color: #64748b !important; }
/* Correction: Chrome maps <col>s onto RENDERED cells, so a display:none first
   cell handed the 0px col to Name and the 62% col to Birthday, which then sat
   on top of the names. Keep the empty column in the grid at zero width
   instead — same visual result, column mapping stays honest. */
#PersonBirthdayDashboardItem th:first-child,
#PersonBirthdayDashboardItem td:first-child:not([colspan]) {
  display: table-cell !important; width: 0 !important; max-width: 0;
  padding: 0 !important; border: 0 !important; font-size: 0; overflow: hidden;
}
#PersonBirthdayDashboardItem colgroup col:first-child { visibility: visible; width: 0 !important; }

/* [mobile /v2/dashboard] Birthdays / Anniversaries are table-layout:fixed
   (set above for the desktop column split). At 390px a fixed layout lets the
   name column ignore its content and every name broke one character per
   line. Below md the content sizes the columns again, and any card table that
   is still wider than the card scrolls inside its own wrapper rather than
   clipping at the card edge. */
@media (max-width: 767.98px) {
  #PersonBirthdayDashboardItem, #FamiliesWithAnniversariesDashboardItem { table-layout: auto !important; width: 100% !important; }
  .card .table-responsive, .card .dt-layout-table > * { overflow-x: auto; }
  .card .table td.vq-nowrap-cell { white-space: normal !important; overflow-wrap: normal; }
}

/* ── AUDIT: GROUPS+EVENTS — follow-up after re-screenshot ── */
/* Calendar month view: a timed event is dot + time + title in one flex row.
   With ellipsis on every label the TIME truncated first ("10:3…"). The time
   keeps its width; only the title gives way. */
.page-body [role="gridcell"] a[style*="--fc-event-color"] > div:not(:first-child) > div:first-child:not(:last-child) {
  flex: none !important; overflow: visible !important; text-overflow: clip !important;
  min-width: max-content; padding-right: 4px !important;
}
/* Event editor: Tom Select draws a border on the wrapper AND on .ts-control,
   so the two fields sat 42px tall beside 40px native inputs in the same row. */
.ts-wrapper.form-select:not(.form-select-sm) { border: 0 !important; }

/* [/FamilyEditor.php Birth Day] 92px still showed "Unk" for "Unknown" once the
   select's own arrow and padding took their share; same floor as Birth Month. */
.table td > select[name^="BirthDay"] { min-width: 108px; }

/* [/people/family/1 Key People] With the names on one line the table ran 5px
   past its column and the Actions ⋮ was clipped at the card edge. In a
   sub-width column the inner cell gutters come down to 12px (the outer cells
   stay at the card inset), which returns ~40px to the table. */
[class*="col-"]:not(.col-12):not(.col-md-12):not(.col-lg-12) > .card > .card-body:not(.p-0):not(.px-0) .table > :not(caption) > * > * { padding-inline: 12px !important; }
[class*="col-"]:not(.col-12):not(.col-md-12):not(.col-lg-12) > .card > .card-body:not(.p-0):not(.px-0) .table > :not(caption) > * > *:first-child { padding-left: 0 !important; }
[class*="col-"]:not(.col-12):not(.col-md-12):not(.col-lg-12) > .card > .card-body:not(.p-0):not(.px-0) .table > :not(caption) > * > *:last-child  { padding-right: 0 !important; }

/* ── FamilyEditor address row: four equal quarters ───────────────────────── */
/* The view ships City col-md-4 / State col-md-3 / Zip col-md-2 / Country
   col-md-3 — 379 / 285 / 190 / 285 — so nothing lined up with the
   Latitude + Longitude col-md-3 pair on the row below. Four quarters put the
   column edges at 277 / 562 / 847 / 1132, and Latitude and Longitude land on
   the first two of those. The hidden duplicate State column is excluded. */
@media (min-width: 768px) {
  form .row:has(> [class*="col-"] input[name="City"]) > [class*="col-"]:not(.d-none) {
    flex: 0 0 25% !important; max-width: 25% !important; width: 25% !important;
  }
}
/* The calendar day-name row was set to 11px as a "table header" treatment, but
   the 12px floor applies there too — every other column header in the product
   moved to 12px. */
.page-body [class*="fc-"] [role="columnheader"],
.page-body [class*="fc-"] [role="columnheader"] * { font-size: 12px !important; }

/* ============================================================================
   PASS 4 — systematic fixes from the numeric rule audit across 30 pages
   ============================================================================ */

/* --soft (#8591a2) is 3.2:1 on white and it is a TEXT token — table headers,
   stat-card labels, pretitles, DataTables info, sort arrows all take it. That
   one value accounted for ~100 of the 122 contrast failures. #64748b is 4.8:1
   and still sits clearly below --muted (#475569) in the hierarchy. */
:root { --soft: #64748b; }

/* Soft badge text was set for contrast against WHITE, but each sits on its own
   tint, which costs about a stop. Darkened to clear 4.5:1 on the tint. */
.badge.bg-success, .badge.bg-green, .badge.bg-success-lt, .badge.bg-green-lt, .badge.bg-teal-lt { color: #15703f !important; }
.badge.bg-warning, .badge.bg-orange, .badge.bg-warning-lt, .badge.bg-orange-lt, .badge.bg-yellow-lt,
.badge.bg-warning.text-dark { color: #8a5410 !important; }
.badge.bg-danger, .badge.bg-red, .badge.bg-danger-lt, .badge.bg-red-lt { color: #a12f2c !important; }
.badge.bg-info-lt, .badge.bg-blue-lt, .badge.bg-azure-lt { background: #eef4ff !important; color: #1d4fd8 !important; }
.badge.bg-secondary-lt { background: #f1f5f9 !important; color: #475569 !important; }

/* [/plugins/management] "plugin.json" in a <code> ran at 10.5px — Bootstrap
   sizes code at .875em of an already-small parent. 12px floor. */
code, kbd, samp, pre, .font-monospace { font-size: 12px !important; }
pre code { font-size: inherit !important; }

/* [/groups/view/N] A DataTables search sitting in a PADDED card body still had
   the 20px layout-row inset, so it sat 20px right of the card title. The
   earlier rule only zeroed rows in a body reached as `.card-body > .dt-container`;
   here the container is nested deeper (inside a tab pane). */
.card-body:not(.p-0):not(.px-0) .dt-container > .row { padding-inline: 0 !important; }

/* [/admin/system/localization date/time format pickers, calendar toolbar]
   Segmented option buttons sat 4px apart — they are wrapped in <label>s, so
   neither the .btn-group rule nor the "div with two adjacent buttons" rule
   reached them. Any row of adjacent labelled buttons gets the 8px control gap. */
.page-body :is(div, form, p):has(> :is(label, .btn) + :is(label, .btn) > .btn),
.page-body :is(div, form, p):has(> label.btn + label.btn) {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
}
.page-body label.btn + label.btn, .page-body .btn-check + .btn { margin-left: 0 !important; }

/* [/admin/system/localization format presets, /event/calendars calendar list]
   Bootstrap's .gap-1 is 4px AND generated with !important, so it beat every
   spacing rule above. A flex row of buttons takes the 8px control gap. */
.page-body .d-flex.gap-1:has(> .btn), .page-body .d-flex.gap-1:has(> label.btn) { gap: 8px !important; }

/* [/people/list Data Quality] .alert-link kept Tabler's #f76707 — 3.0:1 on the
   alert's own tint. Inheriting the alert ink always passes, and the underline
   is what marks it as a link. */
.alert-link { color: inherit !important; text-decoration: underline; font-weight: 700; }
/* Sidebar count badges were still 10.88px — the 12px floor applies here too
   (the .page-body badge rule does not reach the sidebar). */
.navbar-vertical .badge { font-size: 12px !important; padding: .12em .45em; }

/* ── Mobile: the 24px card gutter is a desktop measure ───────────────────── */
/* PASS 3 forced --tblr-gutter-x:24px on every .row-cards / .g-3 / .g-4, which
   also overrode .g-2 at 390px. Tabler's container padding there is only 8px a
   side, so the row's -12px negative gutter escaped the viewport by 4px and the
   page scrolled sideways. Below md the row keeps whatever gutter its own class
   asked for. */
@media (max-width: 767.98px) {
  .page-body .row, .page-body .row.row-cards, .page-body .row.g-3, .page-body .row.g-4 {
    --tblr-gutter-x: unset; --tblr-gutter-y: unset;
  }
  /* A wide listing table scrolls inside its card rather than pushing the page.
     Some views put the table straight in a flex box with no .table-responsive. */
  .page-body .card .table:not(.table-responsive .table) { display: block; overflow-x: auto; }
  .page-body .card .table:not(.table-responsive .table) > * { display: table; width: 100%; }
}

/* ── Touch sizing below xl ───────────────────────────────────────────────── */
/* The tight desktop rhythm — 6px/10px nav rows, 33px quiet buttons — is right
   under a mouse and wrong under a thumb. Measured at 390px: nav links 32px, the
   menu toggler 32px, ghost buttons 31px, against a 44px minimum. Everything
   interactive gets 44px here; the desktop scale above is untouched. */
@media (max-width: 1199.98px) {
  .navbar-vertical .nav-link {
    min-height: 44px !important; padding: 10px 12px !important; font-size: 15px !important;
  }
  .navbar-vertical .navbar-nav .navbar-nav .nav-link { padding: 10px 12px !important; }
  .navbar-vertical .nav-link-arrow {
    min-width: 44px; min-height: 44px; display: flex; align-items: center; justify-content: center;
  }
  .navbar-toggler { width: 44px !important; height: 44px !important; }

  .btn:not(.btn-icon):not(.vq-collapse) {
    min-height: 44px !important; padding: 12px 16px !important; font-size: 14px !important;
  }
  .btn-icon { width: 44px !important; height: 44px !important; }

  /* 16px is not a style choice — below it iOS Safari zooms the page on focus
     and never zooms back out. */
  .form-control, .form-select, .ts-control, input, select, textarea {
    min-height: 44px !important; font-size: 16px !important;
  }

  /* 20px of card padding either side costs 40 of 390 available pixels. */
  .card-body:not(.p-0):not(.px-0) { padding: 16px !important; }
  .card-header { padding: 16px 16px 0 !important; }
  .card > .card-footer { padding: 12px 16px 16px !important; }
  .card .table > :not(caption) > * > *:first-child { padding-left: 16px !important; }
  .card .table > :not(caption) > * > *:last-child  { padding-right: 16px !important; }
  .page-body .card { margin-bottom: 16px !important; }
}
/* The card-header tab pills (Latest Families / Updated People …) are .nav-link
   outside the sidebar, so the sidebar rule above missed them — 31px. */
@media (max-width: 1199.98px) {
  .card .nav-tabs .nav-link { min-height: 44px !important; padding: 10px 14px !important; font-size: 14px !important; }
  .card .nav-tabs { gap: 6px; row-gap: 6px; }
}
/* Pager buttons and the alert dismiss are the last sub-44px targets on a phone
   — and a 28px pager on a 94-page list is the one control you tap most. */
@media (max-width: 1199.98px) {
  .dt-paging .page-link, .pagination .page-link {
    min-width: 44px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center;
    font-size: 14px !important;
  }
  .dt-paging .pagination, .pagination { gap: 4px; flex-wrap: wrap; }
  .btn-close { width: 44px !important; height: 44px !important; }
}

/* ── Sidebar group chevron shows the state ───────────────────────────────── */
/* The markup is a static <i class="fa fa-chevron-down"> that ChurchCRM never
   changes, so the arrow pointed down whether the group was open or shut and
   carried no information. Bootstrap does flip aria-expanded on the toggle, so
   that is the honest hook. Down = closed ("more below"), up = open. */
.navbar-vertical .nav-link-arrow {
  transition: transform .18s ease;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.navbar-vertical .nav-link[aria-expanded="true"] + .nav-link-arrow,
.navbar-vertical .nav-link[aria-expanded="true"] ~ .nav-link-arrow {
  transform: rotate(180deg);
}
