@charset "UTF-8";
/*
  FinanceApp.UI — shared design system
  ------------------------------------
  Fall palette, rooted in burnt orange. Every component below styles itself
  through the custom properties in :root, so retuning the season/theme later
  is a matter of editing this one block, not hunting through components.
*/
@import url("https://fonts.googleapis.com/css2?family=Baloo+2:wght@500;600;700;800&display=swap");
:root {
  /* --- Fall palette, rooted in burnt orange, extended into a Northwest dying-leaf
     sequence: still-green fern moss, through gold, through the root itself, into
     vine-maple ember and huckleberry wine, grounded by the Douglas fir that never
     turns at all. See financeapp-build-styling.html Step 11 for the full reasoning. --- */
  --fa-primary: #bf5b26; /* Burnt Orange — root. header, sidebar, primary actions */
  --fa-primary-dark: #8c431b; /* darker burnt orange — hover/focus states */
  --fa-primary-light: #e0895a; /* lighter tint — hover backgrounds, secondary accents */
  --fa-footer: #f3dfc1; /* light warm sand — footer background */
  --fa-glow: #e8873d; /* pumpkin orange — the border "backlight" glow */
  --fa-gold: #d9a441; /* Golden Larch — badges, highlights, dashboard progress labels */
  --fa-accent: #6b7a3e; /* Fern Moss — the accent. success states, secondary actions */
  --fa-accent-dark: #4f5c2c; /* darker Fern Moss — hover/focus on accent elements */
  --fa-ember: #a63a2c; /* Vine Maple Ember — danger/errors, needs to actually get noticed */
  --fa-wine: #6b2737; /* Huckleberry Wine — deep/hover shade for ember, dark accents */
  --fa-fir: #2b3b30; /* Douglas Fir Shadow — deep neutral-green anchor, "black" icons */
  --fa-cream: #fcf3e6; /* page background */
  --fa-surface: #fffdf9; /* card/input surface */
  --fa-text: #3b2712; /* body text — dark brown */
  --fa-text-muted: #7a6650;
  --fa-text-on-primary: #fff8ef;
  --fa-border: #e3b98a; /* default border — warm tan */
  --fa-border-focus: #8c431b; /* darker border on focus, per spec */
  /* --- Pale tint backgrounds behind alert borders --- */
  --fa-alert-danger-bg: #fbe9e5;
  --fa-alert-success-bg: #eef3e4;
  --fa-alert-info-bg: #fbeee2;
  /* --- Shape & type --- */
  --fa-radius-sm: 8px;
  --fa-radius-md: 14px;
  --fa-radius-lg: 22px;
  --fa-radius-pill: 999px;
  --fa-font: "Baloo 2", ui-rounded, "Segoe UI Rounded", "Nunito", system-ui, sans-serif;
  /* --- The "orange backlight" every bordered element gets by default --- */
  --fa-border-glow: 0 0 0 1px var(--fa-border), 0 0 10px 1px rgba(232, 135, 61, 0.35);
  --fa-border-glow-focus: 0 0 0 2px var(--fa-border-focus), 0 0 12px 2px rgba(232, 135, 61, 0.55);
  /* --- Shared standards every component pulls from, same "one place to change
     it everywhere" contract as the color/radius tokens above. Palette-agnostic —
     redefined here once, not per palette, since border weight and interaction
     speed aren't part of any palette's identity. Component partials should
     reference these instead of repeating the literal values; see Blazor/CLAUDE.md's
     "Themes" section. --- */
  --fa-border-width: 2px;
  --fa-transition-fast: 0.15s ease; /* hover/focus color & shadow changes */
  --fa-transition-medium: 0.2s ease; /* size/layout changes — sidebar collapse, toggle width */
  /* FaHeader's rendered height — also enforced as its own min-height (_layout.scss)
     so it's a reliable constant, not just a guess. A sticky/floating FaSidebar reads
     this to offset itself below the header instead of underneath it. */
  --fa-header-height: 4rem;
}

/* ============================= UI style: terse / typewriter ============================= */
/* A fourth independent axis, alongside palette/mode below and input-style (its own
   comment lives in _inputs.scss next to the code it affects, same precedent this
   follows) — which overall shape/type/motion language is active, not which colors.
   Three values share this one mechanism: "flow" (no attribute, the :root defaults
   above — today's rounded, softly glowing, animated look), "terse" (flatter and
   editorial, no shadow, no motion), "typewriter" (paper-like — a monospaced serif
   font, moderate radii, and a soft neutral drop shadow standing in for the
   colored glow, read as the card physically resting just above the page). All
   three retune the same shared tokens every component already draws its shape
   from (see Blazor/CLAUDE.md's Themes section), so a new value here is a token
   block plus a short explicit list of hardcoded (non-token) shadows each doesn't
   reach — header/sidebar chrome, toasts, tooltips, the avatar ring — get their
   own `[data-fa-ui-style="..."]` overrides in their own partials instead of
   repeating them here. Toggle with window.faSetUiStyle(name) (js/theme.js) or
   <FaUiStyleSwitcher>. Status pills (badges/chips) keep --fa-radius-pill in all
   three — a shape appropriate to a status pill regardless of which style is
   active. */
:root[data-fa-ui-style=terse] {
  --fa-radius-sm: 4px;
  --fa-radius-md: 6px;
  --fa-radius-lg: 10px;
  --fa-font: ui-sans-serif, "Segoe UI", system-ui, sans-serif;
  /* Only meaningful under terse — labels/eyebrows/tabular numbers, see
     _badges.scss/_chip.scss. Flow/typewriter have no equivalent token since
     neither uses a separate monospace treatment (typewriter's *entire* font
     already is one — see below). */
  --fa-font-mono: ui-monospace, "Cascadia Code", Consolas, "Liberation Mono", monospace;
  --fa-border-glow: none;
  --fa-border-glow-focus: 0 0 0 2px var(--fa-border-focus);
  --fa-transition-fast: 0s;
  --fa-transition-medium: 0s;
}

/* Typewriter: a real monospaced serif/slab typeface — 'Courier New' ships on
   effectively every OS, so this reaches the intended look without the forced
   Google Fonts network request a non-system font would need (same "system-font
   fallback only" stance terse takes). Radii are barely-there — just enough to
   soften a corner, not read as "rounded" the way flow or even terse's own scale
   does — since the identity here is font + a whisper of a shadow, not shape.
   Border thins to 1px and --fa-border-glow becomes one barely-there, neutral
   (not palette-colored) drop shadow instead of flow's heavier colored blur or
   terse's none — a clean, minimal "resting on the page" read. The focus variant
   only nudges that shadow very slightly rather than noticeably growing it —
   focus is still signaled the normal way (the border recoloring to
   --fa-border-focus, same as every style), just without an oversized shadow
   piled on top of it. Motion is untouched (still flow's default transition
   speed): unlike terse's "no motion" stance, typewriter's whole point is gentle,
   physical-feeling movement, not the absence of it. */
:root[data-fa-ui-style=typewriter] {
  --fa-radius-sm: 3px;
  --fa-radius-md: 4px;
  --fa-radius-lg: 6px;
  --fa-font: "Courier New", Courier, ui-monospace, monospace;
  --fa-border-width: 1px;
  --fa-border-glow: 0 1px 2px rgba(0, 0, 0, 0.06);
  --fa-border-glow-focus: 0 1px 3px rgba(0, 0, 0, 0.08);
}

/* ============================= Theme variants ============================= */
/* Two independent axes, both applied via data attributes on <html>:

   1. Palette — which seasonal/regional color story is active. data-fa-palette=
      "southwest-summer" | "northeast-spring" | "midwest-winter" | "southeast-beach" |
      "greece-aegean" | "spain-flamenco" | "ireland-emerald" | "jamaica-blue-mountain" |
      "japan-indigo" | "korea-celadon" | "china-cinnabar" | "india-peacock" |
      "cameroon-rainforest" | "sahara-desert" | "brazil-rainforest" | "brazil-favela" |
      "portugal-tiles" | "spain-bullfighting" | "mexico-day-of-the-dead" |
      "london-life" | "new-york-nightlife" | "india-henna" | "ruckus" | "dinner" |
      "hang-in" | "floating" | "fit".
      No attribute (or data-fa-palette="northwest-fall") means the :root defaults
      above. Toggle with window.faSetPalette(name) (js/theme.js — reads/writes
      localStorage the same way faSetTheme does).
   2. Mode — light (default), dark, or colorblind-safe. data-theme="dark"/
      "colorblind", toggled by window.faSetTheme(...) / <FaThemeSwitcher>, with the
      OS's prefers-color-scheme as the fallback for dark before any explicit choice
      is made. Colorblind mode has no OS-level media-query equivalent, so it's
      opt-in only, never automatic.

   Every component reads color exclusively through these custom properties, so a
   palette or mode only has to redefine the tokens that actually change — shape and
   type (radii, font) stay identical across every combination of the two axes. */
/* --- Palettes: light-mode values only. Each block is self-contained (redefines
   every color token the default :root sets), not a diff against Northwest Fall, so
   picking a palette can't accidentally inherit an unrelated hue. See .themes/ (git-
   ignored, local design docs) for the reasoning behind each palette's color choices. --- */
:root[data-fa-palette=southwest-summer] {
  /* Redone from an early "same terracotta family as Northwest Fall" first draft,
     which read as too close to the default theme to tell apart at a glance. This
     version pulls from three different things instead of one: Sea of Cortez/Baja
     ocean blue for primary (a genuinely different hue family from Fall's burnt
     orange, and more saturated than Midwest Winter's greyer slate blue so the two
     don't collapse into each other either), Sonoran Desert wildflowers for gold
     and accent (marigold yellow, penstemon purple), and canyon sandstone for the
     danger family. */
  --fa-primary: #1f77a8; /* Sea of Cortez Blue */
  --fa-primary-dark: #164f70;
  --fa-primary-light: #6bb0d1;
  --fa-footer: #f0ece0;
  --fa-glow: #2f96c9;
  --fa-gold: #e0a940; /* Desert Marigold */
  --fa-accent: #7a4f9e; /* Penstemon Purple */
  --fa-accent-dark: #573a72;
  --fa-ember: #b23a28; /* Canyon Sandstone Red */
  --fa-wine: #6b2018; /* Canyon Shadow */
  --fa-fir: #33283a; /* Canyon Twilight Shadow */
  --fa-cream: #faf6ee;
  --fa-surface: #fffdf8;
  --fa-text: #2e2a24;
  --fa-text-muted: #7d766a;
  --fa-text-on-primary: #f5fbff;
  --fa-border: #d8d0bc;
  --fa-border-focus: #164f70;
  --fa-alert-danger-bg: #f8e3df;
  --fa-alert-success-bg: #efe6f2;
  --fa-alert-info-bg: #e2eef4;
}

:root[data-fa-palette=northeast-spring] {
  --fa-primary: #a24a78; /* Redbud Blossom */
  --fa-primary-dark: #74345a;
  --fa-primary-light: #cf8fae;
  --fa-footer: #f5e6ee;
  --fa-glow: #c96a97;
  --fa-gold: #d9b23c; /* Forsythia Gold */
  --fa-accent: #5a8f4f; /* New Leaf Green */
  --fa-accent-dark: #3f6636;
  --fa-ember: #b3392f; /* Cardinal Red */
  --fa-wine: #6b2030;
  --fa-fir: #33402f; /* Birch Bark Shadow */
  --fa-cream: #faf3f6;
  --fa-surface: #fffbfc;
  --fa-text: #3a2230;
  --fa-text-muted: #7a6070;
  --fa-text-on-primary: #fff5fa;
  --fa-border: #e8c6d6;
  --fa-border-focus: #74345a;
  --fa-alert-danger-bg: #f9e3e1;
  --fa-alert-success-bg: #edf3ea;
  --fa-alert-info-bg: #f7e9ef;
}

:root[data-fa-palette=midwest-winter] {
  --fa-primary: #3d5a73; /* Prairie Slate Blue */
  --fa-primary-dark: #28404f;
  --fa-primary-light: #7098af;
  --fa-footer: #e6edf0;
  --fa-glow: #4f7a94;
  --fa-gold: #c9a227; /* Wheat Stubble Gold */
  --fa-accent: #3f5c42; /* Windbreak Evergreen */
  --fa-accent-dark: #2b4030;
  --fa-ember: #9c3b30; /* Barn Red */
  --fa-wine: #5c2320;
  --fa-fir: #2a3138; /* Frozen Furrow Shadow */
  --fa-cream: #f5f8fa;
  --fa-surface: #fbfdfe;
  --fa-text: #26313a;
  --fa-text-muted: #66727c;
  --fa-text-on-primary: #f5f9fb;
  --fa-border: #c3d2da;
  --fa-border-focus: #28404f;
  --fa-alert-danger-bg: #f3e2df;
  --fa-alert-success-bg: #e6ece4;
  --fa-alert-info-bg: #e3ebf0;
}

:root[data-fa-palette=southeast-beach] {
  --fa-primary: #2c8c8a; /* Seafoam Turquoise */
  --fa-primary-dark: #1e615f;
  --fa-primary-light: #6bbdbb;
  --fa-footer: #f3e9d4;
  --fa-glow: #3ba6a3;
  --fa-gold: #d9b871; /* Sand Dune Gold */
  --fa-accent: #7a9457; /* Sea Oat Green */
  --fa-accent-dark: #566b3c;
  --fa-ember: #d9634a; /* Coral Sunset */
  --fa-wine: #8a3626;
  --fa-fir: #3a3630; /* Driftwood Shadow */
  --fa-cream: #fbf6ea;
  --fa-surface: #fffdf7;
  --fa-text: #3a2f22;
  --fa-text-muted: #7d7261;
  --fa-text-on-primary: #f2fbfa;
  --fa-border: #e3d3ab;
  --fa-border-focus: #1e615f;
  --fa-alert-danger-bg: #f9e6e0;
  --fa-alert-success-bg: #eef1e6;
  --fa-alert-info-bg: #e3f0ee;
}

:root[data-fa-palette=greece-aegean] {
  /* --- Greece — Aegean whitewash-and-sea blue, olive groves, limestone gold, terracotta danger. --- */
  --fa-primary: #1568a8; /* Aegean Blue */
  --fa-primary-dark: #0d4570;
  --fa-primary-light: #5fa8d9;
  --fa-footer: #e6eef1; /* Sea Foam */
  --fa-glow: #2e8fc9; /* Aegean Glow */
  --fa-gold: #d9a53c; /* Limestone Sun */
  --fa-accent: #6f7f3f; /* Olive Grove */
  --fa-accent-dark: #4d5a2b;
  --fa-ember: #c1552f; /* Terracotta Roof */
  --fa-wine: #7a2f22;
  --fa-fir: #2c3a2e; /* Cypress Shadow */
  --fa-cream: #f7f5ef;
  --fa-surface: #fffefb;
  --fa-text: #2b2a26;
  --fa-text-muted: #7d7a6e;
  --fa-text-on-primary: #f5faff;
  --fa-border: #d3e3ec;
  --fa-border-focus: #0d4570;
  --fa-alert-danger-bg: #f7e1da;
  --fa-alert-success-bg: #eaf0e0;
  --fa-alert-info-bg: #e1eef5;
}

:root[data-fa-palette=spain-flamenco] {
  /* --- Spain — flamenco red, Andalusian gold, Manzanilla olive, Rioja wine danger. --- */
  --fa-primary: #a02830; /* Flamenco Red */
  --fa-primary-dark: #701b21;
  --fa-primary-light: #d1707a;
  --fa-footer: #f7ece1; /* Almond Blossom */
  --fa-glow: #c23e46;
  --fa-gold: #d9a13c; /* La Mancha Gold */
  --fa-accent: #7c8a4a; /* Manzanilla Olive */
  --fa-accent-dark: #59642f;
  --fa-ember: #8a3a22; /* Sierra Clay */
  --fa-wine: #5c1f2c;
  --fa-fir: #33302c; /* Sierra Shadow */
  --fa-cream: #faf3ea;
  --fa-surface: #fffaf3;
  --fa-text: #362320;
  --fa-text-muted: #83706a;
  --fa-text-on-primary: #fff6f3;
  --fa-border: #e6c9b0;
  --fa-border-focus: #701b21;
  --fa-alert-danger-bg: #f7e0da;
  --fa-alert-success-bg: #eef0df;
  --fa-alert-info-bg: #f5e7da;
}

:root[data-fa-palette=ireland-emerald] {
  /* --- Ireland — emerald green, Celtic gold, heather-purple accent, peat-fire danger. --- */
  --fa-primary: #1f7a4d; /* Emerald Green */
  --fa-primary-dark: #144f32;
  --fa-primary-light: #5fb888;
  --fa-footer: #e9f0e6; /* Misty Meadow */
  --fa-glow: #2c9c63;
  --fa-gold: #c9a13a; /* Celtic Gold */
  --fa-accent: #7a5a8f; /* Heather Purple */
  --fa-accent-dark: #563f66;
  --fa-ember: #a1432c; /* Peat Fire */
  --fa-wine: #5c2a24;
  --fa-fir: #2b3a3a; /* Cliff Shadow */
  --fa-cream: #f3f6f1;
  --fa-surface: #fbfdf9;
  --fa-text: #23302a;
  --fa-text-muted: #728077;
  --fa-text-on-primary: #f2fbf6;
  --fa-border: #c8ddc9;
  --fa-border-focus: #144f32;
  --fa-alert-danger-bg: #f6e0da;
  --fa-alert-success-bg: #e2efe3;
  --fa-alert-info-bg: #eae3f0;
}

:root[data-fa-palette=jamaica-blue-mountain] {
  /* --- Jamaica — Blue Mountain mist teal, reggae gold, rainforest accent, hibiscus danger. --- */
  --fa-primary: #1f6e6b; /* Blue Mountain Teal */
  --fa-primary-dark: #144a48;
  --fa-primary-light: #5fa8a3;
  --fa-footer: #eaf1ec; /* Coconut Cream */
  --fa-glow: #2c8f8a;
  --fa-gold: #dba428; /* Reggae Sun Gold */
  --fa-accent: #4f8a3f; /* Rainforest Green */
  --fa-accent-dark: #35602a;
  --fa-ember: #b23348; /* Hibiscus Red */
  --fa-wine: #661f2e;
  --fa-fir: #26302a; /* Volcanic Rock */
  --fa-cream: #faf6ec;
  --fa-surface: #fffdf6;
  --fa-text: #2a2620;
  --fa-text-muted: #7c7466;
  --fa-text-on-primary: #f3fbf9;
  --fa-border: #cfe0da;
  --fa-border-focus: #144a48;
  --fa-alert-danger-bg: #f8e0e2;
  --fa-alert-success-bg: #e5efdf;
  --fa-alert-info-bg: #dcece9;
}

:root[data-fa-palette=japan-indigo] {
  /* --- Japan — Ai indigo, sakura-blush footer, bamboo accent, torii vermillion danger. --- */
  --fa-primary: #223a70; /* Ai Indigo */
  --fa-primary-dark: #152548;
  --fa-primary-light: #6a80ac;
  --fa-footer: #f4e3e8; /* Sakura Blush */
  --fa-glow: #33518f;
  --fa-gold: #c9a23e; /* Katsura Gold */
  --fa-accent: #5b7a4f; /* Bamboo Green */
  --fa-accent-dark: #3d5636;
  --fa-ember: #c23b2e; /* Torii Vermillion */
  --fa-wine: #6b1f22;
  --fa-fir: #2a2622; /* Sumi Ink */
  --fa-cream: #f7f3ea;
  --fa-surface: #fffdf7;
  --fa-text: #2a2622;
  --fa-text-muted: #7d7668;
  --fa-text-on-primary: #f3f6fc;
  --fa-border: #d6dced;
  --fa-border-focus: #152548;
  --fa-alert-danger-bg: #f7dfda;
  --fa-alert-success-bg: #e6ecdf;
  --fa-alert-info-bg: #e1e5f2;
}

:root[data-fa-palette=korea-celadon] {
  /* --- Korea — Goryeo celadon jade, dancheong blue accent, dancheong red danger, hanji paper bg. --- */
  --fa-primary: #4f8a7a; /* Celadon Jade */
  --fa-primary-dark: #2f5c4e;
  --fa-primary-light: #8fc0af;
  --fa-footer: #e7efe6; /* Celadon Mist */
  --fa-glow: #5fa08d;
  --fa-gold: #d1a83c; /* Dancheong Gold */
  --fa-accent: #3c6e9e; /* Dancheong Blue */
  --fa-accent-dark: #2a4d70;
  --fa-ember: #b23b30; /* Dancheong Red */
  --fa-wine: #6b201f;
  --fa-fir: #2b3530; /* Ink Mountain Shadow */
  --fa-cream: #f6f2e7;
  --fa-surface: #fffdf6;
  --fa-text: #2a2c26;
  --fa-text-muted: #7a7d70;
  --fa-text-on-primary: #f2f8f5;
  --fa-border: #cfe0d4;
  --fa-border-focus: #2f5c4e;
  --fa-alert-danger-bg: #f7e0dc;
  --fa-alert-success-bg: #e2efe6;
  --fa-alert-info-bg: #dde8f0;
}

:root[data-fa-palette=china-cinnabar] {
  /* --- China — Forbidden City cinnabar, imperial gold, Guilin jade accent, rice-paper bg. --- */
  --fa-primary: #b8342a; /* Cinnabar Red */
  --fa-primary-dark: #832318;
  --fa-primary-light: #d97c6f;
  --fa-footer: #f2e4c4; /* Gilded Parchment */
  --fa-glow: #cf4a35;
  --fa-gold: #d4a92f; /* Imperial Gold */
  --fa-accent: #3f8a6f; /* Guilin Jade */
  --fa-accent-dark: #2b6050;
  --fa-ember: #8a2a1e; /* Burnt Vermillion */
  --fa-wine: #591b17;
  --fa-fir: #262421; /* Ink Stone */
  --fa-cream: #f7f1e4;
  --fa-surface: #fffbf1;
  --fa-text: #2c2521;
  --fa-text-muted: #7d7268;
  --fa-text-on-primary: #fff5f0;
  --fa-border: #e8cd9e;
  --fa-border-focus: #832318;
  --fa-alert-danger-bg: #f6ddd6;
  --fa-alert-success-bg: #e0efe6;
  --fa-alert-info-bg: #f5ecd7;
}

:root[data-fa-palette=india-peacock] {
  /* --- India — peacock teal, marigold gold, monsoon-green accent, Rajasthan rose danger. --- */
  --fa-primary: #146b73; /* Peacock Teal */
  --fa-primary-dark: #0d4a50;
  --fa-primary-light: #4fa3ab;
  --fa-footer: #f4e6cf; /* Marigold Cream */
  --fa-glow: #1f8b95;
  --fa-gold: #dd8f2c; /* Marigold Orange */
  --fa-accent: #4c8a3f; /* Monsoon Green */
  --fa-accent-dark: #345f2b;
  --fa-ember: #b23458; /* Rajasthan Rose */
  --fa-wine: #6b1f38;
  --fa-fir: #262c3a; /* Monsoon Night */
  --fa-cream: #f7f4ec;
  --fa-surface: #fffdf7;
  --fa-text: #2a2723;
  --fa-text-muted: #7c7568;
  --fa-text-on-primary: #f2fbfa;
  --fa-border: #cfe4dd;
  --fa-border-focus: #0d4a50;
  --fa-alert-danger-bg: #f7dee6;
  --fa-alert-success-bg: #e3efdd;
  --fa-alert-info-bg: #d9eceb;
}

:root[data-fa-palette=cameroon-rainforest] {
  /* --- Cameroon — rainforest green, savanna gold, river-blue accent, laterite danger. --- */
  --fa-primary: #256b3f; /* Rainforest Green */
  --fa-primary-dark: #17492b;
  --fa-primary-light: #5fa878;
  --fa-footer: #f0e2bd; /* Savanna Dust */
  --fa-glow: #338a54;
  --fa-gold: #d9a83c; /* Savanna Gold */
  --fa-accent: #2f6e8a; /* River Blue */
  --fa-accent-dark: #204d61;
  --fa-ember: #a63b28; /* Laterite Red */
  --fa-wine: #5c2018;
  --fa-fir: #262620; /* Volcanic Basalt */
  --fa-cream: #f7f2e6;
  --fa-surface: #fffcf5;
  --fa-text: #2b2620;
  --fa-text-muted: #7d7568;
  --fa-text-on-primary: #f2faf5;
  --fa-border: #d8c99e;
  --fa-border-focus: #17492b;
  --fa-alert-danger-bg: #f6ddd6;
  --fa-alert-success-bg: #e1efe4;
  --fa-alert-info-bg: #dbe9ee;
}

:root[data-fa-palette=sahara-desert] {
  /* --- Sahara — dune ochre, desert-sun gold, sparse acacia-green accent, sirocco-dust danger. --- */
  --fa-primary: #c17f2e; /* Sahara Dune Ochre */
  --fa-primary-dark: #8a5920;
  --fa-primary-light: #d9a866;
  --fa-footer: #f0dfb8; /* Pale Dune Sand */
  --fa-glow: #e0973a;
  --fa-gold: #dba13a; /* Desert Sun Gold */
  --fa-accent: #5c7a3a; /* Acacia Green */
  --fa-accent-dark: #3f5527;
  --fa-ember: #a8452e; /* Sirocco Dust Red */
  --fa-wine: #5c2318;
  --fa-fir: #2b2a3a; /* Desert Night Indigo */
  --fa-cream: #f8f0e0;
  --fa-surface: #fffaf0;
  --fa-text: #332a1e;
  --fa-text-muted: #7d7060;
  --fa-text-on-primary: #fdf6ea;
  --fa-border: #dfc89a;
  --fa-border-focus: #8a5920;
  --fa-alert-danger-bg: #f7e1da;
  --fa-alert-success-bg: #ecefe0;
  --fa-alert-info-bg: #f7ecd9;
}

:root[data-fa-palette=brazil-rainforest] {
  /* --- Brazil — Amazon canopy green, ipê-yellow gold, toucan-orange accent, macaw-red danger. --- */
  --fa-primary: #1f6b4f; /* Amazon Canopy Green */
  --fa-primary-dark: #144a36;
  --fa-primary-light: #5fa887;
  --fa-footer: #eef0d8; /* Canopy Dapple */
  --fa-glow: #2f8a63;
  --fa-gold: #e0b23a; /* Ipê Amarelo */
  --fa-accent: #d9722c; /* Toucan Orange */
  --fa-accent-dark: #a8531e;
  --fa-ember: #b23328; /* Macaw Red */
  --fa-wine: #5c1a1a;
  --fa-fir: #1f2420; /* Rio Negro Black */
  --fa-cream: #f2f5ea;
  --fa-surface: #fbfdf7;
  --fa-text: #232a20;
  --fa-text-muted: #74806c;
  --fa-text-on-primary: #f2fbf6;
  --fa-border: #cfe0c2;
  --fa-border-focus: #144a36;
  --fa-alert-danger-bg: #f6ddd6;
  --fa-alert-success-bg: #dfece4;
  --fa-alert-info-bg: #f3e6d8;
}

:root[data-fa-palette=brazil-favela] {
  /* --- Brazil — favela hillside houses: Guanabara-blue accent, carnival gold, samba-red danger. --- */
  --fa-primary: #c81e78; /* Favela Fuchsia */
  --fa-primary-dark: #8f1454;
  --fa-primary-light: #e069a3;
  --fa-footer: #f0e6da; /* Warm Hillside Stucco */
  --fa-glow: #d9367e;
  --fa-gold: #e8b52e; /* Carnival Yellow */
  --fa-accent: #1f7ab2; /* Guanabara Bay Blue */
  --fa-accent-dark: #164f70;
  --fa-ember: #c2362b; /* Samba Red */
  --fa-wine: #6b1f24;
  --fa-fir: #232733; /* Corcovado Night */
  --fa-cream: #fdf3ea;
  --fa-surface: #fffaf3;
  --fa-text: #2b241d;
  --fa-text-muted: #7d7168;
  --fa-text-on-primary: #fdf2f8;
  --fa-border: #e6cfd8;
  --fa-border-focus: #8f1454;
  --fa-alert-danger-bg: #f8e0dc;
  --fa-alert-success-bg: #e6efe0;
  --fa-alert-info-bg: #dde9f2;
}

:root[data-fa-palette=portugal-tiles] {
  /* --- Portugal — azulejo cobalt blue, Sintra gold, terracotta-roof accent, Porto-wine danger. --- */
  --fa-primary: #2a5f8f; /* Azulejo Cobalt */
  --fa-primary-dark: #1c4463;
  --fa-primary-light: #6ea3c9;
  --fa-footer: #f0e8d8; /* Limewash Cream */
  --fa-glow: #3a7ab0;
  --fa-gold: #d9a53c; /* Sintra Gold */
  --fa-accent: #c06a3a; /* Terracotta Roof */
  --fa-accent-dark: #8f4a26;
  --fa-ember: #a8342f; /* Douro Red */
  --fa-wine: #5c1620; /* Porto Wine */
  --fa-fir: #1f2d3a; /* Lisbon Night Cobalt */
  --fa-cream: #f5f2ea;
  --fa-surface: #fffdf9;
  --fa-text: #262420;
  --fa-text-muted: #79705f;
  --fa-text-on-primary: #f2f8fc;
  --fa-border: #d6cbb2;
  --fa-border-focus: #1c4463;
  --fa-alert-danger-bg: #f7e0d9;
  --fa-alert-success-bg: #e2ede0;
  --fa-alert-info-bg: #dde9f2;
}

:root[data-fa-palette=spain-bullfighting] {
  /* --- Spain — corrida: capote magenta-purple, traje-de-luces gold, muleta-red danger. --- */
  --fa-primary: #8a2a5c; /* Capote Magenta-Purple */
  --fa-primary-dark: #5c1c3d;
  --fa-primary-light: #b96a95;
  --fa-footer: #f0e2c9; /* Arena Sand Tint */
  --fa-glow: #a83a74;
  --fa-gold: #c9982e; /* Traje de Luces Gold */
  --fa-accent: #3f6b3a; /* Verde Torero */
  --fa-accent-dark: #2a4a27;
  --fa-ember: #a8272c; /* Muleta Red */
  --fa-wine: #5c1418; /* Sangre de Toro */
  --fa-fir: #241f26; /* Ruedo Night */
  --fa-cream: #f2e6d0; /* Arena Sand */
  --fa-surface: #fffbf3;
  --fa-text: #2b2318;
  --fa-text-muted: #7d7160;
  --fa-text-on-primary: #faf2f7;
  --fa-border: #dcc79a;
  --fa-border-focus: #5c1c3d;
  --fa-alert-danger-bg: #f7dcdd;
  --fa-alert-success-bg: #e6ece0;
  --fa-alert-info-bg: #e6e0ea;
}

:root[data-fa-palette=mexico-day-of-the-dead] {
  /* --- Mexico — Día de los Muertos: obsidian purple, marigold accent, papel-picado gold, calavera-red danger. --- */
  --fa-primary: #6b2d6e; /* Obsidian Purple */
  --fa-primary-dark: #45204a;
  --fa-primary-light: #9c66a0;
  --fa-footer: #f4e0c2; /* Marigold Cream */
  --fa-glow: #8a3d8f;
  --fa-gold: #e8c23a; /* Papel Picado Gold */
  --fa-accent: #dd8a2e; /* Marigold Orange */
  --fa-accent-dark: #a8621e;
  --fa-ember: #a8342e; /* Calavera Red */
  --fa-wine: #5c1a22;
  --fa-fir: #241f2e; /* Obsidian Night */
  --fa-cream: #f7ede0;
  --fa-surface: #fffaf2;
  --fa-text: #2e2318;
  --fa-text-muted: #85735d;
  --fa-text-on-primary: #faf2fb;
  --fa-border: #e0c7a0;
  --fa-border-focus: #45204a;
  --fa-alert-danger-bg: #f7dcda;
  --fa-alert-success-bg: #eef0dc;
  --fa-alert-info-bg: #e9e0ee;
}

:root[data-fa-palette=london-life] {
  /* --- London — Underground roundel blue, telephone-box red accent, Big-Ben brass, Thames-fog neutral. --- */
  --fa-primary: #17417a; /* Underground Roundel Blue */
  --fa-primary-dark: #0f2d57;
  --fa-primary-light: #5a83b3;
  --fa-footer: #e6e4de; /* Foggy Grey-Cream */
  --fa-glow: #2f5f9e;
  --fa-gold: #b6923c; /* Big Ben Brass */
  --fa-accent: #b3272c; /* Telephone Box Red */
  --fa-accent-dark: #7a1a1e;
  --fa-ember: #8f1f28; /* Poppy Red */
  --fa-wine: #4a1319;
  --fa-fir: #2a2d33; /* Thames Fog Charcoal */
  --fa-cream: #f2f0ec;
  --fa-surface: #fbfaf7;
  --fa-text: #26282b;
  --fa-text-muted: #6f7378;
  --fa-text-on-primary: #f0f6fc;
  --fa-border: #d7d5cf;
  --fa-border-focus: #0f2d57;
  --fa-alert-danger-bg: #f4dcdd;
  --fa-alert-success-bg: #e2e8de;
  --fa-alert-info-bg: #dde6f0;
}

:root[data-fa-palette=new-york-nightlife] {
  /* --- New York — Times Square electric violet, taxi-cab gold, electric-cyan accent, siren-red danger. --- */
  --fa-primary: #5a3fb0; /* Times Square Electric Violet */
  --fa-primary-dark: #3c2a78;
  --fa-primary-light: #9683d4;
  --fa-footer: #ece6ee; /* Dusky Violet-Grey */
  --fa-glow: #7454d6;
  --fa-gold: #e8b13a; /* Taxi Cab Yellow */
  --fa-accent: #1596b0; /* Electric Cyan */
  --fa-accent-dark: #0e6b80;
  --fa-ember: #c2272e; /* Siren Red */
  --fa-wine: #6b151a;
  --fa-fir: #1c1f2e; /* Midnight Skyline */
  --fa-cream: #f5f0f2;
  --fa-surface: #fffbfa;
  --fa-text: #241f26;
  --fa-text-muted: #786f78;
  --fa-text-on-primary: #f6f2fc;
  --fa-border: #ddd0d8;
  --fa-border-focus: #3c2a78;
  --fa-alert-danger-bg: #f7dcdd;
  --fa-alert-success-bg: #e0ece0;
  --fa-alert-info-bg: #dbe8ea;
}

:root[data-fa-palette=india-henna] {
  /* --- India — mehndi henna red-brown, turmeric gold, leaf-green accent, kumkum-vermillion danger. --- */
  --fa-primary: #8a3a24; /* Henna Red-Brown */
  --fa-primary-dark: #5c2617;
  --fa-primary-light: #c07050;
  --fa-footer: #f0dfc0; /* Henna-Paper Tan */
  --fa-glow: #a8532f;
  --fa-gold: #e0a13c; /* Turmeric Gold */
  --fa-accent: #5c7a3a; /* Mehndi Leaf Green */
  --fa-accent-dark: #3f5527;
  --fa-ember: #b23428; /* Kumkum Vermillion */
  --fa-wine: #5c1a1c;
  --fa-fir: #232a3a; /* Indigo Night */
  --fa-cream: #f7ede0;
  --fa-surface: #fffaf2;
  --fa-text: #2e2318;
  --fa-text-muted: #85735d;
  --fa-text-on-primary: #faf1ec;
  --fa-border: #e0c7a0;
  --fa-border-focus: #5c2617;
  --fa-alert-danger-bg: #f7dcd6;
  --fa-alert-success-bg: #e9efdc;
  --fa-alert-info-bg: #dde6ee;
}

:root[data-fa-palette=ruckus] {
  /* --- Ruckus — a sidewalk rack of folded shirts, sorted dark-to-light: charcoal
     stack up top down through cobalt, moss, dusty-rose clearance tags, and khaki
     twine tickets. Not a place/season like the rest of the set — a rack, not a
     region — so primary comes from the rack's one true standout color instead of
     a national or seasonal reference: the cobalt blue folded partway down the
     stack. Danger deliberately isn't a true red (there wasn't one on the rack) —
     it's the dustiest rose deepened into a "clearance sticker" brick instead,
     staying honest to what was actually hanging there. --- */
  --fa-primary: #3b57cf; /* Cobalt Rack */
  --fa-primary-dark: #26399b;
  --fa-primary-light: #7f93e0;
  --fa-footer: #f7e2e4; /* Petal Pink */
  --fa-glow: #4f6ee0;
  --fa-gold: #b99a5a; /* Tag Twine Gold */
  --fa-accent: #6e9150; /* Moss Bright */
  --fa-accent-dark: #4c6650; /* Forest Muted */
  --fa-ember: #a85c62; /* Clearance Tag Red */
  --fa-wine: #6b3238;
  --fa-fir: #2a2b30; /* Ruckus Charcoal */
  --fa-cream: #f7f3ec;
  --fa-surface: #fffdf9;
  --fa-text: #2a2b30;
  --fa-text-muted: #7d7669;
  --fa-text-on-primary: #f3f5ff;
  --fa-border: #d7dcee;
  --fa-border-focus: #26399b;
  --fa-alert-danger-bg: #f6e3e3;
  --fa-alert-success-bg: #e9efe1;
  --fa-alert-info-bg: #e2e6f7;
}

:root[data-fa-palette=dinner] {
  /* --- Dinner — pulled straight from a photo of an antique dealer's table set for
     browsing: sun-warmed walnut tabletop and shelving for primary, a brass pepper
     mill for gold, a dusty sage book-spine green for accent, a mounted antler's
     rust-brown for danger, and the wire cafe chairs' charcoal grounding everything
     as the "black" anchor. Like Ruckus, this isn't a place/season — it's a scene,
     so primary comes from the single warmest wood tone across the whole table
     rather than a national/seasonal reference. --- */
  --fa-primary: #a8672e; /* Walnut Tabletop */
  --fa-primary-dark: #7a4820;
  --fa-primary-light: #cf9a63;
  --fa-footer: #ece4d3; /* Stucco Wall Cream */
  --fa-glow: #c9843d;
  --fa-gold: #c9a13c; /* Brass Pepper Mill */
  --fa-accent: #4f6b52; /* Book-Spine Sage */
  --fa-accent-dark: #364a38;
  --fa-ember: #a6572c; /* Mounted Antler Rust */
  --fa-wine: #5c2f1c;
  --fa-fir: #2a2825; /* Wire Cafe Chair Charcoal */
  --fa-cream: #f7f1e4;
  --fa-surface: #fffcf5;
  --fa-text: #332818;
  --fa-text-muted: #7d7060;
  --fa-text-on-primary: #fdf6ea;
  --fa-border: #ddc9a0;
  --fa-border-focus: #7a4820;
  --fa-alert-danger-bg: #f5ded2;
  --fa-alert-success-bg: #e2e8dd;
  --fa-alert-info-bg: #f3e5d0;
}

:root[data-fa-palette=hang-in] {
  /* --- Hang'In — lifted straight from an abstract painting leaned against a
     shop wall: a muted slate-grey-blue field of blocky brushwork for primary,
     a mustard-ochre streak for gold, a small dusty teal-blue fragment for
     accent, and a terracotta-rust patch for danger, all grounded by the
     painting's darkest charcoal block. Like Ruckus/Dinner, this one's a scene
     rather than a place/season — the whole story is "colors read off one
     canvas," so nothing here is a national/seasonal reference. --- */
  --fa-primary: #5c6670; /* Slate Grey-Blue Field */
  --fa-primary-dark: #3f4750;
  --fa-primary-light: #9aa3ab;
  --fa-footer: #ece7db; /* Canvas Cream */
  --fa-glow: #7d8993;
  --fa-gold: #b8874a; /* Mustard Ochre Streak */
  --fa-accent: #4f7080; /* Dusty Teal Fragment */
  --fa-accent-dark: #35505c;
  --fa-ember: #a8503a; /* Terracotta Patch */
  --fa-wine: #5c2a1e;
  --fa-fir: #333633; /* Canvas Charcoal Block */
  --fa-cream: #f5f1e6;
  --fa-surface: #fffdf8;
  --fa-text: #2e2b26;
  --fa-text-muted: #7d786d;
  --fa-text-on-primary: #f5f2ec;
  --fa-border: #d6d0c2;
  --fa-border-focus: #3f4750;
  --fa-alert-danger-bg: #f2ded4;
  --fa-alert-success-bg: #dfe8e6;
  --fa-alert-info-bg: #dfe2e6;
}

:root[data-fa-palette=floating] {
  /* --- Floating — lifted from a framed desert-dusk painting: a sunset-peach
     gradient band for primary, a near-black silhouetted ridge for the dark
     neutral anchor, a dusty slate-blue streak (from the canyon-wall half of
     the canvas) for accent, sandy tan for gold, and the dusk sky's deep
     wine-plum for danger. Like Ruckus/Dinner/Hang'In, this is a scene rather
     than a place/season — everything here is read off one canvas. --- */
  --fa-primary: #c9814a; /* Sunset Peach */
  --fa-primary-dark: #8f5a30;
  --fa-primary-light: #e0ac7c;
  --fa-footer: #ede6da; /* Dusk Sky Cream */
  --fa-glow: #d99a5c;
  --fa-gold: #c2a06c; /* Canyon Sand Tan */
  --fa-accent: #6b7a8a; /* Canyon-Wall Slate */
  --fa-accent-dark: #48545f;
  --fa-ember: #7a3f4a; /* Dusk Wine-Plum */
  --fa-wine: #4a232b;
  --fa-fir: #1c1620; /* Silhouetted Ridge */
  --fa-cream: #f2ece1;
  --fa-surface: #fffdf8;
  --fa-text: #2b2530;
  --fa-text-muted: #7d7580;
  --fa-text-on-primary: #fdf3e8;
  --fa-border: #ddd0c4;
  --fa-border-focus: #8f5a30;
  --fa-alert-danger-bg: #f0dfe0;
  --fa-alert-success-bg: #e2e6e8;
  --fa-alert-info-bg: #f5e6d6;
}

:root[data-fa-palette=fit] {
  /* --- Fit — lifted from a photo of a black textured knit shirt with a vivid
     abstract brushstroke print (cobalt blue through emerald green, mustard
     gold, and coral-red speckling) paired with black leather gloves whose
     fingertips are piped in mint, coral, purple, gold, and pink. Primary is
     the brushstroke's cobalt blue, accent its emerald green, gold its mustard
     stripe, danger the coral-red speckling, and the dark neutral anchor is
     the garment's own black knit. Like Ruckus/Dinner/Hang'In/Floating, this
     is a scene rather than a place/season. --- */
  --fa-primary: #1f4fa0; /* Brushstroke Cobalt */
  --fa-primary-dark: #163a78;
  --fa-primary-light: #5f86c9;
  --fa-footer: #ece9e2; /* Gallery Cream */
  --fa-glow: #2f6fc9;
  --fa-gold: #d98a2a; /* Mustard Brushstroke */
  --fa-accent: #2f9e6e; /* Emerald Brushstroke */
  --fa-accent-dark: #1f6e4c;
  --fa-ember: #d9432f; /* Coral Speckle Red */
  --fa-wine: #7a2318;
  --fa-fir: #141414; /* Knit Black */
  --fa-cream: #f5f3ee;
  --fa-surface: #fffefb;
  --fa-text: #201f1c;
  --fa-text-muted: #756f66;
  --fa-text-on-primary: #f5f8fc;
  --fa-border: #d8d4c8;
  --fa-border-focus: #163a78;
  --fa-alert-danger-bg: #f7ddd8;
  --fa-alert-success-bg: #dcefe4;
  --fa-alert-info-bg: #dbe6f5;
}

/* --- Dark mode, per palette. Northwest Fall's dark block (no data-fa-palette
   attribute needed — it's the default) stays a single-attribute selector; every
   other palette needs data-fa-palette AND data-theme="dark" together so it wins
   over the single-attribute selector regardless of source order (two attributes
   beats one, always, independent of where each rule sits in the file). Same
   transform recipe every time: darken cream/surface/footer, lighten text, border-
   focus becomes the palette's --fa-glow, primary-dark becomes primary-light
   (still legible as hover text against a dark surface), accent-dark lightens, and
   the three alert backgrounds become translucent rgba() of ember/accent/primary. */
:root[data-theme=dark] {
  --fa-cream: #1c140d;
  --fa-surface: #261c12;
  --fa-text: #f1e6d6;
  --fa-text-muted: #b7a78d;
  --fa-border: #4a3524;
  --fa-border-focus: #e8873d;
  --fa-footer: #2a2015;
  --fa-primary-dark: #e0895a;
  --fa-accent-dark: #9db06a;
  --fa-alert-danger-bg: rgba(166, 58, 44, 0.22);
  --fa-alert-success-bg: rgba(107, 122, 62, 0.22);
  --fa-alert-info-bg: rgba(191, 91, 38, 0.22);
}

:root[data-fa-palette=southwest-summer][data-theme=dark] {
  --fa-cream: #17140f;
  --fa-surface: #221d15;
  --fa-text: #f0ece2;
  --fa-text-muted: #beb5a4;
  --fa-border: #4a4030;
  --fa-border-focus: #2f96c9;
  --fa-footer: #1f1b12;
  --fa-primary-dark: #6bb0d1;
  --fa-accent-dark: #a985c9;
  --fa-alert-danger-bg: rgba(178, 58, 40, 0.22);
  --fa-alert-success-bg: rgba(122, 79, 158, 0.22);
  --fa-alert-info-bg: rgba(31, 119, 168, 0.22);
}

:root[data-fa-palette=northeast-spring][data-theme=dark] {
  --fa-cream: #170f14;
  --fa-surface: #211621;
  --fa-text: #f2e2ec;
  --fa-text-muted: #c0a6b8;
  --fa-border: #4a3040;
  --fa-border-focus: #c96a97;
  --fa-footer: #241825;
  --fa-primary-dark: #cf8fae;
  --fa-accent-dark: #8fb384;
  --fa-alert-danger-bg: rgba(179, 57, 47, 0.22);
  --fa-alert-success-bg: rgba(90, 143, 79, 0.22);
  --fa-alert-info-bg: rgba(162, 74, 120, 0.22);
}

:root[data-fa-palette=midwest-winter][data-theme=dark] {
  --fa-cream: #0f161c;
  --fa-surface: #172029;
  --fa-text: #e7edf1;
  --fa-text-muted: #a9b7c0;
  --fa-border: #33434f;
  --fa-border-focus: #4f7a94;
  --fa-footer: #1a2530;
  --fa-primary-dark: #7098af;
  --fa-accent-dark: #7a9a7e;
  --fa-alert-danger-bg: rgba(156, 59, 48, 0.22);
  --fa-alert-success-bg: rgba(63, 92, 66, 0.22);
  --fa-alert-info-bg: rgba(61, 90, 115, 0.22);
}

:root[data-fa-palette=southeast-beach][data-theme=dark] {
  --fa-cream: #14100a;
  --fa-surface: #1e170f;
  --fa-text: #f2e9d8;
  --fa-text-muted: #beae94;
  --fa-border: #423a28;
  --fa-border-focus: #3ba6a3;
  --fa-footer: #221b12;
  --fa-primary-dark: #6bbdbb;
  --fa-accent-dark: #a7bb84;
  --fa-alert-danger-bg: rgba(217, 99, 74, 0.22);
  --fa-alert-success-bg: rgba(122, 148, 87, 0.22);
  --fa-alert-info-bg: rgba(44, 140, 138, 0.22);
}

:root[data-fa-palette=greece-aegean][data-theme=dark] {
  --fa-cream: #0d151b;
  --fa-surface: #142029;
  --fa-text: #eef3f6;
  --fa-text-muted: #a9b8c2;
  --fa-border: #294555;
  --fa-border-focus: #2e8fc9;
  --fa-footer: #182430;
  --fa-primary-dark: #5fa8d9;
  --fa-accent-dark: #a1ac82;
  --fa-alert-danger-bg: rgba(193, 85, 47, 0.22);
  --fa-alert-success-bg: rgba(111, 127, 63, 0.22);
  --fa-alert-info-bg: rgba(21, 104, 168, 0.22);
}

:root[data-fa-palette=spain-flamenco][data-theme=dark] {
  --fa-cream: #170f0d;
  --fa-surface: #221614;
  --fa-text: #f3e6df;
  --fa-text-muted: #c2a99e;
  --fa-border: #4a2f28;
  --fa-border-focus: #c23e46;
  --fa-footer: #241512;
  --fa-primary-dark: #d1707a;
  --fa-accent-dark: #aab389;
  --fa-alert-danger-bg: rgba(138, 58, 34, 0.22);
  --fa-alert-success-bg: rgba(124, 138, 74, 0.22);
  --fa-alert-info-bg: rgba(217, 161, 60, 0.22);
}

:root[data-fa-palette=ireland-emerald][data-theme=dark] {
  --fa-cream: #0d1512;
  --fa-surface: #14201a;
  --fa-text: #e9f1ec;
  --fa-text-muted: #a7bcae;
  --fa-border: #2c4536;
  --fa-border-focus: #2c9c63;
  --fa-footer: #182720;
  --fa-primary-dark: #5fb888;
  --fa-accent-dark: #a994b6;
  --fa-alert-danger-bg: rgba(161, 67, 44, 0.22);
  --fa-alert-success-bg: rgba(44, 156, 99, 0.22);
  --fa-alert-info-bg: rgba(122, 90, 143, 0.22);
}

:root[data-fa-palette=jamaica-blue-mountain][data-theme=dark] {
  --fa-cream: #0d1310;
  --fa-surface: #141d18;
  --fa-text: #edf2ee;
  --fa-text-muted: #a9b8ae;
  --fa-border: #2a4540;
  --fa-border-focus: #2c8f8a;
  --fa-footer: #182420;
  --fa-primary-dark: #5fa8a3;
  --fa-accent-dark: #8db382;
  --fa-alert-danger-bg: rgba(178, 51, 72, 0.22);
  --fa-alert-success-bg: rgba(79, 138, 63, 0.22);
  --fa-alert-info-bg: rgba(31, 110, 107, 0.22);
}

:root[data-fa-palette=japan-indigo][data-theme=dark] {
  --fa-cream: #10131c;
  --fa-surface: #171b26;
  --fa-text: #ecedf2;
  --fa-text-muted: #a8adba;
  --fa-border: #2e3550;
  --fa-border-focus: #33518f;
  --fa-footer: #1b202e;
  --fa-primary-dark: #6a80ac;
  --fa-accent-dark: #94a98d;
  --fa-alert-danger-bg: rgba(194, 59, 46, 0.22);
  --fa-alert-success-bg: rgba(91, 122, 79, 0.22);
  --fa-alert-info-bg: rgba(51, 81, 143, 0.22);
}

:root[data-fa-palette=korea-celadon][data-theme=dark] {
  --fa-cream: #0f1512;
  --fa-surface: #172019;
  --fa-text: #eaf0ec;
  --fa-text-muted: #a7b7ac;
  --fa-border: #2c453a;
  --fa-border-focus: #5fa08d;
  --fa-footer: #182420;
  --fa-primary-dark: #8fc0af;
  --fa-accent-dark: #80a1c0;
  --fa-alert-danger-bg: rgba(178, 59, 48, 0.22);
  --fa-alert-success-bg: rgba(79, 138, 113, 0.22);
  --fa-alert-info-bg: rgba(60, 110, 158, 0.22);
}

:root[data-fa-palette=china-cinnabar][data-theme=dark] {
  --fa-cream: #160f0c;
  --fa-surface: #221712;
  --fa-text: #f2e6da;
  --fa-text-muted: #c0a996;
  --fa-border: #4a3524;
  --fa-border-focus: #cf4a35;
  --fa-footer: #241813;
  --fa-primary-dark: #d97c6f;
  --fa-accent-dark: #82b3a1;
  --fa-alert-danger-bg: rgba(138, 42, 30, 0.22);
  --fa-alert-success-bg: rgba(63, 138, 111, 0.22);
  --fa-alert-info-bg: rgba(212, 169, 47, 0.22);
}

:root[data-fa-palette=india-peacock][data-theme=dark] {
  --fa-cream: #0d1312;
  --fa-surface: #141d1c;
  --fa-text: #e9f0ee;
  --fa-text-muted: #a4b7b2;
  --fa-border: #2a453f;
  --fa-border-focus: #1f8b95;
  --fa-footer: #182420;
  --fa-primary-dark: #4fa3ab;
  --fa-accent-dark: #8bb382;
  --fa-alert-danger-bg: rgba(178, 52, 88, 0.22);
  --fa-alert-success-bg: rgba(76, 138, 63, 0.22);
  --fa-alert-info-bg: rgba(31, 139, 149, 0.22);
}

:root[data-fa-palette=cameroon-rainforest][data-theme=dark] {
  --fa-cream: #0f130c;
  --fa-surface: #171e12;
  --fa-text: #edf1e6;
  --fa-text-muted: #a8b39a;
  --fa-border: #3a4a2c;
  --fa-border-focus: #338a54;
  --fa-footer: #1c2415;
  --fa-primary-dark: #5fa878;
  --fa-accent-dark: #78a1b3;
  --fa-alert-danger-bg: rgba(166, 59, 40, 0.22);
  --fa-alert-success-bg: rgba(51, 138, 84, 0.22);
  --fa-alert-info-bg: rgba(47, 110, 138, 0.22);
}

:root[data-fa-palette=sahara-desert][data-theme=dark] {
  --fa-cream: #17130d;
  --fa-surface: #221c13;
  --fa-text: #f0e6d4;
  --fa-text-muted: #b8a98d;
  --fa-border: #4a3c24;
  --fa-border-focus: #e0973a;
  --fa-footer: #241d13;
  --fa-primary-dark: #d9a866;
  --fa-accent-dark: #8ba66a;
  --fa-alert-danger-bg: rgba(168, 69, 46, 0.22);
  --fa-alert-success-bg: rgba(92, 122, 58, 0.22);
  --fa-alert-info-bg: rgba(224, 151, 58, 0.22);
}

:root[data-fa-palette=brazil-rainforest][data-theme=dark] {
  --fa-cream: #0d130f;
  --fa-surface: #141d17;
  --fa-text: #e9f0e6;
  --fa-text-muted: #a4b79f;
  --fa-border: #2a452f;
  --fa-border-focus: #2f8a63;
  --fa-footer: #182016;
  --fa-primary-dark: #5fa887;
  --fa-accent-dark: #e89a5c;
  --fa-alert-danger-bg: rgba(178, 51, 40, 0.22);
  --fa-alert-success-bg: rgba(31, 107, 79, 0.22);
  --fa-alert-info-bg: rgba(217, 114, 44, 0.22);
}

:root[data-fa-palette=brazil-favela][data-theme=dark] {
  --fa-cream: #150d12;
  --fa-surface: #1f141b;
  --fa-text: #f0e2ea;
  --fa-text-muted: #b596a5;
  --fa-border: #45242f;
  --fa-border-focus: #d9367e;
  --fa-footer: #24141c;
  --fa-primary-dark: #e069a3;
  --fa-accent-dark: #5aa8d1;
  --fa-alert-danger-bg: rgba(194, 54, 43, 0.22);
  --fa-alert-success-bg: rgba(232, 181, 46, 0.22);
  --fa-alert-info-bg: rgba(31, 122, 178, 0.22);
}

:root[data-fa-palette=portugal-tiles][data-theme=dark] {
  --fa-cream: #0f1418;
  --fa-surface: #171f26;
  --fa-text: #e6edf2;
  --fa-text-muted: #a0acb5;
  --fa-border: #2a3a45;
  --fa-border-focus: #3a7ab0;
  --fa-footer: #1c2731;
  --fa-primary-dark: #6ea3c9;
  --fa-accent-dark: #d9926a;
  --fa-alert-danger-bg: rgba(168, 52, 47, 0.22);
  --fa-alert-success-bg: rgba(217, 165, 60, 0.22);
  --fa-alert-info-bg: rgba(58, 122, 176, 0.22);
}

:root[data-fa-palette=spain-bullfighting][data-theme=dark] {
  --fa-cream: #140d12;
  --fa-surface: #1e141b;
  --fa-text: #ede0e6;
  --fa-text-muted: #b39aa8;
  --fa-border: #3f2a38;
  --fa-border-focus: #a83a74;
  --fa-footer: #20141b;
  --fa-primary-dark: #b96a95;
  --fa-accent-dark: #6a9a64;
  --fa-alert-danger-bg: rgba(168, 39, 44, 0.22);
  --fa-alert-success-bg: rgba(63, 107, 58, 0.22);
  --fa-alert-info-bg: rgba(201, 152, 46, 0.22);
}

:root[data-fa-palette=mexico-day-of-the-dead][data-theme=dark] {
  --fa-cream: #130d17;
  --fa-surface: #1c1420;
  --fa-text: #ede0f0;
  --fa-text-muted: #b09ab8;
  --fa-border: #3a2a45;
  --fa-border-focus: #8a3d8f;
  --fa-footer: #1a1420;
  --fa-primary-dark: #9c66a0;
  --fa-accent-dark: #e8a75c;
  --fa-alert-danger-bg: rgba(168, 52, 46, 0.22);
  --fa-alert-success-bg: rgba(232, 194, 58, 0.22);
  --fa-alert-info-bg: rgba(138, 61, 143, 0.22);
}

:root[data-fa-palette=london-life][data-theme=dark] {
  --fa-cream: #14161a;
  --fa-surface: #1c1f24;
  --fa-text: #e8eaec;
  --fa-text-muted: #a0a5ab;
  --fa-border: #30363d;
  --fa-border-focus: #2f5f9e;
  --fa-footer: #1a1d22;
  --fa-primary-dark: #5a83b3;
  --fa-accent-dark: #d9636a;
  --fa-alert-danger-bg: rgba(143, 31, 40, 0.22);
  --fa-alert-success-bg: rgba(182, 146, 60, 0.22);
  --fa-alert-info-bg: rgba(47, 95, 158, 0.22);
}

:root[data-fa-palette=new-york-nightlife][data-theme=dark] {
  --fa-cream: #130f18;
  --fa-surface: #1c1622;
  --fa-text: #ede6f0;
  --fa-text-muted: #a89ab5;
  --fa-border: #352a45;
  --fa-border-focus: #7454d6;
  --fa-footer: #191320;
  --fa-primary-dark: #9683d4;
  --fa-accent-dark: #4ec4de;
  --fa-alert-danger-bg: rgba(194, 39, 46, 0.22);
  --fa-alert-success-bg: rgba(21, 150, 176, 0.22);
  --fa-alert-info-bg: rgba(232, 177, 58, 0.22);
}

:root[data-fa-palette=india-henna][data-theme=dark] {
  --fa-cream: #130e0c;
  --fa-surface: #1e1712;
  --fa-text: #f0e6da;
  --fa-text-muted: #b5a58d;
  --fa-border: #45351f;
  --fa-border-focus: #a8532f;
  --fa-footer: #201810;
  --fa-primary-dark: #c07050;
  --fa-accent-dark: #8ba668;
  --fa-alert-danger-bg: rgba(178, 52, 40, 0.22);
  --fa-alert-success-bg: rgba(92, 122, 58, 0.22);
  --fa-alert-info-bg: rgba(224, 161, 60, 0.22);
}

:root[data-fa-palette=ruckus][data-theme=dark] {
  --fa-cream: #16151a;
  --fa-surface: #201e23;
  --fa-text: #efece4;
  --fa-text-muted: #b3aca0;
  --fa-border: #3a3742;
  --fa-border-focus: #4f6ee0;
  --fa-footer: #241a1d;
  --fa-primary-dark: #7f93e0;
  --fa-accent-dark: #a0c17f;
  --fa-alert-danger-bg: rgba(168, 92, 98, 0.22);
  --fa-alert-success-bg: rgba(110, 145, 80, 0.22);
  --fa-alert-info-bg: rgba(59, 87, 207, 0.22);
}

:root[data-fa-palette=dinner][data-theme=dark] {
  --fa-cream: #16110a;
  --fa-surface: #201a10;
  --fa-text: #f0e6d4;
  --fa-text-muted: #b7a78d;
  --fa-border: #4a3a24;
  --fa-border-focus: #c9843d;
  --fa-footer: #241d12;
  --fa-primary-dark: #cf9a63;
  --fa-accent-dark: #8aab86;
  --fa-alert-danger-bg: rgba(166, 87, 44, 0.22);
  --fa-alert-success-bg: rgba(79, 107, 82, 0.22);
  --fa-alert-info-bg: rgba(168, 103, 46, 0.22);
}

:root[data-fa-palette=hang-in][data-theme=dark] {
  --fa-cream: #131210;
  --fa-surface: #1c1a17;
  --fa-text: #ece7db;
  --fa-text-muted: #b0a99a;
  --fa-border: #443f38;
  --fa-border-focus: #7d8993;
  --fa-footer: #201e1a;
  --fa-primary-dark: #9aa3ab;
  --fa-accent-dark: #7fa3ae;
  --fa-alert-danger-bg: rgba(168, 80, 58, 0.22);
  --fa-alert-success-bg: rgba(79, 112, 128, 0.22);
  --fa-alert-info-bg: rgba(92, 102, 112, 0.22);
}

:root[data-fa-palette=floating][data-theme=dark] {
  --fa-cream: #14100e;
  --fa-surface: #1e1815;
  --fa-text: #ede6df;
  --fa-text-muted: #b0a89f;
  --fa-border: #453a34;
  --fa-border-focus: #d99a5c;
  --fa-footer: #201a17;
  --fa-primary-dark: #e0ac7c;
  --fa-accent-dark: #93a3b0;
  --fa-alert-danger-bg: rgba(122, 63, 74, 0.22);
  --fa-alert-success-bg: rgba(107, 122, 138, 0.22);
  --fa-alert-info-bg: rgba(201, 129, 74, 0.22);
}

:root[data-fa-palette=fit][data-theme=dark] {
  --fa-cream: #0e0e0c;
  --fa-surface: #171613;
  --fa-text: #ece9e0;
  --fa-text-muted: #b0a99c;
  --fa-border: #3a362c;
  --fa-border-focus: #2f6fc9;
  --fa-footer: #1a1916;
  --fa-primary-dark: #5f86c9;
  --fa-accent-dark: #6bc79a;
  --fa-alert-danger-bg: rgba(217, 67, 47, 0.22);
  --fa-alert-success-bg: rgba(47, 158, 110, 0.22);
  --fa-alert-info-bg: rgba(31, 79, 160, 0.22);
}

/* --- Same dark values again, gated on prefers-color-scheme instead of an explicit
   data-theme="dark" — the OS-level fallback before any explicit mode choice. --- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #1c140d;
    --fa-surface: #261c12;
    --fa-text: #f1e6d6;
    --fa-text-muted: #b7a78d;
    --fa-border: #4a3524;
    --fa-border-focus: #e8873d;
    --fa-footer: #2a2015;
    --fa-primary-dark: #e0895a;
    --fa-accent-dark: #9db06a;
    --fa-alert-danger-bg: rgba(166, 58, 44, 0.22);
    --fa-alert-success-bg: rgba(107, 122, 62, 0.22);
    --fa-alert-info-bg: rgba(191, 91, 38, 0.22);
  }
  :root[data-fa-palette=southwest-summer]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #17140f;
    --fa-surface: #221d15;
    --fa-text: #f0ece2;
    --fa-text-muted: #beb5a4;
    --fa-border: #4a4030;
    --fa-border-focus: #2f96c9;
    --fa-footer: #1f1b12;
    --fa-primary-dark: #6bb0d1;
    --fa-accent-dark: #a985c9;
    --fa-alert-danger-bg: rgba(178, 58, 40, 0.22);
    --fa-alert-success-bg: rgba(122, 79, 158, 0.22);
    --fa-alert-info-bg: rgba(31, 119, 168, 0.22);
  }
  :root[data-fa-palette=northeast-spring]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #170f14;
    --fa-surface: #211621;
    --fa-text: #f2e2ec;
    --fa-text-muted: #c0a6b8;
    --fa-border: #4a3040;
    --fa-border-focus: #c96a97;
    --fa-footer: #241825;
    --fa-primary-dark: #cf8fae;
    --fa-accent-dark: #8fb384;
    --fa-alert-danger-bg: rgba(179, 57, 47, 0.22);
    --fa-alert-success-bg: rgba(90, 143, 79, 0.22);
    --fa-alert-info-bg: rgba(162, 74, 120, 0.22);
  }
  :root[data-fa-palette=midwest-winter]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #0f161c;
    --fa-surface: #172029;
    --fa-text: #e7edf1;
    --fa-text-muted: #a9b7c0;
    --fa-border: #33434f;
    --fa-border-focus: #4f7a94;
    --fa-footer: #1a2530;
    --fa-primary-dark: #7098af;
    --fa-accent-dark: #7a9a7e;
    --fa-alert-danger-bg: rgba(156, 59, 48, 0.22);
    --fa-alert-success-bg: rgba(63, 92, 66, 0.22);
    --fa-alert-info-bg: rgba(61, 90, 115, 0.22);
  }
  :root[data-fa-palette=southeast-beach]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #14100a;
    --fa-surface: #1e170f;
    --fa-text: #f2e9d8;
    --fa-text-muted: #beae94;
    --fa-border: #423a28;
    --fa-border-focus: #3ba6a3;
    --fa-footer: #221b12;
    --fa-primary-dark: #6bbdbb;
    --fa-accent-dark: #a7bb84;
    --fa-alert-danger-bg: rgba(217, 99, 74, 0.22);
    --fa-alert-success-bg: rgba(122, 148, 87, 0.22);
    --fa-alert-info-bg: rgba(44, 140, 138, 0.22);
  }
  :root[data-fa-palette=greece-aegean]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #0d151b;
    --fa-surface: #142029;
    --fa-text: #eef3f6;
    --fa-text-muted: #a9b8c2;
    --fa-border: #294555;
    --fa-border-focus: #2e8fc9;
    --fa-footer: #182430;
    --fa-primary-dark: #5fa8d9;
    --fa-accent-dark: #a1ac82;
    --fa-alert-danger-bg: rgba(193, 85, 47, 0.22);
    --fa-alert-success-bg: rgba(111, 127, 63, 0.22);
    --fa-alert-info-bg: rgba(21, 104, 168, 0.22);
  }
  :root[data-fa-palette=spain-flamenco]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #170f0d;
    --fa-surface: #221614;
    --fa-text: #f3e6df;
    --fa-text-muted: #c2a99e;
    --fa-border: #4a2f28;
    --fa-border-focus: #c23e46;
    --fa-footer: #241512;
    --fa-primary-dark: #d1707a;
    --fa-accent-dark: #aab389;
    --fa-alert-danger-bg: rgba(138, 58, 34, 0.22);
    --fa-alert-success-bg: rgba(124, 138, 74, 0.22);
    --fa-alert-info-bg: rgba(217, 161, 60, 0.22);
  }
  :root[data-fa-palette=ireland-emerald]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #0d1512;
    --fa-surface: #14201a;
    --fa-text: #e9f1ec;
    --fa-text-muted: #a7bcae;
    --fa-border: #2c4536;
    --fa-border-focus: #2c9c63;
    --fa-footer: #182720;
    --fa-primary-dark: #5fb888;
    --fa-accent-dark: #a994b6;
    --fa-alert-danger-bg: rgba(161, 67, 44, 0.22);
    --fa-alert-success-bg: rgba(44, 156, 99, 0.22);
    --fa-alert-info-bg: rgba(122, 90, 143, 0.22);
  }
  :root[data-fa-palette=jamaica-blue-mountain]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #0d1310;
    --fa-surface: #141d18;
    --fa-text: #edf2ee;
    --fa-text-muted: #a9b8ae;
    --fa-border: #2a4540;
    --fa-border-focus: #2c8f8a;
    --fa-footer: #182420;
    --fa-primary-dark: #5fa8a3;
    --fa-accent-dark: #8db382;
    --fa-alert-danger-bg: rgba(178, 51, 72, 0.22);
    --fa-alert-success-bg: rgba(79, 138, 63, 0.22);
    --fa-alert-info-bg: rgba(31, 110, 107, 0.22);
  }
  :root[data-fa-palette=japan-indigo]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #10131c;
    --fa-surface: #171b26;
    --fa-text: #ecedf2;
    --fa-text-muted: #a8adba;
    --fa-border: #2e3550;
    --fa-border-focus: #33518f;
    --fa-footer: #1b202e;
    --fa-primary-dark: #6a80ac;
    --fa-accent-dark: #94a98d;
    --fa-alert-danger-bg: rgba(194, 59, 46, 0.22);
    --fa-alert-success-bg: rgba(91, 122, 79, 0.22);
    --fa-alert-info-bg: rgba(51, 81, 143, 0.22);
  }
  :root[data-fa-palette=korea-celadon]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #0f1512;
    --fa-surface: #172019;
    --fa-text: #eaf0ec;
    --fa-text-muted: #a7b7ac;
    --fa-border: #2c453a;
    --fa-border-focus: #5fa08d;
    --fa-footer: #182420;
    --fa-primary-dark: #8fc0af;
    --fa-accent-dark: #80a1c0;
    --fa-alert-danger-bg: rgba(178, 59, 48, 0.22);
    --fa-alert-success-bg: rgba(79, 138, 113, 0.22);
    --fa-alert-info-bg: rgba(60, 110, 158, 0.22);
  }
  :root[data-fa-palette=china-cinnabar]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #160f0c;
    --fa-surface: #221712;
    --fa-text: #f2e6da;
    --fa-text-muted: #c0a996;
    --fa-border: #4a3524;
    --fa-border-focus: #cf4a35;
    --fa-footer: #241813;
    --fa-primary-dark: #d97c6f;
    --fa-accent-dark: #82b3a1;
    --fa-alert-danger-bg: rgba(138, 42, 30, 0.22);
    --fa-alert-success-bg: rgba(63, 138, 111, 0.22);
    --fa-alert-info-bg: rgba(212, 169, 47, 0.22);
  }
  :root[data-fa-palette=india-peacock]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #0d1312;
    --fa-surface: #141d1c;
    --fa-text: #e9f0ee;
    --fa-text-muted: #a4b7b2;
    --fa-border: #2a453f;
    --fa-border-focus: #1f8b95;
    --fa-footer: #182420;
    --fa-primary-dark: #4fa3ab;
    --fa-accent-dark: #8bb382;
    --fa-alert-danger-bg: rgba(178, 52, 88, 0.22);
    --fa-alert-success-bg: rgba(76, 138, 63, 0.22);
    --fa-alert-info-bg: rgba(31, 139, 149, 0.22);
  }
  :root[data-fa-palette=cameroon-rainforest]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #0f130c;
    --fa-surface: #171e12;
    --fa-text: #edf1e6;
    --fa-text-muted: #a8b39a;
    --fa-border: #3a4a2c;
    --fa-border-focus: #338a54;
    --fa-footer: #1c2415;
    --fa-primary-dark: #5fa878;
    --fa-accent-dark: #78a1b3;
    --fa-alert-danger-bg: rgba(166, 59, 40, 0.22);
    --fa-alert-success-bg: rgba(51, 138, 84, 0.22);
    --fa-alert-info-bg: rgba(47, 110, 138, 0.22);
  }
  :root[data-fa-palette=sahara-desert]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #17130d;
    --fa-surface: #221c13;
    --fa-text: #f0e6d4;
    --fa-text-muted: #b8a98d;
    --fa-border: #4a3c24;
    --fa-border-focus: #e0973a;
    --fa-footer: #241d13;
    --fa-primary-dark: #d9a866;
    --fa-accent-dark: #8ba66a;
    --fa-alert-danger-bg: rgba(168, 69, 46, 0.22);
    --fa-alert-success-bg: rgba(92, 122, 58, 0.22);
    --fa-alert-info-bg: rgba(224, 151, 58, 0.22);
  }
  :root[data-fa-palette=brazil-rainforest]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #0d130f;
    --fa-surface: #141d17;
    --fa-text: #e9f0e6;
    --fa-text-muted: #a4b79f;
    --fa-border: #2a452f;
    --fa-border-focus: #2f8a63;
    --fa-footer: #182016;
    --fa-primary-dark: #5fa887;
    --fa-accent-dark: #e89a5c;
    --fa-alert-danger-bg: rgba(178, 51, 40, 0.22);
    --fa-alert-success-bg: rgba(31, 107, 79, 0.22);
    --fa-alert-info-bg: rgba(217, 114, 44, 0.22);
  }
  :root[data-fa-palette=brazil-favela]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #150d12;
    --fa-surface: #1f141b;
    --fa-text: #f0e2ea;
    --fa-text-muted: #b596a5;
    --fa-border: #45242f;
    --fa-border-focus: #d9367e;
    --fa-footer: #24141c;
    --fa-primary-dark: #e069a3;
    --fa-accent-dark: #5aa8d1;
    --fa-alert-danger-bg: rgba(194, 54, 43, 0.22);
    --fa-alert-success-bg: rgba(232, 181, 46, 0.22);
    --fa-alert-info-bg: rgba(31, 122, 178, 0.22);
  }
  :root[data-fa-palette=portugal-tiles]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #0f1418;
    --fa-surface: #171f26;
    --fa-text: #e6edf2;
    --fa-text-muted: #a0acb5;
    --fa-border: #2a3a45;
    --fa-border-focus: #3a7ab0;
    --fa-footer: #1c2731;
    --fa-primary-dark: #6ea3c9;
    --fa-accent-dark: #d9926a;
    --fa-alert-danger-bg: rgba(168, 52, 47, 0.22);
    --fa-alert-success-bg: rgba(217, 165, 60, 0.22);
    --fa-alert-info-bg: rgba(58, 122, 176, 0.22);
  }
  :root[data-fa-palette=spain-bullfighting]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #140d12;
    --fa-surface: #1e141b;
    --fa-text: #ede0e6;
    --fa-text-muted: #b39aa8;
    --fa-border: #3f2a38;
    --fa-border-focus: #a83a74;
    --fa-footer: #20141b;
    --fa-primary-dark: #b96a95;
    --fa-accent-dark: #6a9a64;
    --fa-alert-danger-bg: rgba(168, 39, 44, 0.22);
    --fa-alert-success-bg: rgba(63, 107, 58, 0.22);
    --fa-alert-info-bg: rgba(201, 152, 46, 0.22);
  }
  :root[data-fa-palette=mexico-day-of-the-dead]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #130d17;
    --fa-surface: #1c1420;
    --fa-text: #ede0f0;
    --fa-text-muted: #b09ab8;
    --fa-border: #3a2a45;
    --fa-border-focus: #8a3d8f;
    --fa-footer: #1a1420;
    --fa-primary-dark: #9c66a0;
    --fa-accent-dark: #e8a75c;
    --fa-alert-danger-bg: rgba(168, 52, 46, 0.22);
    --fa-alert-success-bg: rgba(232, 194, 58, 0.22);
    --fa-alert-info-bg: rgba(138, 61, 143, 0.22);
  }
  :root[data-fa-palette=london-life]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #14161a;
    --fa-surface: #1c1f24;
    --fa-text: #e8eaec;
    --fa-text-muted: #a0a5ab;
    --fa-border: #30363d;
    --fa-border-focus: #2f5f9e;
    --fa-footer: #1a1d22;
    --fa-primary-dark: #5a83b3;
    --fa-accent-dark: #d9636a;
    --fa-alert-danger-bg: rgba(143, 31, 40, 0.22);
    --fa-alert-success-bg: rgba(182, 146, 60, 0.22);
    --fa-alert-info-bg: rgba(47, 95, 158, 0.22);
  }
  :root[data-fa-palette=new-york-nightlife]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #130f18;
    --fa-surface: #1c1622;
    --fa-text: #ede6f0;
    --fa-text-muted: #a89ab5;
    --fa-border: #352a45;
    --fa-border-focus: #7454d6;
    --fa-footer: #191320;
    --fa-primary-dark: #9683d4;
    --fa-accent-dark: #4ec4de;
    --fa-alert-danger-bg: rgba(194, 39, 46, 0.22);
    --fa-alert-success-bg: rgba(21, 150, 176, 0.22);
    --fa-alert-info-bg: rgba(232, 177, 58, 0.22);
  }
  :root[data-fa-palette=india-henna]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #130e0c;
    --fa-surface: #1e1712;
    --fa-text: #f0e6da;
    --fa-text-muted: #b5a58d;
    --fa-border: #45351f;
    --fa-border-focus: #a8532f;
    --fa-footer: #201810;
    --fa-primary-dark: #c07050;
    --fa-accent-dark: #8ba668;
    --fa-alert-danger-bg: rgba(178, 52, 40, 0.22);
    --fa-alert-success-bg: rgba(92, 122, 58, 0.22);
    --fa-alert-info-bg: rgba(224, 161, 60, 0.22);
  }
  :root[data-fa-palette=ruckus]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #16151a;
    --fa-surface: #201e23;
    --fa-text: #efece4;
    --fa-text-muted: #b3aca0;
    --fa-border: #3a3742;
    --fa-border-focus: #4f6ee0;
    --fa-footer: #241a1d;
    --fa-primary-dark: #7f93e0;
    --fa-accent-dark: #a0c17f;
    --fa-alert-danger-bg: rgba(168, 92, 98, 0.22);
    --fa-alert-success-bg: rgba(110, 145, 80, 0.22);
    --fa-alert-info-bg: rgba(59, 87, 207, 0.22);
  }
  :root[data-fa-palette=dinner]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #16110a;
    --fa-surface: #201a10;
    --fa-text: #f0e6d4;
    --fa-text-muted: #b7a78d;
    --fa-border: #4a3a24;
    --fa-border-focus: #c9843d;
    --fa-footer: #241d12;
    --fa-primary-dark: #cf9a63;
    --fa-accent-dark: #8aab86;
    --fa-alert-danger-bg: rgba(166, 87, 44, 0.22);
    --fa-alert-success-bg: rgba(79, 107, 82, 0.22);
    --fa-alert-info-bg: rgba(168, 103, 46, 0.22);
  }
  :root[data-fa-palette=hang-in]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #131210;
    --fa-surface: #1c1a17;
    --fa-text: #ece7db;
    --fa-text-muted: #b0a99a;
    --fa-border: #443f38;
    --fa-border-focus: #7d8993;
    --fa-footer: #201e1a;
    --fa-primary-dark: #9aa3ab;
    --fa-accent-dark: #7fa3ae;
    --fa-alert-danger-bg: rgba(168, 80, 58, 0.22);
    --fa-alert-success-bg: rgba(79, 112, 128, 0.22);
    --fa-alert-info-bg: rgba(92, 102, 112, 0.22);
  }
  :root[data-fa-palette=floating]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #14100e;
    --fa-surface: #1e1815;
    --fa-text: #ede6df;
    --fa-text-muted: #b0a89f;
    --fa-border: #453a34;
    --fa-border-focus: #d99a5c;
    --fa-footer: #201a17;
    --fa-primary-dark: #e0ac7c;
    --fa-accent-dark: #93a3b0;
    --fa-alert-danger-bg: rgba(122, 63, 74, 0.22);
    --fa-alert-success-bg: rgba(107, 122, 138, 0.22);
    --fa-alert-info-bg: rgba(201, 129, 74, 0.22);
  }
  :root[data-fa-palette=fit]:not([data-theme=light]):not([data-theme=colorblind]) {
    --fa-cream: #0e0e0c;
    --fa-surface: #171613;
    --fa-text: #ece9e0;
    --fa-text-muted: #b0a99c;
    --fa-border: #3a362c;
    --fa-border-focus: #2f6fc9;
    --fa-footer: #1a1916;
    --fa-primary-dark: #5f86c9;
    --fa-accent-dark: #6bc79a;
    --fa-alert-danger-bg: rgba(217, 67, 47, 0.22);
    --fa-alert-success-bg: rgba(47, 158, 110, 0.22);
    --fa-alert-info-bg: rgba(31, 79, 160, 0.22);
  }
}
/* Colorblind-safe: swaps the two colors that matter most, the same way regardless
   of which palette is active — deliberately palette-agnostic (this block must stay
   *after* the palette blocks above so it wins the equal-specificity, single-
   attribute tie against whichever data-fa-palette is set). A theme's own accent/
   danger hues are exactly what colorblind mode exists to override, so reusing one
   known-safe pair everywhere is the point, not a shortcut: green and red-orange are
   the pair most likely to collapse into each other under red-green color vision
   deficiency (deuteranopia/protanopia, ~8% of men) in every one of these palettes,
   not just Northwest Fall's. The accent moves to a teal that's distinguishable from
   red under every common CVD type, not just fine-tuned within the red-green axis;
   danger moves to a darker, more desaturated red so it stays readable as "darker/
   more urgent" even when its hue is hard to place. Each palette's primary is left
   alone — it's the brand color, not part of the red/green confusion pair. */
:root[data-theme=colorblind] {
  --fa-accent: #14776b;
  --fa-accent-dark: #0d554c;
  --fa-ember: #8b2e2e;
  --fa-wine: #5c1f2e;
  --fa-fir: #23281f;
  --fa-alert-danger-bg: #f6e5e0;
  --fa-alert-success-bg: #e2ece9;
}

/* ============================= Base / reset ============================= */
/* No third-party CSS library (Bootstrap or otherwise) — this replaces the handful of
   browser-default resets Bootstrap's reboot.css used to provide. */
*, *::before, *::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: var(--fa-font);
  background: var(--fa-cream);
  color: var(--fa-text);
}

h1, h2, h3, h4, h5, h6 {
  margin: 0 0 0.6em;
  font-weight: 700;
}

p {
  margin: 0 0 0.75em;
}

a {
  color: var(--fa-primary-dark);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

table {
  border-collapse: collapse;
}

/* ============================= Page shells ============================= */
.fa-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.fa-shell-main {
  flex: 1;
  padding: 1.75rem 2rem;
}

.fa-shell-sidebar .fa-shell-body {
  flex: 1;
  display: flex;
  flex-direction: row;
  align-items: stretch;
}

/* Wraps <main> + FaFooter together as .fa-shell-body's second flex child (alongside
   the sidebar) instead of the footer trailing after .fa-shell-body as a sibling —
   see FaSidebarShell's own comment on why. min-width: 0 is the usual flex-item fix
   so this column can actually shrink below its content's intrinsic width instead of
   forcing the row wider than the viewport. */
.fa-shell-main-col {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

/* FaStandardShell.ContainScroll / FaSidebarShell.ContainScroll — opt-in, off by
   default. Standard's own .fa-shell above only sets min-height: 100vh, so header,
   sidebar, main, and footer all just grow the document past one viewport and the
   whole page scrolls together — fine for most content, but wrong for a page that
   wants header/sidebar/footer pinned to the viewport edges with only .fa-shell-main
   scrolling internally (a dashboard-style layout). A separate class rather than
   changing .fa-shell itself, so every existing whole-page-scroll consumer is
   unaffected. min-height: 0 undoes the flex-item default of min-height: auto, which
   would otherwise refuse to shrink below content height and never let the intended
   child's overflow kick in. */
.fa-shell-contained {
  height: 100vh;
  overflow: hidden;
}

.fa-shell-contained .fa-shell-body,
.fa-shell-contained .fa-shell-main-col {
  min-height: 0;
}

.fa-shell-contained .fa-shell-main {
  overflow-y: auto;
  min-height: 0;
}

/* A Standard-position sidebar (Sticky/Floating already scroll independently via
   .fa-sidebar-sticky/.fa-sidebar-floating further down) would otherwise just get
   silently clipped by .fa-shell-contained's overflow: hidden once its content is
   taller than the viewport, with no way to reach the rest of it. Scoped to
   .fa-sidebar-scroll rather than .fa-sidebar itself, same reasoning as the
   Sticky/Floating rules below — .fa-sidebar needs to stay overflow: visible so the
   collapse toggle and collapsed-state tooltips can still spill past its edge. */
.fa-shell-contained .fa-sidebar-scroll {
  overflow-y: auto;
  min-height: 0;
}

/* ============================= Header ============================= */
.fa-header {
  background: var(--fa-primary);
  color: var(--fa-text-on-primary);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1.5rem;
  min-height: var(--fa-header-height);
  box-shadow: 0 2px 0 var(--fa-glow), 0 4px 14px rgba(140, 67, 27, 0.35);
}

/* --- FaHeader.Position: Standard (default, no class) scrolls away with the page.
   Sticky/Floating both pin it to the top once scrolled to; Floating additionally
   insets it with margin + rounded corners so it reads as a detached bar instead of
   a full-bleed edge (the header's own box-shadow already gives it the "lifted"
   look, so Floating doesn't need one of its own). --- */
.fa-header-sticky, .fa-header-floating {
  position: sticky;
  top: 0;
  z-index: 40;
}

.fa-header-floating {
  margin: 0.75rem 1rem 0;
  border-radius: var(--fa-radius-lg);
}

.fa-header-left {
  display: flex;
  align-items: center;
  gap: 0.9rem;
}

.fa-header-brand {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--fa-font);
  font-weight: 800;
  font-size: 1.35rem;
  letter-spacing: 0.02em;
  color: var(--fa-text-on-primary);
  text-decoration: none;
}

/* FaHeader.BrandIconUrl — omitted entirely (no img in the markup) when unset. */
.fa-header-brand-icon {
  height: 1.6rem;
  width: auto;
  border-radius: var(--fa-radius-sm);
}

/* FaHeader.ShowSidebarToggle — hidden here unconditionally; _responsive.scss's
   small-screen breakpoint is what actually shows it (and hides .fa-sidebar
   off-canvas until this is clicked). Always present in the markup so there's no
   flash-of-missing-button while CSS loads, just display:none until the
   breakpoint applies. */
.fa-header-menu-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 2.1rem;
  height: 2.1rem;
  flex: none;
  border-radius: var(--fa-radius-md);
  border: none;
  background: rgba(0, 0, 0, 0.14);
  color: var(--fa-text-on-primary);
  cursor: pointer;
  transition: background-color var(--fa-transition-fast);
}

.fa-header-menu-toggle:hover {
  background: rgba(255, 255, 255, 0.16);
}

.fa-header-menu-toggle:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--fa-text-on-primary);
}

.fa-header-user {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.fa-header-username {
  font-weight: 600;
  color: var(--fa-text-on-primary);
}

/* ============================= Theme switcher ============================= */
/* Sits in the header, which stays burnt orange across all three modes — so its
   own icons are always white, regardless of which theme is currently active. */
.fa-theme-switcher {
  display: flex;
  align-items: center;
  gap: 0.2rem;
  background: rgba(0, 0, 0, 0.14);
  border-radius: var(--fa-radius-pill);
  padding: 0.2rem;
}

.fa-theme-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.9rem;
  height: 1.9rem;
  border-radius: 50%;
  border: none;
  background: transparent;
  cursor: pointer;
  opacity: 0.6;
  transition: background-color var(--fa-transition-fast), opacity var(--fa-transition-fast);
}

.fa-theme-btn:hover {
  opacity: 1;
  background: rgba(255, 255, 255, 0.16);
}

.fa-theme-btn.fa-theme-btn-active {
  opacity: 1;
  background: rgba(255, 255, 255, 0.24);
  box-shadow: 0 0 0 2px var(--fa-glow);
}

.fa-theme-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--fa-text-on-primary);
}

/* Same inset-pill treatment as .fa-theme-switcher, but a native <select> instead of a
   button row — fourteen palette options don't fit a pill row the way three theme
   modes do. Sits in the header alongside FaThemeSwitcher, so it wears the same
   always-white-on-burnt-orange styling regardless of the active theme mode. */
.fa-palette-switcher {
  appearance: none;
  font: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--fa-text-on-primary);
  background: rgba(0, 0, 0, 0.14);
  border: none;
  border-radius: var(--fa-radius-pill);
  padding: 0.35rem 1.7rem 0.35rem 0.75rem;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='4 6 8 10 12 6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.55rem center;
  background-size: 0.7rem;
  transition: background-color var(--fa-transition-fast);
}

.fa-palette-switcher:hover {
  background-color: rgba(255, 255, 255, 0.16);
}

.fa-palette-switcher:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--fa-text-on-primary);
}

.fa-palette-switcher option {
  color: var(--fa-text);
  background: var(--fa-surface);
}

/* Unlike FaThemeSwitcher/FaPaletteSwitcher above, FaInputStyleSwitcher isn't
   header-locked — it's just as likely to sit in a settings panel as in the header —
   so it wears normal surface colors instead of the always-white-on-burnt-orange
   header chrome treatment. */
.fa-input-style-switcher {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  background: var(--fa-footer);
  border-radius: var(--fa-radius-pill);
  padding: 0.2rem;
}

.fa-input-style-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.35rem 0.9rem;
  border-radius: var(--fa-radius-pill);
  border: none;
  background: transparent;
  font-family: var(--fa-font);
  font-weight: 600;
  font-size: 0.82rem;
  color: var(--fa-text-muted);
  cursor: pointer;
  transition: background-color var(--fa-transition-fast), color var(--fa-transition-fast);
}

.fa-input-style-btn:hover {
  color: var(--fa-text);
}

.fa-input-style-btn.fa-input-style-btn-active {
  background: var(--fa-surface);
  color: var(--fa-primary-dark);
  box-shadow: var(--fa-border-glow);
}

.fa-input-style-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--fa-border-focus);
}

/* FaUiStyleSwitcher — same "not header-locked" reasoning and identical look as
   FaInputStyleSwitcher just above; kept as its own class pair rather than reusing
   .fa-input-style-switcher/-btn since the two switch genuinely different axes and
   a consumer may want both switchers styled independently later. */
.fa-ui-style-switcher {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  background: var(--fa-footer);
  border-radius: var(--fa-radius-pill);
  padding: 0.2rem;
}

.fa-ui-style-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.35rem 0.9rem;
  border-radius: var(--fa-radius-pill);
  border: none;
  background: transparent;
  font-family: var(--fa-font);
  font-weight: 600;
  font-size: 0.82rem;
  color: var(--fa-text-muted);
  cursor: pointer;
  transition: background-color var(--fa-transition-fast), color var(--fa-transition-fast);
}

.fa-ui-style-btn:hover {
  color: var(--fa-text);
}

.fa-ui-style-btn.fa-ui-style-btn-active {
  background: var(--fa-surface);
  color: var(--fa-primary-dark);
  box-shadow: var(--fa-border-glow);
}

.fa-ui-style-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--fa-border-focus);
}

/* ============================= Footer ============================= */
.fa-footer {
  background: var(--fa-footer);
  color: var(--fa-text-muted);
  text-align: center;
  padding: 0.85rem 1.5rem;
  font-size: 0.9rem;
  border-top: 3px solid var(--fa-glow);
}

/* --- FaFooter.Position: same Standard/Sticky/Floating shape as .fa-header-*
   above, mirrored to the bottom edge instead of the top. --- */
.fa-footer-sticky, .fa-footer-floating {
  position: sticky;
  bottom: 0;
  z-index: 40;
}

.fa-footer-floating {
  margin: 0 1rem 0.75rem;
  border-radius: var(--fa-radius-lg);
}

/* ============================= Sidebar ============================= */
/* Collapse/expand is plain-JS UI state (js/sidebar.js) stamped as .fa-sidebar-collapsed
   on <html>, same pattern as the light/dark/colorblind theme — everything below keys
   off that one class, no Blazor state involved.

   Every collapse-specific selector below is additionally scoped to .fa-sidebar-
   collapsible (FaSidebar.Collapsible, off by default — no toggle renders unless a
   consumer opts in). That scoping is load-bearing, not just descriptive: the
   collapsed/expanded flag lives in localStorage and gets restamped onto <html> on
   every page load regardless of what that page's own sidebar supports, so a
   non-collapsible sidebar sharing a browser profile with a collapsible one
   elsewhere in the app would otherwise still inherit width: 64px/hidden labels from
   a toggle it doesn't even render — with no way for its own missing button to ever
   set the class back. */
/* FaPaletteSwitcher's own CSS (_layout.scss, above) sizes its <select> to the
   header's inline pill — auto-width, sized to fit its longest option text with no
   cap. That's fine in the header, which has room to spare, but the same element
   dropped into a sidebar's ~176px content column (200px minus its own padding)
   simply doesn't fit and got clipped by .fa-sidebar-scroll's overflow-x: hidden.
   Scoped here rather than changing .fa-palette-switcher itself so the header's own
   usage is untouched. */
.fa-sidebar .fa-palette-switcher {
  width: 100%;
  max-width: 100%;
}

.fa-sidebar {
  background: var(--fa-primary);
  width: 200px;
  flex: 0 0 200px;
  padding: 1.25rem 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  box-shadow: 2px 0 0 var(--fa-glow), 4px 0 14px rgba(140, 67, 27, 0.25);
  position: relative;
  overflow: visible; /* the toggle button and collapsed-state tooltips both spill outside the sidebar's own edge */
  transition: width var(--fa-transition-medium), flex-basis var(--fa-transition-medium);
}

html.fa-sidebar-collapsed .fa-sidebar.fa-sidebar-collapsible {
  width: 64px;
  flex-basis: 64px;
  padding-left: 0.5rem;
  padding-right: 0.5rem;
}

/* FaSidebar's ChildContent lives in this wrapper rather than directly in .fa-sidebar
   so that Sticky/Floating's own scrolling (below) can't clip the toggle button, which
   stays a sibling of this div and needs .fa-sidebar's own overflow: visible intact.
   flex: 1 + min-height: 0 (not the flex-item default auto, which would refuse to
   shrink below its content's height and defeat the scrolling entirely) lets it fill
   whatever height .fa-sidebar itself has — its natural content height in Standard,
   or the fixed pinned height in Sticky/Floating below. */
.fa-sidebar-scroll {
  flex: 1;
  min-height: 0;
}

/* --- FaSidebar.Position: unlike the header/footer, pinning the sidebar full-height
   means its own content (nav links) needs to scroll independently once it's taller
   than the viewport, since the sidebar itself no longer scrolls away with the rest
   of the page — hence overflow-y on .fa-sidebar-scroll above once one of these
   applies, rather than just position: sticky. align-self overrides .fa-shell-sidebar
   .fa-shell-body's align-items: stretch, which would otherwise stretch the sidebar to
   its sibling <main>'s (scrolling) height instead of the viewport's.

   top/height are offset by --fa-header-height rather than 0/100vh so the sidebar
   settles in right below the header instead of sliding underneath it — this assumes
   a header of that same standard height sits above it (sticky/floating or not; see
   FaHeader's own min-height), which is how both shells pair them in practice.

   z-index: 41 (one above .fa-header-sticky/-floating's 40) is load-bearing, not
   decorative: position: sticky + z-index here makes .fa-sidebar its own stacking
   context, and everything inside it — including the toggle button below, whatever
   z-index *it* carries — is painted within that context as a unit. A descendant's
   z-index can only out-rank its own siblings; it can never escape its ancestor's
   context to beat something outside it. With this context ranked *below* the
   header's (as it was originally, at 30), the whole sidebar subtree — toggle
   included, regardless of the toggle's own z-index — painted behind the header.
   Since the sidebar's box never actually overlaps the header except at the toggle's
   own negative-margin poke above it, ranking the sidebar's context above the
   header's here doesn't cause the two to fight over any other shared pixels. --- */
.fa-sidebar-sticky, .fa-sidebar-floating {
  position: sticky;
  top: var(--fa-header-height);
  align-self: flex-start;
  height: calc(100vh - var(--fa-header-height));
  z-index: 41;
}

.fa-sidebar-floating {
  top: calc(var(--fa-header-height) + 0.75rem);
  margin: 0.75rem 0 0.75rem 1rem;
  border-radius: var(--fa-radius-lg);
  height: calc(100vh - var(--fa-header-height) - 1.5rem);
}

/* Scoped to .fa-sidebar-scroll, not .fa-sidebar itself — see the comment above it.
   Thin, palette-colored scrollbar instead of the browser's chunky default; Firefox
   via the standard property, Chromium/WebKit via the vendor pseudo-elements (no
   standard equivalent yet, so both are needed to cover every browser).

   overflow-x: hidden is explicit, not the default — leaving it unset meant the
   browser silently force-converted it to auto too (the CSS overflow spec does this
   whenever one axis is scrollable and the other is left as visible), and a nav link
   sitting even a pixel wider than the sidebar's own content box — an icon + label
   that just brushes the edge, a palette <select> at its intrinsic width — was enough
   to pop open a second, horizontal scrollbar nobody wanted. */
.fa-sidebar-sticky .fa-sidebar-scroll,
.fa-sidebar-floating .fa-sidebar-scroll {
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
  scrollbar-color: var(--fa-glow) transparent;
}

.fa-sidebar-sticky .fa-sidebar-scroll::-webkit-scrollbar,
.fa-sidebar-floating .fa-sidebar-scroll::-webkit-scrollbar {
  width: 6px;
}

/* Without this, Chromium/WebKit still draws its native up/down arrow buttons at
   the scrollbar's ends — chunky and out of place next to the thin thumb/track
   above, which is the whole point of styling those in the first place. */
.fa-sidebar-sticky .fa-sidebar-scroll::-webkit-scrollbar-button,
.fa-sidebar-floating .fa-sidebar-scroll::-webkit-scrollbar-button {
  display: none;
}

.fa-sidebar-sticky .fa-sidebar-scroll::-webkit-scrollbar-thumb,
.fa-sidebar-floating .fa-sidebar-scroll::-webkit-scrollbar-thumb {
  background: var(--fa-glow);
  border-radius: var(--fa-radius-pill);
}

.fa-sidebar-sticky .fa-sidebar-scroll::-webkit-scrollbar-track,
.fa-sidebar-floating .fa-sidebar-scroll::-webkit-scrollbar-track {
  background: transparent;
}

.fa-sidebar-toggle {
  position: absolute;
  /* Sits right at the sidebar's top edge and pokes up a little over the header
     above it. This z-index is only ever compared against its own siblings inside
     .fa-sidebar's stacking context (the collapsed-tooltip ::after at z-index: 30
     is the only other one) — getting the toggle above the header itself is
     .fa-sidebar-sticky/-floating's own z-index (see its comment above), not this
     one. A larger number here wouldn't fix a header that outranks its ancestor. */
  top: -0.65rem;
  right: -0.85rem;
  width: 1.7rem;
  height: 1.7rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: var(--fa-border-width) solid var(--fa-glow);
  background: var(--fa-primary-dark);
  color: var(--fa-text-on-primary);
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  z-index: 31;
  transition: transform var(--fa-transition-medium), background-color var(--fa-transition-fast);
}

.fa-sidebar-toggle:hover {
  background: var(--fa-primary);
}

.fa-sidebar-toggle:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--fa-text-on-primary);
}

.fa-sidebar-toggle svg {
  transition: transform var(--fa-transition-medium);
}

html.fa-sidebar-collapsed .fa-sidebar-toggle svg {
  transform: rotate(180deg);
}

.fa-sidebar-link {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.6rem 0.9rem;
  border-radius: var(--fa-radius-md);
  color: var(--fa-text-on-primary);
  text-decoration: none;
  font-weight: 600;
  opacity: 0.9;
  position: relative;
  transition: background-color var(--fa-transition-fast), opacity var(--fa-transition-fast), gap var(--fa-transition-medium), padding var(--fa-transition-medium);
}

/* A white-tinted overlay here (as every other hover state in this file uses,
   e.g. .fa-header-menu-toggle/.fa-theme-btn above) washes out against this link's
   own color: var(--fa-text-on-primary), which every palette defines as a near-
   white off-white (_palettes.scss) — lightening the background behind
   already-light text on hover pushes both toward the same color instead of
   apart. Darkening it instead (the same direction .active already goes, just a
   lighter step before it) keeps the light text legible against every palette
   rather than fading it out. */
.fa-sidebar-link:hover {
  background: rgba(0, 0, 0, 0.18);
  opacity: 1;
}

.fa-sidebar-link.active {
  background: var(--fa-primary-dark);
  opacity: 1;
  box-shadow: inset 0 0 0 2px var(--fa-glow);
}

/* max-width (not display:none, and no opacity fade) so collapsing reads as the
   sidebar's edge closing directly over the label — text stays fully opaque and gets
   clipped by overflow:hidden as max-width shrinks, down to just the first letter or
   two, rather than fading out independently of the width animation. */
.fa-sidebar-link-text {
  display: inline-block;
  white-space: nowrap;
  overflow: hidden;
  max-width: 160px;
  transition: max-width var(--fa-transition-medium);
}

html.fa-sidebar-collapsed .fa-sidebar-collapsible .fa-sidebar-link {
  gap: 0;
  padding-left: 0.6rem;
  padding-right: 0.6rem;
}

/* justify-content isn't animatable, so centering the icon has to be a discrete jump —
   applying it via this separate class (added by js/sidebar.js only once the label has
   actually finished collapsing) instead of directly off .fa-sidebar-collapsed keeps
   that jump from happening at the same instant the collapse starts, which read as the
   icon recentering before the text had visually finished closing. */
html.fa-sidebar-collapsed-settled .fa-sidebar-collapsible .fa-sidebar-link {
  justify-content: center;
}

html.fa-sidebar-collapsed .fa-sidebar-collapsible .fa-sidebar-link-text {
  max-width: 0;
}

/* The "really cool" tooltip: a small pill in the app's own palette, not the browser's
   plain title tooltip. Built from data-tooltip (set alongside each label in
   NavMenu.razor) via a pseudo-element, so it costs nothing extra to render. */
html.fa-sidebar-collapsed .fa-sidebar-collapsible .fa-sidebar-link::after {
  content: attr(data-tooltip);
  position: absolute;
  left: calc(100% + 0.9rem);
  top: 50%;
  transform: translateY(-50%) translateX(-6px) scale(0.94);
  background: var(--fa-primary-dark);
  color: var(--fa-text-on-primary);
  padding: 0.45rem 0.8rem;
  border-radius: var(--fa-radius-md);
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35), 0 0 0 1.5px var(--fa-glow);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--fa-transition-fast), transform var(--fa-transition-fast);
  z-index: 30;
}

html.fa-sidebar-collapsed .fa-sidebar-collapsible .fa-sidebar-link:hover::after,
html.fa-sidebar-collapsed .fa-sidebar-collapsible .fa-sidebar-link:focus-visible::after {
  opacity: 1;
  transform: translateY(-50%) translateX(0) scale(1);
}

/* Terse UI style (data-fa-ui-style="terse", see _palettes.scss) — this file's own
   header/sidebar "lifted" shadows are hardcoded, not routed through
   --fa-border-glow like most components, so they need their own flattening here
   instead of falling out of the token overrides for free. A flat bottom/right
   border replaces the shadow where it was doing edge-separation work; the active
   sidebar link's inset ring becomes a left accent bar instead — the same
   left-border-accent language the reference terse look uses in place of filled/
   glowing highlights. */
:root[data-fa-ui-style=terse] {
  /* :not(:focus-visible) rather than a plain .fa-sidebar-toggle rule — this
     block is appended after the component's own :focus-visible box-shadow
     (the focus ring, not decorative), and at equal specificity a later plain
     rule would otherwise win and silently eat that ring while terse is active. */
}
:root[data-fa-ui-style=terse] .fa-header {
  box-shadow: none;
  border-bottom: var(--fa-border-width) solid var(--fa-glow);
}
:root[data-fa-ui-style=terse] .fa-sidebar {
  box-shadow: none;
  border-right: var(--fa-border-width) solid var(--fa-glow);
}
:root[data-fa-ui-style=terse] .fa-sidebar-toggle:not(:focus-visible) {
  box-shadow: none;
}
:root[data-fa-ui-style=terse] .fa-sidebar-link.active {
  box-shadow: none;
  border-left: 3px solid var(--fa-text-on-primary);
}

/* :root[data-fa-ui-style="terse"] html.fa-sidebar-collapsed ... above would never
   match — :root IS <html>, so it can't also be html's ancestor via a descendant
   combinator. The attribute has to land on the same html element instead. */
html[data-fa-ui-style=terse].fa-sidebar-collapsed .fa-sidebar-collapsible .fa-sidebar-link::after {
  box-shadow: none;
  border: 1px solid var(--fa-glow);
}

/* Typewriter UI style (data-fa-ui-style="typewriter", see _palettes.scss) — same
   reason as the terse block above (these shadows are hardcoded, not token-
   driven), swapped to the soft neutral "resting" shadow instead of flattening to
   a border. The active sidebar link keeps its filled background as the only
   "active" signal (no border-glow token used for insets like this one), same as
   flow — nothing needed here for that one selector. */
:root[data-fa-ui-style=typewriter] .fa-header {
  box-shadow: var(--fa-border-glow);
}
:root[data-fa-ui-style=typewriter] .fa-sidebar {
  box-shadow: var(--fa-border-glow);
}
:root[data-fa-ui-style=typewriter] .fa-sidebar-toggle:not(:focus-visible) {
  box-shadow: var(--fa-border-glow);
}

html[data-fa-ui-style=typewriter].fa-sidebar-collapsed .fa-sidebar-collapsible .fa-sidebar-link::after {
  box-shadow: var(--fa-border-glow);
}

/* ============================= Buttons ============================= */
.fa-btn {
  font-family: var(--fa-font);
  font-weight: 700;
  font-size: 0.95rem;
  border-radius: var(--fa-radius-pill);
  padding: 0.55rem 1.4rem;
  border: var(--fa-border-width) solid transparent;
  cursor: pointer;
  transition: background-color var(--fa-transition-fast), border-color var(--fa-transition-fast), color var(--fa-transition-fast), transform 0.05s ease;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.fa-btn:active {
  transform: translateY(1px);
}

.fa-btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.fa-btn-primary {
  background: var(--fa-primary);
  color: var(--fa-text-on-primary);
  border-color: var(--fa-primary);
}

.fa-btn-primary:hover:not(:disabled) {
  background: var(--fa-primary-dark);
  border-color: var(--fa-primary-dark);
}

.fa-btn-primary:focus-visible {
  background: var(--fa-glow);
  border-color: var(--fa-border-focus);
  outline: none;
}

.fa-btn-secondary {
  background: var(--fa-surface);
  color: var(--fa-primary-dark);
  border-color: var(--fa-border);
}

.fa-btn-secondary:hover:not(:disabled) {
  background: var(--fa-footer);
  border-color: var(--fa-glow);
}

.fa-btn-secondary:focus-visible {
  border-color: var(--fa-border-focus);
  color: var(--fa-border-focus);
  outline: none;
}

.fa-btn-outline {
  background: transparent;
  color: var(--fa-primary-dark);
  border-color: var(--fa-primary);
}

.fa-btn-outline:hover:not(:disabled) {
  background: var(--fa-primary);
  color: var(--fa-text-on-primary);
}

.fa-btn-outline:focus-visible {
  background: var(--fa-primary-dark);
  color: var(--fa-text-on-primary);
  border-color: var(--fa-border-focus);
  outline: none;
}

.fa-btn-danger {
  background: var(--fa-ember);
  color: var(--fa-text-on-primary);
  border-color: var(--fa-ember);
}

.fa-btn-danger:hover:not(:disabled) {
  background: var(--fa-wine);
  border-color: var(--fa-wine);
}

.fa-btn-danger:focus-visible {
  border-color: var(--fa-border-focus);
  outline: none;
}

.fa-btn-outline-danger {
  background: transparent;
  color: var(--fa-ember);
  border-color: var(--fa-ember);
}

.fa-btn-outline-danger:hover:not(:disabled) {
  background: var(--fa-ember);
  color: var(--fa-text-on-primary);
}

.fa-btn-outline-danger:focus-visible {
  background: var(--fa-wine);
  color: var(--fa-text-on-primary);
  border-color: var(--fa-border-focus);
  outline: none;
}

.fa-btn-accent {
  background: var(--fa-accent);
  color: var(--fa-text-on-primary);
  border-color: var(--fa-accent);
}

.fa-btn-accent:hover:not(:disabled) {
  background: var(--fa-accent-dark);
  border-color: var(--fa-accent-dark);
}

.fa-btn-accent:focus-visible {
  border-color: var(--fa-border-focus);
  outline: none;
}

.fa-btn-outline-accent {
  background: transparent;
  color: var(--fa-accent-dark);
  border-color: var(--fa-accent);
}

.fa-btn-outline-accent:hover:not(:disabled) {
  background: var(--fa-accent);
  color: var(--fa-text-on-primary);
}

.fa-btn-outline-accent:focus-visible {
  background: var(--fa-accent-dark);
  color: var(--fa-text-on-primary);
  border-color: var(--fa-border-focus);
  outline: none;
}

/* FaButton.Size (FaSize) — Medium is the default and renders with none of these,
   the same look .fa-btn always had. */
.fa-btn-xs {
  padding: 0.2rem 0.6rem;
  font-size: 0.72rem;
}

.fa-btn-sm {
  padding: 0.32rem 0.9rem;
  font-size: 0.82rem;
}

.fa-btn-lg {
  padding: 0.75rem 1.9rem;
  font-size: 1.08rem;
}

.fa-btn-xl {
  padding: 0.95rem 2.4rem;
  font-size: 1.2rem;
}

/* Terse UI style (data-fa-ui-style="terse", see _palettes.scss) — a button isn't a
   status pill, so it drops to the same small radius as boxed inputs instead of
   inheriting --fa-radius-pill. Everything else about .fa-btn (padding, weight,
   the border-glow/transition tokens it already reads) falls out of the token
   overrides in _palettes.scss with no change needed here. */
:root[data-fa-ui-style=terse] .fa-btn {
  border-radius: var(--fa-radius-sm);
}

/* Typewriter UI style (data-fa-ui-style="typewriter", see _palettes.scss) — same
   "a button isn't a status pill" reasoning as terse's override above, but to the
   rounded-rectangle --fa-radius-md instead of terse's small-and-square. .fa-btn
   never draws a shadow at all in flow/terse, so the signature soft "resting"
   shadow needs adding explicitly here to actually show on buttons too. */
:root[data-fa-ui-style=typewriter] .fa-btn {
  border-radius: var(--fa-radius-md);
  box-shadow: var(--fa-border-glow);
}

:root[data-fa-ui-style=typewriter] .fa-btn:focus-visible {
  box-shadow: var(--fa-border-glow-focus);
}

/* ============================= Inputs & selects ============================= */
.fa-field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.fa-label {
  font-weight: 600;
  font-size: 0.85rem;
  color: var(--fa-text-muted);
}

.fa-input, .fa-select {
  font-family: var(--fa-font);
  font-size: 0.95rem;
  color: var(--fa-text);
  background: var(--fa-surface);
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-md);
  padding: 0.5rem 0.9rem;
  box-shadow: var(--fa-border-glow);
  transition: border-color var(--fa-transition-fast), box-shadow var(--fa-transition-fast);
}

.fa-input:focus, .fa-select:focus {
  outline: none;
  border-color: var(--fa-border-focus);
  box-shadow: var(--fa-border-glow-focus);
}

.fa-input::placeholder {
  color: var(--fa-text-muted);
  opacity: 0.7;
}

/* FaInput/FaSelect/FaTextarea/FaCurrency's Size (FaSize) — all four share this one
   ladder (applied via the "fa-input-{size}" prefix even on a <select>/<textarea>;
   they're the same padding/font-size as a plain input already) since Medium is
   identical across all four to begin with. Medium itself renders with none of
   these, the same look every one of these already had before Size existed. */
.fa-input-xs, .fa-select.fa-input-xs, .fa-textarea.fa-input-xs {
  padding: 0.25rem 0.55rem;
  font-size: 0.78rem;
}

.fa-input-sm, .fa-select.fa-input-sm, .fa-textarea.fa-input-sm {
  padding: 0.35rem 0.7rem;
  font-size: 0.86rem;
}

.fa-input-lg, .fa-select.fa-input-lg, .fa-textarea.fa-input-lg {
  padding: 0.7rem 1.15rem;
  font-size: 1.05rem;
}

.fa-input-xl, .fa-select.fa-input-xl, .fa-textarea.fa-input-xl {
  padding: 0.9rem 1.4rem;
  font-size: 1.15rem;
}

/* Shared "input type" readonly look — FaInput/FaSelect/FaTextarea/FaCurrency: same
   box as normal, just muted and non-interactive. (FaCheckbox/FaToggle/FaRadioGroup/
   FaDate/FaDateRange/FaSearchSelect/FaDropdown use the flattened
   .fa-readonly-flat look instead — see below — since they aren't plain boxed
   inputs to begin with.) */
.fa-input[readonly], .fa-input:disabled,
.fa-select:disabled,
.fa-textarea[readonly] {
  opacity: 0.65;
  cursor: not-allowed;
}

.fa-input[readonly]:focus, .fa-input:disabled:focus,
.fa-select:disabled:focus,
.fa-textarea[readonly]:focus {
  box-shadow: var(--fa-border-glow);
}

.fa-input-group {
  display: flex;
  align-items: stretch;
}

.fa-input-group .fa-field {
  flex: 1;
}

.fa-input-group .fa-input {
  border-radius: var(--fa-radius-md) 0 0 var(--fa-radius-md);
  border-right: none;
}

.fa-input-group .fa-btn {
  border-radius: 0 var(--fa-radius-md) var(--fa-radius-md) 0;
}

.fa-input-group-sm .fa-input, .fa-input-group-sm .fa-btn {
  padding: 0.32rem 0.9rem;
  font-size: 0.82rem;
}

/* --- Validation (see Fran.Validation, FaValidationMessageRenderer) ---
   Every InputBase-derived Fran input adds .fa-input-invalid (or, for the two
   components with their own distinct box style, .fa-select-invalid) to itself
   whenever EditContext reports an error for its field (or its own element-tier
   Validate override does) — fa- prefixed rather than reviving the stock
   unprefixed .invalid/.valid.modified Blazor-template classes that used to live
   in _blazor-chrome.scss, since a bare .invalid could collide with anything else
   a consuming app's own page happens to use that selector for. --fa-ember is
   this library's already-established danger/error color token — no new one
   needed. */
.fa-input-invalid, .fa-select-invalid {
  border-color: var(--fa-ember);
  box-shadow: 0 0 0 1px var(--fa-ember);
}

.fa-validation-message {
  color: var(--fa-ember);
  font-size: 0.82rem;
}

/* ============================= Input style (standard/minimal/maximal) =============================
   A third independent axis alongside palette (data-fa-palette) and mode (data-theme),
   both on <html> — see theme.js's own comment for the full three-axis picture. No
   attribute (or data-fa-input-style="standard") is today's default look, defined
   above; "minimal"/"maximal" only override the handful of properties that actually
   change. Applies to the boxed native-input-like controls that already share this
   base look (.fa-input/.fa-select/.fa-textarea/.fa-currency-input) — not the
   flattened controls (checkbox/toggle/date/etc., see _checkbox-radio.scss's own
   comment on why those never were boxed to begin with). Toggle with
   window.faSetInputStyle(...) (js/theme.js) or <FaInputStyleSwitcher>. */
:root[data-fa-input-style=minimal] .fa-input, :root[data-fa-input-style=minimal] .fa-select, :root[data-fa-input-style=minimal] .fa-textarea, :root[data-fa-input-style=minimal] .fa-currency-input {
  border-width: 1px;
  border-radius: 0;
  box-shadow: none;
}
:root[data-fa-input-style=minimal] .fa-input:focus, :root[data-fa-input-style=minimal] .fa-select:focus, :root[data-fa-input-style=minimal] .fa-textarea:focus, :root[data-fa-input-style=minimal] .fa-currency-input:focus {
  box-shadow: none;
}

:root[data-fa-input-style=maximal] .fa-input, :root[data-fa-input-style=maximal] .fa-select, :root[data-fa-input-style=maximal] .fa-textarea, :root[data-fa-input-style=maximal] .fa-currency-input {
  border-width: 3px;
  border-radius: var(--fa-radius-lg);
}

/* ============================= Floating label ============================= */
/* FaInput.FloatingLabel — pure CSS, no JS: the label sits absolutely positioned
   inside the input until the input is focused or non-empty, then animates up to sit
   on the border. Relies on :placeholder-shown (which needs a non-empty placeholder —
   FaInput.cs supplies a single space when none is set) and the label coming *after*
   the <input> in markup so the ~ general-sibling combinator can reach it. */
.fa-field-floating {
  position: relative;
  display: block;
}

.fa-field-floating .fa-input {
  width: 100%;
}

.fa-label-floating {
  position: absolute;
  left: 0.9rem;
  top: 0.6rem;
  font-size: 0.95rem;
  color: var(--fa-text-muted);
  background: var(--fa-surface);
  padding: 0 0.3rem;
  pointer-events: none;
  transition: transform var(--fa-transition-fast), font-size var(--fa-transition-fast), color var(--fa-transition-fast);
  transform-origin: left top;
}

.fa-input:focus ~ .fa-label-floating,
.fa-input:not(:placeholder-shown) ~ .fa-label-floating {
  transform: translateY(-1.35rem) scale(0.85);
  color: var(--fa-primary-dark);
}

.fa-input:focus ~ .fa-label-floating {
  color: var(--fa-border-focus);
}

/* ============================= Date ============================= */
.fa-date {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: var(--fa-surface);
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-md);
  padding: 0.4rem 0.7rem;
  box-shadow: var(--fa-border-glow);
  transition: border-color var(--fa-transition-fast), box-shadow var(--fa-transition-fast);
}

.fa-date:focus-within {
  border-color: var(--fa-border-focus);
  box-shadow: var(--fa-border-glow-focus);
}

.fa-date-fields {
  display: flex;
  align-items: center;
  /* A visible gap between the day/month/year fields (beyond the "/" separators
     themselves) so the three segments read as distinct tappable/typeable targets
     instead of one crowded run of digits. */
  gap: 0.15rem;
}

.fa-date-input {
  /* box-sizing is border-box globally (_base.scss), so the lateral padding below
     is subtracted from a plain "width: Nch" instead of adding to it — with only
     ~2ch left for content, the "mm"/"dd"/"yyyy" placeholder letters (each wider
     than the "0" a "ch" is measured from) clip. calc() adds the padding back in
     so the content box itself stays a full N characters regardless of box model. */
  width: calc(3.2ch + 0.6rem);
  border: none;
  border-radius: var(--fa-radius-sm);
  background: transparent;
  font-family: var(--fa-font);
  font-size: 0.95rem;
  color: var(--fa-text);
  text-align: center;
  padding: 0.2rem 0.3rem;
  transition: background-color var(--fa-transition-fast), color var(--fa-transition-fast);
}

/* Width follows the field's own maxlength attribute (2 vs 4 typed digits) rather
   than :last-child — FaDate's Format parameter can put the year first (e.g.
   "yyyy/MM/dd"), so the widest field isn't always the last one rendered. */
.fa-date-input[maxlength="4"] {
  width: calc(5.4ch + 0.6rem);
}

/* Own small pill highlight per field on hover/focus, distinct from the outer
   wrapper's focus-within glow — makes clear which of the three fields is
   actually about to receive typed digits or a wheel-scroll. */
.fa-date-input:hover {
  background: var(--fa-footer);
}

.fa-date-input:focus {
  outline: none;
  background: var(--fa-footer);
  color: var(--fa-primary-dark);
}

.fa-date-separator {
  padding: 0 0.05rem;
  color: var(--fa-text-muted);
  -webkit-user-select: none;
  user-select: none;
}

/* Round icon-button treatment, same idiom as .fa-carousel-arrow — a bordered
   circle instead of a bare icon, so it reads as a tappable control rather than
   decoration next to the fields. */
.fa-date-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.9rem;
  height: 1.9rem;
  border-radius: 50%;
  border: var(--fa-border-width) solid transparent;
  background: none;
  cursor: pointer;
  margin-left: auto;
  transition: background-color var(--fa-transition-fast), border-color var(--fa-transition-fast), transform var(--fa-transition-fast);
}

.fa-date-toggle:hover {
  background: var(--fa-footer);
  border-color: var(--fa-glow);
}

.fa-date-toggle:hover .fa-icon-black,
.fa-date-toggle:focus-visible .fa-icon-black {
  color: var(--fa-primary-dark);
}

.fa-date-toggle:active {
  transform: scale(0.92);
}

.fa-date-toggle:focus-visible {
  outline: none;
  border-color: var(--fa-border-focus);
  box-shadow: var(--fa-border-glow-focus);
}

/* --- Floating label, same idea as the plain .fa-label but overlapping the border --- */
.fa-date-floating {
  min-height: 3.2em;
}

.fa-date-floating-label {
  position: absolute;
  top: -0.6rem;
  left: 0.6rem;
  font-size: 0.7rem;
  background: var(--fa-surface);
  padding: 0 0.3rem;
  border-radius: var(--fa-radius-sm);
}

/* --- Popup: a plain Blazor bool (FaDate._isOpen) drives this class — no JS
   needed to open/close it, just to size/position it would need extra work this
   component intentionally skips (see FaDate.cs remarks). Always rendered,
   just hidden, so no @ref remount churn between opens. --- */
.fa-date-calendar {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 20;
  margin-top: 0.4rem;
  width: 17rem;
  background: var(--fa-surface);
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-lg);
  box-shadow: var(--fa-border-glow);
  padding: 0.6rem;
}

.fa-date-calendar.fa-date-calendar-open {
  display: block;
  animation: fa-date-pop 0.16s ease;
}

@media (prefers-reduced-motion: reduce) {
  .fa-date-calendar.fa-date-calendar-open {
    animation: none;
  }
}
@keyframes fa-date-pop {
  from {
    opacity: 0;
    transform: translateY(-0.35rem) scale(0.97);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}
.fa-date-calendar-header {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.5rem;
}

.fa-date-calendar-month {
  font-weight: 700;
  color: var(--fa-primary-dark);
  flex: 1;
  text-align: center;
}

.fa-date-calendar-year {
  width: 4.5rem;
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-pill);
  padding: 0.15rem 0.5rem;
  font-family: var(--fa-font);
  color: var(--fa-text);
  background: var(--fa-surface);
  text-align: center;
  transition: border-color var(--fa-transition-fast), box-shadow var(--fa-transition-fast);
}

.fa-date-calendar-year:hover {
  border-color: var(--fa-glow);
}

.fa-date-calendar-year:focus {
  outline: none;
  border-color: var(--fa-border-focus);
  box-shadow: var(--fa-border-glow-focus);
}

/* Same round icon-button idiom as .fa-date-toggle above. */
.fa-date-calendar-nav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.7rem;
  height: 1.7rem;
  border-radius: 50%;
  border: var(--fa-border-width) solid transparent;
  background: none;
  cursor: pointer;
  padding: 0;
  transition: background-color var(--fa-transition-fast), border-color var(--fa-transition-fast), transform var(--fa-transition-fast);
}

.fa-date-calendar-nav:hover {
  background: var(--fa-footer);
  border-color: var(--fa-glow);
}

.fa-date-calendar-nav:hover .fa-icon-black,
.fa-date-calendar-nav:focus-visible .fa-icon-black {
  color: var(--fa-primary-dark);
}

.fa-date-calendar-nav:active {
  transform: scale(0.9);
}

.fa-date-calendar-nav:focus-visible {
  outline: none;
  border-color: var(--fa-border-focus);
  box-shadow: var(--fa-border-glow-focus);
}

.fa-date-calendar-weekdays, .fa-date-calendar-days {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.2rem;
}

.fa-date-calendar-weekdays span {
  text-align: center;
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--fa-text-muted);
}

/* Full pill/circle rather than the library's old lightly-rounded square — matches
   the rest of Fran's "round things you tap" language (.fa-btn's pill radius,
   .fa-carousel-dot's circles). */
.fa-date-day {
  aspect-ratio: 1;
  border: var(--fa-border-width) solid transparent;
  border-radius: var(--fa-radius-pill);
  background: none;
  color: var(--fa-text);
  font-family: var(--fa-font);
  cursor: pointer;
  transition: background-color var(--fa-transition-fast), color var(--fa-transition-fast), transform var(--fa-transition-fast), box-shadow var(--fa-transition-fast);
}

/* color-mix over the palette's own --fa-primary instead of a hardcoded hex —
   the old rgba(232, 135, 61, ...) was Northwest Fall's orange glow baked in
   literally, so every other palette's calendar hovered orange regardless of
   its own primary color. This tracks whichever palette is actually active. */
.fa-date-day:hover:not(:disabled) {
  background: color-mix(in srgb, var(--fa-primary) 16%, transparent);
  transform: scale(1.06);
}

.fa-date-day:focus-visible {
  outline: none;
  border-color: var(--fa-border-focus);
}

.fa-date-day:disabled {
  color: var(--fa-text-muted);
  opacity: 0.4;
  cursor: not-allowed;
}

/* Today, when it isn't also the selected day: an outline bubble instead of a
   filled one, so "this is today" and "this is selected" stay visually distinct
   even when they're the same button. */
.fa-date-day-today {
  border-color: var(--fa-primary);
  color: var(--fa-primary-dark);
  font-weight: 700;
}

.fa-date-day-selected {
  background: var(--fa-primary);
  color: var(--fa-text-on-primary);
  box-shadow: var(--fa-border-glow-focus);
}

.fa-date-day-selected:hover:not(:disabled) {
  background: var(--fa-primary-dark);
  transform: scale(1.06);
}

/* --- Compact scroll-picker: an alternate popup body (FaDate.CompactPicker
   forces it on permanently; otherwise the header's mode toggle switches it
   on/off) — three independently scrollable day/month/year lists instead of
   the day grid, each snapping to whichever value sits in the middle band,
   with a plain number input above each one so a value can be typed instead
   of scrolled to. Smaller and thumb-friendlier than the full grid, which is
   the point on a small screen. Typing into the day/month/year fields above
   the popup (_dayText/_monthText/_yearText, unaffected by any of this) still
   works exactly the same in either mode. --- */
.fa-date-calendar-compact {
  width: 14rem;
}

/* --- Auto mode: viewport decides grid vs wheels, no JS involved ----------
   Whenever CompactPicker hasn't locked the mode outright, FaDate.cs's
   RenderCalendar renders *both* an .fa-date-calendar-auto-desktop (the grid)
   and an .fa-date-calendar-auto-mobile (the wheels) every render — which one
   actually shows is entirely up to CSS, never a C# branch. Desktop-first
   here (mobile hidden by default); _responsive.scss's own
   @media (max-width: 720px) block (the same breakpoint every other
   component in this library treats as "small screen") flips it, live, as
   the viewport crosses it — no JS matchMedia listener needed. */
.fa-date-calendar-auto-mobile {
  display: none;
}

/* Added to the outer .fa-date-calendar once the header's own mode-toggle
   button has been clicked (see FaDate.cs's _pickerModeManuallySet) — a
   deliberate choice permanently opts an instance out of the viewport-driven
   default above, in whichever direction was picked. Plain (non-media-query)
   rules, so they participate in the cascade at every viewport width, not
   just where _responsive.scss's own flip happens to apply — !important is
   there specifically to win over that flip on a narrow screen too, not for
   specificity's sake (both rules target the same two classes). */
.fa-date-calendar-force-grid .fa-date-calendar-auto-desktop {
  display: block !important;
}

.fa-date-calendar-force-grid .fa-date-calendar-auto-mobile {
  display: none !important;
}

.fa-date-calendar-force-compact .fa-date-calendar-auto-desktop {
  display: none !important;
}

.fa-date-calendar-force-compact .fa-date-calendar-auto-mobile {
  display: block !important;
}

/* Matches .fa-date-calendar-compact's own width above — same "smaller,
   thumb-friendlier" sizing, just reachable from the force-* class a manual
   toggle click adds instead of the CompactPicker-forced path's own class.
   Only matters on a wide-enough viewport to begin with: at/under 720px
   _responsive.scss's own bottom-sheet override replaces this width with its
   own formula regardless of which mode is showing, same as it already does
   for a manually-forced grid at that width. */
.fa-date-calendar-force-compact {
  width: 14rem;
}

.fa-date-wheels-group {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.fa-date-wheel-inputs {
  display: flex;
  gap: 0.4rem;
}

.fa-date-wheel-input {
  /* flex:1 alone would still respect the input's intrinsic content width as
     a flex-basis floor — width:0 hands sizing entirely to the flex row.
     flex-grow itself is overridden per-field inline (see FaDate.cs's
     WheelFlexStyle) so a 4-digit year field grows wider than a 2-digit
     month/day field instead of all three splitting the row evenly — the
     same ratio is applied to .fa-date-wheel below so the two rows'
     columns still line up with each other. */
  flex: 1;
  width: 0;
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-sm);
  padding: 0.2rem 0.3rem;
  font-family: var(--fa-font);
  font-size: 0.85rem;
  color: var(--fa-text);
  background: var(--fa-surface);
  text-align: center;
  transition: border-color var(--fa-transition-fast), box-shadow var(--fa-transition-fast);
}

.fa-date-wheel-input:hover {
  border-color: var(--fa-glow);
}

.fa-date-wheel-input:focus {
  outline: none;
  border-color: var(--fa-border-focus);
  box-shadow: var(--fa-border-glow-focus);
}

.fa-date-wheels {
  display: flex;
  gap: 0.4rem;
  position: relative;
}

/* A static band across all three columns marking the "selected" row,
   behind the wheel items themselves (transparent background) so it reads
   as a highlighted slot the scrolling passes through — the usual
   wheel-picker affordance. */
.fa-date-wheels::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  height: 1.9rem;
  background: var(--fa-footer);
  border-radius: var(--fa-radius-sm);
  pointer-events: none;
}

/* One of these sits between each pair of adjacent wheel columns (see
   FaDate.cs's RenderWheels) — a real sibling element in the `.fa-date-wheels`
   row itself, not a per-wheel ::before/::after. Each `.fa-date-wheel` is its
   own overflow-y:auto scroll container, and an absolutely positioned
   pseudo-element anchored inside one scrolls (or otherwise mispaints) along
   with that wheel's own — much taller than the visible window — scrollable
   content instead of staying put over the visible band, which is exactly why
   that was tried first and dropped: the two cyclic (tripled-content) columns'
   dividers barely painted at all. A plain, unscrolled sibling row-item has
   none of that — solid at the vertical middle (the highlighted selection
   band) fading to nothing at the topmost/bottommost item, same effect the
   curved items already have. Width matches .fa-date-wheel-input's own border
   weight directly above it, so the two rows read as the same "line" weight
   at the one point (dead center) this one is at full strength. */
.fa-date-wheel-divider {
  align-self: stretch;
  width: var(--fa-border-width);
  background: linear-gradient(to bottom, transparent, var(--fa-border) 50%, transparent);
  pointer-events: none;
}

.fa-date-wheel {
  position: relative;
  flex: 1;
  /* Tall enough to comfortably clear space for two curved rows above/below
     the highlighted band (see fa-date-wheel.js's WHEEL_MAX_STEPS) before
     overflow clips anything further — the previous 8rem cut a 3rd tilted
     row off right at its own edge, reading as cramped/overlapping text. */
  height: 9.5rem;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
  /* Padding top/bottom centers the first/last item in the highlighted band
     instead of pinning them to the wheel's own top/bottom edge. */
  padding: 3rem 0;
  scrollbar-width: none;
  /* The vanishing point for each item's own rotateX/translateZ below —
     fa-date-wheel.js recomputes those continuously while scrolling, tilting
     and pushing items back the further they sit from the highlighted middle
     band, so the column reads as a barrel curving away above and below
     center (the usual native iOS/Android picker-wheel illusion) instead of
     a flat scrolling list. Perspective lives on the scroll container itself
     — transforms on a scrolled child don't affect its own layout/scroll
     position, only how it's painted, so this composes with the
     overflow-y/scroll-snap above without fighting either. */
  perspective: 220px;
  /* Rounded barrel silhouette to match the curvature illusion above: two
     blurred inset shadows in the wheel's own surface color fading the
     top/bottom rows out toward the background instead of hard-clipping
     them — the same soft top/bottom fade native iOS/Android picker wheels
     use. No top/bottom edge (border-radius still rounds these shadows'
     corners) — the left/right edges get their own tapered border below. */
  border-radius: var(--fa-radius-md);
  box-shadow: inset 0 0.9rem 0.6rem -0.5rem var(--fa-surface), inset 0 -0.9rem 0.6rem -0.5rem var(--fa-surface);
  /* Dragging/flicking is handled entirely by fa-date-wheel.js via Pointer
     Events (mouse *and* touch, one code path — see its own remarks) rather
     than the browser's native touch-panning, so touch-action:none stops
     the browser's own touch scroll from fighting the manual scrollTop
     writes that drive it. */
  touch-action: none;
  cursor: grab;
}

.fa-date-wheel:active {
  cursor: grabbing;
}

.fa-date-wheel::-webkit-scrollbar {
  display: none;
}

/* Min/Max collapse this wheel to exactly one selectable item (every other
   item already renders :disabled — see FaDate.cs's RenderWheelColumn) —
   overflow:hidden stops native mouse-wheel/trackpad scroll from moving it
   away from that one value at all, and pointer-events:none stops
   fa-date-wheel.js's own document-level pointerdown listener from ever
   matching this wheel to start a drag (see wheelFromEvent there) — the
   same reasoning .fa-date-wheel-item:disabled below already uses to let a
   pointerdown that starts on a disabled item fall through, just applied
   to the whole column instead of one item. cursor reverts from the
   spinnable grab/grabbing look since there's nothing left to grab. */
.fa-date-wheel-locked {
  overflow: hidden;
  pointer-events: none;
  cursor: default;
}

.fa-date-wheel-item {
  display: block;
  width: 100%;
  padding: 0.35rem 0;
  border: none;
  background: none;
  color: var(--fa-text-muted);
  font-family: var(--fa-font);
  font-size: 0.9rem;
  text-align: center;
  cursor: pointer;
  scroll-snap-align: center;
  transition: color var(--fa-transition-fast);
  /* transform/opacity themselves are set inline by fa-date-wheel.js (per-item,
     recomputed every scroll frame) rather than here — backface-visibility
     just keeps a far-tilted item from ever flashing as mirrored text. */
  transform-style: preserve-3d;
  backface-visibility: hidden;
}

.fa-date-wheel-item:hover {
  color: var(--fa-text);
}

.fa-date-wheel-item:focus-visible {
  outline: none;
  color: var(--fa-primary-dark);
}

.fa-date-wheel-item-selected {
  color: var(--fa-primary-dark);
  font-weight: 700;
}

/* Day always renders all 31 slots and disables whichever tail the
   current month doesn't have (29-31 in February, say) instead of
   omitting them — see FaDate.cs's RenderWheelColumn remarks. Same
   muted/uninteractive treatment .fa-date-day:disabled already uses for
   an out-of-range day in the grid view. */
.fa-date-wheel-item:disabled {
  color: var(--fa-text-muted);
  opacity: 0.35;
  cursor: not-allowed;
  /* Chromium never dispatches pointer events to a disabled form control
     — a drag that happens to start on top of a disabled slot (the 29-31
     tail in a short month) would otherwise silently do nothing instead
     of spinning the wheel. Making it transparent to hit-testing lets
     that pointerdown fall through to the wheel <div> underneath, whose
     document-level listener (fa-date-wheel.js) drives the drag either
     way — nothing about *clicking* a disabled item relied on it being
     hit-testable in the first place, since it was already unclickable. */
  pointer-events: none;
}

.fa-date-calendar-footer {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
  margin-top: 0.5rem;
  padding-top: 0.6rem;
  border-top: var(--fa-border-width) solid var(--fa-border);
}

/* Today/Clear are .fa-btn.fa-btn-outline.fa-btn-sm now (see FaDate.cs) — this
   class just trims that button's own padding back down to fit a calendar footer
   instead of a form's action row. */
.fa-date-calendar-footer-btn {
  padding: 0.28rem 0.75rem;
}

/* ============================= Toggle ============================= */
/* One shared border around the toggle button and, when it's showing, its companion
   input — not two separately-bordered controls sitting next to each other. Compact
   (just the two option buttons) by default; .fa-field is a flex column, whose items
   stretch to its full width by default, so this has to opt back out of that to stay
   hugged to its content instead of spanning the whole form like the inputs above it. */
.fa-toggle-group {
  display: inline-flex;
  align-items: stretch;
  align-self: flex-start;
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-pill);
  background: var(--fa-surface);
  box-shadow: var(--fa-border-glow);
  overflow: hidden;
  transition: border-color var(--fa-transition-fast), box-shadow var(--fa-transition-fast);
}

.fa-toggle-group:focus-within {
  border-color: var(--fa-border-focus);
  box-shadow: var(--fa-border-glow-focus);
}

/* Once the companion input is showing, span the field's full width — the input
   (flex: 1 1 auto below) absorbs the extra space; the option buttons stay put. */
.fa-toggle-group.fa-toggle-group-expanded {
  align-self: stretch;
  width: 100%;
}

/* The two options are always both visible, active one highlighted — same pattern as
   .fa-theme-switcher/.fa-theme-btn: an inset row of pill-shaped buttons (not edge-to-
   edge segments with dividers between them), and instead of a hard fill, the active
   one gets a shaded moss (accent) capsule behind its label. */
.fa-toggle-switch {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  flex: 0 0 auto;
  padding: 0.2rem;
}

.fa-toggle-option {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.3rem;
  height: 1.9rem;
  padding: 0 0.75rem;
  border: none;
  border-radius: var(--fa-radius-pill);
  background: transparent;
  color: var(--fa-text-muted);
  cursor: pointer;
  font-family: var(--fa-font);
  font-size: 0.82rem;
  font-weight: 700;
  white-space: nowrap;
  opacity: 0.7;
  transition: background-color var(--fa-transition-fast), opacity var(--fa-transition-fast), color var(--fa-transition-fast);
}

.fa-toggle-option:hover {
  opacity: 1;
  background: rgba(107, 122, 62, 0.14);
}

.fa-toggle-option:disabled {
  cursor: not-allowed;
  opacity: 0.4;
  background: transparent;
}

.fa-toggle-option:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--fa-border-focus);
}

.fa-toggle-option.fa-toggle-option-active {
  opacity: 1;
  background: var(--fa-accent);
  color: var(--fa-text-on-primary);
  box-shadow: 0 0 0 2px var(--fa-accent-dark);
}

.fa-toggle-input {
  flex: 1 1 auto;
  min-width: 100px;
  border: none;
  border-left: var(--fa-border-width) solid var(--fa-border);
  background: transparent;
  color: var(--fa-text);
  font-family: var(--fa-font);
  font-size: 0.9rem;
  padding: 0.45rem 0.8rem;
}

.fa-toggle-input.fa-toggle-input-before {
  border-left: none;
  border-right: var(--fa-border-width) solid var(--fa-border);
}

.fa-toggle-input:focus {
  outline: none;
}

.fa-toggle-input::placeholder {
  color: var(--fa-text-muted);
  opacity: 0.7;
}

/* ============================= Textarea ============================= */
.fa-textarea {
  font-family: var(--fa-font);
  font-size: 0.95rem;
  color: var(--fa-text);
  background: var(--fa-surface);
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-md);
  padding: 0.5rem 0.9rem;
  box-shadow: var(--fa-border-glow);
  resize: vertical;
  min-height: 6rem;
  transition: border-color var(--fa-transition-fast), box-shadow var(--fa-transition-fast);
}

.fa-textarea:focus {
  outline: none;
  border-color: var(--fa-border-focus);
  box-shadow: var(--fa-border-glow-focus);
}

.fa-textarea-readonly {
  white-space: pre-wrap;
  border-color: transparent;
  box-shadow: none;
  background: none;
  padding: 0;
}

.fa-textarea-counter {
  align-self: flex-end;
  font-size: 0.75rem;
  color: var(--fa-text-muted);
}

/* ============================= Checkbox & radio ============================= */
.fa-checkbox, .fa-radio {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  width: fit-content;
}

.fa-checkbox-input, .fa-radio-input {
  accent-color: var(--fa-primary);
  width: 1.1rem;
  height: 1.1rem;
  cursor: pointer;
}

.fa-checkbox-label, .fa-radio-label {
  font-size: 0.95rem;
  color: var(--fa-text);
}

.fa-checkbox-readonly.fa-readonly-flat {
  display: inline-flex;
  align-items: center;
  width: fit-content;
}

.fa-radio-group {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

/* FaCheckbox.Size (FaSize) — scales the box and its label together; Medium renders
   with none of these. */
.fa-checkbox-xs .fa-checkbox-input {
  width: 0.85rem;
  height: 0.85rem;
}

.fa-checkbox-xs .fa-checkbox-label {
  font-size: 0.8rem;
}

.fa-checkbox-sm .fa-checkbox-input {
  width: 0.95rem;
  height: 0.95rem;
}

.fa-checkbox-sm .fa-checkbox-label {
  font-size: 0.88rem;
}

.fa-checkbox-lg .fa-checkbox-input {
  width: 1.3rem;
  height: 1.3rem;
}

.fa-checkbox-lg .fa-checkbox-label {
  font-size: 1.05rem;
}

.fa-checkbox-xl .fa-checkbox-input {
  width: 1.5rem;
  height: 1.5rem;
}

.fa-checkbox-xl .fa-checkbox-label {
  font-size: 1.15rem;
}

/* ============================= File & currency ============================= */
.fa-file-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
}

.fa-file-input {
  font-family: var(--fa-font);
  color: var(--fa-text);
}

.fa-currency-input {
  text-align: right;
}

/* ============================= Table ============================= */
.fa-table {
  width: 100%;
  /* border-collapse: collapse merges cell borders into the table's own border box,
     which breaks border-radius clipping in most browsers — the corners end up
     square even though border-radius is set. border-collapse: separate with zero
     spacing keeps the same visual seams (via border-bottom on th/td below) while
     letting the table's own border follow its border-radius correctly. */
  border-collapse: separate;
  border-spacing: 0;
  background: var(--fa-surface);
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-md);
  overflow: hidden;
  box-shadow: var(--fa-border-glow);
}

.fa-table th, .fa-table td {
  padding: 0.6rem 0.9rem;
  text-align: left;
  border-bottom: 1px solid var(--fa-border);
}

.fa-table th {
  background: var(--fa-footer);
  font-weight: 700;
  color: var(--fa-primary-dark);
}

.fa-table tbody tr:last-child td {
  border-bottom: none;
}

.fa-table tbody tr:hover {
  background: rgba(232, 135, 61, 0.08);
}

/* Shrink-to-content action column — the width:1%/white-space:nowrap trick, as a
   reusable class instead of every consumer hand-rolling it inline. Card mode
   (below, <=720px) overrides this into its own unlabeled row at the top of the card. */
.fa-table-actions {
  width: 1%;
  white-space: nowrap;
}

/* Visually hidden but still reachable by screen readers — standard accessible-hide
   clip technique. General utility; first used by .fa-table's card mode below. */
.fa-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ============================= Date range ============================= */
.fa-daterange {
  display: inline-flex;
  align-items: flex-end;
  gap: 0.6rem;
}

.fa-daterange-field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.fa-daterange-end-label {
  font-weight: 600;
  font-size: 0.78rem;
  color: var(--fa-text-muted);
}

.fa-daterange-input {
  max-width: 11rem;
}

.fa-daterange-separator {
  padding-bottom: 0.55rem;
  color: var(--fa-text-muted);
}

/* ============================= Search select ============================= */
.fa-searchselect {
  position: relative;
}

.fa-searchselect-input {
  width: 100%;
}

.fa-searchselect-dropdown {
  position: absolute;
  z-index: 20;
  top: calc(100% + 0.3rem);
  left: 0;
  right: 0;
  max-height: 16rem;
  overflow-y: auto;
  background: var(--fa-surface);
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-md);
  box-shadow: var(--fa-border-glow);
  padding: 0.3rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.fa-searchselect-status, .fa-searchselect-empty {
  padding: 0.5rem 0.7rem;
  font-size: 0.88rem;
  color: var(--fa-text-muted);
}

.fa-searchselect-option {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-radius: var(--fa-radius-sm);
  padding: 0.45rem 0.7rem;
  font-family: var(--fa-font);
  font-size: 0.92rem;
  color: var(--fa-text);
  cursor: pointer;
}

.fa-searchselect-option:hover, .fa-searchselect-option-highlighted {
  background: rgba(232, 135, 61, 0.12);
}

.fa-dropdown {
  position: relative;
}

.fa-dropdown-input {
  width: 100%;
  /* Room for .fa-dropdown-arrow so the chevron never overlaps typed/selected text. */
  padding-right: 2.2rem;
}

.fa-dropdown-input[readonly] {
  cursor: pointer;
}

/* Always-visible chevron, floated over the input's end rather than laid out beside
   it — flips to point up while the dropdown is open. pointer-events: none lets
   clicks/typing pass straight through to the input underneath, so it never steals
   the search-field's click-to-open or type-to-search interaction. */
.fa-dropdown-arrow {
  position: absolute;
  top: 50%;
  right: 0.7rem;
  transform: translateY(-50%);
  display: flex;
  pointer-events: none;
}

.fa-dropdown-dropdown {
  position: absolute;
  z-index: 20;
  top: calc(100% + 0.3rem);
  left: 0;
  right: 0;
  background: var(--fa-surface);
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-md);
  box-shadow: var(--fa-border-glow);
  padding: 0.3rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  /* No overflow/scrollbar here — the component windows its own row set, so the
     dropdown's height always matches however many rows are actually rendered. */
  overscroll-behavior: contain;
}

.fa-dropdown-status, .fa-dropdown-empty {
  padding: 0.5rem 0.7rem;
  font-size: 0.88rem;
  color: var(--fa-text-muted);
}

.fa-dropdown-option {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-radius: var(--fa-radius-sm);
  padding: 0.45rem 0.7rem;
  font-family: var(--fa-font);
  font-size: 0.92rem;
  color: var(--fa-text);
  cursor: pointer;
}

.fa-dropdown-option:hover, .fa-dropdown-option-highlighted {
  background: rgba(232, 135, 61, 0.12);
}

/* Shared "other fa styles" readonly look — FaCheckbox/FaToggle/FaRadioGroup/
   FaDate/FaDateRange/FaSearchSelect/FaDropdown: none of these are a plain
   boxed input to begin with (a pill row, a set of buttons, a text field with a
   dropdown affordance, ...), so their readonly state flattens all of that away
   instead of just muting it — no inset/box, no background, same font as
   surrounding text, with only a bottom border left to still read as a field. */
.fa-readonly-flat {
  display: block;
  width: 100%;
  background: none;
  border: none;
  border-bottom: var(--fa-border-width) solid var(--fa-border);
  border-radius: 0;
  box-shadow: none;
  padding: 0.5rem 0.1rem;
  font-family: var(--fa-font);
  font-size: 0.95rem;
  color: var(--fa-text);
  cursor: default;
}

/* ============================= Grid (paging/filters) ============================= */
.fa-grid {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.fa-grid-empty {
  text-align: center;
  color: var(--fa-text-muted);
  padding: 1.4rem 0.9rem !important;
}

.fa-grid-table-wrap {
  position: relative;
}

.fa-grid-loading-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--fa-surface);
  opacity: 0.85;
  font-weight: 600;
  color: var(--fa-text);
}

.fa-grid-filter-row th {
  background: var(--fa-surface);
  padding-top: 0.4rem;
  padding-bottom: 0.4rem;
}

.fa-grid-filter-select {
  width: 100%;
  padding: 0.3rem 0.6rem;
  font-size: 0.85rem;
}

.fa-grid-sort-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-weight: 700;
  color: inherit;
  cursor: pointer;
}

.fa-grid-pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.8rem;
  font-size: 0.88rem;
  color: var(--fa-text-muted);
}

.fa-grid-pagination-size {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.fa-grid-pagination-size select {
  width: auto;
  padding: 0.3rem 0.6rem;
  font-size: 0.85rem;
}

.fa-grid-pagination-nav {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.fa-grid-pagination-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--fa-surface);
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-sm);
  width: 1.9rem;
  height: 1.9rem;
  cursor: pointer;
}

.fa-grid-pagination-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.fa-grid-pagination-btn:not(:disabled):hover {
  border-color: var(--fa-border-focus);
}

/* ============================= List group ============================= */
.fa-list-group {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.fa-list-group-item {
  background: var(--fa-surface);
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-md);
  box-shadow: var(--fa-border-glow);
  padding: 0.75rem 1rem;
}

/* ============================= Progress ============================= */
/* Four fill directions, all sharing the same .fa-progress track + .fa-progress-bar
   fill pair. Right/Down grow from the track's natural top-left origin, so the fill
   just needs its own width/height (set inline per-instance by FaProgress). Left/Up
   grow from the opposite edge instead, so the track becomes a flex container that
   anchors the fill to that far edge — the fill's width/height still comes from the
   same inline style, only which edge it's pinned to changes. */
.fa-progress {
  background: var(--fa-border);
  border-radius: var(--fa-radius-sm);
  overflow: hidden;
}

.fa-progress-bar {
  background: var(--fa-accent);
  transition: width var(--fa-transition-medium), height var(--fa-transition-medium);
}

/* --- Horizontal: Right (default) fills left→right, Left fills right→left. --- */
.fa-progress-right,
.fa-progress-left {
  height: 6px;
  width: 100%;
}

.fa-progress-right .fa-progress-bar,
.fa-progress-left .fa-progress-bar {
  height: 100%;
}

.fa-progress-left {
  display: flex;
  justify-content: flex-end;
}

/* --- Vertical: Down (default direction of gravity) fills top→bottom, Up fills
   bottom→top. Given no explicit height, a vertical track needs one to have
   anything to grow inside — 120px is a reasonable default, override via CssClass. --- */
.fa-progress-up,
.fa-progress-down {
  width: 6px;
  height: 120px;
}

.fa-progress-up .fa-progress-bar,
.fa-progress-down .fa-progress-bar {
  width: 100%;
}

.fa-progress-up {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

/* --- Color variants, shared with the spinner/helix/pong loaders (_loaders.scss). --- */
.fa-loader-primary .fa-progress-bar {
  background: var(--fa-primary);
}

.fa-loader-gold .fa-progress-bar {
  background: var(--fa-gold);
}

.fa-loader-danger .fa-progress-bar {
  background: var(--fa-ember);
}

/* ============================= Loaders ============================= */
/* Four different "still working" indicators, each purely CSS keyframes — no JS,
   consistent with the "vanilla-JS only when Blazor/CSS genuinely can't do it"
   rule in CLAUDE.md. Color variants (.fa-loader-primary/-gold/-danger; default is
   --fa-accent, undecorated) are shared with FaProgress — see _progress.scss. */
/* --- FaSpinner: the classic rotating ring. --- */
.fa-spinner {
  display: inline-block;
  border: 3px solid var(--fa-border);
  border-top-color: var(--fa-accent);
  border-radius: 50%;
  animation: fa-spin 0.7s linear infinite;
}

@keyframes fa-spin {
  to {
    transform: rotate(360deg);
  }
}
.fa-loader-primary.fa-spinner {
  border-top-color: var(--fa-primary);
}

.fa-loader-gold.fa-spinner {
  border-top-color: var(--fa-gold);
}

.fa-loader-danger.fa-spinner {
  border-top-color: var(--fa-ember);
}

/* --- FaLoadingDots: "Loading" + a clipped, animated-width ellipsis. Growing the
   dots by animating width (not by swapping text content) is what keeps this a
   single CSS keyframe instead of a C#/JS timer re-rendering every second. --- */
.fa-loading-dots {
  color: var(--fa-text-muted);
  font-weight: 600;
}

.fa-loading-dots-ellipsis {
  display: inline-block;
  overflow: hidden;
  width: 0;
  vertical-align: bottom;
  animation: fa-loading-dots-grow 1.6s steps(4, end) infinite;
}

@keyframes fa-loading-dots-grow {
  to {
    width: 1.2em;
  }
}
/* --- FaHelixLoader: rungs of top/bottom dot pairs. Each pair swings in opposite
   phase (the "twist"), a per-rung animation-delay sends that twist traveling down
   the row, and the whole loader scales in and out (the "breathe" — expand/
   contract). Delays only cover up to 6 rungs; FaHelixLoader clamps RungCount to
   that range. --- */
.fa-helix-loader {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 32px;
  animation: fa-helix-breathe 2.4s ease-in-out infinite;
}

.fa-helix-rung {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 18px;
  height: 100%;
}

.fa-helix-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--fa-accent);
}

.fa-helix-dot-top {
  animation: fa-helix-twist 1.2s ease-in-out infinite;
}

.fa-helix-dot-bottom {
  animation: fa-helix-twist-inverse 1.2s ease-in-out infinite;
}

.fa-helix-rung:nth-child(1) .fa-helix-dot {
  animation-delay: 0s;
}

.fa-helix-rung:nth-child(2) .fa-helix-dot {
  animation-delay: 0.12s;
}

.fa-helix-rung:nth-child(3) .fa-helix-dot {
  animation-delay: 0.24s;
}

.fa-helix-rung:nth-child(4) .fa-helix-dot {
  animation-delay: 0.36s;
}

.fa-helix-rung:nth-child(5) .fa-helix-dot {
  animation-delay: 0.48s;
}

.fa-helix-rung:nth-child(6) .fa-helix-dot {
  animation-delay: 0.6s;
}

@keyframes fa-helix-twist {
  0%, 100% {
    transform: translateY(-9px) scale(0.7);
    opacity: 0.5;
  }
  50% {
    transform: translateY(9px) scale(1);
    opacity: 1;
  }
}
@keyframes fa-helix-twist-inverse {
  0%, 100% {
    transform: translateY(9px) scale(1);
    opacity: 1;
  }
  50% {
    transform: translateY(-9px) scale(0.7);
    opacity: 0.5;
  }
}
@keyframes fa-helix-breathe {
  0%, 100% {
    transform: scaleX(1);
  }
  50% {
    transform: scaleX(0.55);
  }
}
.fa-loader-primary .fa-helix-dot {
  background: var(--fa-primary);
}

.fa-loader-gold .fa-helix-dot {
  background: var(--fa-gold);
}

.fa-loader-danger .fa-helix-dot {
  background: var(--fa-ember);
}

/* --- FaPongLoader: a ball bouncing corner-to-corner inside a court while the two
   paddles bob up and down, out of phase (the right paddle reuses the left
   paddle's keyframes, just played in reverse). --- */
.fa-pong-loader {
  position: relative;
  display: inline-block;
  width: 64px;
  height: 32px;
  background: var(--fa-border);
  border-radius: var(--fa-radius-sm);
  overflow: hidden;
}

.fa-pong-paddle {
  position: absolute;
  top: 2px;
  width: 4px;
  height: 12px;
  border-radius: var(--fa-radius-sm);
  background: var(--fa-accent);
}

.fa-pong-paddle-left {
  left: 3px;
  animation: fa-pong-paddle-bob 1.1s ease-in-out infinite;
}

.fa-pong-paddle-right {
  right: 3px;
  animation: fa-pong-paddle-bob 1.1s ease-in-out infinite reverse;
}

.fa-pong-ball {
  position: absolute;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--fa-accent);
  animation: fa-pong-ball-bounce 2.2s linear infinite;
}

@keyframes fa-pong-paddle-bob {
  0%, 100% {
    top: 2px;
  }
  50% {
    top: 18px;
  }
}
@keyframes fa-pong-ball-bounce {
  0% {
    left: 12%;
    top: 15%;
  }
  20% {
    left: 82%;
    top: 68%;
  }
  40% {
    left: 20%;
    top: 82%;
  }
  60% {
    left: 78%;
    top: 18%;
  }
  80% {
    left: 14%;
    top: 58%;
  }
  100% {
    left: 12%;
    top: 15%;
  }
}
.fa-loader-primary .fa-pong-paddle,
.fa-loader-primary .fa-pong-ball {
  background: var(--fa-primary);
}

.fa-loader-gold .fa-pong-paddle,
.fa-loader-gold .fa-pong-ball {
  background: var(--fa-gold);
}

.fa-loader-danger .fa-pong-paddle,
.fa-loader-danger .fa-pong-ball {
  background: var(--fa-ember);
}

/* ============================= Carousel ============================= */
.fa-carousel {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
}

.fa-carousel-viewport {
  position: relative;
  overflow: hidden;
  border-radius: var(--fa-radius-lg);
  border: var(--fa-border-width) solid var(--fa-border);
  background: var(--fa-surface);
}

/* Horizontal padding clears the absolutely-positioned arrows (2.2rem wide, 0.6rem
   from each edge — see .fa-carousel-arrow below) so slide content never sits under
   them, whether or not a given carousel actually has ShowArrows on. */
.fa-carousel-slide {
  padding: 1.25rem 3.25rem;
  animation: fa-carousel-fade 0.35s ease;
}

@keyframes fa-carousel-fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
/* Arrows are siblings of .fa-carousel-viewport (not children of it) so they sit on
   top of the clipped viewport instead of being clipped by its overflow:hidden. */
.fa-carousel-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 50%;
  background: var(--fa-surface);
  border: var(--fa-border-width) solid var(--fa-border);
  box-shadow: var(--fa-border-glow);
  cursor: pointer;
}

.fa-carousel-arrow:hover {
  border-color: var(--fa-border-focus);
}

.fa-carousel-arrow-prev {
  left: 0.6rem;
}

.fa-carousel-arrow-next {
  right: 0.6rem;
}

.fa-carousel-dots {
  display: flex;
  justify-content: center;
  gap: 0.5rem;
}

.fa-carousel-dot {
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: var(--fa-border);
  border: none;
  padding: 0;
  cursor: pointer;
}

.fa-carousel-dot-active {
  background: var(--fa-accent);
}

/* ============================= Forms ============================= */
/* Shared by FaForm<TModel>, FaLoginForm, and FaLogoutForm. Field styling itself
   (.fa-field/.fa-label/.fa-input/.fa-checkbox/...) already lives in _inputs.scss/
   _checkbox-radio.scss — this partial only covers the wrapper and the action-button
   row all three add on top of that. */
.fa-form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.fa-form-actions {
  display: flex;
  gap: 0.6rem;
  /* justify-content comes from the always-present .fa-align-* class (_utilities.scss,
     FaForm.ButtonAlign / FaLogoutForm.ButtonAlign). */
}

.fa-logout-message {
  margin: 0;
  color: var(--fa-text);
}

/* ============================= Cards ============================= */
.fa-card {
  background: var(--fa-surface);
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-lg);
  box-shadow: var(--fa-border-glow);
  padding: 1.1rem 1.3rem;
  transition: border-color var(--fa-transition-fast), box-shadow var(--fa-transition-fast);
}

.fa-card:focus-within, .fa-card.fa-card-active {
  border-color: var(--fa-border-focus);
  box-shadow: var(--fa-border-glow-focus);
}

.fa-card[tabindex] {
  cursor: pointer;
}

.fa-card[tabindex]:focus-visible {
  outline: none;
  border-color: var(--fa-border-focus);
  box-shadow: var(--fa-border-glow-focus);
}

/* FaCard.Size (FaSize) — scales padding only; Medium renders with none of these. */
.fa-card-xs {
  padding: 0.55rem 0.7rem;
}

.fa-card-sm {
  padding: 0.8rem 1rem;
}

.fa-card-lg {
  padding: 1.5rem 1.8rem;
}

.fa-card-xl {
  padding: 1.9rem 2.3rem;
}

/* ============================= Modal ============================= */
.fa-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  z-index: 1000;
}

/* Applied instead of unmounting when FaModal's ResetOnClose="false" (the default) keeps
   ChildContent mounted across a close/reopen cycle so its values persist. */
.fa-modal-backdrop-hidden {
  display: none;
}

/* --- FaModal.Position: which edge of the backdrop the dialog sits against, instead
   of the default centered both axes. --- */
.fa-modal-backdrop-top {
  align-items: flex-start;
}

.fa-modal-backdrop-bottom {
  align-items: flex-end;
}

.fa-modal-backdrop-left {
  justify-content: flex-start;
}

.fa-modal-backdrop-right {
  justify-content: flex-end;
}

.fa-modal {
  position: relative;
  background: var(--fa-surface);
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-lg);
  box-shadow: var(--fa-border-glow-focus);
  width: 100%;
  max-width: 520px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* --- FaModal.Size: overrides the 520px default max-width above. --- */
.fa-modal-sm {
  max-width: 360px;
}

.fa-modal-lg {
  max-width: 760px;
}

.fa-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 1.3rem;
  border-bottom: var(--fa-border-width) solid var(--fa-border);
}

.fa-modal-title {
  margin: 0;
  color: var(--fa-text);
}

.fa-modal-close {
  background: none;
  border: none;
  font-size: 1.4rem;
  line-height: 1;
  color: var(--fa-text-muted);
  cursor: pointer;
  padding: 0.2rem 0.4rem;
}

.fa-modal-close:hover {
  color: var(--fa-text);
}

.fa-modal-body {
  padding: 1.3rem;
  overflow-y: auto;
}

/* justify-content comes from the always-present .fa-align-* class (_utilities.scss,
   FaModal.FooterAlign) rather than a hardcoded value here. */
.fa-modal-footer {
  display: flex;
  gap: 0.6rem;
  padding: 1rem 1.3rem;
  border-top: var(--fa-border-width) solid var(--fa-border);
}

/* FaModal.IsLoading: covers the whole dialog (header/body/footer alike), not just
   the body, same overlay-on-top-not-swapped-in shape as .fa-grid-loading-overlay
   (_grid.scss). .fa-modal's own border-radius + overflow:hidden already clip this
   to the dialog's rounded corners. */
.fa-modal-loading-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--fa-surface);
  opacity: 0.85;
  z-index: 1;
}

/* ============================= Badges ============================= */
.fa-badge {
  display: inline-flex;
  align-items: center;
  font-weight: 700;
  font-size: 0.78rem;
  padding: 0.2rem 0.7rem;
  border-radius: var(--fa-radius-pill);
  background: var(--fa-gold);
  color: var(--fa-text);
}

.fa-badge-success {
  background: var(--fa-accent);
  color: var(--fa-text-on-primary);
}

.fa-badge-danger {
  background: var(--fa-ember);
  color: var(--fa-text-on-primary);
}

.fa-badge-primary {
  background: var(--fa-primary);
  color: var(--fa-text-on-primary);
}

/* FaBadge.Size (FaSize) — Medium renders with none of these. */
.fa-badge-xs {
  padding: 0.12rem 0.5rem;
  font-size: 0.68rem;
}

.fa-badge-sm {
  padding: 0.16rem 0.6rem;
  font-size: 0.73rem;
}

.fa-badge-lg {
  padding: 0.28rem 0.9rem;
  font-size: 0.86rem;
}

.fa-badge-xl {
  padding: 0.35rem 1.1rem;
  font-size: 0.95rem;
}

/* Terse UI style (data-fa-ui-style="terse", see _palettes.scss) — the tracked-out
   uppercase mono micro-label treatment from the reference look. Radius stays
   --fa-radius-pill (badges are status pills in both styles, see _palettes.scss's
   terse comment) — only the label typography changes. */
:root[data-fa-ui-style=terse] .fa-badge {
  font-family: var(--fa-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* ============================= Alerts ============================= */
.fa-alert {
  border-radius: var(--fa-radius-md);
  padding: 0.75rem 1.1rem;
  border: var(--fa-border-width) solid var(--fa-border);
  box-shadow: var(--fa-border-glow);
  font-weight: 600;
}

.fa-alert-danger {
  border-color: var(--fa-ember);
  color: var(--fa-ember);
  background: var(--fa-alert-danger-bg);
}

.fa-alert-success {
  border-color: var(--fa-accent);
  color: var(--fa-accent);
  background: var(--fa-alert-success-bg);
}

.fa-alert-info {
  border-color: var(--fa-primary);
  color: var(--fa-primary-dark);
  background: var(--fa-alert-info-bg);
}

/* FaAlert.Size (FaSize) — scales padding and text; Medium renders with none of these. */
.fa-alert-xs {
  padding: 0.4rem 0.6rem;
  font-size: 0.8rem;
}

.fa-alert-sm {
  padding: 0.55rem 0.85rem;
  font-size: 0.88rem;
}

.fa-alert-lg {
  padding: 0.95rem 1.4rem;
  font-size: 1.05rem;
}

.fa-alert-xl {
  padding: 1.2rem 1.7rem;
  font-size: 1.15rem;
}

/* ============================= Avatar ============================= */
.fa-avatar {
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 0.9rem;
  background: var(--fa-primary-light);
  color: var(--fa-text);
  box-shadow: 0 0 0 2px var(--fa-text-on-primary), 0 0 8px rgba(232, 135, 61, 0.6);
  overflow: hidden;
  flex-shrink: 0;
}

.fa-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Terse UI style (data-fa-ui-style="terse", see _palettes.scss) — drops the
   colored glow blur but keeps the plain ring, which is doing real separation
   work against whatever background the avatar sits on. */
:root[data-fa-ui-style=terse] .fa-avatar {
  box-shadow: 0 0 0 2px var(--fa-text-on-primary);
}

/* Typewriter UI style (data-fa-ui-style="typewriter", see _palettes.scss) — keeps
   the plain ring (same separation reasoning as terse's override above) and adds
   the soft neutral shadow behind it, so an avatar reads as gently lifted too. */
:root[data-fa-ui-style=typewriter] .fa-avatar {
  box-shadow: 0 0 0 2px var(--fa-text-on-primary), var(--fa-border-glow);
}

/* ============================= Icons ============================= */
/* Hand-drawn SVG set (FaIcon.razor) instead of a third-party icon font/library —
   every path fills with currentColor, and these two classes are the only place
   an icon's actual color is decided. */
.fa-icon {
  display: inline-block;
  vertical-align: middle;
  flex-shrink: 0;
}

.fa-icon path, .fa-icon rect, .fa-icon circle {
  fill: currentColor;
}

.fa-icon-white {
  color: #ffffff;
}

.fa-icon-black {
  /* var(--fa-text), not var(--fa-fir) — --fa-fir is a fixed "deep neutral" hex
     that no palette's dark-mode block ever redefines, so an icon colored from it
     stayed a dark color even against a dark --fa-surface in dark mode and went
     effectively invisible. --fa-text already flips light/dark correctly per
     palette (every dark-mode block redefines it), so "black" icons now track
     the theme instead of going dark-on-dark when the mode switches. */
  color: var(--fa-text);
}

.fa-nav-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
}

/* ============================= Dashboard tiles & trend chart ============================= */
/* Used by DashboardView.razor's budget-progress tiles and the monthly-spend SVG bar chart —
   previously inline `style="..."` attributes hardcoding Bootstrap-blue/red; now palette-driven
   like everything else. */
.fa-dashboard-tile {
  width: 220px;
}

.fa-dashboard-progress-track {
  background: var(--fa-border);
  border-radius: var(--fa-radius-sm);
  height: 10px;
  margin-top: 0.4rem;
  overflow: hidden;
}

.fa-dashboard-progress-fill {
  height: 100%;
  background: var(--fa-primary);
}

.fa-dashboard-progress-fill.fa-over-budget {
  background: var(--fa-ember);
}

.fa-dashboard-over-budget-label {
  color: var(--fa-ember);
  font-size: 0.85em;
  font-weight: 600;
}

.fa-trend-bar {
  fill: var(--fa-primary);
  cursor: pointer;
  transition: fill var(--fa-transition-fast);
}

.fa-trend-bar:hover {
  fill: var(--fa-primary-dark);
}

.fa-trend-label, .fa-trend-value {
  font-family: var(--fa-font);
  fill: var(--fa-text-muted);
}

/* ============================= Blazor template chrome ============================= */
/* The bits every default Blazor WASM template ships (error UI, loading spinner) —
   retinted to the fall palette instead of the template defaults. The Bootstrap-
   classname rules this section used to carry (.btn-primary, .form-control,
   .form-floating, etc.) are gone along with Bootstrap itself — nothing in the app's
   markup uses those class names anymore, so styling them would just be dead CSS.
   The template's own .valid/.invalid/.validation-message outline rules used to
   live here too, retinted the same way — removed (not just retinted) since no Fran
   input ever used InputBase's own CssClass to trigger them in the first place, so
   they were dead CSS regardless of tint. See _inputs.scss's own .fa-input-invalid/
   .fa-validation-message (Fran.Validation) for the real, wired-up replacement —
   fa-prefixed on purpose, so it can't collide with a bare .invalid a consuming
   app's own page happens to use for something unrelated. */
h1:focus {
  outline: none;
}

.content {
  padding-top: 1.1rem;
}

#blazor-error-ui {
  color-scheme: light only;
  background: lightyellow;
  bottom: 0;
  box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
  box-sizing: border-box;
  display: none;
  left: 0;
  padding: 0.6rem 1.25rem 0.7rem 1.25rem;
  position: fixed;
  width: 100%;
  z-index: 1000;
}

#blazor-error-ui .dismiss {
  cursor: pointer;
  position: absolute;
  right: 0.75rem;
  top: 0.5rem;
}

/* Terse UI style (data-fa-ui-style="terse", see _palettes.scss) — this banner's
   shadow is hardcoded, not routed through --fa-border-glow, so it needs its own
   flattening; a flat top border keeps the same edge-separation from page content. */
:root[data-fa-ui-style=terse] #blazor-error-ui {
  box-shadow: none;
  border-top: var(--fa-border-width) solid var(--fa-border);
}

/* Typewriter UI style (data-fa-ui-style="typewriter", see _palettes.scss) — same
   reasoning as the terse block above, swapped to the soft neutral shadow. */
:root[data-fa-ui-style=typewriter] #blazor-error-ui {
  box-shadow: var(--fa-border-glow);
}

.blazor-error-boundary {
  background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, var(--fa-ember);
  padding: 1rem 1rem 1rem 3.7rem;
  color: white;
}

.blazor-error-boundary::after {
  content: "An error has occurred.";
}

.loading-progress {
  position: absolute;
  display: block;
  width: 8rem;
  height: 8rem;
  inset: 20vh 0 auto 0;
  margin: 0 auto 0 auto;
}

.loading-progress circle {
  fill: none;
  stroke: var(--fa-border);
  stroke-width: 0.6rem;
  transform-origin: 50% 50%;
  transform: rotate(-90deg);
}

.loading-progress circle:last-child {
  stroke: var(--fa-primary);
  stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
  transition: stroke-dasharray 0.05s ease-in-out;
}

.loading-progress-text {
  position: absolute;
  text-align: center;
  font-weight: bold;
  inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
}

.loading-progress-text:after {
  content: var(--blazor-load-percentage-text, "Loading");
}

code {
  font-family: ui-monospace, "Cascadia Code", "SFMono-Regular", Consolas, monospace;
  background: var(--fa-footer);
  color: var(--fa-primary-dark);
  padding: 0.1em 0.4em;
  border-radius: var(--fa-radius-sm);
}

/* ============================= Page templates ============================= */
/* FaDashboardTemplate, FaFormTemplate, FaHomeTemplate, FaAuthTemplate (Templates/) —
   each wraps FaStandardShell/FaSidebarShell (_layout.scss), so this partial only
   covers what those shells don't already style: the page-header row, the centered
   form/hero/auth bodies. */
.fa-template-page-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.5rem;
}

.fa-template-page-header h1 {
  margin: 0;
}

.fa-template-page-actions {
  display: flex;
  gap: 0.6rem;
}

/* --- FaFormTemplate --- */
.fa-template-form-wrap {
  margin: 2.5rem auto;
  width: 100%;
}

.fa-template-back-link {
  display: inline-block;
  margin-bottom: 1rem;
  color: var(--fa-text-muted);
  font-family: var(--fa-font);
  font-size: 0.88rem;
  text-decoration: none;
}

.fa-template-back-link:hover {
  color: var(--fa-primary-dark);
}

.fa-template-form-title {
  margin: 0 0 0.4rem;
}

.fa-template-form-description {
  margin: 0 0 1.2rem;
  color: var(--fa-text-muted);
}

/* --- FaHomeTemplate --- */
.fa-template-hero {
  text-align: center;
  padding: 4rem 1.5rem;
}

.fa-template-hero h1 {
  margin: 0 0 0.8rem;
  font-size: clamp(2rem, 4vw, 3rem);
}

.fa-template-hero p {
  max-width: 46ch;
  margin: 0 auto;
  color: var(--fa-text-muted);
  font-size: 1.05rem;
}

.fa-template-hero-actions {
  display: flex;
  justify-content: center;
  gap: 0.8rem;
  margin-top: 1.6rem;
}

/* --- FaAuthTemplate: chrome-free, so it owns full-viewport centering itself
   instead of relying on a shell's <main>. --- */
.fa-template-auth {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  padding: 2rem 1rem;
  background: var(--fa-cream);
}

.fa-template-auth-brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--fa-font);
  font-weight: 700;
  font-size: 1.3rem;
  color: var(--fa-primary-dark);
  text-decoration: none;
}

/* FaAuthTemplate.BrandIconUrl — omitted entirely (no img in the markup) when unset. */
.fa-template-auth-brand-icon {
  height: 1.5rem;
  width: auto;
  border-radius: var(--fa-radius-sm);
}

.fa-template-auth-card-wrap {
  width: 100%;
}

.fa-template-auth-footer {
  text-align: center;
  color: var(--fa-text-muted);
  font-size: 0.88rem;
}

/* ============================= Tabs ============================= */
.fa-tabs {
  display: flex;
  gap: 0.2rem;
  border-bottom: var(--fa-border-width) solid var(--fa-border);
}

.fa-tabs-tab {
  position: relative;
  font-family: var(--fa-font);
  font-weight: 700;
  font-size: 0.9rem;
  background: none;
  border: none;
  color: var(--fa-text-muted);
  padding: 0.6rem 1rem;
  cursor: pointer;
  transition: color var(--fa-transition-fast);
}

.fa-tabs-tab::after {
  content: "";
  position: absolute;
  left: 0.4rem;
  right: 0.4rem;
  bottom: -1px;
  height: 2px;
  border-radius: 2px;
  background: transparent;
  transition: background-color var(--fa-transition-fast);
}

.fa-tabs-tab:hover {
  color: var(--fa-text);
}

.fa-tabs-tab:focus-visible {
  outline: none;
  color: var(--fa-primary-dark);
}

.fa-tabs-tab-active {
  color: var(--fa-primary-dark);
}

.fa-tabs-tab-active::after {
  background: var(--fa-primary);
}

/* ============================= Accordion ============================= */
.fa-accordion {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.fa-accordion-item {
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-md);
  background: var(--fa-surface);
  overflow: hidden;
}

.fa-accordion-item-open {
  border-color: var(--fa-glow);
}

.fa-accordion-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  font-family: var(--fa-font);
  font-weight: 700;
  font-size: 0.95rem;
  text-align: left;
  color: var(--fa-text);
  background: none;
  border: none;
  padding: 0.85rem 1rem;
  cursor: pointer;
}

.fa-accordion-chevron {
  display: inline-flex;
  transition: transform var(--fa-transition-medium);
}

.fa-accordion-item-open .fa-accordion-chevron {
  transform: rotate(180deg);
}

/* The no-JS smooth-height trick: a grid row that animates from 0fr to 1fr instead
   of animating max-height (which needs a hardcoded upper bound) or requiring JS to
   measure the panel's real height. */
.fa-accordion-panel-wrapper {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--fa-transition-medium);
}

.fa-accordion-item-open .fa-accordion-panel-wrapper {
  grid-template-rows: 1fr;
}

.fa-accordion-panel {
  min-height: 0;
  overflow: hidden;
  padding: 0 1rem;
  color: var(--fa-text-muted);
  font-size: 0.9rem;
  transition: padding var(--fa-transition-medium);
}

.fa-accordion-item-open .fa-accordion-panel {
  padding: 0 1rem 1rem;
}

@media (prefers-reduced-motion: reduce) {
  .fa-accordion-panel-wrapper,
  .fa-accordion-chevron {
    transition: none;
  }
}
/* ============================= Tooltip ============================= */
.fa-tooltip {
  position: relative;
  display: inline-flex;
}

.fa-tooltip-trigger {
  display: inline-flex;
}

.fa-tooltip-bubble {
  position: absolute;
  z-index: 30;
  left: 50%;
  transform: translateX(-50%) translateY(0.2rem);
  background: var(--fa-fir);
  color: var(--fa-text-on-primary);
  font-family: var(--fa-font);
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
  padding: 0.35rem 0.65rem;
  border-radius: var(--fa-radius-sm);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.2);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--fa-transition-fast), transform var(--fa-transition-fast), visibility var(--fa-transition-fast);
}

.fa-tooltip-bottom {
  top: 100%;
  margin-top: 0.4rem;
}

.fa-tooltip-top {
  bottom: 100%;
  margin-bottom: 0.4rem;
}

.fa-tooltip-left {
  top: 50%;
  right: 100%;
  left: auto;
  margin-right: 0.4rem;
  transform: translateY(-50%) translateX(-0.2rem);
}

.fa-tooltip-right {
  top: 50%;
  left: 100%;
  margin-left: 0.4rem;
  transform: translateY(-50%) translateX(0.2rem);
}

.fa-tooltip:hover .fa-tooltip-bubble,
.fa-tooltip:focus-within .fa-tooltip-bubble {
  opacity: 1;
  visibility: visible;
}

.fa-tooltip:hover .fa-tooltip-top,
.fa-tooltip:focus-within .fa-tooltip-top {
  transform: translateX(-50%) translateY(0);
}

.fa-tooltip:hover .fa-tooltip-bottom,
.fa-tooltip:focus-within .fa-tooltip-bottom {
  transform: translateX(-50%) translateY(0);
}

.fa-tooltip:hover .fa-tooltip-left,
.fa-tooltip:focus-within .fa-tooltip-left {
  transform: translateY(-50%) translateX(0);
}

.fa-tooltip:hover .fa-tooltip-right,
.fa-tooltip:focus-within .fa-tooltip-right {
  transform: translateY(-50%) translateX(0);
}

/* Terse UI style (data-fa-ui-style="terse", see _palettes.scss) — flat border
   instead of a drop shadow. */
:root[data-fa-ui-style=terse] .fa-tooltip-bubble {
  box-shadow: none;
  border: 1px solid var(--fa-border);
}

/* Typewriter UI style (data-fa-ui-style="typewriter", see _palettes.scss) — soft
   neutral shadow instead of the harsher literal one. */
:root[data-fa-ui-style=typewriter] .fa-tooltip-bubble {
  box-shadow: var(--fa-border-glow);
}

/* ============================= Popover ============================= */
.fa-popover {
  position: relative;
  display: inline-block;
}

.fa-popover-trigger {
  font-family: var(--fa-font);
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-pill);
  background: var(--fa-surface);
  color: var(--fa-text);
  padding: 0.5rem 1rem;
  cursor: pointer;
  transition: border-color var(--fa-transition-fast), box-shadow var(--fa-transition-fast);
}

.fa-popover-trigger:hover {
  border-color: var(--fa-glow);
}

.fa-popover-trigger:focus-visible,
.fa-popover-trigger[aria-expanded=true] {
  outline: none;
  border-color: var(--fa-border-focus);
  box-shadow: var(--fa-border-glow-focus);
}

.fa-popover-panel {
  display: none;
  position: absolute;
  z-index: 30;
  min-width: 14rem;
  background: var(--fa-surface);
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-lg);
  box-shadow: var(--fa-border-glow);
  padding: 0.8rem;
}

.fa-popover-panel-open {
  display: block;
  animation: fa-popover-pop 0.16s ease;
}

@media (prefers-reduced-motion: reduce) {
  .fa-popover-panel-open {
    animation: none;
  }
}
.fa-popover-bottom {
  top: 100%;
  left: 0;
  margin-top: 0.5rem;
}

.fa-popover-top {
  bottom: 100%;
  left: 0;
  margin-bottom: 0.5rem;
}

.fa-popover-left {
  top: 0;
  right: 100%;
  margin-right: 0.5rem;
}

.fa-popover-right {
  top: 0;
  left: 100%;
  margin-left: 0.5rem;
}

@keyframes fa-popover-pop {
  from {
    opacity: 0;
    transform: translateY(-0.35rem) scale(0.97);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}
/* ============================= Toast ============================= */
.fa-toast-host {
  position: fixed;
  z-index: 2000;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 1rem;
  max-width: 22rem;
  pointer-events: none;
}

.fa-toast-host-top-right {
  top: 0;
  right: 0;
  align-items: flex-end;
}

.fa-toast-host-top-left {
  top: 0;
  left: 0;
  align-items: flex-start;
}

.fa-toast-host-top-center {
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  align-items: center;
}

.fa-toast-host-bottom-right {
  bottom: 0;
  right: 0;
  align-items: flex-end;
  flex-direction: column-reverse;
}

.fa-toast-host-bottom-left {
  bottom: 0;
  left: 0;
  align-items: flex-start;
  flex-direction: column-reverse;
}

.fa-toast-host-bottom-center {
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  align-items: center;
  flex-direction: column-reverse;
}

.fa-toast {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  width: 100%;
  background: var(--fa-surface);
  border: var(--fa-border-width) solid var(--fa-border);
  border-radius: var(--fa-radius-md);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  padding: 0.75rem 0.9rem;
  pointer-events: auto;
  animation: fa-toast-in 0.2s ease;
}

@media (prefers-reduced-motion: reduce) {
  .fa-toast {
    animation: none;
  }
}
.fa-toast-info {
  border-left: 4px solid var(--fa-primary);
}

.fa-toast-success {
  border-left: 4px solid var(--fa-accent);
}

.fa-toast-danger {
  border-left: 4px solid var(--fa-ember);
}

.fa-toast-text {
  flex: 1;
  font-family: var(--fa-font);
  font-size: 0.88rem;
  color: var(--fa-text);
}

.fa-toast-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.4rem;
  height: 1.4rem;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--fa-text-muted);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
  transition: background-color var(--fa-transition-fast), color var(--fa-transition-fast);
}

.fa-toast-close:hover {
  background: var(--fa-footer);
  color: var(--fa-text);
}

/* Terse UI style (data-fa-ui-style="terse", see _palettes.scss) — flat border only,
   no drop shadow; the slide/scale-in entrance also drops since "no motion" is
   part of the same style's identity as the flattened shadow/transition tokens. */
:root[data-fa-ui-style=terse] .fa-toast {
  box-shadow: none;
  animation: none;
}

/* Typewriter UI style (data-fa-ui-style="typewriter", see _palettes.scss) — soft
   neutral shadow instead of the literal one; the slide/scale-in entrance stays
   (unlike terse/brutal's "no motion" stance) since a toast easing in is exactly
   the gentle, physical-feeling movement this style is going for. */
:root[data-fa-ui-style=typewriter] .fa-toast {
  box-shadow: var(--fa-border-glow);
}

@keyframes fa-toast-in {
  from {
    opacity: 0;
    transform: translateY(-0.4rem) scale(0.96);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}
/* ============================= Breadcrumb ============================= */
.fa-breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  list-style: none;
  margin: 0;
  padding: 0;
  font-family: var(--fa-font);
  font-size: 0.88rem;
}

.fa-breadcrumb-item {
  display: flex;
  align-items: center;
}

/* "›" separator before every item except the first, rather than a per-item
   FaIcon — cheap, and never needs its own currentColor/theme wiring. */
.fa-breadcrumb-item:not(:first-child)::before {
  content: "›";
  margin: 0 0.5rem;
  color: var(--fa-text-muted);
}

.fa-breadcrumb-item a {
  color: var(--fa-primary-dark);
  text-decoration: none;
}

.fa-breadcrumb-item a:hover {
  text-decoration: underline;
}

.fa-breadcrumb-item span {
  color: var(--fa-text-muted);
}

.fa-breadcrumb-item span[aria-current=page] {
  color: var(--fa-text);
  font-weight: 600;
}

/* ============================= Pagination ============================= */
.fa-pagination {
  display: flex;
  align-items: center;
  gap: 0.3rem;
}

.fa-pagination-nav,
.fa-pagination-page {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2rem;
  height: 2rem;
  padding: 0 0.4rem;
  border-radius: var(--fa-radius-pill);
  border: var(--fa-border-width) solid transparent;
  background: none;
  font-family: var(--fa-font);
  font-size: 0.88rem;
  color: var(--fa-text);
  cursor: pointer;
  transition: background-color var(--fa-transition-fast), border-color var(--fa-transition-fast), color var(--fa-transition-fast);
}

.fa-pagination-nav:hover:not(:disabled),
.fa-pagination-page:hover:not(:disabled) {
  background: var(--fa-footer);
  border-color: var(--fa-glow);
}

.fa-pagination-nav:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.fa-pagination-nav:focus-visible,
.fa-pagination-page:focus-visible {
  outline: none;
  border-color: var(--fa-border-focus);
  box-shadow: var(--fa-border-glow-focus);
}

.fa-pagination-page-active {
  background: var(--fa-primary);
  color: var(--fa-text-on-primary);
}

.fa-pagination-page-active:hover {
  background: var(--fa-primary-dark);
}

.fa-pagination-ellipsis {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2rem;
  height: 2rem;
  color: var(--fa-text-muted);
}

/* ============================= Skeleton ============================= */
.fa-skeleton-lines {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}

.fa-skeleton {
  display: block;
  background: linear-gradient(90deg, var(--fa-border) 25%, var(--fa-surface) 50%, var(--fa-border) 75%);
  background-size: 200% 100%;
  animation: fa-skeleton-shimmer 1.4s ease-in-out infinite;
}

.fa-skeleton-text {
  width: 100%;
  height: 0.85em;
  border-radius: var(--fa-radius-sm);
}

.fa-skeleton-text-last {
  width: 60%;
}

.fa-skeleton-circle {
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
}

.fa-skeleton-rect {
  width: 100%;
  height: 8rem;
  border-radius: var(--fa-radius-md);
}

@keyframes fa-skeleton-shimmer {
  from {
    background-position: 200% 0;
  }
  to {
    background-position: -200% 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  .fa-skeleton {
    animation: none;
    background: var(--fa-border);
  }
}
/* ============================= Chip ============================= */
.fa-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-family: var(--fa-font);
  font-weight: 600;
  font-size: 0.82rem;
  padding: 0.3rem 0.7rem;
  border-radius: var(--fa-radius-pill);
  background: var(--fa-footer);
  color: var(--fa-text);
  border: var(--fa-border-width) solid transparent;
  transition: background-color var(--fa-transition-fast), border-color var(--fa-transition-fast), transform var(--fa-transition-fast);
}

.fa-chip-clickable {
  cursor: pointer;
}

.fa-chip-clickable:hover {
  border-color: var(--fa-glow);
}

.fa-chip-clickable:active {
  transform: scale(0.97);
}

.fa-chip-clickable:focus-visible {
  outline: none;
  border-color: var(--fa-border-focus);
  box-shadow: var(--fa-border-glow-focus);
}

.fa-chip-selected {
  background: var(--fa-primary);
  color: var(--fa-text-on-primary);
}

/* Terse UI style (data-fa-ui-style="terse", see _palettes.scss) — same tracked-out
   uppercase mono treatment as .fa-badge (_badges.scss). Radius stays
   --fa-radius-pill in both styles. */
:root[data-fa-ui-style=terse] .fa-chip {
  font-family: var(--fa-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.fa-chip-disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.fa-chip-success {
  background: var(--fa-accent);
  color: var(--fa-text-on-primary);
}

.fa-chip-danger {
  background: var(--fa-ember);
  color: var(--fa-text-on-primary);
}

.fa-chip-primary {
  background: var(--fa-primary);
  color: var(--fa-text-on-primary);
}

.fa-chip-label {
  white-space: nowrap;
}

/* FaChip.Size (FaSize) — Medium renders with none of these. */
.fa-chip-xs {
  padding: 0.18rem 0.5rem;
  font-size: 0.7rem;
}

.fa-chip-sm {
  padding: 0.24rem 0.6rem;
  font-size: 0.76rem;
}

.fa-chip-lg {
  padding: 0.4rem 0.9rem;
  font-size: 0.9rem;
}

.fa-chip-xl {
  padding: 0.5rem 1.1rem;
  font-size: 1rem;
}

.fa-chip-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.1rem;
  height: 1.1rem;
  margin-left: 0.1rem;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.12);
  color: inherit;
  cursor: pointer;
  padding: 0;
  transition: background-color var(--fa-transition-fast);
}

.fa-chip-remove:hover:not(:disabled) {
  background: rgba(0, 0, 0, 0.22);
}

.fa-chip-remove:disabled {
  cursor: not-allowed;
}

/* ============================= Divider ============================= */
.fa-divider {
  border: none;
  border-top: var(--fa-border-width) solid var(--fa-border);
  margin: 1rem 0;
}

.fa-divider-vertical {
  border-top: none;
  border-left: var(--fa-border-width) solid var(--fa-border);
  width: 0;
  align-self: stretch;
  margin: 0 1rem;
}

.fa-divider-labeled {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  border-top: none;
  margin: 1rem 0;
  color: var(--fa-text-muted);
  font-family: var(--fa-font);
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.fa-divider-labeled::before,
.fa-divider-labeled::after {
  content: "";
  flex: 1;
  border-top: var(--fa-border-width) solid var(--fa-border);
}

/* ============================= Empty state ============================= */
.fa-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.5rem;
  padding: 2.5rem 1.5rem;
}

.fa-empty-state-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3.4rem;
  height: 3.4rem;
  border-radius: 50%;
  background: var(--fa-footer);
  margin-bottom: 0.4rem;
}

.fa-empty-state-title {
  margin: 0;
  font-family: var(--fa-font);
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--fa-text);
}

.fa-empty-state-description {
  margin: 0;
  max-width: 32ch;
  color: var(--fa-text-muted);
  font-size: 0.9rem;
}

.fa-empty-state-actions {
  display: flex;
  gap: 0.6rem;
  margin-top: 0.6rem;
}

/* FaCodeBlock (Components/Elements/FaCodeBlock.cs) — a read-only source-code panel.
   Background is var(--fa-fir), the one token every palette defines as its deep
   neutral "black" anchor (_palettes.scss) — genuinely darker than that palette's
   --fa-surface/--fa-cream rather than a one-off dark literal, so "a darker color
   from the palette" holds for all 28 palettes without a new token. */
.fa-codeblock {
  background: var(--fa-fir);
  color: #e8e6e0;
  border-radius: var(--fa-radius-md);
  border: var(--fa-border-width) solid var(--fa-border);
  overflow: hidden;
  font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
}

/* No rule here means the browser's own default selection highlight (usually a
   pale, near-white overlay) applies instead — fine against ordinary dark-on-
   light body text, but against this block's light-on-dark token colors it
   washes both the highlight and the text it's covering out to the same near-
   white, unreadable either way. Pin selection to an explicit, always-readable
   pair instead of leaving it to whatever the browser/OS defaults to. */
.fa-codeblock ::selection {
  background: #e8e6e0;
  color: var(--fa-fir);
}

.fa-codeblock ::-moz-selection {
  background: #e8e6e0;
  color: var(--fa-fir);
}

.fa-codeblock-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.5rem 0.9rem;
  background: rgba(0, 0, 0, 0.2);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.fa-codeblock-lang {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: rgba(232, 230, 224, 0.6);
}

.fa-codeblock-copy {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.6rem;
  border-radius: var(--fa-radius-sm);
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: transparent;
  color: rgba(232, 230, 224, 0.85);
  font-size: 0.75rem;
  cursor: pointer;
  transition: background-color var(--fa-transition-fast), border-color var(--fa-transition-fast), color var(--fa-transition-fast);
}

.fa-codeblock-copy:hover {
  background: rgba(255, 255, 255, 0.1);
}

/* Fixed success green, not var(--fa-accent) — same "palette-agnostic on
   purpose" reasoning as the token colors below; a per-palette accent can land
   anywhere in the color wheel (Fit's is green, Floating's is slate-blue,
   Ruckus's is moss) and wouldn't reliably read as "success" against every one. */
.fa-codeblock-copy.fa-codeblock-copied {
  border-color: #6bc79a;
  color: #6bc79a;
}

.fa-codeblock-copy-icon {
  flex-shrink: 0;
}

.fa-codeblock-pre {
  margin: 0;
  padding: 1rem 1.1rem;
  overflow: auto;
  font-family: inherit;
  font-size: 0.85rem;
  line-height: 1.55;
}

/* Resets the site-wide inline `code { background/color/padding/border-radius }`
   rule (_blazor-chrome.scss, meant for a one-off inline snippet in prose) back
   out — this element is itself a <code> tag (FaCodeBlock.cs), so it matches that
   bare-tag selector too. Left alone, that rule's light var(--fa-footer) background
   and padding painted a rounded highlight-pill behind every line's text, right on
   top of this block's own deliberately dark background/light text. */
.fa-codeblock-code {
  font-family: inherit;
  background: none;
  color: inherit;
  padding: 0;
  border-radius: 0;
}

/* Token colors are fixed, not derived per-palette — same reasoning as colorblind
   mode's "one known-safe pair reused everywhere" (_palettes.scss): --fa-fir stays
   dark-enough-to-near-black across every one of the 28 palettes, so a single
   light-on-dark token scheme reads correctly regardless of which palette is
   active, without needing 28 separate highlight-color sets tuned per palette. */
.fa-code-tok-comment {
  color: #8a9199;
  font-style: italic;
}

.fa-code-tok-string {
  color: #9ecb8f;
}

.fa-code-tok-number {
  color: #d8a657;
}

.fa-code-tok-keyword {
  color: #e693c2;
  font-weight: 600;
}

.fa-code-tok-tag {
  color: #7fb0e0;
}

.fa-code-tok-attr {
  color: #a9cf7f;
}

.fa-code-tok-literal {
  color: #d8a657;
}

.fa-code-tok-property {
  color: #7fb0e0;
}

/* ============================= Layout & spacing utilities ============================= */
/* A small, deliberately minimal utility layer — not a full grid framework. Only what the
   app's own pages actually use (a simple wrapping row, a gap, a margin, text alignment). */
.fa-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
}

.fa-col-auto {
  flex: 0 0 auto;
}

.fa-flex {
  display: flex;
  align-items: center;
}

.fa-flex-between {
  justify-content: space-between;
}

.fa-gap-2 {
  gap: 0.5rem;
}

.fa-gap-3 {
  gap: 1rem;
}

.fa-mb-3 {
  margin-bottom: 1rem;
}

.fa-mb-4 {
  margin-bottom: 1.5rem;
}

.fa-mt-2 {
  margin-top: 0.5rem;
}

.fa-mt-3 {
  margin-top: 1rem;
}

.fa-mt-5 {
  margin-top: 3rem;
}

.fa-my-2 {
  margin-top: 0.5rem;
  margin-bottom: 0.5rem;
}

.fa-me-1 {
  margin-right: 0.25rem;
}

.fa-me-2 {
  margin-right: 0.5rem;
}

.fa-text-end {
  text-align: right;
}

.fa-text-center {
  text-align: center;
}

.fa-text-danger {
  color: var(--fa-ember);
}

/* --- justify-content alignment for a flex button row — FaAlign, shared by
   FaModal's footer and FaForm/FaLogoutForm's action bar (Rendering/FaAlignClassNames.cs
   maps the enum to these). --- */
.fa-align-start {
  justify-content: flex-start;
}

.fa-align-center {
  justify-content: center;
}

.fa-align-end {
  justify-content: flex-end;
}

.fa-align-between {
  justify-content: space-between;
}

.fa-align-around {
  justify-content: space-around;
}

.fa-align-evenly {
  justify-content: space-evenly;
}

.fa-display {
  font-size: 2.5rem;
  font-weight: 700;
  line-height: 1.1;
}

/* ============================= Small screens ============================= */
@media (max-width: 720px) {
  /* Shared opt-in utility, not a per-component class — any component with a
     Responsive parameter (FaButton/FaCard/FaInput/FaSelect/FaTextarea/FaCurrency
     today) adds this one class when Responsive="true" instead of each defining
     its own identical "full width below the breakpoint" rule. Off by default:
     a button/card/input's intrinsic width is usually exactly what's wanted even
     on small screens, so this is opt-in per instance rather than automatic. */
  .fa-responsive {
    width: 100%;
  }
  .fa-shell-sidebar .fa-shell-body {
    flex-direction: column;
  }
  /* FaHeader.ShowSidebarToggle's hamburger — hidden at desktop widths
     (_layout.scss), shown here alongside the sidebar going off-canvas below. */
  .fa-header-menu-toggle {
    display: inline-flex;
  }
  /* Off-canvas below this breakpoint, regardless of FaSidebar.Collapsible (that's a
     separate, desktop-only icon-rail affordance) — closed by default and shown only
     once html carries .fa-sidebar-mobile-open (js/sidebar.js's faToggleSidebarMobile,
     wired to the header's hamburger button above). */
  .fa-sidebar {
    display: none;
  }
  html.fa-sidebar-mobile-open .fa-sidebar {
    display: flex;
  }
  /* Collapse/expand is a desktop affordance — the mobile layout is already a compact
     icon+label row, so force expanded and hide the toggle rather than letting the two
     layout modes combine. Scoped to .fa-sidebar-collapsible same as _layout.scss's own
     collapse rules (a non-collapsible sidebar never picks up width: 64px in the first
     place, so it has nothing to undo here — but the selectors stay harmless either way
     since they'd just re-state values already in effect). */
  .fa-sidebar,
  html.fa-sidebar-collapsed .fa-sidebar.fa-sidebar-collapsible {
    width: 100%;
    flex: 0 0 auto;
    flex-direction: row;
    flex-wrap: wrap;
    padding: 0.75rem;
    box-shadow: 0 2px 0 var(--fa-glow), 0 4px 14px rgba(140, 67, 27, 0.25);
  }
  /* Terse UI style (data-fa-ui-style="terse", see _palettes.scss) — same flat
     border treatment as the desktop .fa-sidebar in _layout.scss, restated here
     since this rule (later in cascade, same specificity) would otherwise keep
     winning over that one at this breakpoint. */
  :root[data-fa-ui-style=terse] .fa-sidebar,
  html[data-fa-ui-style=terse].fa-sidebar-collapsed .fa-sidebar.fa-sidebar-collapsible {
    box-shadow: none;
    border-bottom: var(--fa-border-width) solid var(--fa-glow);
  }
  /* Typewriter UI style (data-fa-ui-style="typewriter", see _palettes.scss) —
     same reasoning as the terse block above, swapped to the soft neutral shadow. */
  :root[data-fa-ui-style=typewriter] .fa-sidebar,
  html[data-fa-ui-style=typewriter].fa-sidebar-collapsed .fa-sidebar.fa-sidebar-collapsible {
    box-shadow: var(--fa-border-glow);
  }
  /* FaSidebar.Position: Sticky/Floating's own position: sticky + fixed
     height: calc(100vh - header-height) (_layout.scss) are desktop affordances —
     "stay pinned while the page scrolls" only means something once the sidebar is
     back to a normal in-flow column, and at this breakpoint every position variant
     collapses into the same off-canvas row above regardless of Position. Left
     unreset, a Sticky/Floating sidebar would open as a full-viewport-height pinned
     panel instead of the compact row Standard gets — same bug this whole block
     exists to avoid for Collapsible above, just for Position instead. Floating's
     margin/border-radius are reset alongside its position for the same reason: they
     exist to read as a detached inset bar against a full-height sidebar, and just
     look like uneven padding once the sidebar is a normal-height row. */
  .fa-sidebar-sticky,
  .fa-sidebar-floating {
    position: static;
    top: auto;
    height: auto;
    margin: 0;
    border-radius: 0;
  }
  /* Scoped scrollbar/overflow styling (_layout.scss) only made sense while the
     sidebar scrolled independently at full viewport height above — once it's back
     to a normal-height row, its content should flow (and grow) with the page like
     any other off-canvas panel, not clip to a stale fixed height. */
  .fa-sidebar-sticky .fa-sidebar-scroll,
  .fa-sidebar-floating .fa-sidebar-scroll {
    overflow: visible;
  }
  .fa-sidebar-toggle {
    display: none;
  }
  /* Mobile ignores the collapse state entirely — undo the desktop-collapsed
     tightened gap/padding/centering along with the text's max-width. */
  html.fa-sidebar-collapsed .fa-sidebar-collapsible .fa-sidebar-link,
  html.fa-sidebar-collapsed-settled .fa-sidebar-collapsible .fa-sidebar-link {
    justify-content: flex-start;
    gap: 0.6rem;
    padding-left: 0.9rem;
    padding-right: 0.9rem;
  }
  html.fa-sidebar-collapsed .fa-sidebar-collapsible .fa-sidebar-link-text {
    max-width: none;
  }
  html.fa-sidebar-collapsed .fa-sidebar-collapsible .fa-sidebar-link::after {
    content: none;
  }
  .fa-header-username {
    display: none;
  }
  /* .fa-table card mode — each row becomes its own bordered card, each cell a
     label/value pair sourced from the cell's data-label attribute. FaTable.cs
     emits data-label on every generated <td> automatically; hand-written
     <table class="fa-table"> markup opts in by adding data-label itself. */
  .fa-table thead {
    /* Same clip technique as .fa-sr-only above, inlined here since a class
       can't be applied conditionally per breakpoint without JS. */
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
  .fa-table {
    display: block;
    width: 100%;
    border: none;
    background: transparent;
    box-shadow: none;
    overflow: visible;
  }
  .fa-table tbody {
    display: block;
    width: 100%;
  }
  .fa-table tr {
    display: flex;
    flex-direction: column;
    width: 100%;
    background: var(--fa-surface);
    border: var(--fa-border-width) solid var(--fa-border);
    border-radius: var(--fa-radius-md);
    box-shadow: var(--fa-border-glow);
    margin-bottom: 0.75rem;
    overflow: hidden;
  }
  .fa-table tr:last-child {
    margin-bottom: 0;
  }
  .fa-table td {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem 0.9rem;
    text-align: right;
    border-bottom: 1px solid var(--fa-border);
  }
  /* Assumes the actions column is the last <td> in markup, matching the
     desktop convention — see .fa-table-actions below. */
  .fa-table td:last-child {
    border-bottom: none;
  }
  .fa-table td::before {
    content: attr(data-label);
    font-weight: 700;
    color: var(--fa-primary-dark);
    text-align: left;
  }
  /* Action column: no label, right-aligned, pinned above the data fields
     instead of appearing as just another labeled row. */
  .fa-table-actions {
    order: -1;
    width: auto;
    justify-content: flex-end;
  }
  .fa-table-actions::before {
    content: none;
  }
  /* FaDate: the calendar becomes a sticky sheet pinned near the bottom of the
     viewport instead of a popup anchored under the input — a plain
     top:100%/bottom:100% popup (_date.scss) can run off the top or bottom of
     a short/mobile viewport depending on where the field sits on the page.
     Ported from the mobile behavior of the library FaDate was originally
     split from, but kept at the calendar's own natural width/height (just
     centered and pinned) rather than stretched full-bleed — stretching it
     full width inflates the day grid's cells (aspect-ratio 1, so a wider
     column means a taller row too) past what a capped sheet height can show
     without its own internal scrollbar, which is exactly the clipped,
     partly-hidden calendar this is meant to fix. max-height is generous
     enough that the calendar (desktop or compact) is never actually
     clipped except on a genuinely tiny viewport, where overflow-y still
     falls back to scrolling its own content rather than running off-screen.
     scroll-margin-bottom on the wrapper leaves room for the sheet when the
     browser's own "scroll the focused element into view" kicks in, so
     opening the calendar doesn't hide the field it belongs to above it. */
  .fa-date {
    scroll-margin-bottom: 23rem;
  }
  /* The auto-mode flip: FaDate.cs's RenderCalendar always renders both an
     .fa-date-calendar-auto-desktop (grid) and an .fa-date-calendar-auto-mobile
     (wheels) variant unless CompactPicker or a manual mode-toggle click has
     already settled on one — see _date.scss's own remarks on both classes,
     including the default (desktop-shown) rule this overrides. */
  .fa-date-calendar-auto-desktop {
    display: none;
  }
  .fa-date-calendar-auto-mobile {
    display: block;
  }
  .fa-date-calendar.fa-date-calendar-open {
    position: fixed;
    top: auto;
    left: 50%;
    right: auto;
    bottom: 0.75rem;
    transform: translateX(-50%);
    width: calc(100% - 1.5rem);
    max-width: 20rem;
    max-height: calc(100vh - 1.5rem);
    margin-top: 0;
    box-shadow: 0 -0.25rem 1rem rgba(0, 0, 0, 0.2);
    overflow-y: auto;
    /* Above everything else on the page (matches .fa-modal-backdrop/
       .fa-blazor-error-ui's "top of everything" tier, _modal.scss/
       _blazor-chrome.scss) — a sheet pinned to the viewport bottom is
       pointless if page content it's supposed to sit above can still
       paint over it. */
    z-index: 1000;
    padding-bottom: calc(0.6rem + env(safe-area-inset-bottom));
    animation: fa-date-sheet-up 0.18s ease;
  }
  @keyframes fa-date-sheet-up {
    from {
      transform: translateX(-50%) translateY(100%);
    }
    to {
      transform: translateX(-50%) translateY(0);
    }
  }
}
@media (max-width: 720px) and (prefers-reduced-motion: reduce) {
  .fa-date-calendar.fa-date-calendar-open {
    animation: none;
  }
}