/* ==========================================================================
   Nonprofit Essentials — front-end design system (Kansas City Dream Center).
   The public-site cousin of assets/css/matiq-admin.css. Every redesigned
   front-end surface wraps its markup in a single `.npe-fe` root and composes
   the components below, so it reads as native, polished Divi page content.

   SCOPE RULE — everything is scoped under `.npe-fe`. Nothing here may style,
   restyle, or leak into the surrounding Divi theme. Only `.npe-fe` and its
   descendants are ever targeted.

   TYPOGRAPHY — inherits the Divi theme font. This sheet sets NO font-family on
   `body`, `:root`, or `.npe-fe`. The ONLY font-family declared anywhere is on
   headings, as `var(--npe-heading-font)` (which resolves to `inherit` when the
   client has not chosen a heading font, so it stays safe).

   BRAND TOKEN CONTRACT — these `--npe-*` custom properties are declared on
   `:root` by PHP (Branding::css_tokens()); this sheet only CONSUMES them and
   never redeclares them:
     --npe-primary         brand navy (fills, accents)
     --npe-primary-strong  pre-darkened primary for hover/active
     --npe-secondary       secondary brand colour
     --npe-on-primary      readable text colour to use ON a primary fill
     --npe-heading-font    heading font family (or `inherit`)
   Legacy aliases also present (prefer the names above):
     --npe-primary-color, --npe-secondary-color, --npe-font-family
   All neutrals (ink, muted, lines, backgrounds), status hues, radii and
   shadows are LOCAL vars defined inside `.npe-fe` below — neutral greys /
   off-whites and semantic status colours, never brand colours.

   Sections: Tokens/neutrals -> Brand header -> Cards -> Buttons -> Forms
             -> Tables -> Pills/Badges -> Layout -> Empty/Stat.
   ========================================================================== */

/* ==========================================================================
   Tokens / neutrals — local, self-consistent, NOT brand colours
   ========================================================================== */
.npe-fe{
  /* neutrals */
  --npe-fe-ink:#1f2733; --npe-fe-ink-soft:#3d4653; --npe-fe-muted:#5b6472;
  --npe-fe-line:#e2e5ea; --npe-fe-line-strong:#cfd4dc;
  --npe-fe-bg:#ffffff; --npe-fe-bg-soft:#f6f7f9;
  /* semantic status hues (greens / ambers / reds / greys — never navy) */
  --npe-fe-ok:#1f7a4d;   --npe-fe-ok-bg:#e7f4ec;
  --npe-fe-warn:#9a6a12;  --npe-fe-warn-bg:#fbf1dc;
  --npe-fe-crit:#b23b32;  --npe-fe-crit-bg:#fbe9e7;
  --npe-fe-idle:#5b6472;  --npe-fe-idle-bg:#eef0f3;
  /* radii + shadows */
  --npe-fe-radius:12px; --npe-fe-radius-sm:8px; --npe-fe-radius-pill:999px;
  --npe-fe-shadow:0 1px 2px rgba(16,25,43,.06);
  --npe-fe-shadow-lg:0 8px 24px rgba(16,25,43,.10);
  color:var(--npe-fe-ink); line-height:1.5;
}
.npe-fe *,.npe-fe *::before,.npe-fe *::after{box-sizing:border-box;}

/* headings — the ONLY font-family this sheet sets (safe: token is `inherit`
   when unset). Colour + rhythm only; sizes come from Divi unless overridden. */
.npe-fe h1,.npe-fe h2,.npe-fe h3,.npe-fe h4,.npe-fe h5,.npe-fe h6,.npe-fe .npe-fe-title{
  font-family:var(--npe-heading-font); color:var(--npe-fe-ink); line-height:1.2;}
.npe-fe .npe-fe-title{font-size:1.15rem; font-weight:700; margin:0;}

/* ==========================================================================
   Brand header
   ========================================================================== */
.npe-fe-brand{
  display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  padding:0 0 18px; margin:0 0 22px; border-bottom:1px solid var(--npe-fe-line);}
.npe-fe-brand-logo{display:block; max-height:56px; width:auto;}
.npe-fe-brand-name{
  font-family:var(--npe-heading-font); font-size:1.4rem; font-weight:800;
  letter-spacing:-.01em; line-height:1.1; color:var(--npe-primary); margin:0;}

/* ==========================================================================
   Cards
   ========================================================================== */
.npe-fe-card{
  background:var(--npe-fe-bg); border:1px solid var(--npe-fe-line);
  border-radius:var(--npe-fe-radius); box-shadow:var(--npe-fe-shadow); overflow:hidden;}
.npe-fe-card-header{
  display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;
  padding:16px 20px; border-bottom:1px solid var(--npe-fe-line); background:var(--npe-fe-bg-soft);}
.npe-fe-card-header h2,.npe-fe-card-header h3,.npe-fe-card-header .npe-fe-title{
  font-size:1.05rem; font-weight:700; margin:0;}
.npe-fe-card-body{padding:20px;}
.npe-fe-card-footer{
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  padding:14px 20px; border-top:1px solid var(--npe-fe-line); background:var(--npe-fe-bg-soft);}

/* ==========================================================================
   Buttons
   ========================================================================== */
.npe-fe-btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  padding:10px 18px; border:1px solid var(--npe-fe-line); border-radius:var(--npe-fe-radius-sm);
  background:var(--npe-fe-bg); color:var(--npe-fe-ink);
  font:inherit; font-weight:600; line-height:1.2; text-decoration:none; cursor:pointer;
  transition:background-color .15s,border-color .15s,box-shadow .15s,color .15s;}
.npe-fe-btn:hover{background:var(--npe-fe-bg-soft); border-color:var(--npe-fe-line-strong); color:var(--npe-fe-ink);}
.npe-fe-btn:focus-visible{outline:2px solid var(--npe-primary); outline-offset:2px;}
/* filled — brand navy */
.npe-fe-btn--primary{background:var(--npe-primary); border-color:var(--npe-primary); color:var(--npe-on-primary);}
.npe-fe-btn--primary:hover{
  background:var(--npe-primary-strong); border-color:var(--npe-primary-strong);
  color:var(--npe-on-primary); box-shadow:var(--npe-fe-shadow-lg);}
/* ghost — subtle outline */
.npe-fe-btn--ghost{background:transparent; border-color:var(--npe-fe-line-strong); color:var(--npe-fe-ink-soft);}
.npe-fe-btn--ghost:hover{background:var(--npe-fe-bg-soft); border-color:var(--npe-fe-line-strong); color:var(--npe-fe-ink);}
/* disabled */
.npe-fe-btn[disabled],.npe-fe-btn.is-disabled{opacity:.5; cursor:not-allowed; box-shadow:none; pointer-events:none;}

/* ==========================================================================
   Form fields
   ========================================================================== */
.npe-fe-field{display:block; margin:0 0 18px;}
.npe-fe-field > label,.npe-fe-field .npe-fe-label{
  display:block; font-weight:600; font-size:.95rem; color:var(--npe-fe-ink); margin:0 0 6px;}
.npe-fe-field input:not([type="checkbox"]):not([type="radio"]),
.npe-fe-field select,.npe-fe-field textarea{
  display:block; width:100%; padding:10px 12px; min-height:44px;
  border:1px solid var(--npe-fe-line); border-radius:var(--npe-fe-radius-sm);
  background:var(--npe-fe-bg); color:var(--npe-fe-ink); font:inherit; line-height:1.4;
  transition:border-color .15s,box-shadow .15s;}
.npe-fe-field textarea{min-height:108px; resize:vertical;}
.npe-fe-field select{cursor:pointer;}
.npe-fe-field input::placeholder,.npe-fe-field textarea::placeholder{color:var(--npe-fe-muted);}
.npe-fe-field input:focus,.npe-fe-field select:focus,.npe-fe-field textarea:focus{
  outline:none; border-color:var(--npe-primary);
  box-shadow:0 0 0 3px rgba(0,0,0,.08);                               /* neutral fallback */
  box-shadow:0 0 0 3px color-mix(in srgb,var(--npe-primary) 22%,transparent);}
.npe-fe-help{display:block; margin:6px 0 0; font-size:.85rem; color:var(--npe-fe-muted);}
.npe-fe-error{display:block; margin:6px 0 0; font-size:.85rem; font-weight:600; color:var(--npe-fe-crit);}
/* error state on the field's controls */
.npe-fe-field.has-error input,.npe-fe-field.has-error select,.npe-fe-field.has-error textarea{
  border-color:var(--npe-fe-crit);}
.npe-fe-field.has-error input:focus,.npe-fe-field.has-error select:focus,.npe-fe-field.has-error textarea:focus{
  box-shadow:0 0 0 3px var(--npe-fe-crit-bg);}

/* ==========================================================================
   Tables
   ========================================================================== */
/* horizontal-scroll wrapper for narrow screens (scroll only — the table below
   carries its own frame, so no double border) */
.npe-fe-table-wrap{overflow-x:auto;}
/* separate + border-spacing:0 so the radius clips cleanly (as in the admin sheet) */
.npe-fe-table{
  width:100%; border-collapse:separate; border-spacing:0;
  border:1px solid var(--npe-fe-line); border-radius:var(--npe-fe-radius); overflow:hidden;
  background:var(--npe-fe-bg); box-shadow:var(--npe-fe-shadow); font-size:.95rem;}
.npe-fe-table th,.npe-fe-table td{padding:12px 16px; text-align:left; vertical-align:middle;}
.npe-fe-table thead th{
  background:var(--npe-fe-bg-soft); border-bottom:1px solid var(--npe-fe-line);
  font-weight:700; font-size:.78rem; letter-spacing:.04em; text-transform:uppercase;
  color:var(--npe-fe-muted); white-space:nowrap;}
.npe-fe-table tbody td{border-bottom:1px solid var(--npe-fe-line); color:var(--npe-fe-ink-soft);}
.npe-fe-table tbody tr:last-child td{border-bottom:0;}
.npe-fe-table--zebra tbody tr:nth-child(even) td{background:var(--npe-fe-bg-soft);} /* zebra optional */
.npe-fe-table tbody tr:hover td{background:var(--npe-fe-bg-soft);}

/* ==========================================================================
   Pills / Badges
   ========================================================================== */
/* status pill — small, rounded-full, coloured by status (never navy) */
.npe-fe-pill{
  display:inline-flex; align-items:center; gap:6px; padding:3px 10px;
  border-radius:var(--npe-fe-radius-pill); font-size:.78rem; font-weight:600; line-height:1.4;
  white-space:nowrap; color:var(--npe-fe-idle); background:var(--npe-fe-idle-bg);}
.npe-fe-pill::before{content:""; width:6px; height:6px; border-radius:50%; background:currentColor; flex:none;}
.npe-fe-pill--ok{color:var(--npe-fe-ok); background:var(--npe-fe-ok-bg);}
.npe-fe-pill--warn{color:var(--npe-fe-warn); background:var(--npe-fe-warn-bg);}
.npe-fe-pill--idle{color:var(--npe-fe-idle); background:var(--npe-fe-idle-bg);}
.npe-fe-pill--crit{color:var(--npe-fe-crit); background:var(--npe-fe-crit-bg);}
/* badge — neutral base; phase 2 adds --full / --low / --open colour modifiers */
.npe-fe-badge{
  display:inline-flex; align-items:center; gap:6px; padding:4px 10px;
  border:1px solid var(--npe-fe-line); border-radius:var(--npe-fe-radius-pill);
  background:var(--npe-fe-bg-soft); color:var(--npe-fe-muted);
  font-size:.8rem; font-weight:600; line-height:1.3; white-space:nowrap;}

/* ==========================================================================
   Layout helpers
   ========================================================================== */
.npe-fe-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:20px;}
.npe-fe-stack{display:flex; flex-direction:column; gap:16px;}
.npe-fe-toolbar{display:flex; align-items:flex-end; gap:12px; flex-wrap:wrap; margin:0 0 20px;}
.npe-fe-toolbar .npe-fe-spacer{flex:1 1 auto;}
/* Toolbar fields sit on one baseline (no stacking margin); the checkbox field
   aligns its box with the inputs' bottom edge. */
.npe-fe-toolbar .npe-fe-field{margin:0;}
.npe-fe-toolbar label.npe-fe-field:has(input[type="checkbox"]){display:flex; align-items:center; gap:8px; padding-bottom:9px;}
.npe-fe-cluster{display:flex; align-items:center; gap:10px; flex-wrap:wrap;}

/* ==========================================================================
   Empty state / Stat tile
   ========================================================================== */
.npe-fe-empty{
  text-align:center; padding:44px 24px; border:1px dashed var(--npe-fe-line-strong);
  border-radius:var(--npe-fe-radius); background:var(--npe-fe-bg-soft); color:var(--npe-fe-muted);}
.npe-fe-empty h3,.npe-fe-empty .npe-fe-title{
  font-size:1.05rem; font-weight:700; color:var(--npe-fe-ink-soft); margin:0 0 6px;}
.npe-fe-empty p{margin:0; font-size:.95rem;}
.npe-fe-stat{
  background:var(--npe-fe-bg); border:1px solid var(--npe-fe-line);
  border-radius:var(--npe-fe-radius); box-shadow:var(--npe-fe-shadow); padding:20px;}
.npe-fe-stat-value{
  display:block; font-family:var(--npe-heading-font); font-size:2.1rem; font-weight:800;
  line-height:1; letter-spacing:-.02em; color:var(--npe-primary);}
.npe-fe-stat-label{
  display:block; margin:8px 0 0; font-size:.82rem; font-weight:600;
  letter-spacing:.04em; text-transform:uppercase; color:var(--npe-fe-muted);}

/* ==========================================================================
   Responsive — nothing overflows; multi-column layouts collapse to one column
   ========================================================================== */
@media (max-width:600px){
  .npe-fe-grid{grid-template-columns:1fr;}
  .npe-fe-card-body{padding:16px;}
  .npe-fe-brand-name{font-size:1.2rem;}
  .npe-fe-btn{width:100%;}
  .npe-fe-toolbar .npe-fe-btn{width:auto;}
}

/* ==========================================================================
   PHASE 2 — composition classes for the redesigned public surfaces
   Appends to the design system above and consumes ONLY the tokens already
   defined in `.npe-fe` (neutrals + status pairs) and the brand heading font.
   No new brand colours, no global font-family.
   Sections: Badge states -> Listing cards -> Auth -> Waiver + forms.
   ========================================================================== */

/* --- Badge state modifiers on .npe-fe-badge -------------------------------
   Capacity text: "X spots left" (open/low) / "Full". Solid tinted chips —
   border blends into the status fill so they read cleanly at small sizes. */
.npe-fe-badge--open{background:var(--npe-fe-ok-bg);   border-color:var(--npe-fe-ok-bg);   color:var(--npe-fe-ok);}
.npe-fe-badge--low {background:var(--npe-fe-warn-bg); border-color:var(--npe-fe-warn-bg); color:var(--npe-fe-warn);}
.npe-fe-badge--full{background:var(--npe-fe-crit-bg); border-color:var(--npe-fe-crit-bg); color:var(--npe-fe-crit);}

/* ==========================================================================
   Listing / outreach cards — compose with .npe-fe-grid + .npe-fe-card
   ========================================================================== */
/* full-bleed image band; the card's overflow:hidden clips the top radius */
.npe-fe-card-media{display:block; aspect-ratio:16 / 10; overflow:hidden; background:var(--npe-fe-bg-soft);}
.npe-fe-card-media img{display:block; width:100%; height:100%; object-fit:cover;}
.npe-fe-card-title{
  font-family:var(--npe-heading-font); font-size:1.1rem; font-weight:700;
  line-height:1.25; color:var(--npe-fe-ink); margin:0 0 6px;}
/* muted date / time / location rows */
.npe-fe-card-meta{display:flex; flex-direction:column; gap:3px; margin:0 0 12px; font-size:.9rem; color:var(--npe-fe-muted);}
.npe-fe-card-meta > *{margin:0;}
.npe-fe-card-badges{display:flex; flex-wrap:wrap; gap:8px; margin:0 0 12px;}
/* clamp long descriptions to 3 lines; max-height fallback uses line-height:1.5 */
.npe-fe-clamp{
  display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:3;
  overflow:hidden; max-height:4.5em; color:var(--npe-fe-ink-soft);}

/* ==========================================================================
   Auth card — login / register / forgot
   ========================================================================== */
.npe-fe-auth{max-width:440px; margin:0 auto;}
@media (max-width:600px){
  .npe-fe-auth{padding:16px;}
}
.npe-fe-auth-links{
  display:flex; flex-wrap:wrap; justify-content:center; gap:6px 16px;
  margin:16px 0 0; font-size:.9rem; color:var(--npe-fe-muted);}
.npe-fe-auth-links a{color:var(--npe-fe-muted); text-decoration:underline;}
.npe-fe-auth-links a:hover{color:var(--npe-fe-ink);}

/* ==========================================================================
   Waiver + contact / partner / registration forms
   ========================================================================== */
.npe-fe-waiver{max-width:760px; margin:0 auto;}
/* the long legal text: readable, scrollable, spaced off the signature fields */
.npe-fe-waiver-legal{
  max-height:420px; overflow-y:auto; margin:0 0 24px; padding:18px 20px;
  border:1px solid var(--npe-fe-line); border-radius:var(--npe-fe-radius-sm);
  background:var(--npe-fe-bg-soft); font-size:.95rem; line-height:1.6;}
.npe-fe-form{max-width:640px; margin:0 auto;}
/* section grouping inside a form; reuse .npe-fe-field for the inputs within */
.npe-fe-fieldset{border:0; padding:0; margin:0 0 20px; min-inline-size:0;}
.npe-fe-fieldset > legend{
  width:100%; margin:0 0 14px; padding:0 0 8px;
  font-family:var(--npe-heading-font); font-size:1.05rem; font-weight:700;
  color:var(--npe-fe-ink); border-bottom:1px solid var(--npe-fe-line);}

/* ==========================================================================
   PHASE 3 — VOLUNTEER PORTAL
   Portal chrome (layout wrapper, tab bar, section container, home dashboard,
   quick-links) that sits under `.npe-fe-brand`. Consumes ONLY the tokens
   already defined in `.npe-fe` (neutrals) and the brand primary/heading font.
   No new brand colours, no global font-family.
   ========================================================================== */

/* --- Portal layout — a left sidebar (brand + nav) beside the content. The
   guest gate has no .npe-fe-portal-side, so it stays single-column. A brand
   pinstripe at the top edge separates the portal from the site menu bar above
   it, so the header no longer reads as bleeding into the portal. --------- */
.npe-fe-portal{display:flex; flex-direction:column; border-top:3px solid var(--npe-primary);}
.npe-fe-portal:has(.npe-fe-portal-side){display:grid; grid-template-columns:248px 1fr; grid-template-rows:1fr; gap:0; align-items:stretch;}

/* Sidebar — a full-height rail hugging the far-left edge. Its inner block sticks
   so brand + nav stay in view while a tall section scrolls with the page; the
   rail itself never gets its own scrollbar. Divider + background run the whole
   height (fill between the site header and footer). */
.npe-fe-portal-side{
  display:flex; flex-direction:column;
  padding:24px 22px; border-right:1px solid var(--npe-fe-line); background:var(--npe-fe-bg);}
.npe-fe-portal-side-inner{position:sticky; top:16px; display:flex; flex-direction:column; gap:18px;}
.npe-fe-portal-side .npe-fe-brand{margin:0; padding-bottom:16px;}
.npe-fe-portal-main{min-width:0; padding:28px 32px; background:var(--npe-fe-bg-soft);}

/* --- Nav — a vertical rail of section links inside the sidebar. --------- */
.npe-fe-portal-nav{display:flex; flex-direction:column; gap:3px; align-items:stretch; margin:0; padding:0;}
.npe-fe-portal-nav a{
  display:flex; align-items:center; gap:10px;
  padding:10px 12px; border-radius:8px;
  color:var(--npe-fe-muted); font-weight:600; text-decoration:none;
  transition:color .15s,background-color .15s;}
.npe-fe-portal-nav a:hover{color:var(--npe-fe-ink); background:var(--npe-fe-bg-soft);}
.npe-fe-portal-nav a:focus-visible{outline:2px solid var(--npe-primary); outline-offset:-2px;}
/* active item — brand colour on a soft brand tint */
.npe-fe-portal-nav a.is-active,
.npe-fe-portal-nav a[aria-current="page"]{
  color:var(--npe-primary); font-weight:700; background:color-mix(in srgb, var(--npe-primary) 12%, transparent);}

/* --- Active-section container ------------------------------------------- */
.npe-fe-portal-section{padding-top:0; min-width:0;}

/* Tablet — tighten the rail. */
@media (max-width:1024px) and (min-width:769px){
  .npe-fe-portal:has(.npe-fe-portal-side){grid-template-columns:212px 1fr;}
  .npe-fe-portal-side{padding:20px 16px;}
  .npe-fe-portal-main{padding:24px 22px;}
}

/* Narrow screens: sidebar becomes a horizontal tab rail on top; one column. */
@media (max-width:768px){
  .npe-fe-portal:has(.npe-fe-portal-side){grid-template-columns:1fr; grid-template-rows:auto 1fr;}
  .npe-fe-portal-side{
    border-right:none; border-bottom:1px solid var(--npe-fe-line); padding:10px 16px;}
  .npe-fe-portal-side-inner{position:static; gap:8px;}
  .npe-fe-portal-side .npe-fe-brand{padding-bottom:6px;}
  .npe-fe-portal-nav{
    flex-direction:row; flex-wrap:nowrap; overflow-x:auto; -webkit-overflow-scrolling:touch; gap:4px;}
  .npe-fe-portal-nav a{
    flex:none; border-radius:8px; white-space:nowrap;}
  .npe-fe-portal-main{padding:20px 16px;}
}

/* --- Home dashboard — onboarding + next-shift cards over a row of stat tiles.
   Reuse .npe-fe-grid / .npe-fe-stat for the pieces; this only adds rhythm. -- */
.npe-fe-portal-home{display:flex; flex-direction:column; gap:20px;}
/* two-up feature row (onboarding | next shift) that collapses on narrow screens */
.npe-fe-portal-grid{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(280px,1fr)); gap:20px;}

/* --- Quick-links — a small cluster of ghost-button shortcuts (layout only;
   the buttons themselves reuse .npe-fe-btn / .npe-fe-btn--ghost). ---------- */
.npe-fe-quicklinks{display:flex; flex-wrap:wrap; gap:12px;}
.npe-fe-quicklinks .npe-fe-btn{flex:1 1 auto; min-width:160px;}

/* Responsive — feature grid becomes one column. */
@media (max-width:600px){
  .npe-fe-portal-grid{grid-template-columns:1fr;}
  .npe-fe-quicklinks .npe-fe-btn{flex-basis:100%;}
}

/* ==========================================================================
   Onboarding checklist ([npe_onboarding]) — client-branded (was MatiQ cobalt).
   ========================================================================== */
.npe-fe .npe-onboarding{max-width:560px;}
.npe-fe .npe-onboarding h2{font-size:1.35rem; font-weight:800; margin:0 0 .35rem; color:var(--npe-fe-ink);}
.npe-fe .npe-onboarding .npe-ob-sub{color:var(--npe-fe-muted); margin:0 0 1.25rem;}
.npe-fe .npe-ob-step{display:flex; gap:.85rem; padding:1rem; border:1px solid var(--npe-fe-line); border-radius:var(--npe-fe-radius); background:var(--npe-fe-bg); margin-bottom:.85rem;}
.npe-fe .npe-ob-step .npe-ob-mark{flex:0 0 26px; height:26px; width:26px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:.85rem; font-weight:700; border:2px solid var(--npe-fe-line); color:var(--npe-fe-muted);}
.npe-fe .npe-ob-step.is-done .npe-ob-mark{background:var(--npe-fe-ok); border-color:var(--npe-fe-ok); color:#fff;}
.npe-fe .npe-ob-step .npe-ob-body{flex:1;}
.npe-fe .npe-ob-step h3{margin:.1rem 0 .35rem; font-size:1.02rem; font-weight:700; color:var(--npe-fe-ink);}
.npe-fe .npe-ob-step p{margin:0 0 .5rem; color:var(--npe-fe-muted); font-size:.92rem;}
.npe-fe .npe-ob-step ul{margin:.25rem 0 .6rem 1.1rem; padding:0;}
.npe-fe .npe-ob-btn{display:inline-block; background:var(--npe-primary); color:var(--npe-on-primary,#fff); text-decoration:none; padding:.5rem .95rem; border-radius:var(--npe-fe-radius-sm); font-weight:600; font-size:.9rem;}
.npe-fe .npe-ob-all-set{display:flex; gap:.75rem; align-items:center; padding:1.1rem 1.25rem; border:1px solid var(--npe-fe-line); border-left:4px solid var(--npe-fe-ok); border-radius:var(--npe-fe-radius); background:var(--npe-fe-bg);}
.npe-fe .npe-ob-all-set .npe-ob-mark{flex:0 0 26px; height:26px; width:26px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:.85rem; font-weight:700; background:var(--npe-fe-ok); border:2px solid var(--npe-fe-ok); color:#fff;}

/* ==========================================================================
   Pantry booking ([npe_pantry]) — client-branded (was MatiQ cobalt). Class
   names are load-bearing for assets/js/pantry.js — do not rename.
   ========================================================================== */
/* Booking shell — a bordered card with a branded header, calendar+slots in a
   two-pane picker (Calendly-style), then the recipient form / confirmation. */
.npe-fe .npe-pantry-booking{max-width:880px; border:1px solid var(--npe-fe-line); border-radius:var(--npe-fe-radius); background:var(--npe-fe-bg); box-shadow:var(--npe-fe-shadow); overflow:hidden;}
.npe-fe .npe-pantry-booking [hidden]{display:none!important;}
.npe-fe .npe-pb-header{padding:18px 22px; border-bottom:1px solid var(--npe-fe-line); background:var(--npe-fe-bg-soft);}
.npe-fe .npe-pantry-booking h2{font-family:var(--npe-heading-font); font-size:1.3rem; font-weight:800; margin:0; color:var(--npe-fe-ink); line-height:1.2;}
.npe-fe .npe-pb-sub{color:var(--npe-fe-muted); margin:.25rem 0 0; font-size:.92rem;}

/* Two-pane picker: calendar (fixed) + live slots (fills). Stacks on narrow. */
.npe-fe .npe-pb-picker{display:grid; grid-template-columns:300px 1fr; align-items:stretch;}
.npe-fe .npe-pb-step-cal{padding:18px 20px; border-right:1px solid var(--npe-fe-line);}
.npe-fe .npe-pb-step-slots{padding:18px 20px; min-width:0;}

.npe-fe .npe-pb-cal-head{display:flex; align-items:center; justify-content:space-between; margin:0 0 12px;}
.npe-fe .npe-pb-cal-head strong{font-size:.98rem; font-weight:700; color:var(--npe-fe-ink);}
.npe-fe .npe-pb-nav{display:flex; align-items:center; justify-content:center; background:var(--npe-fe-bg); border:1px solid var(--npe-fe-line); border-radius:var(--npe-fe-radius-sm); height:30px; width:30px; font-size:1rem; line-height:1; cursor:pointer; color:var(--npe-fe-ink); transition:background-color .12s,border-color .12s;}
.npe-fe .npe-pb-nav:hover{background:var(--npe-fe-bg-soft); border-color:var(--npe-fe-line-strong);}
.npe-fe .npe-pb-grid{display:grid; grid-template-columns:repeat(7,1fr); gap:4px;}
.npe-fe .npe-pb-dow{text-align:center; font-size:.66rem; font-weight:700; letter-spacing:.04em; text-transform:uppercase; color:var(--npe-fe-muted); padding:2px 0;}
/* Compact day cells — capped so they never balloon (was aspect-ratio in a 720px grid → ~96px). */
.npe-fe .npe-pb-day{aspect-ratio:1/1; max-height:40px; border:1px solid transparent; border-radius:var(--npe-fe-radius-sm); background:transparent; color:var(--npe-fe-idle); display:flex; align-items:center; justify-content:center; font-size:.82rem;}
.npe-fe .npe-pb-day:not(.is-open):not(.is-empty){color:var(--npe-fe-line-strong);} /* closed: de-emphasised, not clickable */
.npe-fe .npe-pb-day.is-open{background:color-mix(in srgb, var(--npe-primary) 8%, transparent); color:var(--npe-primary); font-weight:700; cursor:pointer; border-color:color-mix(in srgb, var(--npe-primary) 22%, transparent);}
.npe-fe .npe-pb-day.is-open:hover{background:color-mix(in srgb, var(--npe-primary) 16%, transparent); border-color:var(--npe-primary);}
.npe-fe .npe-pb-day.is-open:focus-visible{outline:2px solid var(--npe-primary); outline-offset:1px;}
.npe-fe .npe-pb-day.is-closed{background:var(--npe-fe-line, #eee); text-decoration:line-through; cursor:not-allowed;} /* a day off on a day the pantry would run */
.npe-fe .npe-pb-day.is-selected{background:var(--npe-primary); border-color:var(--npe-primary); color:var(--npe-on-primary,#fff); font-weight:700;}
.npe-fe .npe-pb-day.is-empty{border:none; background:transparent;}

/* Slots panel */
.npe-fe .npe-pb-slots-label{font-size:.92rem; font-weight:700; color:var(--npe-fe-ink); margin:0 0 12px; min-height:1.2em;}
.npe-fe .npe-pb-slots{display:flex; flex-wrap:wrap; gap:8px; margin:0;}
.npe-fe .npe-pb-slot{background:var(--npe-fe-bg); border:1px solid var(--npe-fe-line); border-radius:var(--npe-fe-radius-pill); padding:.5rem 1rem; font-weight:600; font-size:.88rem; cursor:pointer; color:var(--npe-fe-ink); transition:border-color .12s,color .12s,background-color .12s;}
.npe-fe .npe-pb-slot:hover{border-color:var(--npe-primary); color:var(--npe-primary); background:color-mix(in srgb, var(--npe-primary) 6%, transparent);}
.npe-fe .npe-pb-slot.is-selected{background:var(--npe-primary); border-color:var(--npe-primary); color:var(--npe-on-primary,#fff);}
.npe-fe .npe-pb-slots-empty{color:var(--npe-fe-muted); font-size:.9rem;}

/* Recipient form + confirmation live below the picker, full card width. */
.npe-fe .npe-pb-form{margin:0; border-top:1px solid var(--npe-fe-line); background:var(--npe-fe-bg); padding:20px 22px;}
.npe-fe .npe-pb-row{display:grid; grid-template-columns:1fr 1fr; gap:14px;}
.npe-fe .npe-pb-row-3{display:grid; grid-template-columns:1fr 1fr 1fr; gap:14px;}
.npe-fe .npe-pb-field{margin-bottom:14px;}
.npe-fe .npe-pb-field label{display:block; font-size:.8rem; font-weight:600; margin-bottom:5px; color:var(--npe-fe-ink);}
.npe-fe .npe-pb-field input{width:100%; box-sizing:border-box; border:1px solid var(--npe-fe-line); border-radius:var(--npe-fe-radius-sm); padding:.55rem .7rem; font-size:.95rem; color:var(--npe-fe-ink); background:var(--npe-fe-bg);}
.npe-fe .npe-pb-field input:focus{outline:2px solid var(--npe-primary); outline-offset:-1px; border-color:var(--npe-primary);}
.npe-fe .npe-pb-check{display:flex; align-items:center; gap:.5rem; font-size:.9rem; margin:.4rem 0 1rem; color:var(--npe-fe-ink);}
.npe-fe .npe-pb-btn{display:inline-flex; align-items:center; justify-content:center; background:var(--npe-primary); color:var(--npe-on-primary,#fff); border:1px solid var(--npe-primary); text-decoration:none; padding:.6rem 1.2rem; border-radius:var(--npe-fe-radius-sm); font-weight:700; font-size:.95rem; cursor:pointer; transition:filter .12s;}
.npe-fe .npe-pb-btn:hover{filter:brightness(.94);}
.npe-fe .npe-pb-btn[disabled]{opacity:.5; cursor:not-allowed;}
.npe-fe .npe-pb-btn.is-ghost{background:var(--npe-fe-bg); color:var(--npe-primary);}
.npe-fe .npe-pb-error{color:var(--npe-fe-crit); font-size:.88rem; margin:.5rem 0 0; min-height:1.1em;}
.npe-fe .npe-pb-confirm{margin:0; border-top:1px solid var(--npe-fe-line); border-left:3px solid var(--npe-fe-ok); background:var(--npe-fe-ok-bg); padding:20px 22px;}
.npe-fe .npe-pb-confirm h3{margin:0 0 .4rem; font-size:1.05rem; color:var(--npe-fe-ink);}
.npe-fe .npe-pb-hint{color:var(--npe-fe-muted); font-size:.85rem; margin:.3rem 0 0;}
.npe-fe .npe-pb-muted{color:var(--npe-fe-muted);}
@media (max-width:640px){
  .npe-fe .npe-pb-picker{grid-template-columns:1fr;}
  .npe-fe .npe-pb-step-cal{border-right:none; border-bottom:1px solid var(--npe-fe-line);}
  .npe-fe .npe-pb-row,.npe-fe .npe-pb-row-3{grid-template-columns:1fr;}
  .npe-fe .npe-pb-nav{width:44px; height:44px;} /* the month arrows meet the 44px tap target on a phone */
}

/* Booking hub ([npe_pantry_booking]): one "Book appointment" button -> Food/Clothing
   chooser -> the chosen pantry's widget (revealed by assets/js/pantry.js). */
.npe-fe .npe-pantry-hub{margin:0 auto;}
.npe-fe .npe-pb-hub-intro{text-align:center; padding:8px 0;}
.npe-fe .npe-pb-hub-start{min-width:220px;}
.npe-fe .npe-pb-hub-choose{text-align:center; padding:8px 0 4px;}
.npe-fe .npe-pb-hub-prompt{margin:0 0 .9rem; font-weight:700; font-size:1.05rem; color:var(--npe-fe-ink);}
.npe-fe .npe-pb-hub-options{display:flex; flex-wrap:wrap; gap:12px; justify-content:center;}
.npe-fe .npe-pb-hub-pick{min-width:160px;}
.npe-fe .npe-pb-hub-panel{margin-top:6px;}
.npe-fe .npe-pb-hub-back{display:inline-flex; align-items:center; gap:.25rem; background:none; border:none; color:var(--npe-primary); font-weight:600; font-size:.9rem; cursor:pointer; padding:.2rem 0; margin:0 0 .6rem;}
.npe-fe .npe-pb-hub-back:hover{text-decoration:underline;}

/* ==========================================================================
   App shell — the SEAMLESS in-page layout for the portal ([npe_portal]) and the
   front-end console ([npe_console]). The user should not be able to tell the
   dashboard is a plugin: one page scroll, sidebar hugging the far-left edge, and
   the app filling the space between the site header and footer.

   Confirmed Divi shell on this site (header is static / in-flow):
     #page-container > #et-boc > [ header.et-l--header ,
        #et-main-area > [ #main-content > article > .et_pb_section > .et_pb_row
        (max-width:1080px) > .et_pb_column > .et_pb_code (= shortcode),
        footer.et-l--footer ] ]
   (The old rule was scoped under `.et-l--body`, which this site does NOT have —
   only the header/footer are Theme-Builder templated — so it never applied.)
   ------------------------------------------------------------------ */

/* (1) FILL — make the shell a flex column that fills the viewport. The static
   header keeps its height; #et-main-area grows to fill the rest and #main-content
   grows inside it, so a SHORT app still reaches the footer at the bottom of the
   screen and a TALL app just scrolls the page (footer after it). One scroll. */
body.npe-app-portal #et-boc,
body.npe-app-console #et-boc{min-height:100vh; display:flex; flex-direction:column;}
body.npe-app-portal #et-main-area,
body.npe-app-console #et-main-area{flex:1 0 auto; display:flex; flex-direction:column; min-height:0;}
body.npe-app-portal #main-content,
body.npe-app-console #main-content{flex:1 0 auto; display:flex; flex-direction:column; min-height:0;}

/* (2) FULL-BLEED + STRETCH — the app's Divi wrappers go full width (kill the
   1080px row cap and every gutter) and stretch top-to-bottom so the app itself
   fills #main-content down to the footer, with its sidebar flush to the edge. */
body.npe-app-portal #main-content > article,
body.npe-app-console #main-content > article,
body.npe-app-portal #main-content .et_pb_section,
body.npe-app-console #main-content .et_pb_section,
body.npe-app-portal #main-content .et_pb_row,
body.npe-app-console #main-content .et_pb_row,
body.npe-app-portal #main-content .et_pb_column,
body.npe-app-console #main-content .et_pb_column,
body.npe-app-portal #main-content .et_pb_module,
body.npe-app-console #main-content .et_pb_module,
body.npe-app-portal #main-content .et_pb_code_inner,
body.npe-app-console #main-content .et_pb_code_inner{
	width:100%!important; max-width:100%!important; margin:0!important; padding:0!important;
	flex:1 0 auto; display:flex; flex-direction:column; min-height:0;}

/* (2b) OVERLAYS — Divi gives .et_pb_column (z-index 2) and .et_builder_inner_content (z-index 1) their
   own stacking contexts, so a fixed drawer, confirm dialog or toast inside the console was painted UNDER
   the footer's own columns (z-index 2, later in the page): scrolled near the bottom, the footer covered the
   drawer's Save / Cancel buttons and the site header covered its title. With z-index auto the overlays
   join the page's root stacking context, where their own z-index (100001+) applies. */
body.npe-app-console #main-content .et_pb_column,
body.npe-app-console #main-content .et_builder_inner_content{z-index:auto!important;}
/* (2c) SITE HEADER — the theme header's own menus (MY ACCOUNT and the other drop-downs) live inside its
   column, a z-index 2 stacking context, so while Divi's sticky header was not engaged the console's top bar
   (z-index 20, translucent) was painted OVER the drop-down's first entries. Lifting the header above the
   console chrome keeps its menus on top whatever the scroll position; 1000 stays far below the drawers,
   dialogs and toasts (100001 and up), so those still cover the header. Anything else fixed to the window
   (the People peek panel, the check-in mode sheet) must sit at 100000 or it slides under the header. */
body.npe-app-console header.et-l--header,
body.npe-app-portal header.et-l--header{position:relative; z-index:1000;}

/* app roots fill their wrapper */
body.npe-app-portal .npe-fe{flex:1 0 auto; display:flex; flex-direction:column; min-height:0;}
body.npe-app-portal .npe-fe > .npe-fe-portal{flex:1 0 auto; min-height:0;}
/* The console (and a full-screen mode) is at least one screen tall with its own canvas, so
   the sidebar and grey canvas reach the bottom of the window even when a theme wrapper the
   chain above does not name (Divi's .entry-content / .et-l--post) breaks the stretch. */
body.npe-app-console .npe-console[data-context="front"]{flex:1 0 auto; min-height:100vh; background:var(--canvas);}
/* A block theme's constrained content column (.is-layout-constrained > *: the theme's content size,
   ~650px) would squeeze the console: like the theme's own full-width blocks (.has-global-padding >
   .alignfull) it takes the page's full width, edge to edge. Block themes only: Divi has no such wrapper. */
body.npe-app-console .has-global-padding > .npe-console[data-context="front"]{max-width:none; margin-left:calc(var(--wp--style--root--padding-left,0px) * -1)!important; margin-right:calc(var(--wp--style--root--padding-right,0px) * -1)!important;}
/* Divi's `.entry-content ul` (disc bullets, 0 0 23px 1em padding, 26px line-height) is
   0,1,1 and prints after the plugin, so it beat every one-class console list rule. This
   is 0,1,2: it wins over Divi in any order and still loses to a `.npe-console .x` rule.
   Margin is left alone (Divi does not set it); a one-class list that wants padding
   (.npe-k-cal__events) carries a .npe-console selector in console-kit.css. */
body.npe-app-console :where(.npe-console) ul{list-style:none; padding:0; line-height:inherit;}
/* The same Divi rule on My KCDC (FF2 #5-#7): the kit's bare lists (sign-up "Who is coming?",
   the results card, requirement and item lists) lose their bullets at 0,1,2. Named lists
   only: .npe-my-agreed / .npe-my-lines and any prose keep their bullets; a two-class rule
   (.npe-my .npe-k-cal__events) still sets its own padding. */
body.npe-app-portal :where(.npe-my) ul:where(.npe-my-people,.npe-my-reqs,.npe-my-list,.npe-my-opp__roles,.npe-k-chart__legend,.npe-k-cal__events){list-style:none; padding:0; line-height:inherit;}

/* (3) PUBLIC KIT PAGES ON A PHONE — the Divi row is 80% wide and the kit wrapper
   (.npe-my-pub: public-one.css, public-vol.css) has its own 16px side padding: a
   double gutter, about 55px a side at 390px. Under 720px the row runs edge to edge,
   so the wrapper's padding is the one 16px gutter, as on My KCDC. */
@media (max-width:720px){
	#main-content .et_pb_row:has(.npe-my-pub){width:100%!important; max-width:100%!important;}
}

/* The theme footer's row is 1296px wide and 16px past a 1280px window (it sits in a -16px gutter): on the home page
   the body clips it, but the app pages' body does not, so the console and portal scrolled sideways by 16px. Clip
   the footer itself; nothing in it is meant to stick out. */
body.npe-app-console footer.et-l--footer,
body.npe-app-portal footer.et-l--footer{overflow-x:hidden;}

/* Drop the Instagram / social slider on the console & portal pages. */
body.npe-app-console footer.et-l--footer .et_pb_section:has(.sb_instagram_feed),
body.npe-app-portal footer.et-l--footer .et_pb_section:has(.sb_instagram_feed) { display: none !important; }
body.npe-app-console .sb_instagram_feed,
body.npe-app-portal .sb_instagram_feed { display: none !important; }

/* ---------- Messaging IM (portal) — chat with the team --------------------- */
.npe-fe-portal-nav a{position:relative;}
.npe-fe-portal-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;margin-left:6px;border-radius:999px;background:var(--npe-primary); color:var(--npe-on-primary); font-size:.72rem; font-weight:700; line-height:1;}
.npe-fe-messages{display:flex; flex-direction:column; max-width:720px;}
.npe-fe-msgs{display:flex; flex-direction:column; gap:2px; max-height:56vh; min-height:220px; overflow-y:auto; padding:16px; margin:12px 0; background:var(--npe-fe-bg); border:1px solid var(--npe-fe-line); border-radius:var(--npe-fe-radius);}
.npe-fe-msgs-empty{margin:auto; color:var(--npe-fe-muted); font-size:.95rem;}
.npe-fe-msg{max-width:80%; margin-bottom:12px;}
.npe-fe-msg.is-you{align-self:flex-end;}
.npe-fe-msg.is-team{align-self:flex-start;}
.npe-fe-msg-body{padding:10px 13px; font-size:.95rem; line-height:1.45; white-space:pre-wrap; overflow-wrap:anywhere; border-radius:14px;}
.npe-fe-msg.is-you .npe-fe-msg-body{background:var(--npe-primary); color:var(--npe-on-primary); border-bottom-right-radius:4px;}
.npe-fe-msg.is-team .npe-fe-msg-body{background:var(--npe-fe-bg-soft); color:var(--npe-fe-ink); border-bottom-left-radius:4px;}
.npe-fe-msg-stamp{font-size:.72rem; color:var(--npe-fe-muted); margin-top:4px;}
.npe-fe-msg.is-you .npe-fe-msg-stamp{text-align:right;}
.npe-fe-msg-compose{display:flex; gap:10px; align-items:flex-end;}
/* UX-PORTAL-a (PP-7.1): under 600px every .npe-fe-btn is width:100%, which left the textarea ~26px wide. */
.npe-fe-msg-compose .npe-fe-btn{width:auto; flex:none;}
.npe-fe-msg-compose textarea{flex:1; min-width:0; font:inherit; padding:10px 12px; border:1px solid var(--npe-fe-line); border-radius:var(--npe-fe-radius-sm); background:var(--npe-fe-bg); color:var(--npe-fe-ink); resize:vertical; min-height:44px;}
.npe-fe-msg-compose textarea:focus{outline:none; border-color:var(--npe-primary); box-shadow:0 0 0 3px color-mix(in srgb, var(--npe-primary) 20%, transparent);}
@media (max-width:600px){ .npe-fe-msg{max-width:90%;} .npe-fe-msgs{max-height:60vh;} }

/* ---------- V3 portal polish — every rule scoped under .npe-fe-portal.is-polish,
   which the shell emits only when the `portal_polish` flag is visible. ----------- */
/* Live empty-state link + embedded browse keep a visible focus ring. */
.npe-fe-portal.is-polish [data-npe-browse-link]:focus-visible,
.npe-fe-portal.is-polish [data-npe-portal-browse] a:focus-visible{outline:2px solid var(--npe-primary); outline-offset:2px;}
.npe-fe-portal.is-polish .npe-fe-empty [data-npe-browse-link]{margin-top:14px;}
.npe-fe-portal.is-polish #npe-portal-browse{scroll-margin-top:24px;}

/* Tablet — the stat trio reads as one even row instead of wrapping 2 + 1. */
@media (min-width:601px) and (max-width:820px){
  .npe-fe-portal.is-polish .npe-fe-grid:has(> .npe-fe-stat){grid-template-columns:repeat(auto-fit,minmax(140px,1fr)); gap:12px;}
}

/* Narrow — the horizontal nav rail fades at its trailing edge (a scroll cue) and
   snaps so the active tab settles fully in view. The zero minimums stop the 1fr
   track / sidebar from growing to the rail's full width (which widened the whole
   page instead of letting the rail scroll). */
@media (max-width:768px){
  /* UX-PORTAL-a (PP-1.4): these two apply to EVERY legacy portal, not only .is-polish —
     without them the 1fr track grows to the nav's full width and the page scrolls to 691px. */
  .npe-fe-portal:has(.npe-fe-portal-side){grid-template-columns:minmax(0,1fr);}
  .npe-fe-portal .npe-fe-portal-side{min-width:0;}
  .npe-fe-portal.is-polish .npe-fe-portal-nav{
    scroll-snap-type:x proximity; scroll-padding-inline:16px; padding-right:24px;
    -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 32px),transparent);
    mask-image:linear-gradient(to right,#000 calc(100% - 32px),transparent);}
  .npe-fe-portal.is-polish .npe-fe-portal-nav a{scroll-snap-align:start; scroll-margin-inline:16px;}
  .npe-fe-portal.is-polish .npe-fe-portal-nav a[aria-current="page"]{scroll-snap-align:center;}
}

/* Phone — tables whose cells carry data-label stack into label/value cards. */
@media (max-width:600px){
  .npe-fe-portal.is-polish .npe-fe-table:has(td[data-label]){border:0; box-shadow:none; background:transparent; overflow:visible;}
  .npe-fe-portal.is-polish .npe-fe-table:has(td[data-label]) thead{
    position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap;}
  .npe-fe-portal.is-polish .npe-fe-table:has(td[data-label]) tbody,
  .npe-fe-portal.is-polish .npe-fe-table:has(td[data-label]) tr{display:block;}
  .npe-fe-portal.is-polish .npe-fe-table:has(td[data-label]) tr{
    margin:0 0 12px; padding:6px 14px; background:var(--npe-fe-bg);
    border:1px solid var(--npe-fe-line); border-radius:var(--npe-fe-radius); box-shadow:var(--npe-fe-shadow);}
  .npe-fe-portal.is-polish .npe-fe-table:has(td[data-label]) tr:last-child{margin-bottom:0;}
  .npe-fe-portal.is-polish .npe-fe-table td[data-label]{
    display:flex; justify-content:space-between; align-items:baseline; gap:16px;
    padding:8px 0; text-align:right; overflow-wrap:anywhere; border-bottom:1px solid var(--npe-fe-line); background:transparent;}
  .npe-fe-portal.is-polish .npe-fe-table tr td[data-label]:last-child{border-bottom:0;}
  .npe-fe-portal.is-polish .npe-fe-table td[data-label]::before{
    content:attr(data-label); flex:none; text-align:left; font-weight:700; font-size:.78rem;
    letter-spacing:.04em; text-transform:uppercase; color:var(--npe-fe-muted);}
}

/* ==========================================================================
   R2 — public live impact page ([npe_impact]). Composition only; all values
   from --npe-* / --npe-fe-* tokens.
   ========================================================================== */
.npe-fe.npe-impact{max-width:1040px; margin:0 auto;}
.npe-fe .npe-impact-head{margin:8px 0 24px;}
.npe-fe .npe-impact-range{color:var(--npe-fe-muted); margin:4px 0 0;}
.npe-fe .npe-impact-stats{display:grid; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); gap:16px; margin-bottom:24px;}
.npe-fe .npe-impact-stat{padding:20px; border-top:4px solid var(--npe-primary);}
.npe-fe .npe-impact-num{font-family:var(--npe-heading-font); font-size:2.2rem; font-weight:800; line-height:1.1; color:var(--npe-primary-strong);}
.npe-fe .npe-impact-lbl{color:var(--npe-fe-ink-soft); margin-top:6px;}
.npe-fe .npe-impact-charts{display:grid; grid-template-columns:repeat(auto-fit,minmax(300px,1fr)); gap:16px; margin-bottom:24px;}
.npe-fe .npe-impact-chart{margin:0; padding:20px;}
.npe-fe .npe-impact-chart figcaption{font-family:var(--npe-heading-font); font-weight:700; margin-bottom:12px;}
.npe-fe .npe-impact-chart svg{display:block; height:160px;}
.npe-fe .npe-impact-axis{display:flex; justify-content:space-between; color:var(--npe-fe-muted); font-size:.85rem; margin-top:6px;}
.npe-fe .npe-impact-more{display:flex; flex-wrap:wrap; gap:8px 32px; margin-bottom:24px; color:var(--npe-fe-ink-soft);}
.npe-fe .npe-impact-more p{margin:0;}
.npe-fe .npe-impact-more strong{color:var(--npe-primary-strong);}
.npe-fe .npe-impact-types table{width:100%; border-collapse:collapse;}
.npe-fe .npe-impact-types td{padding:8px 0; border-bottom:1px solid var(--npe-fe-line);}
.npe-fe .npe-impact-types td:last-child{text-align:right; font-weight:700;}
.npe-fe .npe-impact-foot{color:var(--npe-fe-muted); font-size:.85rem; margin-top:24px;}

/* ---------- Floating Donate button (DonateFab, Settings › Integrations › Giving) ----------
   A plain link in the bottom corner of every public page. Its layer sits under the console's
   drawers (100001+) and dialogs (100010) and under the site header's menus (9999 and up). */
.npe-donate-fab{position:fixed;bottom:max(20px,env(safe-area-inset-bottom));z-index:9990;display:inline-flex;align-items:center;gap:.5rem;min-height:44px;padding:.65rem 1.15rem;border-radius:999px;background:var(--npe-primary,#15659f);color:var(--npe-on-primary,#fff);font:700 .9rem/1 var(--npe-font-family,inherit);letter-spacing:.04em;text-transform:uppercase;text-decoration:none;box-shadow:0 6px 18px rgba(0,0,0,.28);transition:transform .15s ease,box-shadow .15s ease;}
.npe-donate-fab.is-right{right:max(20px,env(safe-area-inset-right));}
.npe-donate-fab.is-left{left:max(20px,env(safe-area-inset-left));}
.npe-donate-fab:hover,.npe-donate-fab:focus-visible{color:var(--npe-on-primary,#fff);transform:translateY(-2px);box-shadow:0 10px 24px rgba(0,0,0,.34);}
.npe-donate-fab:focus-visible{outline:3px solid var(--npe-primary-strong,#0b3f66);outline-offset:3px;}
@media (prefers-reduced-motion:reduce){.npe-donate-fab{transition:none;}.npe-donate-fab:hover,.npe-donate-fab:focus-visible{transform:none;}}
/* GTranslate's floating English / Español switcher sits fixed in the same bottom corner (inline style, 15px from the edge, ~28px tall): lift the button above it on that side. */
body:has(.gtranslate_wrapper .gt_switcher_wrapper[style*="right"]) .npe-donate-fab.is-right,body:has(.gtranslate_wrapper .gt_switcher_wrapper[style*="left"]) .npe-donate-fab.is-left{bottom:calc(max(20px,env(safe-area-inset-bottom)) + 44px);}
@media print{.npe-donate-fab{display:none;}}
