/* ============================================================
   Glass Vault Design System
   Primary design tokens and component styles
   ============================================================ */

/* ---- CSS Custom Properties (Design Tokens) ---- */
/*
 * THE BRAND PALETTE IS DEFINED ONCE, AS RGB CHANNELS.
 *
 * Each brand colour is declared as space-separated channels ("201 169 110") in a `-rgb` variable,
 * and the familiar `--gv-*` colour is composed from it. Two things depend on that shape:
 *
 *  1. tailwind.config.js maps every `vault-*` utility to `rgb(var(--gv-*-rgb) / <alpha-value>)`.
 *     Tailwind can only compose an opacity modifier — `bg-vault-gold/10`, used throughout this
 *     codebase — onto CHANNELS. A plain `var(--gv-gold)` makes every one of those silently render
 *     at full opacity. Before this, the utilities compiled hex LITERALS into tailwind.css, so the
 *     variables and the utility classes were two independent copies of the same palette.
 *  2. /admin/site-content → Branding overrides these `-rgb` variables in a <style> block per
 *     request (see ThemeTokens.BuildCssVariables). Because Tailwind and glass-vault.css now read
 *     the SAME variables, one override reaches the whole site instead of half of it.
 *
 * Change a brand colour HERE and in nowhere else. The `-rgb` value is the source; every literal
 * below it is derived.
 */
:root {
    /* Background palette */
    --gv-bg-deep-rgb:   8 14 26;
    --gv-bg-base-rgb:   15 23 41;
    --gv-bg-mid-rgb:    26 35 64;
    --gv-bg-light-rgb:  36 48 88;

    --gv-bg-deep:       rgb(var(--gv-bg-deep-rgb));
    --gv-bg-base:       rgb(var(--gv-bg-base-rgb));
    --gv-bg-mid:        rgb(var(--gv-bg-mid-rgb));
    --gv-bg-light:      rgb(var(--gv-bg-light-rgb));

    /* Gold accent palette */
    --gv-gold-rgb:        201 169 110;
    --gv-gold-light-rgb:  226 209 163;
    --gv-gold-muted-rgb:  160 124 74;

    --gv-gold:          rgb(var(--gv-gold-rgb));
    --gv-gold-light:    rgb(var(--gv-gold-light-rgb));
    --gv-gold-muted:    rgb(var(--gv-gold-muted-rgb));
    --gv-gold-shine:    #F0E4C2;

    /* Danger palette — destructive actions only (see .glass-btn-danger).
       Chosen to clear WCAG AA against --gv-text-primary on the dark surfaces. NOT operator-editable:
       "destructive" is a meaning, not a brand choice, and a brandbook red that fails contrast here
       would make delete buttons unreadable. */
    --gv-danger:        #B4232B;
    --gv-danger-light:  #D0323B;

    /* Text palette */
    --gv-text-primary-rgb: 245 241 235;
    --gv-text-dim-rgb:     200 194 184;

    --gv-text-primary:  rgb(var(--gv-text-primary-rgb));
    --gv-text-dim:      rgb(var(--gv-text-dim-rgb));
    --gv-text-muted:    #8A8278;

    /* Glass effects. Derived from the gold channels so a rebrand carries the glass borders with it
       — these were literal rgba(201,169,110,…), i.e. the old gold frozen into four more places. */
    --gv-glass-bg:      rgba(255, 255, 255, 0.04);
    --gv-glass-border:  rgb(var(--gv-gold-rgb) / 0.18);
    --gv-glass-border-hover: rgb(var(--gv-gold-rgb) / 0.40);
    --gv-glass-blur:    blur(12px);
    --gv-glass-blur-heavy: blur(24px);

    /* Typography
     * "Noto Sans Georgian" sits in BOTH primary stacks on purpose. Playfair Display and Inter
     * carry no Georgian glyphs, so without it every ka page fell through to whatever serif or
     * sans the visitor's OS happened to have (Sylfaen on Windows, tofu where nothing is
     * installed) — outside the design system entirely. CSS falls back per GLYPH, not per
     * element, so latin and cyrillic still render in Playfair/Inter and only the Georgian
     * glyphs reach Noto. It must come BEFORE the generic Georgia/system-ui, or the system
     * font wins the Georgian glyphs again.
     * --gv-font-geo (and the font-geo utility) is the Georgian-FIRST stack, for admin inputs
     * that are always Georgian; public surfaces want the per-glyph stacks above. */
    --gv-font-display:  "Playfair Display", "Noto Sans Georgian", Georgia, serif;
    --gv-font-body:     Inter, "Noto Sans Georgian", system-ui, sans-serif;
    --gv-font-geo:      "Noto Sans Georgian", Inter, sans-serif;

    /* Spacing */
    --gv-section-py:    6rem;
    --gv-section-py-sm: 4rem;

    /* Transitions */
    --gv-transition:    all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    --gv-transition-slow: all 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}

/* ---- Accessibility: Skip to main content ---- */
.skip-to-main {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 9999;
    padding: 0.75rem 1.5rem;
    background: var(--gv-gold);
    color: var(--gv-bg-deep);
    font-weight: 600;
    font-size: 0.875rem;
    text-decoration: none;
    border-radius: 0 0 0.5rem 0;
}

.skip-to-main:focus {
    left: 0;
}

/* ---- Accessibility: Focus rings (gold) ---- */
*:focus-visible {
    outline: 2px solid var(--gv-gold);
    outline-offset: 2px;
}

/* Remove focus outlines from headings — Blazor programmatically focuses h1
   after enhanced navigation, causing a distracting gold rectangle. */
h1:focus-visible,
h2:focus-visible,
h3:focus-visible,
h4:focus-visible,
h5:focus-visible,
h6:focus-visible {
    outline: none;
}

.glass-input:focus-visible {
    outline: 2px solid var(--gv-gold);
    outline-offset: 2px;
    box-shadow: 0 0 0 3px rgb(var(--gv-gold-rgb) / 0.1);
}

/* ---- Base Resets & Global ---- */
*, *::before, *::after {
    box-sizing: border-box;
}

html {
    /* Smooth scrolling inside a page. A PAGE CHANGE must not glide: Blazor resets the scroll to the top
       after every in-site navigation, and a smooth reset was a 1–3 s glide from the BOTTOM of the new page
       during which a second click hit that page's buttons. glass-vault.js ("Page changes jump") switches
       this to auto around every history change. */
    scroll-behavior: smooth;
    /* Hard cap to prevent any descendant from triggering page-level horizontal scroll.
       Individual scroll surfaces (e.g. <table> with `min-w-[500px]`) are wrapped with
       overflow-x:auto where needed, so internal scrolling still works. */
    overflow-x: hidden;
}

body {
    background-color: var(--gv-bg-deep);
    color: var(--gv-text-primary);
    font-family: var(--gv-font-body);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    /* clip, not hidden: `hidden` on <body> (with <html> also non-visible) makes the body a scroll
       container, and every position:sticky element — the services side menu — stopped sticking.
       clip cuts horizontal overflow the same way without creating one. `hidden` stays as the
       fallback for browsers without clip. */
    overflow-x: hidden;
    overflow-x: clip;
    /* Georgian and Russian words can be long enough to push narrow flex/grid cells past
       the viewport on mobile. Allow them to break anywhere within a column. */
    overflow-wrap: break-word;
    word-wrap: break-word;
}

/* Selection styling */
::selection {
    background-color: rgb(var(--gv-gold-rgb) / 0.25);
    color: var(--gv-text-primary);
}

/* Scrollbar styling */
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: var(--gv-bg-deep); }
::-webkit-scrollbar-thumb { background: var(--gv-gold-muted); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--gv-gold); }

/* ---- Navigation ---- */
#main-nav {
    transition: var(--gv-transition);
}

.nav-transparent {
    background: linear-gradient(to bottom, rgb(var(--gv-bg-deep-rgb) / 0.8) 0%, transparent 100%);
    backdrop-filter: blur(0px);
}

/* Scrolled header: a near-opaque THEMED surface so hero copy and the .ticker-strip never read
   through it. It starts at --gv-bg-base (one step lighter than the page) rather than --gv-bg-deep
   — on a dark brand palette (e.g. NEO burgundy, bgDeep #170A0E) bgDeep alone reads as black. */
.nav-scrolled {
    background: linear-gradient(to bottom, rgb(var(--gv-bg-base-rgb) / 0.96) 0%, rgb(var(--gv-bg-deep-rgb) / 0.94) 100%);
    backdrop-filter: var(--gv-glass-blur);
    border-bottom: 1px solid var(--gv-glass-border);
    box-shadow: 0 4px 32px rgba(0, 0, 0, 0.4);
}

.nav-link {
    color: var(--gv-text-dim);
    font-size: 0.875rem;
    font-weight: 500;
    letter-spacing: 0.02em;
    transition: var(--gv-transition);
    position: relative;
    padding-bottom: 2px;
    white-space: nowrap;
    flex-shrink: 0;
}

/* Tighter nav at lg breakpoint to accommodate longer Russian/Georgian text */
@media (min-width: 1024px) and (max-width: 1279px) {
    .nav-link {
        font-size: 0.8125rem;
    }
}

.nav-link::after {
    content: '';
    position: absolute;
    bottom: -2px;
    left: 0;
    width: 0;
    height: 2px;
    background: var(--gv-gold);
    transition: width 0.3s ease;
}

.nav-link:hover,
.nav-link-active {
    color: var(--gv-gold);
}

.nav-link-active {
    font-weight: 600;
}

.nav-link:hover::after,
.nav-link-active::after {
    width: 100%;
}

.nav-link-mobile {
    color: var(--gv-text-dim);
    font-size: 0.9375rem;
    font-weight: 500;
    padding: 0.5rem 0;
    border-bottom: 1px solid rgba(255,255,255,0.05);
    transition: var(--gv-transition);
    display: block;
}

.nav-link-mobile:hover {
    color: var(--gv-gold);
    padding-left: 0.5rem;
}

/* ---- Glass Panels & Cards ---- */
.glass-panel {
    background: var(--gv-glass-bg);
    backdrop-filter: var(--gv-glass-blur);
    -webkit-backdrop-filter: var(--gv-glass-blur);
    border: 1px solid var(--gv-glass-border);
}

.glass-card {
    background: var(--gv-glass-bg);
    backdrop-filter: var(--gv-glass-blur);
    -webkit-backdrop-filter: var(--gv-glass-blur);
    border: 1px solid var(--gv-glass-border);
    border-radius: 1rem;
    transition: var(--gv-transition);
}

.glass-card:hover {
    border-color: var(--gv-glass-border-hover);
    background: rgba(255, 255, 255, 0.06);
    transform: translateY(-2px);
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4), 0 0 0 1px var(--gv-glass-border-hover);
}

.glass-card-heavy {
    background: rgb(var(--gv-bg-base-rgb) / 0.8);
    backdrop-filter: var(--gv-glass-blur-heavy);
    -webkit-backdrop-filter: var(--gv-glass-blur-heavy);
    border: 1px solid var(--gv-glass-border);
    border-radius: 1rem;
}

/* ---- Buttons ---- */
.glass-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.75rem 2rem;
    background: var(--gv-gold);
    color: var(--gv-bg-deep);
    font-weight: 600;
    font-size: 0.875rem;
    letter-spacing: 0.04em;
    border-radius: 0.375rem;
    border: 1px solid var(--gv-gold);
    transition: var(--gv-transition);
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
}

.glass-btn:hover {
    background: var(--gv-gold-light);
    border-color: var(--gv-gold-light);
    box-shadow: 0 0 24px rgb(var(--gv-gold-rgb) / 0.35);
    transform: translateY(-1px);
    color: var(--gv-bg-deep);
}

/* Destructive twin of .glass-btn — for the confirm button of a delete/erase dialog.
   It exists because ConfirmDialog's default used to be `glass-btn bg-red-600/80 …`:
   .glass-btn's `background` shorthand and the Tailwind utility have the same specificity,
   glass-vault.css is loaded last, so the red never applied and all twelve destructive
   dialogs in /admin rendered a GOLD confirm button indistinguishable from a primary action.
   Style the danger state HERE, in the design system, rather than by stacking utilities on
   a class that already owns `background`. */
.glass-btn-danger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.75rem 2rem;
    background: var(--gv-danger);
    color: var(--gv-text-primary);
    font-weight: 600;
    font-size: 0.875rem;
    letter-spacing: 0.04em;
    border-radius: 0.375rem;
    border: 1px solid var(--gv-danger-light);
    transition: var(--gv-transition);
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
}

.glass-btn-danger:hover {
    background: var(--gv-danger-light);
    border-color: var(--gv-danger-light);
    box-shadow: 0 0 24px rgba(180, 35, 43, 0.40);
    transform: translateY(-1px);
    color: var(--gv-text-primary);
}

.glass-btn-outline {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.625rem 1.5rem;
    background: transparent;
    color: var(--gv-gold);
    font-weight: 500;
    font-size: 0.875rem;
    letter-spacing: 0.04em;
    border-radius: 0.375rem;
    border: 1px solid var(--gv-glass-border-hover);
    transition: var(--gv-transition);
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
}

.glass-btn-outline:hover {
    background: rgb(var(--gv-gold-rgb) / 0.1);
    border-color: var(--gv-gold);
    box-shadow: 0 0 16px rgb(var(--gv-gold-rgb) / 0.15);
}

.glass-btn-ghost {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 1.5rem;
    background: transparent;
    color: var(--gv-text-dim);
    font-weight: 500;
    font-size: 0.875rem;
    border-radius: 0.375rem;
    border: 1px solid rgba(255,255,255,0.1);
    transition: var(--gv-transition);
    text-decoration: none;
    cursor: pointer;
}

.glass-btn-ghost:hover {
    border-color: rgba(255,255,255,0.2);
    color: var(--gv-text-primary);
    background: rgba(255,255,255,0.04);
}

.glass-btn:disabled,
.glass-btn-outline:disabled,
.glass-btn-ghost:disabled {
    opacity: 0.45;
    cursor: not-allowed;
    pointer-events: none;
}

/* ---- Form Inputs ---- */
.glass-input {
    width: 100%;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--gv-glass-border);
    border-radius: 0.5rem;
    padding-top: 0.75rem;
    padding-right: 1rem;
    padding-bottom: 0.75rem;
    padding-left: 1rem;
    color: var(--gv-text-primary);
    font-size: 0.875rem;
    font-family: var(--gv-font-body);
    transition: var(--gv-transition);
    outline: none;
}

.glass-input::placeholder {
    color: var(--gv-text-muted);
}

.glass-input:focus {
    border-color: var(--gv-gold-muted);
    background: rgba(255, 255, 255, 0.06);
    box-shadow: 0 0 0 3px rgb(var(--gv-gold-rgb) / 0.1);
}

.glass-input:hover {
    border-color: rgb(var(--gv-gold-rgb) / 0.30);
}

/* Native <select> popup options: browsers render the option list using OS-themed
   widgets and ignore the parent <select>'s glass background, so the inherited
   white/cream text ended up on a white system background → invisible options.
   Forcing explicit dark-on-cream colours fixes legibility across Chromium, Firefox
   and Safari. */
select.glass-input option,
select.glass-input optgroup {
    background-color: var(--gv-bg-mid);
    color: var(--gv-text-primary);
}
select.glass-input option:checked,
select.glass-input option:hover {
    background-color: var(--gv-gold);
    color: var(--gv-bg-deep);
}

/* ---- Gold Dividers ---- */
.gold-divider {
    width: 60px;
    height: 2px;
    background: linear-gradient(90deg, var(--gv-gold-muted), var(--gv-gold), var(--gv-gold-muted));
    border-radius: 1px;
}

.gold-divider-full {
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--gv-gold), transparent);
    opacity: 0.4;
}

/* ---- Section Titles ---- */
.section-eyebrow {
    display: inline-block;
    color: var(--gv-gold);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    margin-bottom: 1rem;
}

.section-title {
    font-family: var(--gv-font-display);
    font-size: clamp(2rem, 4vw, 3rem);
    font-weight: 700;
    color: var(--gv-text-primary);
    line-height: 1.15;
}

/* A page title that is a whole sentence (the About page opens with one). */
.section-title.section-title-long {
    font-size: clamp(1.625rem, 2.6vw, 2.25rem);
    line-height: 1.25;
}

.section-subtitle {
    color: var(--gv-text-dim);
    font-size: 1.0625rem;
    line-height: 1.7;
    max-width: 52ch;
}

/* Several intro paragraphs (the About page): use the desktop width, still a readable line length. */
.section-subtitle.section-subtitle-wide {
    max-width: 80ch;
}

/* ---- Hero ---- */
.hero-section {
    position: relative;
    /* Two full screens of banner was too much once the hero became the whole home page:
       the content sets the height, with a floor that still reads as a banner. */
    min-height: min(100svh, 760px);
    display: flex;
    align-items: center;
    overflow: hidden;
    background: var(--gv-bg-deep);
}

/* ---- Brand pattern background ----
   The brand book prints the griffin mark tiled in a 4-fold rotated pattern, very faintly, over
   the background. `.brand-pattern` renders that as a ::before layer: the tile is used ONLY as a
   mask (its alpha), filled with the accent colour, so it re-tints itself with the theme.

   Variable contract (set by the admin-driven <style> block, NEVER here):
     --gv-pattern-image    url('/images/brand/griffin-pattern.png') (or another same-origin tile)
                           default: none
     --gv-pattern-opacity  0..1, alpha of the accent fill — keep it tiny (0.03–0.08)
                           default: 0  → the layer is invisible and the site looks unchanged
     --gv-pattern-size     tile edge length, e.g. 220px                      default: 220px
   --gv-pattern-image and --gv-pattern-opacity MUST be set together: opacity > 0 with
   mask-image:none paints a solid accent wash over the whole section.

   Stacking: the host becomes its own stacking context (isolation:isolate) and the layer sits at
   z-index:-1 inside it — above the host's background, below all of its content. */
.brand-pattern {
    position: relative;
    isolation: isolate;
}

.brand-pattern::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    /* --gv-pattern-rgb: "0 0 0" for the brand book's darker-than-surface griffins; unset = accent tint. */
    background-color: rgb(var(--gv-pattern-rgb, var(--gv-gold-rgb)) / var(--gv-pattern-opacity, 0));
    -webkit-mask-image: var(--gv-pattern-image, none);
    mask-image: var(--gv-pattern-image, none);
    -webkit-mask-repeat: repeat;
    mask-repeat: repeat;
    -webkit-mask-size: var(--gv-pattern-size, 220px);
    mask-size: var(--gv-pattern-size, 220px);
    -webkit-mask-position: center top;
    mask-position: center top;
}

.hero-bg-gradient {
    position: absolute;
    inset: 0;
    background:
        radial-gradient(ellipse 80% 60% at 50% 0%, rgb(var(--gv-bg-light-rgb) / 0.6) 0%, transparent 70%),
        radial-gradient(ellipse 40% 40% at 80% 20%, rgb(var(--gv-gold-rgb) / 0.06) 0%, transparent 60%),
        radial-gradient(ellipse 40% 40% at 20% 80%, rgb(var(--gv-bg-base-rgb) / 0.8) 0%, transparent 60%);
    pointer-events: none;
}

.hero-grid-overlay {
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(rgb(var(--gv-gold-rgb) / 0.03) 1px, transparent 1px),
        linear-gradient(90deg, rgb(var(--gv-gold-rgb) / 0.03) 1px, transparent 1px);
    background-size: 60px 60px;
    pointer-events: none;
    /* 0 while the brand pattern is on (set by BrandAssets.BuildPatternVariables) — see there. */
    opacity: var(--gv-hero-grid-opacity, 1);
}

.hero-title {
    font-family: var(--gv-font-display);
    font-size: clamp(2rem, 4.2vw, 3.5rem);
    font-weight: 700;
    color: var(--gv-text-primary);
    line-height: 1.12;
    letter-spacing: -0.02em;
    /* Whole words move to the next line; a word is only split if it alone is wider than the line
       (a long CMS token on a phone). No auto-hyphenation: it cut "საქართველოში" into
       "საქართვე-" / "ლოში" even when the whole word fitted on the next line. */
    overflow-wrap: break-word;
    hyphens: manual;
    text-wrap: balance;
}

.hero-title .gold-word {
    color: var(--gv-gold);
}

.hero-subtitle {
    font-size: clamp(1rem, 1.6vw, 1.15rem);
    overflow-wrap: break-word;
    color: var(--gv-text-dim);
    line-height: 1.7;
    max-width: 50ch;
}

/* ---- Animated counter ---- */
.counter-value {
    font-family: var(--gv-font-display);
    font-size: 2.75rem;
    font-weight: 700;
    color: var(--gv-gold);
    line-height: 1;
    letter-spacing: -0.02em;
}

/* ---- Footer ---- */
.footer-link {
    color: var(--gv-text-dim);
    transition: var(--gv-transition);
    display: block;
    padding: 0.15rem 0;
}

.footer-link:hover {
    color: var(--gv-gold);
    padding-left: 0.25rem;
}

/* ---- Regulatory badges ---- */
.badge-regulatory {
    display: inline-block;
    font-size: 0.625rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--gv-gold-muted);
    border: 1px solid rgb(var(--gv-gold-rgb) / 0.25);
    border-radius: 0.25rem;
    padding: 0.2rem 0.5rem;
    background: rgb(var(--gv-gold-rgb) / 0.06);
}

/* ---- Value pillars / stat cards ---- */
.stat-card {
    background: var(--gv-glass-bg);
    border: 1px solid var(--gv-glass-border);
    border-radius: 1rem;
    padding: 2rem;
    text-align: center;
    transition: var(--gv-transition);
    /* Stretch every card to the tallest sibling in the same row so Georgian / Russian
       translations (which wrap to more lines than English) don't break the 2x2 mobile
       grid into a stair-step layout. */
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    height: 100%;
}

.stat-card:hover {
    border-color: var(--gv-glass-border-hover);
    background: rgba(255,255,255,0.06);
}

.stat-card .counter-value {
    line-height: 1.1;
}

/* Force every row of any grid containing stat-cards to take an equal share of available
   height so all four cards end up the same height regardless of which translation has
   the longest copy. Without this, Georgian (wrapping to 3 lines) makes the top row
   ~20px taller than the bottom row, producing a stair-step layout on mobile. */
.grid:has(> .stat-card) {
    grid-auto-rows: 1fr;
}

/* ---- Service cards ---- */
.service-icon-wrap {
    width: 3rem;
    height: 3rem;
    border-radius: 0.75rem;
    background: rgb(var(--gv-gold-rgb) / 0.1);
    border: 1px solid rgb(var(--gv-gold-rgb) / 0.2);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--gv-gold);
    transition: var(--gv-transition);
}

.glass-card:hover .service-icon-wrap {
    background: rgb(var(--gv-gold-rgb) / 0.18);
    border-color: rgb(var(--gv-gold-rgb) / 0.4);
}

/* ---- Inline mark (VaultIcon inside a run of text) ----
   [ICON-EMOJI-LATENT] The arrows, ticks and category marks used to be text characters, so they
   scaled with their sentence and sat on its baseline for free. They are inline SVG now — none of
   those characters are inside the unicode-ranges fonts.css declares, so the site never shipped them
   — and this keeps the same typographic behaviour: 1em square, baseline-aligned, colour inherited
   via currentColor. Sized in em ON PURPOSE, so text-xs and text-lg call sites both stay correct. */
.icon-inline {
    display: inline-block;
    width: 1em;
    height: 1em;
    vertical-align: -0.125em;
    flex-shrink: 0;
}

/* ---- Gold list bullet ----
   [ICON-EMOJI-LATENT] The Services page feature lists marked each item with ◆ U+25C6, written as
   the numeric entity &#9670; so no character scan could see it. Two defects in one span: Geometric
   Shapes is outside every unicode-range fonts.css declares, so the visitor's font stack decided
   whether the bullet appeared; and with no aria-hidden it also joined the list item's text. A
   bullet is not an icon — a rotated square is the same mark with no font dependency at all. */
.gold-bullet {
    display: inline-block;
    width: 0.375rem;
    height: 0.375rem;
    margin-top: 0.4rem;
    background: currentColor;
    transform: rotate(45deg);
    flex-shrink: 0;
}

/* ---- License / trust badge ---- */
.trust-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    background: rgb(var(--gv-gold-rgb) / 0.08);
    border: 1px solid rgb(var(--gv-gold-rgb) / 0.25);
    border-radius: 2rem;
    padding: 0.4rem 1rem;
    font-size: 0.75rem;
    color: var(--gv-gold-light);
    font-weight: 500;
    letter-spacing: 0.03em;
}

/* ---- Scroll animations ---- */
/* Visible by default (no-JS / SSR). JS adds .js-animations-ready to <body> to enable scroll-triggered hide→reveal. */
.fade-in-up {
    transition: opacity 0.7s ease, transform 0.7s ease;
}

.js-animations-ready .fade-in-up {
    opacity: 0;
    transform: translateY(24px);
}

.fade-in-up.visible {
    opacity: 1;
    transform: translateY(0);
}

/* ---- Service panels (/services, /corporate): one service per screen ----
   On a wide screen each panel is most of a screen tall with its card centred; the card in view rises in
   from below (.is-active) and the ones scrolled past fade out upwards (.is-past). glass-vault.js
   initServicePanels sets the classes; without JS (no .js-animations-ready) every card is shown. */
.service-panel {
    display: flex;
    align-items: center;
    padding: 1.5rem 0;
}
@media (min-width: 1024px) {
    .service-panel {
        min-height: 72vh;
    }
}
.service-panel-card {
    width: 100%;
    transition: opacity 0.8s ease, transform 0.8s ease, border-color 0.3s ease, background 0.3s ease;
}
.js-animations-ready .service-panel-card {
    opacity: 0;
    transform: translateY(56px);
}
.js-animations-ready .service-panel.is-active .service-panel-card {
    opacity: 1;
    transform: translateY(0);
}
.js-animations-ready .service-panel.is-past .service-panel-card {
    opacity: 0;
    transform: translateY(-56px);
}

.fade-in {
    transition: opacity 0.7s ease;
}

.js-animations-ready .fade-in {
    opacity: 0;
}

.fade-in.visible {
    opacity: 1;
}

/* Stagger delay helpers */
.delay-100 { transition-delay: 0.1s; }
.delay-200 { transition-delay: 0.2s; }
.delay-300 { transition-delay: 0.3s; }
.delay-400 { transition-delay: 0.4s; }
.delay-500 { transition-delay: 0.5s; }

/* ---- Section padding ---- */
.section-py {
    padding-top: var(--gv-section-py);
    padding-bottom: var(--gv-section-py);
}

.section-py-sm {
    padding-top: var(--gv-section-py-sm);
    padding-bottom: var(--gv-section-py-sm);
}

/* ---- Utility: gold gradient text ---- */
.text-gold-gradient {
    background: linear-gradient(135deg, var(--gv-gold-muted) 0%, var(--gv-gold-light) 50%, var(--gv-gold) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
}

/* ---- Hero particles (subtle animated dots) ---- */
.hero-particles {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
}

.hero-particle {
    position: absolute;
    width: 3px;
    height: 3px;
    border-radius: 50%;
    background: var(--gv-gold);
    opacity: 0;
    animation: heroParticleFloat 12s ease-in-out infinite;
}

.hero-particle-1 {
    top: 20%;
    left: 70%;
    animation-delay: 0s;
    animation-duration: 14s;
}

.hero-particle-2 {
    top: 60%;
    left: 85%;
    animation-delay: 3s;
    animation-duration: 10s;
}

.hero-particle-3 {
    top: 40%;
    left: 75%;
    animation-delay: 6s;
    animation-duration: 16s;
}

@keyframes heroParticleFloat {
    0%, 100% { opacity: 0; transform: translate(0, 0) scale(1); }
    25% { opacity: 0.4; transform: translate(-20px, -30px) scale(1.5); }
    50% { opacity: 0.15; transform: translate(10px, -60px) scale(1); }
    75% { opacity: 0.3; transform: translate(-10px, -20px) scale(1.2); }
}

/* ---- Social proof ticker ---- */
.ticker-strip {
    background: rgb(var(--gv-bg-base-rgb) / 0.9);
    border-top: 1px solid var(--gv-glass-border);
    border-bottom: 1px solid var(--gv-glass-border);
    overflow: hidden;
}

.ticker-track {
    overflow: hidden;
    position: relative;
    flex: 1;
    mask-image: linear-gradient(to right, transparent, black 5%, black 95%, transparent);
    -webkit-mask-image: linear-gradient(to right, transparent, black 5%, black 95%, transparent);
}

.ticker-content {
    display: flex;
    gap: 3rem;
    animation: tickerScroll 45s linear infinite;
    white-space: nowrap;
    width: max-content;
}

.ticker-item {
    display: inline-flex;
    align-items: center;
    gap: 0.75rem;
    color: var(--gv-text-dim);
    font-size: 0.8125rem;
    letter-spacing: 0.01em;
}

.ticker-dot {
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--gv-gold);
    opacity: 0.6;
    flex-shrink: 0;
}

@keyframes tickerScroll {
    0% { transform: translateX(0); }
    100% { transform: translateX(-50%); }
}

.ticker-strip:hover .ticker-content {
    animation-play-state: paused;
}

/* ---- Timeline ---- */
.timeline-container {
    position: relative;
    padding-left: 2rem;
}

.timeline-container::before {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0.5rem;
    width: 1px;
    background: linear-gradient(to bottom, var(--gv-gold-muted), var(--gv-gold), var(--gv-gold-muted));
    opacity: 0.4;
}

.timeline-item {
    position: relative;
    padding-bottom: 2rem;
}

.timeline-item:last-child {
    padding-bottom: 0;
}

.timeline-marker {
    position: absolute;
    left: -2rem;
    top: 1.25rem;
    width: 1rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

.timeline-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--gv-gold);
    border: 2px solid var(--gv-bg-deep);
    box-shadow: 0 0 0 3px rgb(var(--gv-gold-rgb) / 0.2);
    transition: var(--gv-transition);
}

.timeline-item:hover .timeline-dot {
    box-shadow: 0 0 0 5px rgb(var(--gv-gold-rgb) / 0.3), 0 0 12px rgb(var(--gv-gold-rgb) / 0.2);
    transform: scale(1.2);
}

.timeline-content {
    margin-left: 0.5rem;
}

/* Responsive timeline for larger screens */
@media (min-width: 768px) {
    .timeline-container {
        padding-left: 3rem;
    }

    .timeline-container::before {
        left: 1rem;
    }

    .timeline-marker {
        left: -3rem;
        width: 2rem;
    }

    .timeline-content {
        margin-left: 1rem;
    }
}

/* ---- Coming Soon badge ---- */
.coming-soon-badge {
    position: absolute;
    top: 1rem;
    right: 1rem;
    font-size: 0.625rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--gv-gold);
    background: rgb(var(--gv-gold-rgb) / 0.1);
    border: 1px solid rgb(var(--gv-gold-rgb) / 0.25);
    border-radius: 2rem;
    padding: 0.25rem 0.75rem;
}

/* ---- Enhanced glass card hover (Sprint 2 polish) ---- */
.glass-card {
    position: relative;
}

.glass-card::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: radial-gradient(
        ellipse 60% 60% at 50% 0%,
        rgb(var(--gv-gold-rgb) / 0.06) 0%,
        transparent 70%
    );
    opacity: 0;
    transition: opacity 0.4s ease;
    pointer-events: none;
}

.glass-card:hover::before {
    opacity: 1;
}

/* ---- Stat card hover glow ---- */
.stat-card {
    position: relative;
    overflow: hidden;
}

.stat-card::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 60%;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--gv-gold), transparent);
    opacity: 0;
    transition: opacity 0.3s ease;
}

.stat-card:hover::after {
    opacity: 0.6;
}

/* ---- Service icon hover pulse ---- */
.service-icon-wrap {
    position: relative;
}

.glass-card:hover .service-icon-wrap {
    box-shadow: 0 0 16px rgb(var(--gv-gold-rgb) / 0.15);
}

/* ---- Service section anchor offset (clears sticky nav) ---- */
.service-section {
    scroll-margin-top: 100px;
}

/* ---- Services sidebar navigation ---- */
.services-sidebar {
    padding: 1.5rem;
    background: var(--gv-glass-bg);
    backdrop-filter: var(--gv-glass-blur);
    -webkit-backdrop-filter: var(--gv-glass-blur);
    border: 1px solid var(--gv-glass-border);
    border-radius: 1rem;
}

.services-nav-link {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.625rem 0.75rem;
    color: var(--gv-text-dim);
    font-size: 0.8125rem;
    font-weight: 500;
    border-radius: 0.5rem;
    transition: var(--gv-transition);
    text-decoration: none;
}

.services-nav-link:hover {
    color: var(--gv-text-primary);
    background: rgba(255, 255, 255, 0.04);
}

.services-nav-link.active {
    color: var(--gv-gold);
    background: rgb(var(--gv-gold-rgb) / 0.08);
}

.services-nav-indicator {
    width: 3px;
    height: 16px;
    border-radius: 2px;
    background: transparent;
    transition: var(--gv-transition);
    flex-shrink: 0;
}

.services-nav-link.active .services-nav-indicator {
    background: var(--gv-gold);
}

/* ---- Onboarding step hover ---- */
.onboarding-step {
    transition: var(--gv-transition);
}

.onboarding-step:hover {
    background: rgb(var(--gv-gold-rgb) / 0.18) !important;
    border-color: rgb(var(--gv-gold-rgb) / 0.5) !important;
    box-shadow: 0 0 16px rgb(var(--gv-gold-rgb) / 0.15);
    transform: scale(1.1);
}

/* ---- Slide-in animations ---- */
.slide-in-left {
    transition: opacity 0.7s ease, transform 0.7s ease;
}

.js-animations-ready .slide-in-left {
    opacity: 0;
    transform: translateX(-30px);
}

.slide-in-left.visible {
    opacity: 1;
    transform: translateX(0);
}

.slide-in-right {
    transition: opacity 0.7s ease, transform 0.7s ease;
}

.js-animations-ready .slide-in-right {
    opacity: 0;
    transform: translateX(30px);
}

.slide-in-right.visible {
    opacity: 1;
    transform: translateX(0);
}

/* ---- Document icon styles (Sprint 4) ---- */
.doc-icon-wrap {
    width: 3rem;
    height: 3rem;
    border-radius: 0.75rem;
    background: rgb(var(--gv-gold-rgb) / 0.1);
    border: 1px solid rgb(var(--gv-gold-rgb) / 0.2);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--gv-gold);
    transition: var(--gv-transition);
}

.glass-card:hover .doc-icon-wrap,
.group:hover .doc-icon-wrap {
    background: rgb(var(--gv-gold-rgb) / 0.18);
    border-color: rgb(var(--gv-gold-rgb) / 0.4);
    box-shadow: 0 0 12px rgb(var(--gv-gold-rgb) / 0.1);
}

.doc-icon-financial {
    background: rgba(52, 211, 153, 0.08);
    border-color: rgba(52, 211, 153, 0.2);
    color: #34d399;
}

.doc-icon-regulatory {
    background: rgba(96, 165, 250, 0.08);
    border-color: rgba(96, 165, 250, 0.2);
    color: #60a5fa;
}

.doc-icon-legal {
    background: rgba(251, 191, 36, 0.08);
    border-color: rgba(251, 191, 36, 0.2);
    color: #fbbf24;
}

.doc-icon-compliance {
    background: rgba(167, 139, 250, 0.08);
    border-color: rgba(167, 139, 250, 0.2);
    color: #a78bfa;
}

.doc-coming-soon-badge {
    display: inline-block;
    font-size: 0.625rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--gv-text-muted);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 2rem;
    padding: 0.35rem 0.75rem;
    background: rgba(255, 255, 255, 0.03);
}

/* ---- Rich-text body styles -------------------------------------------------------------------
   THE one prose style for operator-authored HTML rendered through MarkupString: news article
   bodies (/news/{slug}), vacancy descriptions (/careers/{slug}) and the admin article preview.
   Do NOT add a second prose class — /careers/{slug} referenced a `prose-vault` that was never
   defined anywhere, so a whole job posting rendered as one flat block of 16 px body text.

   Element coverage must track Services/HtmlSanitizer.cs's allow-list: anything the sanitizer
   keeps can reach a public page, and anything without a rule here arrives with Tailwind
   Preflight's reset still on it (headings at font-size:inherit, lists with list-style:none,
   every block at margin:0) — i.e. invisible as structure. */
.article-body h2 {
    font-family: var(--gv-font-display);
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--gv-text-primary);
    margin-top: 2rem;
    margin-bottom: 0.75rem;
}

.article-body h3 {
    font-family: var(--gv-font-display);
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--gv-gold-light);
    margin-top: 1.75rem;
    margin-bottom: 0.5rem;
}

/* h1 is the PAGE title's level on both hosts, so an operator's h1 inside the body is a mistake;
   render it at the h2 scale rather than letting it out-shout the page heading. h4–h6 are in the
   sanitizer's allow-list and so must be styled, not left at Preflight's font-size:inherit. */
.article-body h1 {
    font-family: var(--gv-font-display);
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--gv-text-primary);
    margin-top: 2rem;
    margin-bottom: 0.75rem;
}

.article-body h4,
.article-body h5,
.article-body h6 {
    font-family: var(--gv-font-body);
    font-size: 1.0625rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--gv-text-primary);
    margin-top: 1.5rem;
    margin-bottom: 0.5rem;
}

.article-body p {
    color: var(--gv-text-dim);
    font-size: 1rem;
    line-height: 1.8;
    margin-bottom: 1rem;
}

/* Preflight sets list-style:none on every ul/ol, so the markers have to be restored explicitly —
   padding-left alone (what this rule used to be) indents a list that still shows no bullets. */
.article-body ul,
.article-body ol {
    color: var(--gv-text-dim);
    margin-bottom: 1rem;
    padding-left: 1.5rem;
}

.article-body ul {
    list-style: disc outside;
}

.article-body ol {
    list-style: decimal outside;
}

.article-body ul ul {
    list-style: circle outside;
}

.article-body ol ol {
    list-style: lower-alpha outside;
}

.article-body li {
    margin-bottom: 0.5rem;
    line-height: 1.7;
}

.article-body li::marker {
    color: var(--gv-gold);
}

/* Nested lists sit inside an <li>, so their own margin-bottom would double the gap. */
.article-body li > ul,
.article-body li > ol {
    margin-top: 0.5rem;
    margin-bottom: 0;
}

.article-body dl {
    margin-bottom: 1rem;
    color: var(--gv-text-dim);
}

.article-body dt {
    color: var(--gv-text-primary);
    font-weight: 600;
    margin-top: 1rem;
}

.article-body dd {
    margin-left: 1.5rem;
    line-height: 1.7;
}

.article-body strong,
.article-body b {
    color: var(--gv-text-primary);
    font-weight: 600;
}

.article-body em,
.article-body i {
    font-style: italic;
}

.article-body u {
    text-decoration: underline;
    text-underline-offset: 2px;
}

.article-body s {
    text-decoration: line-through;
    color: var(--gv-text-muted);
}

.article-body sub,
.article-body sup {
    font-size: 0.75em;
    line-height: 0;
}

.article-body sup { vertical-align: super; }
.article-body sub { vertical-align: sub; }

.article-body a {
    color: var(--gv-gold);
    text-decoration: underline;
    text-underline-offset: 2px;
    transition: var(--gv-transition);
}

.article-body a:hover {
    color: var(--gv-gold-light);
}

.article-body blockquote {
    border-left: 3px solid var(--gv-gold);
    padding-left: 1.25rem;
    margin: 1.5rem 0;
    color: var(--gv-text-dim);
    font-style: italic;
}

.article-body hr {
    border: 0;
    border-top: 1px solid var(--gv-glass-border);
    margin: 2rem 0;
}

.article-body code {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: 0.875em;
    color: var(--gv-gold-light);
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--gv-glass-border);
    border-radius: 0.25rem;
    padding: 0.1rem 0.35rem;
}

.article-body pre {
    background: rgba(0, 0, 0, 0.25);
    border: 1px solid var(--gv-glass-border);
    border-radius: 0.5rem;
    padding: 1rem;
    margin: 1.5rem 0;
    overflow-x: auto;
    color: var(--gv-text-dim);
}

.article-body pre code {
    background: none;
    border: 0;
    padding: 0;
    color: inherit;
}

/* An operator-supplied width/height attribute must not push the image past the panel on a phone. */
.article-body img {
    max-width: 100%;
    height: auto;
    border-radius: 0.5rem;
    margin: 1.5rem 0;
}

.article-body figure {
    margin: 1.5rem 0;
}

.article-body figure img {
    margin: 0;
}

.article-body figcaption {
    margin-top: 0.5rem;
    font-size: 0.875rem;
    color: var(--gv-text-muted);
    text-align: center;
}

/* Tables are in the allow-list, so a rate card pasted into a posting must stay readable on a
   480 px phone rather than widening the whole panel. */
.article-body table {
    width: 100%;
    margin: 1.5rem 0;
    border-collapse: collapse;
    color: var(--gv-text-dim);
    font-size: 0.9375rem;
    display: block;
    overflow-x: auto;
}

.article-body th,
.article-body td {
    border: 1px solid var(--gv-glass-border);
    padding: 0.6rem 0.85rem;
    text-align: left;
    vertical-align: top;
}

.article-body th {
    color: var(--gv-text-primary);
    font-weight: 600;
    background: rgba(255, 255, 255, 0.04);
}

.article-body caption {
    caption-side: bottom;
    margin-top: 0.5rem;
    font-size: 0.875rem;
    color: var(--gv-text-muted);
}

/* The body's first block sits directly under a panel edge or a page heading; its own top margin
   would only add to that padding. */
.article-body > :first-child {
    margin-top: 0;
}

.article-body > :last-child {
    margin-bottom: 0;
}

/* ---- Line clamp utility ---- */
.line-clamp-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.line-clamp-3 {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* ---- Blazor error UI override ---- */
#blazor-error-ui {
    display: none;
}

#blazor-error-ui[style*="display: block"],
#blazor-error-ui.show {
    display: flex;
}

/* ============================================================
   Admin Dashboard Styles
   ============================================================ */

.admin-wrapper {
    display: flex;
    min-height: 100vh;
}

.admin-sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 260px;
    background: var(--gv-bg-base);
    border-right: 1px solid rgb(var(--gv-gold-rgb) / 0.12);
    display: flex;
    flex-direction: column;
    z-index: 40;
    overflow-y: auto;
}

.admin-main {
    margin-left: 260px;
    flex: 1;
    /* Without min-width:0, a flex child's content (wide admin tables) can push
       this element beyond the viewport, defeating the table's overflow-x:auto
       and clipping the right-most Actions column at 1280px-wide screens. */
    min-width: 0;
    padding: 2rem;
    min-height: 100vh;
}

.admin-nav-link {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.625rem 0.75rem;
    border-radius: 0.5rem;
    color: var(--gv-text-dim);
    text-decoration: none;
    font-size: 0.875rem;
    transition: all 0.2s ease;
}

.admin-nav-link:hover {
    background: rgba(255, 255, 255, 0.05);
    color: var(--gv-text-primary);
}

.admin-nav-link-active,
.admin-nav-link.active {
    background: rgb(var(--gv-gold-rgb) / 0.12);
    color: var(--gv-gold);
}

/* Sidebar grouping. Every link in the group is behind its own AuthorizeView, and AuthorizeView
   renders NOTHING (not even a wrapper) when it denies — so a narrow custom role can empty a group
   completely. :has() drops the heading with it rather than leaving a label over blank space.
   Browsers without :has() simply keep the heading, which is the pre-grouping behaviour. */
.admin-nav-group {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.admin-nav-group:not(:has(.admin-nav-link)) {
    display: none;
}

.admin-nav-heading {
    margin: 1rem 0 0.25rem;
    padding: 0 0.75rem;
    color: var(--gv-gold);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    opacity: 0.75;
}

/* Admin stat cards */
.admin-stat-card {
    background: var(--gv-glass-bg);
    border: 1px solid var(--gv-glass-border);
    border-radius: 0.75rem;
    padding: 1.5rem;
    backdrop-filter: var(--gv-glass-blur);
}

/* Admin data table */
.admin-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.875rem;
}

.admin-table th {
    text-align: left;
    padding: 0.75rem 1rem;
    color: var(--gv-gold);
    font-weight: 500;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    border-bottom: 1px solid rgb(var(--gv-gold-rgb) / 0.2);
}

.admin-table td {
    padding: 0.75rem 1rem;
    color: var(--gv-text-dim);
    border-bottom: 1px solid rgba(255, 255, 255, 0.04);
}

.admin-table tbody tr:hover {
    background: rgba(255, 255, 255, 0.02);
}

/* Admin badges */
.admin-badge {
    display: inline-block;
    padding: 0.125rem 0.5rem;
    border-radius: 9999px;
    font-size: 0.75rem;
    font-weight: 500;
}

.admin-badge-gold {
    background: rgb(var(--gv-gold-rgb) / 0.2);
    color: var(--gv-gold-light);
}

.admin-badge-green {
    background: rgba(34, 197, 94, 0.2);
    color: #86efac;
}

.admin-badge-blue {
    background: rgba(59, 130, 246, 0.2);
    color: #93c5fd;
}

.admin-badge-dim {
    background: rgba(255, 255, 255, 0.06);
    color: var(--gv-text-muted);
}

/* The only badge that reports a FAULT rather than a state — a lead nobody was told about
   (LeadNotificationBadge). #fca5a5 over the composited surface is ~6.6:1, above AA for small text. */
.admin-badge-red {
    background: rgba(239, 68, 68, 0.2);
    color: #fca5a5;
}

/* Admin responsive */
@media (max-width: 768px) {
    .admin-sidebar {
        width: 100%;
        position: relative;
        border-right: none;
        border-bottom: 1px solid rgb(var(--gv-gold-rgb) / 0.12);
    }
    .admin-main {
        margin-left: 0;
        padding: 1rem;
    }
    .admin-wrapper {
        flex-direction: column;
    }
}

/* ---- Loading Spinner ---- */
.loading-spinner {
    width: 36px;
    height: 36px;
    border: 3px solid rgb(var(--gv-gold-rgb) / 0.2);
    border-top-color: var(--gv-gold);
    border-radius: 50%;
    animation: gv-spin 0.8s linear infinite;
}

@keyframes gv-spin {
    to { transform: rotate(360deg); }
}

/* ---- Table Scroll Hint ---- */
.table-scroll-wrapper {
    position: relative;
}

.table-scroll-wrapper::after {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 40px;
    background: linear-gradient(to right, transparent, var(--gv-bg-mid));
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.3s ease;
}

.table-scroll-wrapper.can-scroll-right::after {
    opacity: 1;
}

/* ---- Cookie Consent ----
   This notice is the ONE glass surface on the site that sits directly over the hero's
   large light headline copy; every other .glass-panel user sits over quiet background.
   The shared token is rgba(255,255,255,0.04) + blur(12px) — a 4%-white fill is very
   nearly transparent and 12px of blur cannot erase 20px+ type behind it, so the hero
   paragraph read straight THROUGH the consent text (measured 2026-08-15 at 1440px in
   ka: the boxes do not overlap, h4 ends y=808 and p starts y=812, so it was never a
   layout bug — elementsFromPoint at the heading returned the banner chain over
   SECTION.hero-section). This is the GDPR notice, the first thing a visitor must be
   able to read, so it gets an opaque surface of its OWN rather than a weakened shared
   token — .glass-panel is correct everywhere else it is used.
   Contrast against this fill (computed, WCAG 2.x relative luminance):
     body copy   --gv-text-dim   #C8C2B8 -> 10.1:1 on #0F1729, 8.7:1 on #1A2340
     heading     --gv-text-white #F5F1EB -> higher still
   both clear AA (4.5:1) with room to spare at either end of the gradient. */
.cookie-consent-panel {
    background: linear-gradient(160deg, var(--gv-bg-base) 0%, var(--gv-bg-mid) 100%);
    border: 1px solid var(--gv-glass-border);
    /* Kept for the translucent edge only — the fill above is opaque, so this cannot be
       what carries legibility. That was the original defect. */
    backdrop-filter: var(--gv-glass-blur-heavy);
    -webkit-backdrop-filter: var(--gv-glass-blur-heavy);
}

/* ---- Cookie Consent slide-up ---- */
.cookie-consent-slide-up {
    animation: cookieSlideUp 0.4s cubic-bezier(0.4, 0, 0.2, 1) both;
}

@keyframes cookieSlideUp {
    from {
        opacity: 0;
        transform: translateY(100%);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* ---- Accessibility: Reduced Motion ---- */
@media (prefers-reduced-motion: reduce) {
    /* Disable scroll-triggered animations — show content immediately */
    .fade-in-up,
    .fade-in,
    .slide-in-left,
    .slide-in-right {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }

    /* Disable hero particle floating */
    .hero-particle {
        animation: none !important;
        opacity: 0 !important;
    }

    /* Disable ticker scrolling — show static content */
    .ticker-content {
        animation: none !important;
    }

    /* Disable cookie consent slide-up */
    .cookie-consent-slide-up {
        animation: none !important;
    }

    /* Disable loading spinner animation */
    .loading-spinner {
        animation: none !important;
        border-top-color: var(--gv-gold);
    }

    /* Reduce hover transforms and transitions */
    .glass-card,
    .glass-btn,
    .glass-btn-outline,
    .glass-btn-ghost,
    .glass-input,
    .stat-card,
    .service-icon-wrap,
    .onboarding-step,
    .nav-link,
    .nav-link::after,
    .nav-link-mobile,
    .footer-link,
    .timeline-dot,
    .glass-card::before,
    .stat-card::after,
    #main-nav {
        transition: none !important;
    }

    .glass-card:hover,
    .glass-btn:hover,
    .onboarding-step:hover,
    .timeline-item:hover .timeline-dot {
        transform: none !important;
    }

    /* Disable smooth scrolling */
    html {
        scroll-behavior: auto !important;
    }

    /* Service panels: all shown, none move */
    .js-animations-ready .service-panel-card,
    .js-animations-ready .service-panel.is-past .service-panel-card {
        opacity: 1;
        transform: none;
    }

    /* Stagger delays are irrelevant without transitions */
    .delay-100, .delay-200, .delay-300, .delay-400, .delay-500 {
        transition-delay: 0s !important;
    }

}

/* ---- Blazor reconnect notice ----
   A dropped SignalR connection used to throw a full-screen blurred overlay over the page — even a
   two-second network blip made the site look broken. Now: the page stays fully visible; a drop shorter
   than ~4 s shows nothing (the animation is delayed); a longer one shows only this small pill at the
   bottom; and when the circuit cannot be restored (failed / rejected) glass-vault.js reloads the page
   instead of asking the visitor to. The element is rendered in App.razor so Blazor uses it instead of
   its own white "Rejoining the server" dialog. */
#components-reconnect-modal {
    display: none;
    position: fixed;
    left: 50%;
    bottom: 1.25rem;
    z-index: 10000;
    transform: translateX(-50%);
    padding: 0.5rem 1rem;
    border-radius: 9999px;
    background: rgb(var(--gv-bg-mid-rgb) / 0.92);
    border: 1px solid rgb(var(--gv-gold-rgb) / 0.25);
    color: var(--gv-text-dim);
    font: 500 0.8125rem/1.4 var(--gv-font-body);
    box-shadow: 0 4px 16px rgb(0 0 0 / 0.35);
    pointer-events: none;
    white-space: nowrap;
}

#components-reconnect-modal.components-reconnect-show,
#components-reconnect-modal.components-reconnect-retrying {
    display: block;
    animation: gv-reconnect-in 0.3s ease-out 4s both;
}

/* failed / rejected: glass-vault.js reloads the page — nothing to show meanwhile. */
#components-reconnect-modal.components-reconnect-hide,
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-rejected {
    display: none;
}

@keyframes gv-reconnect-in {
    from { opacity: 0; transform: translate(-50%, 6px); }
    to   { opacity: 1; transform: translate(-50%, 0); }
}

/* Hide default Blazor reconnect content (replaced by ::after pseudo-elements) */
#components-reconnect-modal > * {
    display: none !important;
}

/* ---- Print: show all content regardless of animation state ---- */
@media print {
    .fade-in-up,
    .fade-in,
    .slide-in-left,
    .slide-in-right {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }
}
