/* =============================================================================
   Give-Kit theme layer
   -----------------------------------------------------------------------------
   Loaded AFTER vendor/bootstrap.min.css. Bootstrap 5.3 is vendored unmodified so
   upgrading is "replace one file"; everything Give-Kit-specific lives here.

   THE RULE THAT MATTERS (this bug has already bitten this codebase once):
   the complete LIGHT palette is declared on :root. Dark is only ever an
   OVERRIDE of those same tokens under [data-bs-theme="dark"]. A page that
   renders before the theme script runs, or with JavaScript off, therefore gets
   a complete, correct light page — never light text on a white background.
   Every surface sets its background-color explicitly; nothing inherits "none".

   Sections
     1. Brand tokens (light)        5. Public donor pages
     2. Brand tokens (dark)         6. Dashboard shell
     3. Bootstrap re-skin           7. Data display: stats, status, bars
     4. Focus + base                8. Print
   ========================================================================== */

/* -----------------------------------------------------------------------------
   0. Type. Figtree, self-hosted, SIL Open Font License (see fonts/OFL.txt).
      Variable 300–800 in one 20 KB file, so a light display weight and a 600
      label cost one request between them. Propshaft digests and serves it from
      the asset load path; nothing is fetched from a font CDN, which keeps the
      dashboard working on a machine that cannot reach one.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "Figtree";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("/assets/figtree-f7c28c58.woff2") format("woff2");
}

/* -----------------------------------------------------------------------------
   1. Brand tokens — LIGHT. The full palette. Dark only overrides these.
   -------------------------------------------------------------------------- */
:root {
  color-scheme: light;

  /* Brand. --gk-brand is the readable-as-text navy; --gk-brand-solid is the
     one that always carries --gk-on-brand text on top of it. In light they are
     the same colour; in dark they deliberately diverge (see §2). */
  --gk-brand:            #1F4E79;   /* 8.3:1 on --gk-bg  */
  --gk-brand-strong:     #163A5A;   /* hover             */
  --gk-brand-stronger:   #102B43;   /* active            */
  --gk-brand-solid:      #1F4E79;   /* button / fill bg  */
  --gk-on-brand:         #FFFFFF;   /* 8.7:1 on solid    */
  --gk-brand-subtle:     #E9F0F7;   /* cool block ground */
  --gk-brand-border:     #C3D6E8;

  /* The warm accent was doing two unrelated jobs under one name: "a human must
     act now" and "this goal has been met". Those are opposite messages, and a
     reader who learns the colour means one will misread the other. They are
     split here so they CAN diverge; they share a hue today because goal-met is
     deliberately coupled to the amber thermometer, and recolouring that is a
     semantic change to the dashboard rather than a palette change.

     --gk-accent stays as the shared hue so nothing downstream breaks. */
  --gk-accent:           #B45309;
  --gk-accent-subtle:    #FDEEDC;
  --gk-accent-border:    #EFC894;

  /* Alarm: forms needed, gifts waiting. The only thing on the overview allowed
     to interrupt, so it keeps a saturated ground rather than becoming a block
     at the same volume as the six tiles that are merely reporting. */
  --gk-alert:            #9C4707;   /* 5.1:1 on --gk-alert-subtle. Darker than
                                      the shared accent because the alert
                                      ground is deliberately the strongest
                                      tint in the palette, and #B45309 only
                                      managed 4.0:1 on it. */
  --gk-alert-subtle:     #FBE3C4;
  --gk-alert-border:     #E0A961;

  /* Celebration: goal met. Same hue, quieter ground — "well done" should not
     shout as loudly as "fix this". */
  --gk-celebrate:        #B45309;
  --gk-celebrate-subtle: #FDF2E3;   /* the shared accent reads 4.5:1 here; the
                                      darker tint I first tried was 4.4:1 */
  --gk-celebrate-border: #EFC894;

  /* Surfaces. White ground AND white cards: the ring is what separates them,
     not a change of tone. The previous arrangement put the page at #FFFFFF and
     a card at #FAFAFA, which reads as a faint grey wash once a screen carries
     eight tiles and two tables — the dashboard is mostly cards, so mostly the
     page was the darker colour.

     With both at white the hairline has to carry the whole job, so --gk-line
     is a little stronger than it was, and the remaining greys are neutral
     rather than warm: a warm tint only reads as warmth next to something
     cooler, and against pure white it reads as dirty. */
  --gk-bg:               #FFFFFF;
  --gk-surface:          #FFFFFF;
  --gk-surface-sunk:     #F5F5F5;
  --gk-line:             #DEDEDE;
  --gk-line-soft:        #ECECEC;
  --gk-ink:              #1F2022;   /* near-black, never pure black */
  --gk-ink-muted:        #55585C;   /* 7.9:1 on --gk-bg */

  /* Progress track and fill. WCAG 1.4.11 wants >=3:1 between them, because the
     bar is a graphical object carrying meaning. Light: 7.0:1. */
  --gk-track:            #E9E9E9;
  --gk-fill:             #1F4E79;

  --gk-focus:            #1F4E79;
  --gk-focus-ring:       rgba(31, 78, 121, 0.35);

  /* Shape. 12px cards, 16px for the largest panels, pills for actions and
     progress, and 8px for form controls — a 12px radius on an input reads as a
     toy. --gk-radius is consumed in 16 places, so the value moves all of them. */
  --gk-radius:           0.75rem;
  --gk-radius-lg:        1rem;
  --gk-radius-control:   0.5rem;
  --gk-radius-pill:      9999px;

  /* A ring, not a lift. Both of these are consumed by exactly one rule each
     (a card and the one lifted surface), so re-pointing the token restyles
     them without touching a component — and an inset ring, unlike a border,
     never moves the box it is added to. */
  --gk-shadow:           inset 0 0 0 1px var(--gk-line);

  /* --- Bootstrap tokens re-pointed at the brand --- */
  --bs-body-bg:                  var(--gk-bg);
  --bs-body-color:               var(--gk-ink);
  --bs-emphasis-color:           var(--gk-ink);
  --bs-secondary-color:          var(--gk-ink-muted);
  --bs-border-color:             var(--gk-line);
  --bs-border-color-translucent: var(--gk-line);
  --bs-tertiary-bg:              var(--gk-surface-sunk);
  --bs-secondary-bg:             var(--gk-surface-sunk);
  --bs-heading-color:            var(--gk-ink);

  --bs-primary:              #1F4E79;
  --bs-primary-rgb:          31, 78, 121;
  --bs-primary-text-emphasis:#102B43;
  --bs-primary-bg-subtle:    #E7EFF7;
  --bs-primary-border-subtle:#B9CFE4;

  --bs-link-color:           var(--gk-brand);
  --bs-link-color-rgb:       31, 78, 121;
  --bs-link-hover-color:     var(--gk-brand-strong);
  --bs-link-hover-color-rgb: 22, 58, 90;

  --bs-focus-ring-color:     var(--gk-focus-ring);
  --bs-border-radius:        var(--gk-radius-control);
  --bs-border-radius-lg:     var(--gk-radius);

  /* One token carries the typeface to every Bootstrap component at once. */
  --gk-font-sans: "Figtree", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
  --bs-body-font-family: var(--gk-font-sans);
  --bs-body-font-size: 1rem;
}

/* -----------------------------------------------------------------------------
   2. Brand tokens — DARK. Overrides only. Never introduces a new token.
   -------------------------------------------------------------------------- */
[data-bs-theme="dark"] {
  color-scheme: dark;

  --gk-brand:            #5FA3DC;   /* 6.8:1 on --gk-bg — safe as text   */
  --gk-brand-strong:     #83BCEA;
  --gk-brand-stronger:   #A3CFF2;
  --gk-brand-solid:      #2F6FA8;   /* 5.6:1 under white text            */
  --gk-on-brand:         #FFFFFF;
  --gk-brand-subtle:     #1A2D40;
  --gk-brand-border:     #2E4A63;

  --gk-accent:           #E8A33D;   /* 8.5:1 on --gk-bg */
  --gk-accent-subtle:    #3A2A12;
  --gk-accent-border:    #5F4824;

  --gk-alert:            #E8A33D;
  --gk-alert-subtle:     #4A3415;
  --gk-alert-border:     #7A5A28;

  --gk-celebrate:        #E8A33D;
  --gk-celebrate-subtle: #3A2A12;
  --gk-celebrate-border: #5F4824;

  --gk-bg:               #141517;
  --gk-surface:          #1C1D1F;
  --gk-surface-sunk:     #26282A;
  --gk-line:             #313336;
  --gk-line-soft:        #26282A;
  --gk-ink:              #EDEDEE;
  --gk-ink-muted:        #B0B4B8;   /* 8.6:1 on --gk-bg */

  --gk-track:            #2A2C2F;
  --gk-fill:             #5FA3DC;   /* 5.5:1 on --gk-track; the solid navy is 2.5:1 */

  --gk-focus:            #8CC2F0;
  --gk-focus-ring:       rgba(140, 194, 240, 0.40);

  --gk-shadow:           inset 0 0 0 1px var(--gk-line);

  --bs-primary:              #5FA3DC;
  --bs-primary-rgb:          95, 163, 220;
  --bs-primary-text-emphasis:#A3CFF2;
  --bs-primary-bg-subtle:    #16242F;
  --bs-primary-border-subtle:#2A4258;

  --bs-link-color:           var(--gk-brand);
  --bs-link-color-rgb:       95, 163, 220;
  --bs-link-hover-color:     var(--gk-brand-strong);
  --bs-link-hover-color-rgb: 131, 188, 234;
}

/* -----------------------------------------------------------------------------
   3. Bootstrap re-skin
   Bootstrap's component colours are compile-time literals (--bs-btn-bg: #0d6efd),
   not references to --bs-primary, so overriding --bs-primary alone is not enough.
   These blocks re-point the component-level variables. Theme-aware: they read
   the tokens above, so there is no second copy for dark.
   -------------------------------------------------------------------------- */
.btn-primary {
  --bs-btn-color:                var(--gk-on-brand);
  --bs-btn-bg:                   var(--gk-brand-solid);
  --bs-btn-border-color:         var(--gk-brand-solid);
  --bs-btn-hover-color:          var(--gk-on-brand);
  --bs-btn-hover-bg:             var(--gk-brand-strong);
  --bs-btn-hover-border-color:   var(--gk-brand-strong);
  --bs-btn-active-color:         var(--gk-on-brand);
  --bs-btn-active-bg:            var(--gk-brand-stronger);
  --bs-btn-active-border-color:  var(--gk-brand-stronger);
  --bs-btn-disabled-color:       var(--gk-on-brand);
  --bs-btn-disabled-bg:          var(--gk-brand-solid);
  --bs-btn-disabled-border-color:var(--gk-brand-solid);
  --bs-btn-focus-shadow-rgb:     var(--bs-primary-rgb);
}

[data-bs-theme="dark"] .btn-primary {
  /* The solid navy is readable under white but too dark to hover *into*;
     hovering should get lighter in dark mode, not darker. */
  --bs-btn-hover-bg:            #3B81C0;
  --bs-btn-hover-border-color:  #3B81C0;
  --bs-btn-active-bg:           #4A90CE;
  --bs-btn-active-border-color: #4A90CE;
}

.btn-outline-primary {
  --bs-btn-color:                var(--gk-brand);
  --bs-btn-border-color:         var(--gk-brand);
  --bs-btn-hover-color:          var(--gk-on-brand);
  --bs-btn-hover-bg:             var(--gk-brand-solid);
  --bs-btn-hover-border-color:   var(--gk-brand-solid);
  --bs-btn-active-color:         var(--gk-on-brand);
  --bs-btn-active-bg:            var(--gk-brand-strong);
  --bs-btn-active-border-color:  var(--gk-brand-strong);
  --bs-btn-disabled-color:       var(--gk-brand);
  --bs-btn-disabled-border-color:var(--gk-brand);
  --bs-btn-focus-shadow-rgb:     var(--bs-primary-rgb);
}

/* Bootstrap's outline-secondary is a fixed #6c757d, which measures 3.5:1 on
   the dark surface — it failed the contrast sweep on the unmatched queue,
   where it is the "other suggestion" button. Theme-aware instead. */
.btn-outline-secondary {
  --bs-btn-color:                var(--gk-ink);
  --bs-btn-border-color:         var(--gk-line);
  --bs-btn-hover-color:          var(--gk-ink);
  --bs-btn-hover-bg:             var(--gk-surface-sunk);
  --bs-btn-hover-border-color:   var(--gk-ink-muted);
  --bs-btn-active-color:         var(--gk-ink);
  --bs-btn-active-bg:            var(--gk-surface-sunk);
  --bs-btn-active-border-color:  var(--gk-ink-muted);
  --bs-btn-disabled-color:       var(--gk-ink-muted);
  --bs-btn-disabled-border-color:var(--gk-line);
  --bs-btn-focus-shadow-rgb:     var(--bs-primary-rgb);
}

/* Bootstrap hardcodes white on .text-bg-primary / .bg-primary, which would be
   white-on-light-blue in dark mode. Point them at the solid pair instead. */
.bg-primary      { background-color: var(--gk-brand-solid) !important; }
.text-bg-primary { color: var(--gk-on-brand) !important;
                   background-color: var(--gk-brand-solid) !important; }

.progress, .progress-stacked {
  --bs-progress-bg:     var(--gk-track);
  --bs-progress-bar-bg: var(--gk-fill);
  --bs-progress-box-shadow: none;
}

.form-control:focus,
.form-select:focus {
  border-color: var(--gk-brand);
  box-shadow: 0 0 0 .25rem var(--gk-focus-ring);
}
.form-check-input:checked { background-color: var(--gk-brand-solid);
                            border-color: var(--gk-brand-solid); }
.form-check-input:focus   { border-color: var(--gk-brand);
                            box-shadow: 0 0 0 .25rem var(--gk-focus-ring); }

.nav-pills { --bs-nav-pills-link-active-bg: var(--gk-brand-solid);
             --bs-nav-pills-link-active-color: var(--gk-on-brand); }

.card      { --bs-card-bg: var(--gk-surface);
             --bs-card-border-color: var(--gk-line);
             --bs-card-cap-bg: transparent; }
.table     { --bs-table-bg: transparent;
             --bs-table-border-color: var(--gk-line-soft); }
.list-group{ --bs-list-group-bg: var(--gk-surface);
             --bs-list-group-border-color: var(--gk-line);
             --bs-list-group-action-hover-bg: var(--gk-brand-subtle); }

/* -----------------------------------------------------------------------------
   4. Focus + base
   -------------------------------------------------------------------------- */

/* Headings across both layouts: the compressed scale. Bootstrap ships h1-h6 at
   weight 500 already, so this is mostly about tracking — at Figtree's display
   sizes the default letter-spacing reads loose. */
h1, h2, h3, .h1, .h2, .h3 { letter-spacing: -.02em; }
h1, .h1 { font-weight: 500; }

/* Actions are pills. --bs-border-radius stays at the control radius so inputs
   and selects keep an 8px corner; a button is not an input. */
.btn { border-radius: var(--gk-radius-pill); }

html { background-color: var(--gk-bg); }

body {
  /* Explicit, always. Never inherit the background. */
  background-color: var(--gk-bg);
  color: var(--gk-ink);
  -webkit-text-size-adjust: 100%;
}

:focus-visible {
  outline: 3px solid var(--gk-focus);
  outline-offset: 2px;
  border-radius: 2px;
}
.btn:focus-visible,
.form-control:focus-visible,
.form-select:focus-visible {
  outline: 3px solid var(--gk-focus);
  outline-offset: 2px;
}

/* Skip link: first thing in the tab order on every page. */
.gk-skip {
  position: absolute;
  left: .5rem;
  top: -4rem;
  z-index: 1080;
  padding: .6rem 1rem;
  background-color: var(--gk-surface);
  color: var(--gk-brand);
  border: 2px solid var(--gk-brand);
  border-radius: var(--gk-radius);
  font-weight: 600;
  text-decoration: none;
  transition: top .15s ease-out;
}
.gk-skip:focus { top: .5rem; }

.gk-muted   { color: var(--gk-ink-muted); }
.gk-surface { background-color: var(--gk-surface); }

/* A card that is genuinely a surface in both themes. */
.gk-panel {
  background-color: var(--gk-surface);
  /* The ring, not a border. Carrying both drew them adjacent — a 2px hairline
     where a .gk-stat beside it draws 1px. */
  border-radius: var(--gk-radius-lg);
  box-shadow: var(--gk-shadow);
}

.gk-tabular { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  .gk-thermo__fill, .gk-bar__fill, .gk-skip { transition: none !important; }
}

/* -----------------------------------------------------------------------------
   5. Public donor pages
   Phone-first. No webfont, no above-the-fold image, no JavaScript needed to
   render — the LCP element is the "to go" figure, which is plain text.
   -------------------------------------------------------------------------- */
.gk-public {
  max-width: 33rem;
  margin: 0 auto;
  padding: 1.25rem 1.125rem 4rem;
}

.gk-eyebrow {
  display: block;
  font-size: .8125rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--gk-ink-muted);
  margin-bottom: .375rem;
}

.gk-public h1 {
  font-size: 1.875rem;
  line-height: 1.08;
  /* Weight goes DOWN as size goes up. A 500 at this size reads as composed;
     the 700 it replaces read as a headline shouting at a donor. */
  font-weight: 500;
  letter-spacing: -.025em;
  color: var(--gk-ink);
  margin: 0 0 .25rem;
}
@media (min-width: 36em) { .gk-public h1 { font-size: 2.5rem; letter-spacing: -.03em; } }

/* The hero figure. What is LEFT, because that is the number that moves a donor.
   Raised-of-goal is true but it is a status report, not an ask. */
.gk-hero {
  display: flex;
  align-items: stretch;
  gap: 1.25rem;
  margin: 1.5rem 0;
}
.gk-hero__nums { flex: 1 1 auto; align-self: center; }

.gk-figure {
  display: block;
  font-size: 2.75rem;
  line-height: 1;
  /* 600 rather than the display 500: tabular numerals at a light weight read
     as thin where letterforms read as elegant, and this is the one number on
     the page a donor is meant to act on. */
  font-weight: 600;
  letter-spacing: -.03em;
  color: var(--gk-brand);
  font-variant-numeric: tabular-nums;
}
@media (min-width: 36em) { .gk-figure { font-size: 3.25rem; } }

/* Goal met: the figure switches to the warm accent so it agrees with the
   thermometer instead of sitting navy next to an amber tube. */
.gk-figure--met { color: var(--gk-celebrate); }

.gk-figure-label {
  display: block;
  font-size: 1.0625rem;
  font-weight: 600;
  color: var(--gk-ink);
  margin-top: .25rem;
}
.gk-figure-sub {
  display: block;
  font-size: .9375rem;
  color: var(--gk-ink-muted);
  margin-top: .5rem;
}

/* The thermometer. Fills from the bottom; height is the only thing that moves,
   so it is one paint and no layout. */
.gk-thermo {
  flex: 0 0 auto;
  width: 72px;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.gk-thermo__tube {
  position: relative;
  width: 72px;
  height: 240px;
  border-radius: 36px;
  background-color: var(--gk-track);
  border: 1px solid var(--gk-line);
  overflow: hidden;
}
.gk-thermo__fill {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  background-color: var(--gk-fill);
  transition: height .5s cubic-bezier(.22, .61, .36, 1);
}
.gk-thermo--met .gk-thermo__fill { background-color: var(--gk-celebrate); }
.gk-thermo__pct {
  margin-top: .5rem;
  font-size: .875rem;
  font-weight: 700;
  color: var(--gk-ink-muted);
  font-variant-numeric: tabular-nums;
}

/* The ask. 56px tall, full width, thumb-reachable, and repeated at the bottom
   of a long donor list so nobody has to scroll back up. */
.gk-give {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 3.5rem;
  padding: .875rem 1.25rem;
  background-color: var(--gk-brand-solid);
  color: var(--gk-on-brand);
  border: 1px solid var(--gk-brand-solid);
  border-radius: var(--gk-radius-pill);
  font-size: 1.125rem;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
}
.gk-give:hover,
.gk-give:focus { background-color: var(--gk-brand-strong);
                 border-color: var(--gk-brand-strong);
                 color: var(--gk-on-brand); }
[data-bs-theme="dark"] .gk-give:hover,
[data-bs-theme="dark"] .gk-give:focus { background-color: #3B81C0; border-color: #3B81C0; }

.gk-reassure {
  display: block;
  text-align: center;
  font-size: .9375rem;
  color: var(--gk-ink-muted);
  margin-top: .625rem;
}

/* The unit maths, stated as what the donor's money does rather than what has
   already been raised. */
.gk-impact {
  margin: 1.5rem 0;
  padding: .875rem 1rem;
  background-color: var(--gk-brand-subtle);
  border: 1px solid var(--gk-brand-border);
  border-radius: var(--gk-radius);
  color: var(--gk-ink);
  font-size: .9375rem;
  line-height: 1.5;
}
.gk-impact strong { color: var(--gk-brand); }

.gk-met {
  margin: 1.5rem 0;
  padding: .875rem 1rem;
  background-color: var(--gk-accent-subtle);
  border: 1px solid var(--gk-accent-border);
  border-left: 4px solid var(--gk-accent);
  border-radius: var(--gk-radius);
  color: var(--gk-ink);
}
.gk-met strong { color: var(--gk-accent); }

.gk-section-title {
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: .01em;
  color: var(--gk-ink);
  margin: 2rem 0 .5rem;
}

.gk-donors { list-style: none; padding: 0; margin: 0; }
.gk-donors li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: .625rem .25rem;
  border-bottom: 1px solid var(--gk-line-soft);
  color: var(--gk-ink);
}
.gk-donors li:last-child { border-bottom: 0; }
.gk-donors .amount { color: var(--gk-ink-muted); font-variant-numeric: tabular-nums; }

.gk-public footer {
  margin-top: 2.5rem;
  padding-top: 1rem;
  border-top: 1px solid var(--gk-line);
  color: var(--gk-ink-muted);
  font-size: .875rem;
}
.gk-public footer a { color: var(--gk-brand); }

/* Campaign page: one business per row, each a link to its own page. */
.gk-biz-list { list-style: none; padding: 0; margin: 0; display: grid; gap: .5rem; }
.gk-biz {
  display: block;
  padding: .75rem .875rem;
  background-color: var(--gk-surface);
  border: 1px solid var(--gk-line);
  border-radius: var(--gk-radius);
  color: var(--gk-ink);
  text-decoration: none;
}
.gk-biz:hover, .gk-biz:focus-visible { border-color: var(--gk-brand);
                                       background-color: var(--gk-brand-subtle);
                                       color: var(--gk-ink); }
.gk-biz__top { display: flex; justify-content: space-between; gap: .75rem;
               align-items: baseline; margin-bottom: .5rem; }
.gk-biz__name { font-weight: 600; }
.gk-biz__pct  { font-size: .875rem; color: var(--gk-ink-muted);
                font-variant-numeric: tabular-nums; white-space: nowrap; }

/* -----------------------------------------------------------------------------
   6. Dashboard shell — desktop-first, data-dense
   -------------------------------------------------------------------------- */
.gk-topbar {
  background-color: var(--gk-brand-solid);
  color: var(--gk-on-brand);
  border-bottom: 1px solid var(--gk-brand-stronger);
}
[data-bs-theme="dark"] .gk-topbar { border-bottom-color: var(--gk-line); }

.gk-topbar__inner {
  display: flex;
  align-items: center;
  gap: 1rem;
  max-width: 88rem;
  margin: 0 auto;
  padding: .625rem 1rem;
}
.gk-topbar a { color: var(--gk-on-brand); }
.gk-wordmark {
  white-space: nowrap;
  font-weight: 800;
  letter-spacing: -.01em;
  font-size: 1.0625rem;
  text-decoration: none;
  color: var(--gk-on-brand);
}
.gk-topbar__spacer { margin-left: auto; }
.gk-topbar__who { font-size: .875rem; opacity: .9; }

/* Buttons that sit on the navy bar. */
.gk-bar-btn {
  display: inline-flex;
  align-items: center;
  gap: .375rem;
  min-height: 2.25rem;
  padding: .3125rem .75rem;
  background-color: rgba(255, 255, 255, .14);
  color: var(--gk-on-brand);
  border: 1px solid rgba(255, 255, 255, .28);
  border-radius: var(--gk-radius);
  font-size: .875rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}
.gk-bar-btn:hover { background-color: rgba(255, 255, 255, .24); color: var(--gk-on-brand); }
.gk-bar-btn:focus-visible { outline: 3px solid #fff; outline-offset: 2px; }

.gk-subnav {
  background-color: var(--gk-surface);
  border-bottom: 1px solid var(--gk-line);
}
.gk-subnav__inner {
  display: flex;
  align-items: center;
  gap: .25rem;
  max-width: 88rem;
  margin: 0 auto;
  padding: 0 1rem;
  overflow-x: auto;
}
.gk-subnav a {
  display: inline-block;
  padding: .75rem .875rem;
  border-bottom: 3px solid transparent;
  color: var(--gk-ink-muted);
  font-size: .9375rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}
.gk-subnav a:hover { color: var(--gk-brand); }
.gk-subnav a[aria-current="page"] { color: var(--gk-brand);
                                    border-bottom-color: var(--gk-brand); }

.gk-main {
  max-width: 88rem;
  margin: 0 auto;
  padding: 1.5rem 1rem 4rem;
}

.gk-page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: .75rem;
  margin-bottom: 1.25rem;
}
.gk-page-head h1 { font-size: 1.75rem; font-weight: 500; letter-spacing: -.025em; margin: 0; color: var(--gk-ink); }
.gk-page-head .gk-sub { color: var(--gk-ink-muted); font-size: .9375rem; margin: .25rem 0 0; }
.gk-actions { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }

.gk-crumb { font-size: .875rem; margin-bottom: .5rem; }
.gk-crumb a { color: var(--gk-ink-muted); text-decoration: none; }
.gk-crumb a:hover { color: var(--gk-brand); text-decoration: underline; }

/* The sign-in page is its own thing: centred, nothing else on screen. */
.gk-auth {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 1.5rem;
  background-color: var(--gk-bg);
}
.gk-auth__card { width: 100%; max-width: 26rem; padding: 1.75rem; }

/* -----------------------------------------------------------------------------
   7. Data display
   -------------------------------------------------------------------------- */
.gk-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
  gap: .75rem;
  margin-bottom: 1.25rem;
}
.gk-stat {
  padding: .875rem 1rem;
  background-color: var(--gk-surface);
  border: 1px solid var(--gk-line);
  border-radius: var(--gk-radius-lg);
}
.gk-stat__label {
  display: block;
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--gk-ink-muted);
  margin-bottom: .25rem;
}
.gk-stat__value {
  display: block;
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.15;
  color: var(--gk-ink);
  font-variant-numeric: tabular-nums;
}
.gk-stat__note { display: block; font-size: .8125rem; color: var(--gk-ink-muted); margin-top: .25rem; }
.gk-stat--brand .gk-stat__value { color: var(--gk-brand); }
/* Loud on purpose. This is the one tile permitted to interrupt the overview. */
.gk-stat--alert { border-color: var(--gk-alert-border); background-color: var(--gk-alert-subtle); }
.gk-stat--alert .gk-stat__value { color: var(--gk-alert); }
/* The link that acts on the alert belongs to the alert, not to the brand. The
   brand blue measured 4.33:1 on the dark alert ground; this is 5.4:1 and says
   "this tile is one thing" at the same time. */
.gk-stat--alert .gk-stat__note a { color: var(--gk-alert); }

/* Horizontal bar used in tables and on the campaign page. */
.gk-bar {
  /* Width is explicit so it still has a size as a flex item in a table cell. */
  width: 100%;
  min-width: 2.5rem;
  height: .5rem;
  border-radius: 999px;
  background-color: var(--gk-track);
  overflow: hidden;
}
.gk-bar__fill {
  height: 100%;
  /* No radius: the track clips it. A pill-shaped fill at 4% renders as a
     circle and reads as a slider handle rather than progress. */
  background-color: var(--gk-fill);
  transition: width .5s cubic-bezier(.22, .61, .36, 1);
}
.gk-bar--met .gk-bar__fill { background-color: var(--gk-celebrate); }
.gk-bar--lg { height: .875rem; }

/* Status badges. One class per pipeline state so the table scans by colour
   without relying on colour alone — the word is always there too. */
.gk-status {
  display: inline-block;
  padding: .1875rem .5rem;
  border-radius: 999px;
  border: 1px solid transparent;
  font-size: .75rem;
  font-weight: 700;
  line-height: 1.35;
  white-space: nowrap;
}
.gk-status--prospect      { background-color: var(--gk-surface-sunk); color: var(--gk-ink-muted);
                            border-color: var(--gk-line); }
/* Reused for the "Needed" badge in the businesses table's Form column. Inside
   a dense table a saturated chip fights every row around it, so this one takes
   the quiet ground and lets the word carry the meaning. */
.gk-status--asked         { background-color: var(--gk-celebrate-subtle); color: var(--gk-accent);
                            border-color: var(--gk-celebrate-border); }
.gk-status--committed,
.gk-status--kit_delivered { background-color: var(--gk-brand-subtle); color: var(--gk-brand);
                            border-color: var(--gk-brand-border); }
.gk-status--active        { background-color: var(--gk-brand-solid); color: var(--gk-on-brand);
                            border-color: var(--gk-brand-solid); }
.gk-status--goal_met      { background-color: var(--gk-celebrate); color: #fff;
                            border-color: var(--gk-celebrate); }
[data-bs-theme="dark"] .gk-status--goal_met { color: #1B1304; }
.gk-status--declined      { background-color: var(--bs-danger-bg-subtle);
                            color: var(--bs-danger-text-emphasis);
                            border-color: var(--bs-danger-border-subtle); }

/* The pipeline, shown as counts so "where is this campaign stuck" is one look. */
.gk-pipeline { display: flex; flex-wrap: wrap; gap: .375rem; margin-bottom: 1.25rem; }
.gk-pipeline a {
  display: flex;
  flex-direction: column;
  gap: .125rem;
  min-width: 6.5rem;
  padding: .5rem .75rem;
  background-color: var(--gk-surface);
  border: 1px solid var(--gk-line);
  border-radius: var(--gk-radius);
  color: var(--gk-ink);
  text-decoration: none;
}
.gk-pipeline a:hover { border-color: var(--gk-brand); background-color: var(--gk-brand-subtle); }
.gk-pipeline a[aria-current="true"] { border-color: var(--gk-brand);
                                      box-shadow: inset 0 0 0 1px var(--gk-brand);
                                      background-color: var(--gk-brand-subtle); }
.gk-pipeline .n { font-size: 1.25rem; font-weight: 700; line-height: 1;
                  font-variant-numeric: tabular-nums; }
.gk-pipeline .k { font-size: .75rem; color: var(--gk-ink-muted); font-weight: 600; }

/* Tables: a surface with a sticky header, because these lists get long. */
.gk-table-wrap {
  background-color: var(--gk-surface);
  border: 1px solid var(--gk-line);
  border-radius: var(--gk-radius-lg);
  overflow: auto;
  max-height: 72vh;
}
.gk-table { width: 100%; margin: 0; border-collapse: separate; border-spacing: 0; }
.gk-table th, .gk-table td {
  padding: .625rem .75rem;
  border-bottom: 1px solid var(--gk-line-soft);
  vertical-align: middle;
  font-size: .9375rem;
}
.gk-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background-color: var(--gk-surface-sunk);
  border-bottom: 1px solid var(--gk-line);
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--gk-ink-muted);
  white-space: nowrap;
}
.gk-table tbody tr:last-child td { border-bottom: 0; }
.gk-table tbody tr:hover td { background-color: var(--gk-brand-subtle); }
.gk-table .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.gk-table .shrink { width: 1%; white-space: nowrap; }

.gk-filters {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  align-items: end;
  padding: .875rem 1rem;
  background-color: var(--gk-surface);
  border: 1px solid var(--gk-line);
  border-radius: var(--gk-radius-lg);
  margin-bottom: 1rem;
}
.gk-filters .field { display: flex; flex-direction: column; gap: .25rem; }
.gk-filters label { font-size: .75rem; font-weight: 700; letter-spacing: .04em;
                    text-transform: uppercase; color: var(--gk-ink-muted); }

/* The unmatched queue: one decision per row, suggestions first. */
.gk-decide { display: flex; flex-wrap: wrap; gap: .375rem; align-items: center; }
.gk-decide form { display: flex; gap: .375rem; align-items: center; margin: 0; }
.gk-quote { color: var(--gk-ink); }

.gk-empty {
  padding: 2.5rem 1.5rem;
  text-align: center;
  background-color: var(--gk-surface);
  border: 1px dashed var(--gk-line);
  border-radius: var(--gk-radius-lg);
  color: var(--gk-ink-muted);
}
.gk-empty strong { display: block; color: var(--gk-ink); font-size: 1.0625rem; margin-bottom: .25rem; }

/* Forms: a fieldset is a titled panel, not a browser-default box. */
.gk-fieldset {
  border: 1px solid var(--gk-line);
  border-radius: var(--gk-radius-lg);
  background-color: var(--gk-surface);
  padding: 1rem 1.125rem 1.125rem;
  margin-bottom: 1.25rem;
}
.gk-fieldset > legend {
  float: none;
  width: auto;
  padding: 0 .375rem;
  margin: 0 0 .5rem -.375rem;
  font-size: .8125rem;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--gk-ink-muted);
}

.gk-form-grid { display: grid; gap: 1rem; grid-template-columns: 1fr; }
@media (min-width: 48em) { .gk-form-grid--2 { grid-template-columns: 1fr 1fr; } }

.gk-code {
  display: block;
  padding: .625rem .75rem;
  background-color: var(--gk-surface-sunk);
  border: 1px solid var(--gk-line);
  border-radius: var(--gk-radius);
  color: var(--gk-ink);
  font-size: .875rem;
  word-break: break-all;
}

/* -----------------------------------------------------------------------------
   8. Print — the counter sign and the gift list both get printed.
   -------------------------------------------------------------------------- */
@media print {
  .gk-topbar, .gk-subnav, .gk-skip, .gk-actions, .gk-filters { display: none !important; }
  .gk-table-wrap { max-height: none; overflow: visible; border: 0; }
  body { background: #fff; color: #000; }

  /* Print drops background colours, and the alert tile's loudest signal is its
     ground. On paper it keeps only the same 1px border every other tile has,
     so on a mono print of the board report "a human must act now" looks
     exactly like "here is a number". A heavier rule survives both the dropped
     background and a black-and-white printer. */
  .gk-stat--alert { border-width: 1px 1px 1px 6px; }

  /* The ring is a box-shadow and box-shadows do not print, so the panel would
     lose its edge entirely on paper. Borders do print. */
  .gk-panel { box-shadow: none; border: 1px solid var(--gk-line); }
}
