/* ============================================================
   TEAYS UI 2.0 — canonical design tokens + component layer
   Source of truth: https://teayspm-guides.pages.dev (tv-tokens.css)
   Loaded by every TVPM internal app AFTER fonts, BEFORE app CSS.

   Functionality rule: this file is presentation-only. Nothing in
   here may change behavior — math, API pulls, and PDF generation
   are styled elsewhere and untouched by design.
   ============================================================ */

:root {
    /* Brand */
    --primary: #002a53;
    --primary-hover: #003a72;
    --primary-container: #1c406d;
    --primary-light: #3a6494;
    --red: #D44A38;
    --red-dark: #B33428;
    --red-hover: #BE3E2E;
    --red-container: #fbecea;
    --red-border: rgba(212, 74, 56, 0.18);

    /* Surfaces */
    --surface: #fcf9f8;
    --surface-low: #f6f3f2;
    --surface-card: #ffffff;
    --on-surface: #1b1c1c;
    --on-variant: #44474e;
    --muted: #6b7280;
    --muted-light: #9ca3af;

    /* Semantic */
    --success: #1a6b3a;
    --success-bg: #e8f5ee;
    --warning: #8a5c00;
    --warning-bg: #fef5dc;
    --info: #1a4f7a;
    --info-bg: #e8f3fb;
    --danger: #b32020;
    --danger-bg: #fdeaea;

    /* Typefaces — Neue Haas scans, Source Serif 4 reads, mono counts.
       Kit uct5bca serves neue-haas-grotesk-display and -text at
       400/700 ONLY — never ask for 500/600 (faux weights). Display
       = headings/labels/eyebrows; Text = buttons/nav/chips/UI. */
    --font-sans: "neue-haas-grotesk-display", "Helvetica Neue", sans-serif;
    --font-sans-text: "neue-haas-grotesk-text", "Helvetica Neue", sans-serif;
    --font-serif: 'Source Serif 4', 'Georgia', serif;
    --font-mono: 'Courier New', monospace;

    /* Radius — sharp, editorial: buttons 4 / cards 6 / sections 8 */
    --r-xs: 2px;
    --r-sm: 3px;
    --r-md: 4px;
    --r-lg: 6px;
    --r-xl: 8px;
    --r-2xl: 12px;
    --r-pill: 100px;

    /* Elevation */
    --shadow-xs: 0 1px 4px rgba(27, 28, 28, 0.05);
    --shadow-sm: 0 2px 8px rgba(27, 28, 28, 0.07);
    --shadow-md: 0 6px 24px rgba(27, 28, 28, 0.09);
    --shadow-lg: 0 14px 44px rgba(27, 28, 28, 0.12);
    --shadow-xl: 0 24px 64px rgba(27, 28, 28, 0.15);

    /* Motion — Estate Ease; never bouncy */
    --ease: cubic-bezier(0.25, 0.46, 0.45, 0.94);
    --ease-out: cubic-bezier(0.0, 0.0, 0.2, 1);
    --dur-fast: 150ms;
    --dur-std: 300ms;
    --dur-slow: 450ms;

    /* Spacing (base-4) */
    --sp-1: 4px;  --sp-2: 8px;   --sp-3: 12px; --sp-4: 16px;
    --sp-5: 24px; --sp-6: 32px;  --sp-7: 40px; --sp-8: 56px;
    --sp-9: 80px; --sp-10: 112px; --sp-11: 160px;

    /* Z-index */
    --z-base: 0; --z-up: 10; --z-nav: 100; --z-modal: 200;

    /* ----------------------------------------------------------
       BACK-COMPAT ALIASES — legacy variable names used across the
       existing apps, re-pointed at Teays UI 2.0 values so older
       CSS reskins without surgery. New code should use the
       canonical names above.
       ---------------------------------------------------------- */
    --color-primary: var(--primary);
    --color-coral: var(--red);
    --color-gray-blue: var(--muted-light);
    --color-light-coral: var(--red-container);
    --color-text: var(--on-surface);
    --color-text-secondary: var(--muted);
    --color-text-light: #ffffff;
    --color-success: var(--success);
    --color-warning: var(--warning);
    --color-error: var(--danger);
    --color-dark: var(--on-surface);
    --bg-gradient: linear-gradient(135deg, var(--surface), var(--surface-low));
    --bg-card: var(--surface-card);
    --bg-light: var(--surface-low);
    --font-display: var(--font-sans);
    --font-text: var(--font-sans-text);
    --ease-spring: var(--ease); /* bouncy retired — Estate Ease everywhere */
    --ease-in: var(--ease);
    --space-xs: var(--sp-1); --space-sm: var(--sp-2); --space-md: var(--sp-4);
    --space-lg: var(--sp-5); --space-xl: var(--sp-6); --space-2xl: var(--sp-8);
}

/* ============================================================
   BASE TYPOGRAPHY (Typewolf-compliant)
   ============================================================ */
.tv-app, body.tv-app {
    background: var(--surface);
    color: var(--on-surface);
    font-family: var(--font-serif);
    font-kerning: normal;
    font-feature-settings: "kern", "liga", "clig", "calt";
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* Headlines scan — Neue Haas Display, tight tracking. Never letterspace body. */
.tv-display-xl { font-family: var(--font-sans); font-weight: 700; font-size: 3.5rem;   letter-spacing: -0.025em; line-height: 1.1; color: var(--on-surface); }
.tv-h2         { font-family: var(--font-sans); font-weight: 700; font-size: 1.75rem;  letter-spacing: -0.02em;  line-height: 1.15; color: var(--on-surface); }
.tv-title      { font-family: var(--font-serif); font-weight: 600; font-size: 1.375rem; line-height: 1.3; color: var(--on-surface); }
.tv-body-lg    { font-family: var(--font-serif); font-weight: 400; font-size: 1.0625rem; line-height: 1.8; color: var(--on-variant); max-width: 38em; }
.tv-body       { font-family: var(--font-serif); font-weight: 400; font-size: 0.875rem;  line-height: 1.8; color: var(--on-variant); }

/* Uppercase gets letterspacing; nothing else does. */
.tv-label   { font-family: var(--font-sans); font-weight: 700; font-size: 0.75rem;   letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }
.tv-eyebrow { font-family: var(--font-sans); font-weight: 700; font-size: 0.6875rem; letter-spacing: 0.2em; text-transform: uppercase; color: var(--red); }

/* Numbers are data: mono, tabular by construction, right-aligned in tables. */
.tv-num, .tv-mono { font-family: var(--font-mono); font-size: 0.8125rem; font-weight: 700; color: var(--on-surface); }
td.tv-num, th.tv-num { text-align: right; }

/* ============================================================
   HERITAGE STRIPE — 4px red left border for high-emphasis blocks
   ============================================================ */
.tv-stripe { border-left: 4px solid var(--red); }

/* ============================================================
   TOPOGRAPHIC TEXTURE — apply to every large dark span.
   Contour-line SVG tile; opacity per guide (≤6%).
   ============================================================ */
/* Official brand topography (assets/textures/topography.svg) applied
   as a CSS mask so ONE asset tones to any surface: the mask's filled
   contour shapes punch through to the ::before background color. */
.topo-dark, .topo-light, .topo-red { position: relative; isolation: isolate; }
.topo-dark::before, .topo-light::before, .topo-red::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    -webkit-mask-image: url('/assets/textures/topography.svg');
    mask-image: url('/assets/textures/topography.svg');
    -webkit-mask-repeat: repeat;
    mask-repeat: repeat;
    -webkit-mask-size: 560px 560px;
    mask-size: 560px 560px;
}
.topo-dark::before  { background: #ffffff; opacity: 0.055; }
.topo-light::before { background: var(--on-surface); opacity: 0.032; }
.topo-red::before   { background: var(--red); opacity: 0.06; }

/* Official scene + wash imagery (assets/textures/) */
/* Navy contour scene — login pages, splash screens, hero dark bands.
   The image IS brand-navy; the color fallback covers slow loads. */
.tv-scene-navy {
    background-color: var(--primary);
    background-image: url('/assets/textures/blob-scene.jpg');
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}
/* Soft warm wash — decorative backdrop for modal heads / feature
   cards. White gradient keeps text contrast; image stays a whisper. */
.tv-wash {
    background-color: var(--surface-card);
    background-image: linear-gradient(rgba(255,255,255,0.78), #ffffff 88%),
                      url('/assets/textures/card-back-blur.jpg');
    background-size: cover;
    background-position: center;
}

/* ============================================================
   BUTTONS — filled / outlined / ghost. 4px corners, 12×22 padding.
   States animate transform+opacity-ish properties only.
   ============================================================ */
.tv-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    font-family: var(--font-sans-text);
    font-weight: 700; /* NHG text ships 400/700 only — no faux 600 */
    font-size: 0.9375rem;
    line-height: 1;
    padding: 12px 22px;
    border-radius: var(--r-md);
    border: none;
    cursor: pointer;
    text-decoration: none;
    transition: background-color var(--dur-fast) var(--ease),
                color var(--dur-fast) var(--ease),
                box-shadow var(--dur-fast) var(--ease),
                transform var(--dur-fast) var(--ease);
    min-height: 44px; /* touch target */
}
.tv-btn:active { transform: translateY(1px); }
.tv-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

.tv-btn-primary { background: var(--red); color: #fff; }
.tv-btn-primary:hover { background: var(--red-hover); box-shadow: var(--shadow-sm); }
.tv-btn-primary:disabled { background: var(--muted-light); cursor: not-allowed; }

.tv-btn-navy { background: var(--primary); color: #fff; }
.tv-btn-navy:hover { background: var(--primary-hover); box-shadow: var(--shadow-sm); }

.tv-btn-outline { background: transparent; color: var(--primary); box-shadow: inset 0 0 0 2px var(--primary); }
.tv-btn-outline:hover { background: var(--primary); color: #fff; }

.tv-btn-ghost { background: var(--surface-low); color: var(--on-surface); }
.tv-btn-ghost:hover { background: var(--red-container); color: var(--red-dark); }

/* ============================================================
   INPUTS — no 1px gray borders: background shifts + focus ring.
   16px minimum font (iOS zoom). Numeric inputs go mono.
   ============================================================ */
.tv-input, .tv-select, .tv-textarea {
    width: 100%;
    box-sizing: border-box;
    font-family: var(--font-serif);
    font-size: 16px;
    color: var(--on-surface);
    background: var(--surface-low);
    border: 1px solid transparent; /* keeps box model; color shift does the work */
    border-radius: var(--r-md);
    padding: 11px 14px;
    transition: background-color var(--dur-fast) var(--ease),
                box-shadow var(--dur-fast) var(--ease);
}
.tv-input::placeholder, .tv-textarea::placeholder { color: var(--muted-light); }
.tv-input:hover, .tv-select:hover, .tv-textarea:hover { background: #f1edec; }
.tv-input:focus, .tv-select:focus, .tv-textarea:focus {
    outline: none;
    background: var(--surface-card);
    box-shadow: 0 0 0 3px rgba(0, 42, 83, 0.14), var(--shadow-xs);
}
.tv-input.tv-num { font-family: var(--font-mono); font-weight: 700; }
.tv-input.tv-invalid { background: var(--danger-bg); box-shadow: 0 0 0 3px rgba(179, 32, 32, 0.15); }

/* ============================================================
   CARDS — 6px corners, resting sm shadow, hover md. No borders.
   ============================================================ */
.tv-card {
    background: var(--surface-card);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-sm);
    padding: var(--sp-5);
    transition: box-shadow var(--dur-std) var(--ease), transform var(--dur-std) var(--ease);
}
.tv-card-hover:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); }
.tv-card-emphasis { border-left: 4px solid var(--red); }

/* ============================================================
   TABLES — Neue Haas label headers, serif cells, mono numerics,
   separation via background shifts (no gray rules).
   ============================================================ */
.tv-table { width: 100%; border-collapse: collapse; }
.tv-table th {
    font-family: var(--font-sans);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
    text-align: left;
    padding: 12px 16px;
    background: var(--surface-low);
}
.tv-table td {
    font-family: var(--font-serif);
    font-size: 0.9375rem;
    color: var(--on-surface);
    padding: 13px 16px;
    border-bottom: 1px solid var(--surface-low); /* background-tone hairline */
}
.tv-table tbody tr:hover td { background: var(--surface-low); }
.tv-table td.tv-num { font-family: var(--font-mono); font-weight: 700; font-size: 0.8125rem; text-align: right; }

/* ============================================================
   BADGES & CHIPS
   ============================================================ */
.tv-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-sans);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 4px 10px;
    border-radius: var(--r-sm);
    background: var(--surface-low);
    color: var(--on-variant);
}
.tv-badge-red     { background: var(--red-container); color: var(--red-dark); }
.tv-badge-navy    { background: #e7edf5; color: var(--primary); }
.tv-badge-success { background: var(--success-bg); color: var(--success); }
.tv-badge-warning { background: var(--warning-bg); color: var(--warning); }
.tv-badge-danger  { background: var(--danger-bg); color: var(--danger); }
.tv-chip {
    display: inline-flex; align-items: center; gap: 6px;
    font-family: var(--font-sans-text); font-weight: 700; font-size: 0.8125rem;
    padding: 7px 14px; border-radius: var(--r-pill);
    background: var(--surface-low); color: var(--on-variant);
    cursor: pointer;
    transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.tv-chip:hover { background: var(--red-container); color: var(--red-dark); }
.tv-chip.active { background: var(--primary); color: #fff; }

/* ============================================================
   MODAL SYSTEM — the canonical Teays UI 2.0 dialog.
   Structure (markup chrome; JS hooks — ids, .show/.active,
   closeModal() — are untouched by adopting these classes):

     <div class="modal" id="...">              ← overlay (legacy class kept)
       <div class="modal-content tv-modal">    ← card
         <div class="tv-modal-head [tv-wash]">
           <span class="tv-eyebrow">OPTIONAL KICKER</span>
           <h2 class="tv-modal-title">Title</h2>
           <p class="tv-modal-sub">Optional one-line context.</p>
           <button class="tv-modal-close" aria-label="Close">(SVG X)</button>
         </div>
         <div class="tv-modal-body"> … </div>
         <div class="tv-modal-foot"> [ghost] [primary] </div>
       </div>
     </div>
   ============================================================ */
.tv-modal {
    padding: 0 !important; /* sections own their spacing */
    border-radius: var(--r-xl);
    box-shadow: var(--shadow-xl);
    overflow: hidden; /* lets the head wash bleed to the corners */
    display: flex;
    flex-direction: column;
    max-height: 88vh;
}
.tv-modal-head {
    position: relative;
    padding: 24px 64px 14px 28px; /* right gap clears the close button */
    flex: 0 0 auto;
}
.tv-modal-head .tv-eyebrow { display: block; margin-bottom: 6px; }
.tv-modal-title {
    font-family: var(--font-sans);
    font-weight: 700;
    font-size: 1.375rem;
    letter-spacing: -0.02em;
    line-height: 1.2;
    color: var(--on-surface);
    margin: 0;
}
.tv-modal-sub {
    font-family: var(--font-serif);
    font-size: 0.9375rem;
    line-height: 1.55;
    color: var(--muted);
    margin: 6px 0 0;
}
.tv-modal-close {
    position: absolute;
    top: 16px;
    right: 16px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: none;
    background: var(--surface-low);
    color: var(--on-variant);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.tv-modal-close:hover { background: var(--red-container); color: var(--red-dark); }
.tv-modal-close svg { width: 16px; height: 16px; flex: 0 0 auto; min-width: 16px; stroke: currentColor; stroke-width: 2.25; fill: none; stroke-linecap: round; }
.tv-modal-body {
    padding: 10px 28px 24px;
    overflow-y: auto;
    flex: 1 1 auto;
    font-family: var(--font-serif);
}
.tv-modal-foot {
    padding: 16px 28px 22px;
    border-top: 1px solid var(--surface-low);
    display: flex;
    gap: 12px;
    justify-content: flex-end;
    flex: 0 0 auto;
    background: var(--surface-card);
}
@media (max-width: 640px) {
    .tv-modal-head { padding: 20px 60px 12px 20px; }
    .tv-modal-body { padding: 8px 20px 20px; }
    .tv-modal-foot { padding: 14px 20px 18px; flex-direction: column-reverse; }
    .tv-modal-foot button, .tv-modal-foot .tv-btn { width: 100%; }
}

/* ============================================================
   ALERTS — heritage stripe + semantic tint, serif body.
   ============================================================ */
.tv-alert {
    border-left: 4px solid;
    border-radius: var(--r-md);
    padding: 14px 18px;
    font-family: var(--font-serif);
    font-size: 0.9375rem;
    line-height: 1.6;
}
.tv-alert-success { background: var(--success-bg); border-color: var(--success); color: var(--on-surface); }
.tv-alert-warning { background: var(--warning-bg); border-color: var(--warning); color: var(--on-surface); }
.tv-alert-danger  { background: var(--danger-bg);  border-color: var(--danger);  color: var(--on-surface); }
.tv-alert-info    { background: var(--info-bg);    border-color: var(--info);    color: var(--on-surface); }

/* ============================================================
   LOADERS — calm, never bouncy.
   ============================================================ */
.tv-spinner {
    width: 22px; height: 22px;
    border: 3px solid var(--surface-low);
    border-top-color: var(--red);
    border-radius: 50%;
    animation: tv-spin 0.8s linear infinite;
}
.tv-skeleton {
    background: linear-gradient(90deg, var(--surface-low), #efe9e7, var(--surface-low));
    background-size: 200% 100%;
    animation: tv-shimmer 1.8s linear infinite;
    border-radius: var(--r-md);
}
@keyframes tv-spin { to { transform: rotate(360deg); } }
@keyframes tv-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* Scroll/entry reveal — 400ms, 14px lift, 80ms stagger via --tv-i */
.tv-reveal {
    opacity: 0;
    transform: translateY(14px);
    animation: tv-reveal 400ms var(--ease-out) forwards;
    animation-delay: calc(var(--tv-i, 0) * 80ms);
}
@keyframes tv-reveal { to { opacity: 1; transform: translateY(0); } }

/* ============================================================
   LOADING OVERLAYS — one unified system across every app.
   Two experiences, one family (Luke 2026-06):
     (A) .loading-overlay → app boot + quick ops. Warm near-opaque
         scrim, centered red-arc spinner + label. Card-wrapped
         (.loading-container / .loading-content) and bare markup
         render identically because the wrapper is neutralised to a
         transparent passthrough — so no per-app markup churn.
     (B) owner-reports .pull-overlay → long pulls / generation.
         Navy takeover + white card + determinate red bar + ETA +
         step chips. Defined locally; shares the red spinner arc and
         red progress fill so both experiences read as one system.
   No backdrop-filter anywhere (Intel-Mac perf, fin66). This block
   is the SINGLE source — the old copies in tvpm-styles.css and the
   per-app inline overrides were removed so this always wins. */
.loading-overlay {
    position: fixed;
    inset: 0;
    background: rgba(252, 249, 248, 0.94); /* warm surface, near-opaque */
    display: none;
    flex-direction: column; /* stack spinner + label for bare-markup apps */
    align-items: center;
    justify-content: center;
    gap: 18px;
    z-index: 9999;
    opacity: 0;
    transition: opacity var(--dur-std) var(--ease);
    pointer-events: none;
}
.loading-overlay.show,
.loading-overlay.active {
    display: flex;
    opacity: 1;
    pointer-events: auto;
}
/* Wrapper neutralised so a bare overlay (spinner straight on the
   scrim) and a card-wrapped one look the same. Keeps a width so any
   progress bar inside has room to render. */
.loading-overlay .loading-container,
.loading-overlay .loading-content {
    background: transparent;
    box-shadow: none;
    border: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 18px;
    min-width: 260px;
    max-width: 360px;
    text-align: center;
}
/* Canonical spinner — navy-tint track, red arc (matches .tv-spinner). */
.loading-overlay .loading-spinner,
.loading-overlay .spinner {
    width: 48px;
    height: 48px;
    border: 4px solid rgba(0, 42, 83, 0.12);
    border-top-color: var(--red);
    border-radius: 50%;
    animation: tv-spin 0.8s linear infinite;
    margin: 0;
}
/* Label — NHG 700, dark on the warm scrim. Covers .loading-text and
   the bare <span>/<p> some apps use. */
.loading-overlay .loading-text,
.loading-overlay > span,
.loading-overlay > p,
.loading-overlay .loading-container span,
.loading-overlay .loading-container p,
.loading-overlay .loading-content span,
.loading-overlay .loading-content p {
    font-family: var(--font-display);
    font-size: 17px;
    font-weight: 700;
    color: var(--color-text);
    text-align: center;
    margin: 0;
    line-height: 1.4;
}
/* Determinate bar (ringcentral / newtown / uplync). */
.loading-overlay .progress-bar-container {
    width: 100%;
    height: 8px;
    background: rgba(0, 42, 83, 0.1);
    border-radius: 999px;
    overflow: hidden;
    position: relative;
}
.loading-overlay .progress-bar {
    height: 100%;
    width: 0;
    background: var(--red);
    border-radius: 999px;
    transition: width var(--dur-std) var(--ease);
    position: relative;
    overflow: hidden;
}
.loading-overlay .progress-bar::after {
    content: '';
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.35), transparent);
    animation: tv-progress-sweep 1.5s linear infinite;
}
@keyframes tv-progress-sweep { to { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) {
    .loading-overlay { transition: none; }
    .loading-overlay .loading-spinner,
    .loading-overlay .spinner { animation-duration: 2.4s; }
    .loading-overlay .progress-bar::after { animation: none; }
}

/* "Syncing with Teays Cloud" pill — bottom-right, white cloud glyph.
   Was orphaned in ringcentral (referenced, no CSS); now shared so
   every allocator matches uplync's treatment. */
.firebase-sync-indicator {
    position: fixed;
    bottom: 20px;
    right: 20px;
    background: var(--primary);
    color: #ffffff;
    padding: 10px 16px;
    border-radius: var(--r-md);
    font-family: var(--font-sans);
    font-size: 13px;
    font-weight: 400; /* NHG ships 400/700 only */
    box-shadow: var(--shadow-md);
    display: flex;
    align-items: center;
    gap: 8px;
    opacity: 0;
    transform: translateY(20px);
    pointer-events: none;
    transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
    z-index: 9000;
}
.firebase-sync-indicator.show { opacity: 1; transform: translateY(0); }
.firebase-sync-indicator::before {
    content: '';
    width: 16px;
    height: 16px;
    flex: 0 0 auto;
    background-repeat: no-repeat;
    background-size: 16px 16px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 18a4.5 4.5 0 1 1 .9-8.9A6 6 0 0 1 19.6 11 3.8 3.8 0 0 1 18 18z'/%3E%3C/svg%3E");
}
@media (prefers-reduced-motion: reduce) {
    .firebase-sync-indicator { transition: none; }
}

/* ============================================================
   ICONS — stroke icons, currentColor, optically sized.
   ============================================================ */
.tv-ic { width: 18px; height: 18px; flex: 0 0 auto; stroke: currentColor; fill: none; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; vertical-align: -3px; }
.tv-ic-lg { width: 24px; height: 24px; }

/* ============================================================
   ACCESSIBILITY & MOTION SAFETY
   ============================================================ */
:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.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; }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
    .tv-reveal { opacity: 1; transform: none; animation: none; }
}
