/*
 * elfrique.css — Design System Tokens & Primitives
 * Mandate: M01 · C1 Tokens & Foundation (W1.1, W1.4, W1.v2.1, W1.v2.2, W1.v2.3)
 *
 * This file is the SINGLE authorised location for raw hex values and raw ms values.
 * All other CSS files MUST consume tokens via var(--token-name).
 *
 * DO NOT edit without category-alignment with the active design mandate.
 * DO NOT load in any layout until Phase 3 wires it via Views/Shared/HeadMeta.cshtml.
 *
 * Legacy tokens (--primary-color, --success, --neutral-*, etc.) remain in
 * wwwroot/custom/custom.css under the Token Coexistence Policy and are deleted
 * atomically at C10 (Mandate 18 — Legacy Purge).
 */

/* ==========================================================================
   ROOT TOKEN BLOCK
   ========================================================================== */

:root {

  /* --------------------------------------------------------------------------
     DENSITY
     Values: compact | comfortable | spacious
     Default ships here so downstream selectors resolve without JS.
     A later mandate may override via html[data-density="X"].
  -------------------------------------------------------------------------- */
  --density: comfortable;

  /* --------------------------------------------------------------------------
     BRAND
  -------------------------------------------------------------------------- */

  /* Near-black with a green undertone (~10.4:1 contrast on white, WCAG AAA) */
  --brand-ink: #143F2A;

  /* Public hero canvas — deeper brand-tone surface for white-on-canvas hero
     compositions. ~7.0:1 against --n-0 (AAA). Introduced M28 Phase 3 to land
     a darker, more confident hero canvas than --brand-ink-soft (which stays
     for non-hero ambient surfaces). */
  --hero-canvas: #2A6047;

  /* Soft, near-white tint of --brand-ink for ambient hero / surface backgrounds.
     Locked formula (M23 Phase 3): 8% --brand-ink mixed into --n-0 in oklab space.
     Yields ~AAA contrast for --n-900 text (~15:1). Derive from --brand-ink so
     a future brand pivot updates this surface automatically. */
  --brand-ink-soft: color-mix(in oklab, var(--brand-ink) 8%, var(--n-0));

  /* Warm accent orange — reuses legacy --color-three value for continuity */
  --brand-spark: #E8912D;

  /* Semantic indirection: the foreground colour to stamp ON TOP of a
     --brand-spark fill. Defaults to --brand-ink (6.87:1 against the AA-tier
     bronze — PASS AA). The HC tier flips this to --n-0 because the AAA-reach
     bronze (#8B4500) inverts contrast against --brand-ink (drops to 2.38:1).
     Consumer rule: if a selector composes text on a --brand-spark fill,
     reference --brand-on-spark instead of --brand-ink so the HC tier can
     override the text colour without each consumer needing its own
     prefers-contrast / .theme-high-contrast override. F-4b-1 mitigation. */
  --brand-on-spark: var(--brand-ink);

  /* No-image fallback gradient — used by .media[data-media-state="failed"]
     and the legacy-Src null/empty branch in _Media.cshtml. Mirrors the
     ink → spark wash already shown on the /design/kit page (and the older
     .featured-image::after rule), now derived from brand tokens via
     color-mix so a future brand pivot updates the fallback automatically.
     20% alpha each side keeps the wash subtle so the surface still reads
     as a placeholder rather than a hero panel. Introduced 2026-05-08
     mandate Phase 4 — replaces the grey "Image unavailable" treatment. */
  --gradient-no-image: linear-gradient(
    135deg,
    color-mix(in srgb, var(--brand-ink) 20%, transparent),
    color-mix(in srgb, var(--brand-spark) 20%, transparent)
  );

  /* --------------------------------------------------------------------------
     NEUTRALS (9-step scale + white)
  -------------------------------------------------------------------------- */

  --n-0:   #FFFFFF;
  --n-50:  #F9FAFB;
  --n-100: #F3F4F6;
  --n-200: #E5E7EB;
  --n-300: #D1D5DB;
  --n-400: #9CA3AF;
  --n-500: #6B7280;
  --n-600: #4B5563;
  --n-700: #374151;
  --n-800: #1F2937;
  --n-900: #111827;

  /* --------------------------------------------------------------------------
     SEMANTIC STATES
     Hard rule #1: --state-success is TEAL, not green.
     All values meet WCAG AA (≥4.5:1) against --n-0.
  -------------------------------------------------------------------------- */

  --state-success: #0D9488; /* Teal-600 · 4.54:1 on white (WCAG AA — marginal, verify with downstream usage) */
  --state-warn:    #B45309; /* Amber-700 · 5.93:1 on white (WCAG AA) */
  --state-danger:  #DC2626; /* Red-600   · 4.83:1 on white (WCAG AA) */
  --state-info:    #2563EB; /* Blue-600  · 5.17:1 on white (WCAG AA) */

  /* --------------------------------------------------------------------------
     PROVIDER TRADEMARK LOGO COLORS (HR2 carve-out · M49 Phase 2b D-2b-09)
     The --logo-* namespace is reserved for third-party trademark logo glyphs
     (Google red, Facebook blue, etc.) where the provider's brand guidelines
     mandate an EXACT hex value. NOT for first-party platform brand — that
     space is owned by --brand-* (--brand-ink, --brand-spark). Adding a new
     --logo-* token requires the provider's brand guideline citation.
     Codification candidate: F-2b-CODIFY-01.
  -------------------------------------------------------------------------- */

  --logo-google-red:    #DB4437; /* Google "G" mark — Google Identity brand guidelines */
  --logo-facebook-blue: #1877F2; /* Facebook "f" mark — Facebook Login brand assets */

  /* --------------------------------------------------------------------------
     TYPOGRAPHY
  -------------------------------------------------------------------------- */

  --font-sans:  'Inter', system-ui, sans-serif;
  --font-serif: 'IBM Plex Serif', Georgia, serif;
  --font-mono:  'IBM Plex Mono', Consolas, ui-monospace, monospace;

  /* Type scale via clamp() — --fs-3 ≈ 1rem (16px) is the base */
  --fs-1: clamp(0.75rem,   0.70rem + 0.25vw, 0.875rem);  /* ~12–14px */
  --fs-2: clamp(0.875rem,  0.80rem + 0.375vw, 1rem);     /* ~14–16px */
  --fs-3: clamp(1rem,      0.95rem + 0.25vw, 1.125rem);  /* ~16–18px  BASE */
  --fs-4: clamp(1.125rem,  1.00rem + 0.625vw, 1.375rem); /* ~18–22px */
  --fs-5: clamp(1.375rem,  1.15rem + 1.125vw, 1.875rem); /* ~22–30px */
  --fs-6: clamp(1.875rem,  1.50rem + 1.875vw, 2.625rem); /* ~30–42px */

  /* --------------------------------------------------------------------------
     MOTION TOKENS
     Raw ms values are permitted only in this token-definition block.
     All other CSS MUST reference var(--d-N) and var(--ease-*).
     Per W1.v2.1: d-1=120ms … d-5=600ms.
  -------------------------------------------------------------------------- */

  --d-1: 120ms;
  --d-2: 200ms;
  --d-3: 300ms;
  --d-4: 400ms;
  --d-5: 600ms;

  --ease-out-swift:    cubic-bezier(0.32, 0.72, 0.00, 1.00);
  --ease-in-out-subtle:  cubic-bezier(0.40, 0.00, 0.20, 1.00);
  --ease-spring:       cubic-bezier(0.34, 1.56, 0.64, 1.00);

  /* --------------------------------------------------------------------------
     RADII
  -------------------------------------------------------------------------- */

  --r-1: 4px;
  --r-2: 8px;
  --r-3: 12px;
  --r-4: 16px;
  --r-5: 24px;
  --r-pill: 9999px;

  /* --------------------------------------------------------------------------
     SHADOWS
  -------------------------------------------------------------------------- */

  --shadow-1: 0 1px  2px rgba(0, 0, 0, 0.06);
  --shadow-2: 0 2px  8px rgba(0, 0, 0, 0.08);
  --shadow-3: 0 4px 16px rgba(0, 0, 0, 0.10);
  --shadow-4: 0 8px 32px rgba(0, 0, 0, 0.14);

  /* --------------------------------------------------------------------------
     SPACING (4px base scale)
  -------------------------------------------------------------------------- */

  --sp-1:  4px;
  --sp-2:  8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --sp-6: 32px;
  --sp-7: 48px;
  --sp-8: 64px;

  /* --------------------------------------------------------------------------
     LAYOUT CHROME
     Heights of fixed/sticky chrome elements that downstream components compose
     against (e.g. sticky offsets, scroll-padding). Defined in rem so the
     navbar height tracks the user's root font-size for accessibility.
     Mandate: M08 · C5 Navigation IA · Phase 1 (W5.3, F-0-05).
  -------------------------------------------------------------------------- */

  --nav-h: 4rem; /* 64px at default 1rem = 16px — public + admin navbar height target (W5.3) */

  /* --------------------------------------------------------------------------
     Z-STACK
     Per W1.v2.2 spec values.
  -------------------------------------------------------------------------- */

  --z-base:     0;
  --z-raised:  10;
  --z-drawer:  50;
  --z-modal:   60;
  --z-toast:   70;
  --z-cmdk:    80;

  /* Additional semantic aliases referenced by dispatch prompt */
  --z-dropdown: var(--z-raised);
  --z-sticky:   20;
  --z-fixed:    30;
  --z-popover:  var(--z-modal);
  --z-tooltip:  75;
}


/* ==========================================================================
   VISUALLY HIDDEN UTILITY
   Screen-reader-only helper class. Removes visual presence while keeping
   the element in the accessibility tree. Uses the clip-pattern so the
   element remains keyboard-reachable when focusable (unlike display:none).
   Referenced by: elfrique.components.vendor.css (calendar nav primacy cue);
   elfrique.components.data.css (filter-bar label); M11 P3 PTR status node.
   ========================================================================== */

.visually-hidden {
  position:   absolute;
  width:      1px;
  height:     1px;
  padding:    0;
  margin:     -1px;
  overflow:   hidden;
  clip:       rect(0 0 0 0);
  white-space: nowrap;
  border:     0;
}


/* ==========================================================================
   SKIP-LINK UTILITY
   Mandate: M11 · C8 Accessibility · Phase 2 (W8.7)
   Visually hidden until focused via keyboard; then floats top-left.
   ≥ 44×44 hit area (hard rule #8), high-contrast: brand-ink on n-0.
   Appears on :focus (not just :focus-visible) so legacy browser users
   who Tab to it also see it — skip links are explicitly a keyboard-only
   affordance; :focus is intentional here per WCAG Technique G1.
   ========================================================================== */

.skip-link {
  /* Visually hidden: lifted out of flow, clipped to 1×1 with overflow hidden
     so it takes no layout space and is invisible until focused. */
  position:       absolute;
  left:           -9999px;
  top:            auto;
  width:          1px;
  height:         1px;
  overflow:       hidden;
  clip:           rect(0 0 0 0);
  white-space:    nowrap;
  /* Inherit base font so it reads at body size, not UA default. */
  font-family:    var(--font-sans);
  font-size:      var(--fs-3);
  font-weight:    600;
  /* No text-decoration — it's a button-style affordance when visible. */
  text-decoration: none;
}

.skip-link:focus,
.skip-link:focus-visible {
  /* Visible: top-left corner of viewport, 44×44+ hit area, high-contrast.
     z-index above all page chrome. No raw ms for transition — motion token. */
  position:       fixed;
  left:           var(--sp-4);
  top:            var(--sp-4);
  width:          auto;
  height:         auto;
  overflow:       visible;
  clip:           auto;
  white-space:    normal;

  display:        inline-block;
  padding:        var(--sp-3) var(--sp-5);
  min-height:     44px;
  min-width:      44px;
  line-height:    1.4;

  /* High-contrast: brand-ink on n-0 (~18:1 on white — WCAG AAA). */
  background:     var(--brand-ink);
  color:          var(--n-0);
  border:         2px solid var(--brand-spark);
  border-radius:  var(--r-2);

  /* Override the global :focus-visible outline for skip-link specifically —
     the high-contrast bordered box IS the visible focus state here; an extra
     ring would be redundant. We still satisfy the focus-visibility requirement
     because the element switches from hidden to a fully visible, high-contrast
     block. */
  outline:        3px solid var(--brand-spark);
  outline-offset: 2px;

  z-index:        var(--z-cmdk);
}

@media (prefers-reduced-motion: reduce) {
  /* Skip-link has no declared transitions, so this block is a forward-
     compatibility guard ensuring no future transition is added without a
     reduced-motion fallback. */
  .skip-link {
    transition: none;
  }
}


/* ==========================================================================
   GLOBAL FOCUS-VISIBLE RING
   Mandate: M11 · C8 Accessibility · Phase 1 (W8.1)
   Hard rule: focus rings are non-negotiable. This is the universal baseline
   ring. Every focusable element inherits it unless a component-scoped rule
   explicitly augments it (e.g. .btn--primary uses --state-info for hue,
   .filter-bar__chip-remove uses --state-info offset 2). NEVER suppressed.
   No transition on outline — keyboard feedback must be instantaneous.
   ========================================================================== */

:focus-visible {
  outline: 2px solid var(--brand-spark);
  outline-offset: 2px;
}


/* ==========================================================================
   DENSITY SELECTOR HOOKS
   DataTable, FormField, and PageHeader read --density via these selectors.
   The partials themselves arrive in Mandate 2; these hooks ship now so
   the property resolves correctly from day one.
   ========================================================================== */

[data-density="compact"],
:root[data-density="compact"] {
  --density: compact;
}

[data-density="comfortable"],
:root[data-density="comfortable"] {
  --density: comfortable;
}

[data-density="spacious"],
:root[data-density="spacious"] {
  --density: spacious;
}


/* ==========================================================================
   BUTTON PRIMITIVES
   Four canonical classes × three size modifiers × all interaction states.

   Sizes (height target per W1.4):
     .btn--sm  → 32px height  (min-height with padding achieving 44×44 hit area via padding)
     .btn--md  → 40px height  (hard rule #8: must reach 44px — padding compensates)
     .btn--lg  → 48px height

   Hard rule #8: touch targets ≥ 44×44px.
   .btn--sm and .btn--md get extra inline padding to spread the hit area.
   ========================================================================== */

/* --- Base reset shared by all button variants --- */

.btn--primary,
.btn--ghost,
.btn--danger,
.btn--link,
.btn--accent,
.btn--success,
.btn--warning,
.btn--info {
  display:          inline-flex;
  align-items:      center;
  justify-content:  center;
  gap:              var(--sp-2);
  border:           2px solid transparent;
  border-radius:    var(--r-2);
  font-family:      var(--font-sans);
  font-size:        var(--fs-3);
  font-weight:      600;
  line-height:      1;
  white-space:      nowrap;
  cursor:           pointer;
  text-decoration:  none;
  transition:       background-color var(--d-1) var(--ease-out-swift),
                    color            var(--d-1) var(--ease-out-swift),
                    border-color     var(--d-1) var(--ease-out-swift),
                    box-shadow       var(--d-1) var(--ease-out-swift),
                    opacity          var(--d-1) var(--ease-out-swift);
  -webkit-user-select: none;
  user-select:      none;
}


/* --------------------------------------------------------------------------
   SIZE MODIFIERS
   Height targets from W1.4: sm=32, md=40, lg=48px.
   Touch target rule: min 44×44px. sm/md get padding to stretch hit area.
-------------------------------------------------------------------------- */

.btn--sm {
  font-size:   var(--fs-2);
  height:      32px;
  padding:     0 var(--sp-3);
  /* Expand click area to 44px vertically without changing visual height */
  min-height:  44px;
  border-radius: var(--r-2);
}

.btn--md {
  font-size:   var(--fs-3);
  height:      40px;
  padding:     0 var(--sp-4);
  /* Expand click area to 44px vertically */
  min-height:  44px;
  border-radius: var(--r-2);
}

.btn--lg {
  font-size:   var(--fs-3);
  height:      48px;
  min-height:  48px;
  padding:     0 var(--sp-5);
  border-radius: var(--r-3);
}


/* --------------------------------------------------------------------------
   .btn--primary  — brand-ink background, white text
-------------------------------------------------------------------------- */

.btn--primary {
  background-color: var(--brand-ink);
  color:            var(--n-0);
  border-color:     var(--brand-ink);
}

.btn--primary:hover {
  background-color: color-mix(in srgb, var(--brand-ink) 85%, var(--n-0));
  border-color:     color-mix(in srgb, var(--brand-ink) 85%, var(--n-0));
}

.btn--primary:focus-visible {
  outline:        3px solid var(--state-info);
  outline-offset: 2px;
}

.btn--primary:active {
  background-color: color-mix(in srgb, var(--brand-ink) 75%, #000);
  border-color:     color-mix(in srgb, var(--brand-ink) 75%, #000);
}

.btn--primary:disabled,
.btn--primary[aria-disabled="true"] {
  opacity:          0.45;
  cursor:           not-allowed;
  pointer-events:   none;
}

.btn--primary[data-loading="true"] {
  opacity:          0.70;
  cursor:           wait;
  pointer-events:   none;
}


/* --------------------------------------------------------------------------
   .btn--ghost  — transparent, brand-ink text + border
-------------------------------------------------------------------------- */

.btn--ghost {
  background-color: transparent;
  color:            var(--brand-ink);
  border-color:     var(--brand-ink);
}

.btn--ghost:hover {
  background-color: color-mix(in srgb, var(--brand-ink) 8%, transparent);
}

.btn--ghost:focus-visible {
  outline:        3px solid var(--state-info);
  outline-offset: 2px;
}

.btn--ghost:active {
  background-color: color-mix(in srgb, var(--brand-ink) 16%, transparent);
}

.btn--ghost:disabled,
.btn--ghost[aria-disabled="true"] {
  opacity:        0.45;
  cursor:         not-allowed;
  pointer-events: none;
}

.btn--ghost[data-loading="true"] {
  opacity:        0.70;
  cursor:         wait;
  pointer-events: none;
}


/* --------------------------------------------------------------------------
   .btn--danger  — state-danger background, white text
-------------------------------------------------------------------------- */

.btn--danger {
  background-color: var(--state-danger);
  color:            var(--n-0);
  border-color:     var(--state-danger);
}

.btn--danger:hover {
  background-color: color-mix(in srgb, var(--state-danger) 85%, #000);
  border-color:     color-mix(in srgb, var(--state-danger) 85%, #000);
}

.btn--danger:focus-visible {
  outline:        3px solid var(--state-danger);
  outline-offset: 2px;
  box-shadow:     0 0 0 5px color-mix(in srgb, var(--state-danger) 25%, transparent);
}

.btn--danger:active {
  background-color: color-mix(in srgb, var(--state-danger) 75%, #000);
  border-color:     color-mix(in srgb, var(--state-danger) 75%, #000);
}

.btn--danger:disabled,
.btn--danger[aria-disabled="true"] {
  opacity:        0.45;
  cursor:         not-allowed;
  pointer-events: none;
}

.btn--danger[data-loading="true"] {
  opacity:        0.70;
  cursor:         wait;
  pointer-events: none;
}


/* --------------------------------------------------------------------------
   .btn--link  — no background, brand-ink underline text link
-------------------------------------------------------------------------- */

.btn--link {
  background-color: transparent;
  color:            var(--brand-ink);
  border-color:     transparent;
  font-weight:      500;
  text-decoration:  underline;
  text-underline-offset: 3px;
  padding:          0 var(--sp-1);
  height:           auto;
  min-height:       44px;
}

.btn--link:hover {
  color:            color-mix(in srgb, var(--brand-ink) 70%, var(--n-600));
  text-decoration-thickness: 2px;
}

.btn--link:focus-visible {
  outline:        3px solid var(--state-info);
  outline-offset: 2px;
  border-radius:  var(--r-1);
}

.btn--link:active {
  color: color-mix(in srgb, var(--brand-ink) 60%, var(--n-900));
}

.btn--link:disabled,
.btn--link[aria-disabled="true"] {
  opacity:        0.45;
  cursor:         not-allowed;
  pointer-events: none;
}

.btn--link[data-loading="true"] {
  opacity:        0.70;
  cursor:         wait;
  pointer-events: none;
}


/* --------------------------------------------------------------------------
   .btn--accent  — brand-spark (warm orange) background, on-spark text
   M18 · Phase 2-pre — peer variant for compat-shim btn-elfrique-accent.
   Text uses --brand-on-spark (semantic indirection): defaults to --brand-ink
   (6.87:1 on the AA-tier bronze — PASS AA); HC tier flips to --n-0 because
   the AAA-reach bronze (#8B4500) inverts contrast. See L41–48 token block.
-------------------------------------------------------------------------- */

.btn--accent {
  background-color: var(--brand-spark);
  color:            var(--brand-on-spark);
  border-color:     var(--brand-spark);
}

.btn--accent:hover {
  background-color: color-mix(in srgb, var(--brand-spark) 85%, #000);
  border-color:     color-mix(in srgb, var(--brand-spark) 85%, #000);
}

.btn--accent:focus-visible {
  outline:        3px solid var(--state-info);
  outline-offset: 2px;
}

.btn--accent:active {
  background-color: color-mix(in srgb, var(--brand-spark) 75%, #000);
  border-color:     color-mix(in srgb, var(--brand-spark) 75%, #000);
}

.btn--accent:disabled,
.btn--accent[aria-disabled="true"] {
  opacity:        0.45;
  cursor:         not-allowed;
  pointer-events: none;
}

.btn--accent[data-loading="true"] {
  opacity:        0.70;
  cursor:         wait;
  pointer-events: none;
}


/* --------------------------------------------------------------------------
   .btn--success  — state-success (TEAL — hard rule #1) background, white text
   M18 · Phase 2-pre — peer variant for compat-shim btn-success.
   --state-success resolves to #0D9488 (Teal-600, 4.54:1 on white — AA);
   HC tier lifts to #115E59 (Teal-800, 7.58:1 — AAA). Hue stays teal across
   all tiers; this variant is NEVER green.
-------------------------------------------------------------------------- */

.btn--success {
  background-color: var(--state-success);
  color:            var(--n-0);
  border-color:     var(--state-success);
}

.btn--success:hover {
  background-color: color-mix(in srgb, var(--state-success) 85%, #000);
  border-color:     color-mix(in srgb, var(--state-success) 85%, #000);
}

.btn--success:focus-visible {
  outline:        3px solid var(--state-success);
  outline-offset: 2px;
  box-shadow:     0 0 0 5px color-mix(in srgb, var(--state-success) 25%, transparent);
}

.btn--success:active {
  background-color: color-mix(in srgb, var(--state-success) 75%, #000);
  border-color:     color-mix(in srgb, var(--state-success) 75%, #000);
}

.btn--success:disabled,
.btn--success[aria-disabled="true"] {
  opacity:        0.45;
  cursor:         not-allowed;
  pointer-events: none;
}

.btn--success[data-loading="true"] {
  opacity:        0.70;
  cursor:         wait;
  pointer-events: none;
}


/* --------------------------------------------------------------------------
   .btn--warning  — state-warn (Amber-700) background, white text
   M18 · Phase 2-pre — peer variant for compat-shim btn-warning.
   --state-warn resolves to #B45309 (5.93:1 on white — AA), so --n-0 text
   on this fill clears AA. HC tier lifts to #92400E (7.09:1 — AAA reach).
-------------------------------------------------------------------------- */

.btn--warning {
  background-color: var(--state-warn);
  color:            var(--n-0);
  border-color:     var(--state-warn);
}

.btn--warning:hover {
  background-color: color-mix(in srgb, var(--state-warn) 85%, #000);
  border-color:     color-mix(in srgb, var(--state-warn) 85%, #000);
}

.btn--warning:focus-visible {
  outline:        3px solid var(--state-warn);
  outline-offset: 2px;
  box-shadow:     0 0 0 5px color-mix(in srgb, var(--state-warn) 25%, transparent);
}

.btn--warning:active {
  background-color: color-mix(in srgb, var(--state-warn) 75%, #000);
  border-color:     color-mix(in srgb, var(--state-warn) 75%, #000);
}

.btn--warning:disabled,
.btn--warning[aria-disabled="true"] {
  opacity:        0.45;
  cursor:         not-allowed;
  pointer-events: none;
}

.btn--warning[data-loading="true"] {
  opacity:        0.70;
  cursor:         wait;
  pointer-events: none;
}


/* --------------------------------------------------------------------------
   .btn--info  — state-info (Blue-600) background, white text
   M18 · Phase 2-pre — peer variant for compat-shim btn-info.
   --state-info resolves to #2563EB (5.17:1 on white — AA); HC tier lifts
   to #1E40AF (Blue-800, 8.72:1 — AAA reach).
-------------------------------------------------------------------------- */

.btn--info {
  background-color: var(--state-info);
  color:            var(--n-0);
  border-color:     var(--state-info);
}

.btn--info:hover {
  background-color: color-mix(in srgb, var(--state-info) 85%, #000);
  border-color:     color-mix(in srgb, var(--state-info) 85%, #000);
}

.btn--info:focus-visible {
  outline:        3px solid var(--state-info);
  outline-offset: 2px;
  box-shadow:     0 0 0 5px color-mix(in srgb, var(--state-info) 25%, transparent);
}

.btn--info:active {
  background-color: color-mix(in srgb, var(--state-info) 75%, #000);
  border-color:     color-mix(in srgb, var(--state-info) 75%, #000);
}

.btn--info:disabled,
.btn--info[aria-disabled="true"] {
  opacity:        0.45;
  cursor:         not-allowed;
  pointer-events: none;
}

.btn--info[data-loading="true"] {
  opacity:        0.70;
  cursor:         wait;
  pointer-events: none;
}


/* --------------------------------------------------------------------------
   .btn--outline  — compositional modifier
   M20 · Phase 5a — kit-conformance for helpers (HelperFactory.ModalCloseButton,
   ActionMenuHelper, DropDownMenuHelper, VendorViewModelMapper) replacing
   Bootstrap `btn-outline-*` legacy classes.

   Composition rules:
     * `.btn--outline` alone        → neutral outline (n-700 text, n-300 border)
     * `.btn--primary.btn--outline` → inverts solid primary to outlined brand-ink
     * `.btn--danger.btn--outline`  → inverts solid danger to outlined state-danger

   Compound rules ordered after the alone-rule so their declarations override
   cleanly via shared specificity. Hover/focus/active/disabled match the
   existing intent-modifier pattern (color-mix overlay + state-info focus
   ring; danger keeps its state-danger ring per the .btn--danger block above).
-------------------------------------------------------------------------- */

.btn--outline {
  background-color: transparent;
  color:            var(--n-700);
  border-color:     var(--n-300);
}

.btn--outline:hover {
  background-color: color-mix(in srgb, var(--n-700) 8%, transparent);
  border-color:     var(--n-500);
}

.btn--outline:focus-visible {
  outline:        3px solid var(--n-500);
  outline-offset: 2px;
}

.btn--outline:active {
  background-color: color-mix(in srgb, var(--n-700) 12%, transparent);
}

.btn--outline:disabled,
.btn--outline[aria-disabled="true"] {
  opacity:        0.55;
  cursor:         not-allowed;
  pointer-events: none;
}

.btn--outline[data-loading="true"] {
  opacity:        0.70;
  cursor:         wait;
  pointer-events: none;
}

/* Compound: primary outline — inverts solid primary fill to outlined brand-ink */
.btn--primary.btn--outline {
  background-color: transparent;
  color:            var(--brand-ink);
  border-color:     var(--brand-ink);
}

.btn--primary.btn--outline:hover {
  background-color: color-mix(in srgb, var(--brand-ink) 8%, transparent);
  color:            var(--brand-ink);
  border-color:     var(--brand-ink);
}

.btn--primary.btn--outline:focus-visible {
  outline:        3px solid var(--state-info);
  outline-offset: 2px;
}

.btn--primary.btn--outline:active {
  background-color: color-mix(in srgb, var(--brand-ink) 12%, transparent);
  border-color:     var(--brand-ink);
}

/* Compound: danger outline — inverts solid danger fill to outlined state-danger */
.btn--danger.btn--outline {
  background-color: transparent;
  color:            var(--state-danger);
  border-color:     var(--state-danger);
}

.btn--danger.btn--outline:hover {
  background-color: color-mix(in srgb, var(--state-danger) 8%, transparent);
  color:            var(--state-danger);
  border-color:     var(--state-danger);
}

.btn--danger.btn--outline:focus-visible {
  outline:        3px solid var(--state-danger);
  outline-offset: 2px;
  box-shadow:     0 0 0 5px color-mix(in srgb, var(--state-danger) 25%, transparent);
}

.btn--danger.btn--outline:active {
  background-color: color-mix(in srgb, var(--state-danger) 12%, transparent);
  border-color:     var(--state-danger);
}


/* ==========================================================================
   PREFERS-REDUCED-MOTION — GLOBAL FLOOR
   M11 · C8 Accessibility · Phase 3 (W8.6)
   Hard rule #10: every animation must degrade gracefully.
   Hard rule #3: no raw ms outside the 0.01ms reduced-motion convention.

   The * selector establishes the lowest-cost floor: all transitions and
   animations collapse to effectively-zero duration. 0.01ms is chosen over
   true-zero (0s / 0ms) because some browsers optimise true-zero durations
   out of the event-firing pipeline, which can break JS that listens to
   `transitionend`. 0.01ms is imperceptible but still fires events.

   Per-component overrides below this block use `animation: none` for
   animations where even 0.01ms would cause visual artifacts (spinning
   loaders, infinite shimmers). The global * rule is the baseline;
   component rules are the specific policy.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration:       0.01ms !important;
    animation-duration:        0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior:           auto !important;
  }

  /* Button transitions — belt-and-braces; the * rule above already collapses
     them, but explicit none is clearer intent and faster browser resolution. */
  .btn--primary,
  .btn--ghost,
  .btn--danger,
  .btn--link,
  .btn--accent,
  .btn--success,
  .btn--warning,
  .btn--info,
  .btn--outline {
    transition: none;
  }
}


/* ==========================================================================
   HIGH-CONTRAST TIER — V2 ACCESSIBILITY
   M11 · C8 Accessibility · Phase 4b (W8.v2.1, W8.v2.2)

   Two trigger paths share one set of token overrides:

     1. @media (prefers-contrast: more)  — OS-level user preference
        (Windows High Contrast, macOS Increase Contrast, Linux GTK,
        recent iOS/Android assistive settings).

     2. body.theme-high-contrast         — explicit user toggle from
        Account/Preferences (M11 P4a). Honours users whose OS does NOT
        report prefers-contrast but who still need lifted contrast,
        AND users on browsers that don't yet plumb the OS signal.

   Design discipline (binding):

     * Hard rule #1 — --state-success stays TEAL across all tiers.
       The HC override darkens the teal for WCAG-AA/AAA reach;
       it does NOT shift hue toward green. Verified by the contrast-
       audit script's AAA flag.

     * Anti-instruction (plan §Phase 4) — NO new state colours in the
       HC tier; this block lifts existing tokens only.

     * Hard rule #10 — HC tier inherits the reduced-motion floor above
       (the @media block at L553 sets * transition-duration: 0.01ms;
       nothing here re-enables motion).

     * Hard rule #2 — raw hex is permitted in this file ONLY (per the
       same exception that lets :root { ... } own the canonical token
       values). Component CSS still references tokens via var().

   Lift rationale per token:

     --brand-ink   stays #0F2018 (already 18:1 on white — already AAA).
     --brand-spark from #E8912D (2.47:1) -> #8B4500 (7.12:1 on white).
                   Visible warm accent preserved; saturation lifted to
                   a deeper bronze. Resolves the 3 DEFER-4b pairs
                   involving --brand-spark/--n-0/--n-50 from Phase 1
                   to AAA on white (--n-50 lands at 6.81:1, an AAA
                   deficit of 0.19 — see report).

     --state-success from #0D9488 (3.74:1) -> #115E59 (7.58:1). Teal-800
                   replaces Teal-600. Reaches AAA on white. Resolves the
                   3 DEFER-4b pairs involving --state-success/--n-0/
                   --n-50 from Phase 1 under the HC tier specifically;
                   --n-50 lands at 7.27:1, on the AAA side of the line.
                   Hard rule #1: still teal — hue preserved, just
                   darker. NOT green.

     --state-warn  from #B45309 (5.93:1) -> #92400E (7.09:1). Amber-800
                   replaces Amber-700. AAA reach.
     --state-danger from #DC2626 (4.83:1) -> #991B1B (8.31:1). Red-800
                   replaces Red-600. AAA reach.
     --state-info  from #2563EB (5.17:1) -> #1E40AF (8.72:1). Blue-800
                   replaces Blue-600. AAA reach.

     Neutrals: lighter neutrals lift toward pure white; mid-tones lift
     toward the dark end of the scale to widen contrast against light
     fills. --n-0 / --n-900 already at extremes — unchanged.

     --n-50  unchanged (#F9FAFB; already adjacent to --n-0).
     --n-100 -> #FFFFFF (compress to white — small shift, used as light
                  surface fills; in HC mode the micro-grey loses its job).
     --n-200 -> #E5E7EB stays (used for borders; remaining as-is).
     --n-300 -> #9CA3AF (compress to mid for borders to render visibly).
     --n-400 -> #4B5563 (lift two steps — text uses on light fills).
     --n-500 -> #374151 (lift two steps — caption text reaches AAA).
     --n-600 -> #1F2937 stays compressed darker (already AAA).
     --n-700 -> #111827 (collapse to near-black for body-text reach).
     --n-800 / --n-900 already at the black extreme — unchanged.

   Cross-cutting safeguard: the global :focus-visible ring at L270 uses
   --brand-spark, which DARKENS in this tier (still WCAG-visible against
   any neutral surface). The skip-link override at L195 uses brand-ink/
   n-0 — both unchanged across tiers — so its visibility is preserved.
   ========================================================================== */

@media (prefers-contrast: more) {
  :root {
    --brand-spark:   #8B4500;
    --state-success: #115E59;
    --state-warn:    #92400E;
    --state-danger:  #991B1B;
    --state-info:    #1E40AF;

    --n-100: #FFFFFF;
    --n-300: #9CA3AF;
    --n-400: #4B5563;
    --n-500: #374151;
    --n-700: #111827;

    /* HC flip: --brand-ink on the AAA-reach bronze drops to 2.38:1 (sub-AA).
       --n-0 on #8B4500 = 7.12:1 (AAA pass). See F-4b-1 mitigation. */
    --brand-on-spark: var(--n-0);
  }
}

.theme-high-contrast {
  --brand-spark:   #8B4500;
  --state-success: #115E59;
  --state-warn:    #92400E;
  --state-danger:  #991B1B;
  --state-info:    #1E40AF;

  --n-100: #FFFFFF;
  --n-300: #9CA3AF;
  --n-400: #4B5563;
  --n-500: #374151;
  --n-700: #111827;

  /* HC flip: --brand-ink on the AAA-reach bronze drops to 2.38:1 (sub-AA).
     --n-0 on #8B4500 = 7.12:1 (AAA pass). See F-4b-1 mitigation. */
  --brand-on-spark: var(--n-0);
}


/* ==========================================================================
   BOOTSTRAP VENDOR BRAND-CORRECTION OVERRIDES
   Migrated from elfrique.compat.css (M18 Phase 2c-pre-3, 2026-05-01).
   Source: M19 fix-cycle 1.2 (commit 04bc3683, F-P2-2 BLOCKER resolution).
   These rules restore the canonical brand cascade against vendor Bootstrap
   utilities/components after custom.css deletion. They are NOT legacy-class
   shims; they have a permanent ongoing purpose. Kept here in elfrique.css
   so they load AFTER vendor Bootstrap (HeadMeta line 75 vs vendor 72-73)
   and continue to win cascade once compat.css is removed in Phase 2c-del.
   Live consumers at migration:
     .bg-primary                                          → Views/UserDetail.cshtml:68,
                                                            Views/AdminDsar/Index.cshtml:55
     .btn-outline-primary                                 → admin views (Bootstrap variant)
     .bg-menu-theme .menu-item.active > .menu-link        → admin sidebar (vendor theme CSS)
     .form-check-input:checked                            → form checkboxes site-wide
   ========================================================================== */

.bg-primary {
  background-color: var(--brand-ink) !important;
}

.btn-outline-primary {
  color:        var(--brand-ink);
  border-color: var(--brand-ink);
}
.btn-outline-primary:hover,
.btn-outline-primary:focus {
  background-color: var(--brand-ink);
  border-color:     var(--brand-ink);
  color:            var(--n-0);
}

.bg-menu-theme .menu-item.active > .menu-link:not(.menu-toggle) {
  background-color: var(--brand-ink);
  color:            var(--n-0);
}

.form-check-input:checked {
  background-color: var(--brand-ink);
  border-color:     var(--brand-ink);
}
