@charset "UTF-8";

/* ── Self-hosted brand fonts (SIL OFL 1.1) ───────────────────
   Lato and Fjalla One ship inside this Razor Class Library
   under wwwroot/fonts/, so consuming apps get them via the
   /_content/Capstone/ static-asset mount — no third-party
   CDN, no extra DNS lookup, and no Google Fonts request
   (which has been ruled a GDPR concern in EU jurisdictions).

   WOFF2 first, TTF as fallback: WOFF2 is ~half the byte size
   and supported by every browser we target, so it lands fast;
   the .ttf src is only fetched by browsers too old for WOFF2.

   font-display: optional (not swap): the browser gives the
   font a brief window to arrive, otherwise locks the system
   fallback for that page load. Combined with the <link
   rel="preload"> hints emitted by <capstone-head>, the
   preloaded weights are almost always ready within that
   window — so we get the brand font without the swap re-paint
   (FOUT) or the layout shift the swap reflow used to cause.
   Text is always visible (never FOIT), and there is no CLS. */
@font-face {
    font-family: 'Lato';
    font-style: normal;
    font-weight: 400;
    font-display: optional;
    src: url('../fonts/Lato/Lato-Regular.woff2') format('woff2'),
         url('../fonts/Lato/Lato-Regular.ttf') format('truetype');
}
@font-face {
    font-family: 'Lato';
    font-style: italic;
    font-weight: 400;
    font-display: optional;
    src: url('../fonts/Lato/Lato-Italic.woff2') format('woff2'),
         url('../fonts/Lato/Lato-Italic.ttf') format('truetype');
}
@font-face {
    font-family: 'Lato';
    font-style: normal;
    font-weight: 700;
    font-display: optional;
    src: url('../fonts/Lato/Lato-Bold.woff2') format('woff2'),
         url('../fonts/Lato/Lato-Bold.ttf') format('truetype');
}
@font-face {
    font-family: 'Lato';
    font-style: normal;
    font-weight: 900;
    font-display: optional;
    src: url('../fonts/Lato/Lato-Black.woff2') format('woff2'),
         url('../fonts/Lato/Lato-Black.ttf') format('truetype');
}
@font-face {
    font-family: 'Fjalla One';
    font-style: normal;
    font-weight: 400;
    font-display: optional;
    src: url('../fonts/Fjalla_One/FjallaOne-Regular.woff2') format('woff2'),
         url('../fonts/Fjalla_One/FjallaOne-Regular.ttf') format('truetype');
}

/* Put this AFTER Bootstrap's CSS so it overrides */
:root {
  /* ── SRU brand typography ─────────────────────────────────
     Lato (regular / italic / bold / black) for body and most
     UI; Fjalla One — a single-weight condensed display sans —
     for marquee headings. The display stack falls back to
     Lato Black before generic sans-serif so the visual weight
     stays close when Fjalla One hasn't finished loading yet.
     Both fonts are self-hosted via the @font-face block above
     with display=optional + preload hints, so first paint
     lands in the brand font without a re-paint (FOUT) or
     layout shift; text is never hidden waiting on the network.
     Note: --bs-headings-font-family is Bootstrap 5.3's hook
     for restyling every <hN>. Scope rules below the variable
     block restore Lato on h3–h6 so dense forms don't get
     condensed-display shouting on sub-section labels. */
  --bs-body-font-family: 'Lato', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --capstone-display-font-family: 'Fjalla One', 'Lato', 'Helvetica Neue', Arial, sans-serif;

  /* ── Brand gradient ribbon ────────────────────────────────
     The SRU green→gold sweep that already appeared inside the
     .loader bar in capstone-site.css, promoted to a CSS
     variable so the navbar stripe, footer top edge, and
     .text-header accent all draw from a single source. Change
     it once and every brand surface follows. */
    /* ReSharper disable once InvalidValue */
  --capstone-brand-gradient: linear-gradient(90deg, var(--bs-primary), var(--capstone-green-bright) 55%, var(--bs-secondary));

  /* core brand */
  --bs-primary: #007055;
  --bs-primary-rgb: 0, 112, 85;
  --bs-secondary: #f7d117;
  --bs-secondary-rgb: 247, 209, 23;
  /* Links use Bootstrap blue (web convention, visually distinct from
     brand-green UI). Default Bootstrap blue #0d6efd passes 4.62:1 on #fff
     but only 4.26:1 on #f8f9fa (.bg-body-tertiary) — fails WCAG AA on
     Capstone's own form-card background. Use Bootstrap's own darker
     primary-text-emphasis shade #0a58ca which clears AA on both. */
  --bs-link-color: #0a58ca;
  --bs-link-color-rgb: 10, 88, 202;
  --bs-link-hover-color: #084298;
  --bs-link-hover-color-rgb: 8, 66, 152;
  /* button hover/active brand shades */
  --brand-primary-hover: #005945;
  --brand-primary-active: #004c3d;
  --brand-primary-hover: color-mix(in oklab, var(--bs-primary), black 12%);
  --brand-primary-active: color-mix(in oklab, var(--bs-primary), black 18%);
  --brand-secondary-hover: #e0bc0e;
  --brand-secondary-active: #ccab0a;
  --brand-secondary-hover: color-mix(in oklab, var(--bs-secondary), black 10%);
  --brand-secondary-active: color-mix(in oklab, var(--bs-secondary), black 16%);
  /* Text on the gold .btn-secondary. --bs-primary (#007055) is only
     4.08:1 on #f7d117 — fails AA for the 14px button label. This deeper
     brand green clears AA in every state: 7.3:1 on the base gold,
     5.9:1 on hover (#e0bc0e), 4.9:1 on active (#ccab0a). Dark mode's
     hover/active golds are lighter, so ratios only improve there. */
  --brand-on-secondary: #004633;

  /* ── Brand hairline ───────────────────────────────────────
     The 1px SRU-green rule used for quiet sub-divisions: the
     <capstone-section-header> / <capstone-section-separator>
     rule and the grid's header rule (capstone-grid.css reads
     this as its default). Split per theme like .text-brand —
     #007055 is under 2:1 on the dark surfaces, so dark mode
     uses the same lighter green every other brand accent
     switches to. */
  --capstone-rule-color: #007055;

  /* ── Primary "subtle" ramp ────────────────────────────────
     Bootstrap derives the accordion's open state, .alert-primary,
     .list-group-item-primary, .bg-primary-subtle and
     .text-primary-emphasis from these three tokens — and they
     stayed Bootstrap-blue when --bs-primary moved to SRU green,
     so an open accordion header was a light-blue band on a green
     system. Shade/tint of #007055 at Bootstrap's own ratios
     (text 60% shade, bg 80% tint, border 60% tint). */
  --bs-primary-text-emphasis: #002d22;
  --bs-primary-bg-subtle: #cce2dd;
  --bs-primary-border-subtle: #99c6bb;

  /* ── Warning and info re-pointed to colours the system owns ──
     Bootstrap's #ffc107 warning is a near-twin of SRU gold
     (#f7d117), so a warning badge and a gold brand badge were
     indistinguishable. The amber below is already Capstone's
     pre-production signal (navbar-preprod border, test banner),
     so it reads as "caution" everywhere. Bootstrap's #0dcaf0 info
     cyan is nowhere in the brand book; the SRU sky secondary is.
     Both stay light fills that take BLACK text (amber 9.6:1, sky
     12.6:1); neither is a text colour on white. */
  --bs-warning: #e8a317;
  --bs-warning-rgb: 232, 163, 23;
  --bs-info: var(--capstone-sky);
  --bs-info-rgb: 139, 211, 230;

  /* ── SRU secondary & neutral palette (Brand Standards 2025, p.14) ──
     The official palette beyond the green/gold anchors above, exposed so
     consuming apps reference brand-true tokens instead of Bootstrap's
     generic theme colors. The guide calls these SUPPORTING colors: use
     "sparingly and only in a supporting manner to the primary brand
     colors," at 100% opacity.

     Every one of them is LIGHT — they are fill/background colors that pair
     with DARK text, never white (SRU's secondaries are too luminous to take
     white text, same reason .text-bg-secondary is banned for the gold).
     Ratios below are vs #fff and vs near-black text so callers pick safely.

     Secondary accents
       --capstone-mint   #a5dfd3 (PMS 572): 1.49:1 on white (FAIL as text) ·
                          14:1 with black text — fill/background only.
       --capstone-sky    #8bd3e6 (PMS 636): 1.67:1 on white (FAIL as text) ·
                          12.6:1 with black text — fill/background only.
       --capstone-green-bright #6cc24a (PMS 360): 2.2:1 on white (FAIL as
                          text) · 9.4:1 with black text; ~6:1 as TEXT on the
                          dark-theme surfaces (#212529/#2c3034) — the one
                          secondary that doubles as a dark-mode accent/text.
     Neutral ramp (PMS 429 + black tints; names mirror the brand doc labels)
       --capstone-gray-20  #d1d3d4 (Black 20%): 1.5:1 on white — dividers/
                          fills only, never text.
       --capstone-gray     #a2aaad (PMS 429): 2.36:1 on white — clears the
                          3:1 non-text bar for borders/icons; fails as text.
       --capstone-gray-50  #939598 (Black 50%): 3.0:1 on white — AA only for
                          large text (≥18pt / 14pt bold) and non-text UI;
                          fails for normal body copy. */
  --capstone-mint: #a5dfd3;
  --capstone-sky: #8bd3e6;
  --capstone-green-bright: #6cc24a;
  --capstone-gray-20: #d1d3d4;
  --capstone-gray: #a2aaad;
  --capstone-gray-50: #939598;
}

/* ── Apply display font to top-level headings only ─────────
   Fjalla One is a single-weight condensed display sans —
   beautiful at marquee sizes, awkward at h5/h6 dimensions
   where its tight tracking starts to read like a toolbar
   label rather than a section heading. Scope it to h1, h2,
   and the .display-* utilities; h3–h6 stay in Lato Bold so
   dense forms with sub-section labels don't get all-caps-
   condensed shouting on every nested header. Letter-spacing
   relaxed slightly because Fjalla One's intrinsic tracking
   is tighter than most UI text expects. */
h1, h2,
.h1, .h2,
.display-1, .display-2, .display-3,
.display-4, .display-5, .display-6 {
    font-family: var(--capstone-display-font-family);
    letter-spacing: 0.01em;
}

/* Dark theme tweaks */
[data-bs-theme=dark] {
    /* Brand primary matches the light-theme value so white-on-green buttons
       keep 6.09:1 contrast. The previous lighter shade (#0a8d64) only gave
       4.19:1 and failed WCAG AA on .btn-primary. */
    --bs-primary: #007055;
    --bs-primary-rgb: 0, 112, 85;
    /* Bootstrap 5.3's own dark-theme link defaults. The :root override
       (#0a58ca) is for light-theme tertiary-bg only — without this it
       leaks into dark mode and drops to 2.06:1 on #2c3034. Bootstrap's
       dark default #6ea8fe gives ~7.5:1 and clears WCAG AA. */
    --bs-link-color: #6ea8fe;
    --bs-link-color-rgb: 110, 168, 254;
    --bs-link-hover-color: #8bb9fe;
    --bs-link-hover-color-rgb: 139, 185, 254;
    --brand-primary-hover: color-mix(in oklab, var(--bs-primary), white 10%);
    --brand-primary-active: color-mix(in oklab, var(--bs-primary), white 16%);
    --brand-secondary-hover: color-mix(in oklab, var(--bs-secondary), white 10%);
    --brand-secondary-active: color-mix(in oklab, var(--bs-secondary), white 16%);
    --bs-border-color: rgba(255, 255, 255, 0.15);
    --bs-border-color-translucent: rgba(255, 255, 255, 0.1);
    --capstone-rule-color: #5cbc94;
    /* Dark half of the primary subtle ramp — text uses the .text-brand
       dark green (~6.5:1), bg/border are 80% / 40% shades of #007055. */
    --bs-primary-text-emphasis: #5cbc94;
    --bs-primary-bg-subtle: #001611;
    --bs-primary-border-subtle: #004333;
}

/* Ensure native date/time picker icons match the active Bootstrap theme */
[data-bs-theme=light] {
    /* ReSharper disable once CssNotResolved */
  color-scheme: light;
}
[data-bs-theme=dark] {
    /* ReSharper disable once CssNotResolved */
    color-scheme: dark;
}

/* ── Links use Bootstrap defaults ────────────────────────────
   A previous version of this file stripped text-decoration on
   every <a> and only restored it on hover. That was an aesthetic
   tweak ("inline links read as text until hovered") but it broke
   WCAG 1.4.1 — links inside body copy were distinguished from
   surrounding text by color alone, which the spec explicitly
   forbids when contrast with surrounding text is below 3:1.
   Bootstrap 5.3 already strips underlines on every structural
   link class designers actually want unstyled (.btn, .nav-link,
   .navbar-brand, .dropdown-item, .page-link, etc.), so the safe
   fix is to keep its default — underlined plain <a>, undecorated
   structural classes — and let consumers wrap collections of
   links in .link-list (below) when individual underlines would
   be redundant. */

/* ── Link-list container ─────────────────────────────────────
   When a container holds nothing but links (nav menus, sidebar
   resource lists, card link collections, footer column links),
   the surrounding context already makes interactivity obvious.
   WCAG 1.4.1 worries about distinguishing a link from non-link
   prose; that concern doesn't apply when every item is a link.
   GOV.UK, WebAIM, and U.S. Web Design System all allow this.
   Hover and keyboard focus restore the underline so users can
   confirm targeting; :focus-visible (not :focus) skips the mouse
   click case where the link is about to navigate away anyway. */
.link-list a {
    text-decoration: none;
}
.link-list a:hover,
.link-list a:focus-visible {
    text-decoration: underline;
}

/* ── Brand text utility ──────────────────────────────────────
   For SRU-green text (headings, labels, callouts). Do NOT use
   .text-primary for text — it's pinned to #007055 in both themes
   so white-on-green buttons keep 6.09:1, which means it fails
   WCAG AA as text on dark backgrounds (2.18:1 on #2c3034).
   .text-brand is split per theme using the same lighter green
   .btn-outline-primary already uses in dark mode:
   - Light: #007055 on #fff      → 6.09:1
   - Dark:  #5cbc94 on #2c3034   → ~6.5:1 */
.text-brand {
    color: #007055;
}
[data-bs-theme=dark] .text-brand {
    color: #5cbc94;
}

/* ── Form control focus ring ─────────────────────────────── */

.form-control:focus,
.form-select:focus {
    border-color: #007055;
    box-shadow: 0 0 0 0.25rem rgba(0, 112, 85, 0.25);
}

[data-bs-theme=dark] .form-control:focus,
[data-bs-theme=dark] .form-select:focus {
    border-color: #0a8d64;
    box-shadow: 0 0 0 0.25rem rgba(10, 141, 100, 0.25);
}

/* ── Checks, radios, switches ────────────────────────────────
   Stock Bootstrap hard-codes #0d6efd for the checked fill and the
   focus ring, so a ticked box was the one blue control on an
   otherwise green form. Checked stays #007055 in BOTH themes (the
   white glyph needs the 6.09:1 the buttons already rely on); the
   focus border/ring follow the text inputs' per-theme split.
   :indeterminate is scoped to checkboxes exactly as Bootstrap scopes
   it: per the HTML spec a RADIO also matches :indeterminate whenever
   no radio in its group is checked, so an unscoped rule filled every
   untouched radio group green as if it were already selected. */
.form-check-input:checked,
.form-check-input[type=checkbox]:indeterminate {
    background-color: var(--bs-primary);
    border-color: var(--bs-primary);
}

.form-check-input:focus {
    border-color: #007055;
    box-shadow: 0 0 0 0.25rem rgba(0, 112, 85, 0.25);
}

[data-bs-theme=dark] .form-check-input:focus {
    border-color: #0a8d64;
    box-shadow: 0 0 0 0.25rem rgba(10, 141, 100, 0.25);
}

/* The unchecked switch knob turns light blue on focus in stock
   Bootstrap — swap in the dark-theme brand green. Checked switches
   keep Bootstrap's white knob. */
.form-switch .form-check-input:focus {
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%235cbc94'/%3e%3c/svg%3e");
}

/* ── Autocomplete active item ────────────────────────────── */

.capstone-autocomplete-active {
    background-color: #007055 !important;
}

[data-bs-theme=dark] .capstone-autocomplete-active {
    background-color: #0a8d64 !important;
}

/* ── Button brand overrides ──────────────────────────────── */

.btn-primary {
  --bs-btn-color: #fff;
  --bs-btn-bg: var(--bs-primary);
  --bs-btn-border-color: var(--bs-primary);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--brand-primary-hover);
  --bs-btn-hover-border-color: var(--brand-primary-hover);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--brand-primary-active);
  --bs-btn-active-border-color: var(--brand-primary-active);
  --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
  --bs-btn-disabled-color: #fff;
  --bs-btn-disabled-bg: var(--bs-primary);
  --bs-btn-disabled-border-color: var(--bs-primary);
  --bs-btn-disabled-opacity: .65;
}

.btn-outline-primary {
  --bs-btn-color: var(--bs-primary);
  --bs-btn-border-color: var(--bs-primary);
  /* Bootstrap's disabled fallbacks are still #0d6efd — without these a
     disabled outline button turns blue in light mode. */
  --bs-btn-disabled-color: var(--bs-primary);
  --bs-btn-disabled-border-color: var(--bs-primary);
  --bs-btn-hover-color: #fff;
  --bs-btn-hover-bg: var(--brand-primary-hover);
  --bs-btn-hover-border-color: var(--brand-primary-hover);
  --bs-btn-active-color: #fff;
  --bs-btn-active-bg: var(--brand-primary-active);
  --bs-btn-active-border-color: var(--brand-primary-active);
  --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
}

.btn-secondary {
  --bs-btn-color: var(--brand-on-secondary);
  --bs-btn-bg: var(--bs-secondary);
  --bs-btn-border-color: var(--bs-secondary);
  --bs-btn-hover-color: var(--brand-on-secondary);
  --bs-btn-hover-bg: var(--brand-secondary-hover);
  --bs-btn-hover-border-color: var(--brand-secondary-hover);
  --bs-btn-active-color: var(--brand-on-secondary);
  --bs-btn-active-bg: var(--brand-secondary-active);
  --bs-btn-active-border-color: var(--brand-secondary-active);
  --bs-btn-focus-shadow-rgb: var(--bs-secondary-rgb);
}

/* Bootstrap's pastel-leaning .btn-outline-* defaults fail WCAG AA in light
   mode:
   - outline-warning: #ffc107 → 1.65:1 on #fff
   - outline-info:    #0dcaf0 → 1.95:1 on #fff
   - outline-success: #198754 → 4.86:1 on #fff (just passes) but 3.82:1
     on #e9ecef (--bs-secondary-bg, the grid toolbar bg)
   Use darker text-emphasis palettes in light mode. The dark-mode rules
   further down already handle the inverse problem against #212529. */
.btn-outline-warning {
    --bs-btn-color: #806000;
    --bs-btn-border-color: #806000;
    --bs-btn-disabled-color: #806000;
    --bs-btn-disabled-border-color: #806000;
}

[data-bs-theme=dark] .btn-outline-warning {
    --bs-btn-color: var(--bs-warning);
    --bs-btn-border-color: var(--bs-warning);
    --bs-btn-hover-bg: var(--bs-warning);
    --bs-btn-hover-border-color: var(--bs-warning);
    --bs-btn-active-bg: var(--bs-warning);
    --bs-btn-active-border-color: var(--bs-warning);
    --bs-btn-disabled-color: var(--bs-warning);
    --bs-btn-disabled-border-color: var(--bs-warning);
}

/* .text-warning as TEXT: the amber --bs-warning is 2.17:1 on #fff (2.06:1 on
   --bs-tertiary-bg), so "Session expired" headings and triangle icons failed
   axe in every app. Light theme uses the same dark amber as
   .btn-outline-warning (#806000: 5.85:1 on #fff, 5.55:1 tertiary, 4.93:1
   secondary); dark keeps #e8a317 (7.1:1 on body, 6.1:1 tertiary). Same shape
   as Bootstrap's own rule so --bs-text-opacity still works. */
.text-warning {
    color: RGBA(128, 96, 0, var(--bs-text-opacity, 1)) !important;
}

[data-bs-theme=dark] .text-warning {
    color: RGBA(var(--bs-warning-rgb), var(--bs-text-opacity, 1)) !important;
}

/* Solid warning / info: Bootstrap compiles these variants with literal
   #ffc107 / #0dcaf0, so re-point them at the tokens above. Hover/active
   darken the fill the same way the brand buttons do. */
.btn-warning {
    --bs-btn-color: #000;
    --bs-btn-bg: var(--bs-warning);
    --bs-btn-border-color: var(--bs-warning);
    --bs-btn-hover-color: #000;
    --bs-btn-hover-bg: color-mix(in oklab, var(--bs-warning), black 10%);
    --bs-btn-hover-border-color: color-mix(in oklab, var(--bs-warning), black 10%);
    --bs-btn-active-color: #000;
    --bs-btn-active-bg: color-mix(in oklab, var(--bs-warning), black 16%);
    --bs-btn-active-border-color: color-mix(in oklab, var(--bs-warning), black 16%);
    --bs-btn-focus-shadow-rgb: var(--bs-warning-rgb);
    --bs-btn-disabled-color: #000;
    --bs-btn-disabled-bg: var(--bs-warning);
    --bs-btn-disabled-border-color: var(--bs-warning);
}

.btn-info {
    --bs-btn-color: #000;
    --bs-btn-bg: var(--bs-info);
    --bs-btn-border-color: var(--bs-info);
    --bs-btn-hover-color: #000;
    --bs-btn-hover-bg: color-mix(in oklab, var(--bs-info), black 10%);
    --bs-btn-hover-border-color: color-mix(in oklab, var(--bs-info), black 10%);
    --bs-btn-active-color: #000;
    --bs-btn-active-bg: color-mix(in oklab, var(--bs-info), black 16%);
    --bs-btn-active-border-color: color-mix(in oklab, var(--bs-info), black 16%);
    --bs-btn-focus-shadow-rgb: var(--bs-info-rgb);
    --bs-btn-disabled-color: #000;
    --bs-btn-disabled-bg: var(--bs-info);
    --bs-btn-disabled-border-color: var(--bs-info);
}

.btn-outline-success {
    --bs-btn-color: #146c43;
    --bs-btn-border-color: #146c43;
    --bs-btn-hover-bg: #146c43;
    --bs-btn-hover-border-color: #146c43;
    --bs-btn-active-bg: #146c43;
    --bs-btn-active-border-color: #146c43;
    --bs-btn-disabled-color: #146c43;
    --bs-btn-disabled-border-color: #146c43;
    --bs-btn-focus-shadow-rgb: 20, 108, 67;
}

/* Stock #dc3545 is 4.53:1 on #fff but 4.3:1 on --bs-tertiary-bg (#f8f9fa)
   and 3.82:1 on --bs-secondary-bg, so a Remove button in a tertiary card
   or the grid toolbar failed axe color-contrast. #b02a37 (Bootstrap red-600)
   is 6.2:1 on tertiary; white text on the hover fill stays at 6.5:1. */
.btn-outline-danger {
    --bs-btn-color: #b02a37;
    --bs-btn-border-color: #b02a37;
    --bs-btn-hover-bg: #b02a37;
    --bs-btn-hover-border-color: #b02a37;
    --bs-btn-active-bg: #b02a37;
    --bs-btn-active-border-color: #b02a37;
    --bs-btn-disabled-color: #b02a37;
    --bs-btn-disabled-border-color: #b02a37;
    --bs-btn-focus-shadow-rgb: 176, 42, 55;
}

.btn-outline-info {
    --bs-btn-color: #087990;
    --bs-btn-border-color: #087990;
    --bs-btn-hover-bg: #087990;
    --bs-btn-hover-border-color: #087990;
    --bs-btn-active-bg: #087990;
    --bs-btn-active-border-color: #087990;
    --bs-btn-disabled-color: #087990;
    --bs-btn-disabled-border-color: #087990;
    --bs-btn-focus-shadow-rgb: 8, 121, 144;
}

/* Outline buttons in dark mode: Bootstrap's defaults (#198754 / #dc3545)
   and our --bs-primary (#007055) all fail WCAG AA contrast against the
   darker --bs-secondary-bg (#343a40) used by the grid toolbar (≈ 2.5:1).
   Swap to lighter equivalents that match Bootstrap's *-text-emphasis
   palette. */
[data-bs-theme=dark] .btn-outline-primary {
    /* #5cbc94 lands at 5:1 on the toolbar/footer --bs-secondary-bg
       (#343a40) so outline-primary buttons in the grid toolbar clear AA.
       Shared with .text-brand (dark) — see "Brand text utility" above. */
    --bs-btn-color: #5cbc94;
    --bs-btn-border-color: #5cbc94;
    --bs-btn-hover-color: #000;
    --bs-btn-hover-bg: #5cbc94;
    --bs-btn-hover-border-color: #5cbc94;
    --bs-btn-active-color: #000;
    --bs-btn-active-bg: #5cbc94;
    --bs-btn-active-border-color: #5cbc94;
    --bs-btn-disabled-color: #5cbc94;
    --bs-btn-disabled-border-color: #5cbc94;
}

[data-bs-theme=dark] .btn-outline-success {
    --bs-btn-color: #75b798;
    --bs-btn-border-color: #75b798;
    --bs-btn-hover-color: #000;
    --bs-btn-hover-bg: #75b798;
    --bs-btn-hover-border-color: #75b798;
    --bs-btn-active-color: #000;
    --bs-btn-active-bg: #75b798;
    --bs-btn-active-border-color: #75b798;
    --bs-btn-disabled-color: #75b798;
    --bs-btn-disabled-border-color: #75b798;
}

/* Bootstrap leaves .badge.bg-* with default white text, which fails WCAG AA
   on the lighter palette (.bg-warning #ffc107 → 1.63:1, .bg-info #0dcaf0,
   .bg-light #f8f9fa). Capstone's .bg-secondary (SRU yellow #f7d117) has
   the same problem (1.49:1). The static demo views work around it by
   adding .text-dark, but JS-rendered badges (grid renderCell) miss the
   helper. Force dark text on these so badges are readable regardless of
   caller. */
.badge.bg-warning,
.badge.bg-info,
.badge.bg-light,
.badge.bg-secondary {
    color: #000;
}

[data-bs-theme=dark] .btn-outline-info {
    --bs-btn-color: var(--bs-info);
    --bs-btn-border-color: var(--bs-info);
    --bs-btn-hover-bg: var(--bs-info);
    --bs-btn-hover-border-color: var(--bs-info);
    --bs-btn-active-bg: var(--bs-info);
    --bs-btn-active-border-color: var(--bs-info);
    --bs-btn-disabled-color: var(--bs-info);
    --bs-btn-disabled-border-color: var(--bs-info);
}

/* Bootstrap does not flip .btn-outline-dark for the dark theme, so the
   #212529 outline disappeared into the #212529 page. Mirror what
   .btn-outline-secondary does: swap to the light-theme values. */
[data-bs-theme=dark] .btn-outline-dark {
    --bs-btn-color: #f8f9fa;
    --bs-btn-border-color: #f8f9fa;
    --bs-btn-hover-color: #000;
    --bs-btn-hover-bg: #f8f9fa;
    --bs-btn-hover-border-color: #f8f9fa;
    --bs-btn-active-color: #000;
    --bs-btn-active-bg: #f8f9fa;
    --bs-btn-active-border-color: #f8f9fa;
    --bs-btn-disabled-color: #f8f9fa;
    --bs-btn-disabled-border-color: #f8f9fa;
}

/* ── Accordion ───────────────────────────────────────────────
   Open state colours come from the primary subtle ramp above (now green).
   The chevron and focus ring are compiled literals in Bootstrap, so they
   need their own overrides; the dark rule matches Bootstrap's own
   (0,2,1) selector and wins on source order. */
.accordion {
    --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(0, 112, 85, 0.25);
    --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23007055' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

[data-bs-theme=dark] .accordion-button::after {
    --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23dee2e6' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
    --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%235cbc94' stroke-linecap='round' stroke-linejoin='round'%3e%3cpath d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}

[data-bs-theme=dark] .btn-outline-danger {
    --bs-btn-color: #ea868f;
    --bs-btn-border-color: #ea868f;
    --bs-btn-hover-color: #000;
    --bs-btn-hover-bg: #ea868f;
    --bs-btn-hover-border-color: #ea868f;
    --bs-btn-active-color: #000;
    --bs-btn-active-bg: #ea868f;
    --bs-btn-active-border-color: #ea868f;
    --bs-btn-disabled-color: #ea868f;
    --bs-btn-disabled-border-color: #ea868f;
}

/* Bootstrap's .btn-outline-secondary (#6c757d) fails AA on the toolbar
   --bs-secondary-bg in both themes: 2.45:1 on dark (#343a40), 3.9:1 on
   light (#e9ecef). Darken/lighten per theme like the variants above. */
.btn-outline-secondary {
    --bs-btn-color: #495057;
    --bs-btn-border-color: #495057;
    --bs-btn-hover-bg: #495057;
    --bs-btn-hover-border-color: #495057;
    --bs-btn-active-bg: #495057;
    --bs-btn-active-border-color: #495057;
    --bs-btn-disabled-color: #495057;
    --bs-btn-disabled-border-color: #495057;
    --bs-btn-focus-shadow-rgb: 73, 80, 87;
}

[data-bs-theme=dark] .btn-outline-secondary {
    --bs-btn-color: #adb5bd;
    --bs-btn-border-color: #adb5bd;
    --bs-btn-hover-color: #000;
    --bs-btn-hover-bg: #adb5bd;
    --bs-btn-hover-border-color: #adb5bd;
    --bs-btn-active-color: #000;
    --bs-btn-active-bg: #adb5bd;
    --bs-btn-active-border-color: #adb5bd;
    --bs-btn-disabled-color: #adb5bd;
    --bs-btn-disabled-border-color: #adb5bd;
}

/* ── Nav tabs & pills brand overrides ────────────────────── */

.nav-tabs .nav-link.active,
.nav-tabs .nav-link.active:hover,
.nav-tabs .nav-link.active:focus {
  background-color: var(--bs-primary);
  color: #fff;
  border-color: var(--bs-primary);
}

.nav-tabs .nav-link:not(.active):hover {
  color: var(--bs-primary);
  border-color: transparent;
  /* ReSharper disable once CssNotResolved */
  /* ReSharper disable once InvalidValue */
  background-color: color-mix(in srgb, var(--bs-primary) 8%, transparent);
}

.nav-pills .nav-link.active,
.nav-pills .nav-link.active:hover,
.nav-pills .nav-link.active:focus {
  background-color: var(--bs-primary);
  color: #fff;
}

.nav-pills .nav-link:not(.active):hover {
  color: var(--bs-primary);
  /* ReSharper disable once CssNotResolved */
  /* ReSharper disable once InvalidValue */
  background-color: color-mix(in srgb, var(--bs-primary) 8%, transparent);
}

.nav-pills .nav-link:not(.active) {
    /* ReSharper disable once CssNotResolved */
  color: var(--bs-body-color);
}

/* ── Nav tabs/pills disabled state during loading ────────── */

.nav-loading {
  pointer-events: none;
  opacity: 0.5;
  transition: opacity 0.2s ease;
}

.nav-loading .nav-link {
  cursor: not-allowed;
}

/* ── Dropdown brand hover ────────────────────────────────── */

.dropdown-item:focus,
.dropdown-item:hover {
    /* ReSharper disable once CssNotResolved */
    color: var(--bs-body-color) !important;
    /* ReSharper disable once CssNotResolved */
    /* ReSharper disable once InvalidValue */
    background-color: color-mix(in srgb, var(--bs-primary) 8%, transparent) !important;
}

[data-bs-theme=dark] .dropdown-item:focus,
[data-bs-theme=dark] .dropdown-item:hover {
    /* ReSharper disable once CssNotResolved */
    /* ReSharper disable once InvalidValue */
    background-color: color-mix(in srgb, var(--bs-primary) 20%, transparent) !important;
}

/* ── Dark mode enhancements ──────────────────────────────── */

[data-bs-theme=dark] .card {
    /* ReSharper disable once RequiresFallbackColor */
    /* ReSharper disable once Redundant */
    --bs-card-bg: rgba(255, 255, 255, 0.05);
    /* ReSharper disable once RequiresFallbackColor */
    /* ReSharper disable once Redundant */
    --bs-card-border-color: var(--bs-border-color);
}

[data-bs-theme=dark] .shadow,
[data-bs-theme=dark] .shadow-sm {
    /* ReSharper disable once RequiresFallbackColor */
    box-shadow: 0 0.125rem 0.5rem rgba(0, 0, 0, 0.5) !important;
}

[data-bs-theme=dark] .navbar-dark {
    /* ReSharper disable once RequiresFallbackColor */
    /* ReSharper disable once Redundant */
    --bs-navbar-color: rgba(255, 255, 255, 0.85);
    /* ReSharper disable once RequiresFallbackColor */
    /* ReSharper disable once Redundant */
    --bs-navbar-hover-color: rgba(255, 255, 255, 1);
    /* ReSharper disable once RequiresFallbackColor */
    /* ReSharper disable once Redundant */
    --bs-navbar-brand-color: rgba(255, 255, 255, 0.9);
}

/* Force navbar dropdowns to float above content on all screen sizes */
.navbar .dropdown-menu {
  position: absolute;
}

/* ── Portal card ─────────────────────────────────────────── */

/* A content container, not a control — so no hover lift. The previous
   translateY/shadow/green-border hover promised a click that did nothing
   (the card isn't a link); the lift now belongs only to the index card,
   whose whole surface IS the link. */
.portalCards {
  border: 1px solid var(--bs-border-color);
}

/* Card titles are pinned to Lato bold whatever heading level the consumer
   picks: the level is a screen-reader/outline choice and must not change
   the look (an h2 got Fjalla One, an h3 got Lato — same card, two faces).
   Fjalla One at 16px in a green bar is also the "condensed display at label
   size" that the section-title rule avoids for the same reason. */
.portal-card-header {
  background-color: var(--bs-primary);
  color: #fff;
  border-radius: 0.375rem;
  padding: 0.5rem 1rem;
  margin: -0.5rem -0.5rem 0.75rem -0.5rem;
  font-family: var(--bs-body-font-family);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0;
  line-height: 1.5;
  /* Long titles wrap inside the bar instead of overflowing it. */
  overflow-wrap: anywhere;
}

.portalCards.p-3 > .portal-card-header:first-child {
  margin: -1rem -1rem 0.75rem -1rem;
  border-radius: 0.375rem 0.375rem 0 0;
}

.portal-card-title {
  font-family: var(--bs-body-font-family);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0;
  line-height: 1.5;
  margin: 0 0 0.5rem;
}

/* No .portalCards a rule on purpose. A previous version stripped
   text-decoration on every anchor inside .portalCards, which silently
   broke WCAG 1.4.1 for any inline prose link a consumer dropped into a
   card. Card-internal link collections opt out via .link-list (above);
   inline prose anchors keep Bootstrap's underline default. */

/* ── Index card (menu / dashboard pages) ─────────────────── */

.capstone-index-card {
    border: 1px solid var(--bs-border-color);
    /* ReSharper disable once CssNotResolved */
    /* ReSharper disable once ValueShouldHaveUnits */
    /* ReSharper disable once RequiresFallbackColor */
    box-shadow: 0 0.125rem 0.25rem rgba(var(--bs-body-color-rgb), 0.075);
    transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out;
    will-change: transform;
    position: relative;
}

    /* The whole card is the link (the button carries .stretched-link), so the
       lift is an honest affordance. :focus-within gives keyboard users the
       same cue when the button takes focus. */
    .capstone-index-card:hover,
    .capstone-index-card:focus-within {
        transform: translateY(-5px);
        /* ReSharper disable once CssNotResolved */
        /* ReSharper disable once ValueShouldHaveUnits */
        /* ReSharper disable once RequiresFallbackColor */
        box-shadow: 0 0.5rem 1rem rgba(var(--bs-body-color-rgb), 0.15);
        border-color: var(--bs-primary);
    }

@media (prefers-reduced-motion: reduce) {
    .capstone-index-card {
        transition: box-shadow 0.2s ease-in-out, border-color 0.2s ease-in-out;
    }

    .capstone-index-card:hover,
    .capstone-index-card:focus-within {
        transform: none;
    }
}

.capstone-index-card .card-body {
  padding: 2rem;
}

/* Same pinning as the portal card: the title face doesn't follow heading level. */
.capstone-index-card .card-title {
  font-family: var(--bs-body-font-family);
  font-weight: 700;
  letter-spacing: 0;
}

.capstone-index-card .btn {
  min-width: 120px;
}

/* ── Index list item hover affordance ─────────────────────
   Mirrors the .um-item:hover pattern in the user menu —
   subtle bg shift (handled by Bootstrap's
   .list-group-item-action :hover) plus a brand-green
   vertical bar that fades in along the left edge.
   Implemented as a pseudo-element rather than swapping the
   list-group's border-left so Bootstrap's first/last-child
   rounded corners and internal border-collapse rules stay
   untouched — no layout shift, no fight with the cascade.
   Honoured on :focus-visible too so keyboard users get the
   same affordance, not just mouse users. */
.capstone-index-list .list-group-item-action {
    position: relative;
}

.capstone-index-list .list-group-item-action::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background-color: var(--bs-primary);
    opacity: 0;
    transition: opacity 0.12s ease;
    pointer-events: none;
    /* Inherit the list-group-item's left rounding so the bar matches
       the rounded top-left / bottom-left corners on first/last items.
       Without this, the bar squares off against a rounded container. */
    border-top-left-radius: inherit;
    border-bottom-left-radius: inherit;
}

.capstone-index-list .list-group-item-action:hover::before,
.capstone-index-list .list-group-item-action:focus-visible::before,
.capstone-index-list .list-group-item-action.active::before {
    opacity: 1;
}

[data-bs-theme=dark] .capstone-index-list .list-group-item-action::before {
    /* --bs-primary (#007055) at 3px on the dark list-group bg reads as
       a near-black stripe (~2.2:1 luminance gap). Use the lighter
       brand green .text-brand uses in dark mode so the affordance
       remains visible without compromising the bar's brand identity. */
    background-color: #5cbc94;
}

/* Respect reduced-motion: keep the color cue (the bar still appears),
   skip the fade so the transition feels instant rather than crossfading
   through a half-visible state. Matches the rest of the library's
   reduced-motion contract. */
@media (prefers-reduced-motion: reduce) {
    .capstone-index-list .list-group-item-action::before {
        transition: none;
    }
}

/* ── Non-production navbar accent ────────────────────────── */

.navbar-preprod {
  border-bottom: 3px solid #e8a317 !important;
}

/* ── Content fade-in ────────────────────────────────────── */

main {
  animation: capstone-fade-in 0.3s ease-in;
}

@keyframes capstone-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  main {
    animation: none;
  }
}

/* ── Test environment banner ─────────────────────────────── */

.test-environment-banner {
  background-color: #e8a317;
  color: #000;
  text-align: center;
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.05em;
  padding: 0.35rem 0;
  position: sticky;
  top: 0;
  z-index: 1050;
}

/* ── Offcanvas menu heading sizes ───────────────────────── */
/* Real heading levels for screen-reader hierarchy; visual styling kept compact
   so the menu doesn't look like a content page. */

.offcanvas-section-title {
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.25;
  margin: 0 0 0.25rem;
}

.offcanvas-group-title {
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.25;
  margin: 0 0 0.25rem;
}

/* ── Brand gradient ribbon ────────────────────────────────
   Reusable thin SRU green→gold sweep — same source as the
   page-title accent and the navbar bottom stripe so the
   brand motif reads as one design language across the page.
   Drop on an <hr class="capstone-brand-rule"> to split
   sections, or apply to any element that should carry the
   brand bar. Uses the gradient variable so a one-line change
   propagates everywhere. */
.capstone-brand-rule {
    border: 0;
    height: 3px;
    background: var(--capstone-brand-gradient);
    border-radius: 999px;
    margin: 0;
    opacity: 1;
}

/* ── In-page section rule + title ────────────────────────
   Quiet within-page section boundary used by
   <capstone-section-separator /> and <capstone-section-header>.
   Solid SRU green at 1px keeps it visually distinct from the
   green→gold ribbon (.capstone-brand-rule), which is reserved
   for page-level brackets at the navbar and footer. The
   visual hierarchy reads as:
     page brackets  → gradient (loud, the brand statement)
     section rules  → solid green (quiet, navigational signal)
   Opacity:1 overrides Bootstrap's reboot which dims <hr> to
   0.25 by default. */
.capstone-section-rule {
    margin: 0.5rem 0;
    border: 0;
    border-top: 1px solid var(--capstone-rule-color);
    opacity: 1;
}

/* The section-header helper emits a real heading element (h2
   by default) so screen readers announce the boundary. We
   force Lato Bold and a fixed size so:
   1) Fjalla One stays a marquee face — section labels in a
      dense form don't read as condensed-display shouting.
   2) The heading-level attribute can change for screen-reader
      semantics (h3 when nested under an h2 etc.) without
      shifting the visual rhythm. */
.capstone-section-title {
    font-family: var(--bs-body-font-family);
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.3;
    letter-spacing: 0;
    color: var(--bs-primary);
    margin: 0 0 0.75rem;
}

[data-bs-theme=dark] .capstone-section-title {
    /* --bs-primary (#007055) on the dark card bg (#2c3034) is only
       2.18:1 — fails AA for text. Use the same lighter green
       .text-brand uses for dark mode (~6.5:1 on #212529). */
    color: #5cbc94;
}

/* ── Primary navbar bottom stripe ─────────────────────────
   Pseudo-element rather than a real border so the existing
   .border-bottom utility class stays in place (preserves
   Bootstrap's intrinsic spacing and the .navbar-preprod
   amber bottom-border in non-prod environments). In prod
   the gradient bar reads as the primary navbar separator;
   in non-prod the .navbar-preprod rule below suppresses it
   so the amber "you are not in production" signal stays
   the dominant indicator. */
nav.capstone-navbar {
    position: relative;
}

nav.capstone-navbar::after {
    content: '';
    position: absolute;
    bottom: -1px;
    left: 0;
    right: 0;
    height: 3px;
    background: var(--capstone-brand-gradient);
    pointer-events: none;
}

nav.capstone-navbar.navbar-preprod::after {
    /* The amber bottom-border already signals "not production" —
       layering the brand stripe under it would dilute the message
       and produce a double-line. */
    display: none;
}

/* ── Alternate navbar border ─────────────────────────────── */

.altNavBar {
  /* Brand gradient on both top and bottom edges via border-image —
     replaces the previous solid green so the alternate header reads
     as the brand-anchored variant. border-image-slice: 1 splits the
     horizontal gradient correctly across the top and bottom edges;
     left/right borders aren't set, so no rotated/cropped slices. */
  border-top: 4px solid var(--bs-primary);
  border-bottom: 4px solid var(--bs-primary);
  border-image-source: var(--capstone-brand-gradient);
  border-image-slice: 1;
}

/* ── Enterprise Services alert color ─────────────────────── */

.alert-enterpriseServices {
  color: #fff;
  background-color: var(--bs-primary);
  border-color: var(--bs-primary);
}

/* ── Utility classes ─────────────────────────────────────── */

.border-alt {
  border-color: var(--bs-secondary) !important;
}

.hidden {
  display: none;
}

.visible {
  display: block;
}

/* ── Touch targets (WCAG 2.5.8 AA / 2.5.5) ─────────────────
   On touch-first devices (pointer: coarse) regular buttons grow to a
   44px minimum. The height comes from padding, not min-height, so the
   label stays vertically centred in Bootstrap's inline-block .btn:
   (44px − one line − both borders) / 2, never below the variant's own
   padding. Exempt:
   - .btn-sm: 31px already clears the 24px AA minimum, and it's what dense
     UI uses (grid commands/toolbars, rich-text toolbar, picker actions).
   - .input-group > .btn: must stay level with its input.
   - .btn-compact: explicit opt-out for any other dense layout.
   Mouse/trackpad layouts are untouched. */
@media (pointer: coarse) {
    .btn:not(.btn-sm, .btn-compact, .input-group > .btn) {
        padding-top: max(var(--bs-btn-padding-y), calc((44px - var(--bs-btn-line-height) * 1em - 2 * var(--bs-btn-border-width)) / 2));
        padding-bottom: max(var(--bs-btn-padding-y), calc((44px - var(--bs-btn-line-height) * 1em - 2 * var(--bs-btn-border-width)) / 2));
    }
}

/* Checkboxes, radios and switches: Bootstrap's 1em (16px) box is below the
   24px minimum. On coarse pointers — and anywhere via .form-check-lg — the
   box is 1.5em (24px at body size), top-aligned with the label's 1.5
   line-height, with the gutter and pull-back margin scaled to match.
   Grid selection checkboxes keep the stock size so rows don't grow. */
@media (pointer: coarse) {
    .form-check:not(.capstone-grid .form-check) {
        --capstone-check-size: 1.5em;
    }
}

.form-check-lg {
    --capstone-check-size: 1.5em;
}

/* Unset --capstone-check-size falls back to Bootstrap's stock geometry
   (1em box, 1.5em gutter, 0.25em top offset; switch 2em × 1em). */
.form-check .form-check-input {
    width: var(--capstone-check-size, 1em);
    height: var(--capstone-check-size, 1em);
    margin-top: calc((1.5em - var(--capstone-check-size, 1em)) / 2);
}

.form-check:not(.form-switch, .form-check-reverse) {
    padding-left: calc(var(--capstone-check-size, 1em) + 0.5em);
}

.form-check:not(.form-switch, .form-check-reverse) .form-check-input {
    margin-left: calc(-1 * (var(--capstone-check-size, 1em) + 0.5em));
}

.form-switch {
    padding-left: calc(var(--capstone-check-size, 1em) * 2 + 0.5em);
}

.form-switch .form-check-input {
    width: calc(var(--capstone-check-size, 1em) * 2);
    margin-left: calc(-1 * (var(--capstone-check-size, 1em) * 2 + 0.5em));
}
