/* =====================================================================
   TrilokWeb — UI/UX Refinement layer  (Issue #37)
   ---------------------------------------------------------------------
   ONE shared stylesheet that enriches the markup classes already used
   across the Dashboard, every Search form, and every Result/grid page.
   Loaded LAST in App.razor so it wins over site.css / isolated-fallback.

   CSS isolation does not load in TrilokWeb — keep all UI styling here.
   Scope: visual only. No layout/logic that affects RBAC gating.

   Sections
     1. Design tokens (light + dark)
     2. Typography & page headers
     3. Search panels + form rows
     4. Dashboard (summary tiles + org sidebar)
     5. KPI / analytics surfaces
     6. Result summary bar + filter chips
     7. Result grids (Syncfusion) — density & polish
     8. Shared states (loading / empty / buttons) + motion
   ===================================================================== */

/* ============================ 1. TOKENS ============================ */
:root {
    /* Brand ramp — anchored to the existing sidebar indigo (#052666) */
    --yb-brand-900: #052666;
    --yb-brand-700: #0e3a93;
    --yb-brand-600: #1453c4;
    --yb-brand-500: #1f6fe5;
    --yb-brand-400: #4a90ff;
    --yb-accent: #007aff;
    --yb-accent-rgb: 0, 122, 255;

    /* Provenance: "inherited from above" — a dusty violet kept distinct from
       the accent blue (which marks the value that actually wins). */
    --yb-inherit: #6a52c9;
    --yb-inherit-rgb: 106, 82, 201;

    /* Semantic */
    --yb-success: #1f9d61;
    --yb-warning: #e0a106;
    --yb-warning-rgb: 224, 161, 6;
    --yb-danger: #d8443c;
    --yb-danger-rgb: 216, 68, 60;

    /* Mandatory-field marker (#147). Its own token rather than --yb-danger directly: the asterisk
       is small, high-frequency text that has to stay legible on both canvases, so dark needs a
       lighter red than the danger fill does. */
    --yb-required: #d8443c;
    --yb-info: #1a86c2;
    --yb-info-rgb: 26, 134, 194;

    /* Counseling / care CTA — the violet that ties the "counseling required"
       status, the hero pending-cases call-to-action and the Counselor section
       identity together. Single source of truth so light/dark stay in sync. */
    --yb-counselor: #7c5cff;
    --yb-counselor-rgb: 124, 92, 255;

    /* rgb tuple of --yb-success, for the Branch Wellbeing jump chip's tint/icon. */
    --yb-success-rgb: 31, 157, 97;

    /* Student section identity — a distinct indigo so it doesn't read as the same
       blue as the Filters chip / brand accent. */
    --yb-indigo: #4f46e5;
    --yb-indigo-rgb: 79, 70, 229;

    /* Surfaces (light) — canvas deepened + cards pulled just off pure white
       so cards read as foreground and whites don't hit HDR peak luminance */
    --yb-page: #eaeef6;
    --yb-surface: #fcfdff;
    --yb-surface-2: #f1f4fa;
    --yb-surface-sunken: #e6ebf4;
    --yb-card: #fcfdff;

    /* Lines & text */
    --yb-border: rgba(16, 31, 64, 0.10);
    --yb-border-strong: rgba(16, 31, 64, 0.16);
    --yb-text: #1b2538;
    --yb-text-muted: #586683;
    --yb-text-soft: #8593ab;

    /* Radii */
    --yb-radius-sm: 9px;
    --yb-radius: 14px;
    --yb-radius-lg: 20px;
    --yb-radius-pill: 999px;

    /* Elevation */
    --yb-shadow-xs: 0 1px 2px rgba(16, 31, 64, 0.06);
    --yb-shadow-sm: 0 2px 8px rgba(16, 31, 64, 0.07);
    --yb-shadow-md: 0 10px 26px rgba(16, 31, 64, 0.10);
    --yb-shadow-lg: 0 22px 50px rgba(16, 31, 64, 0.14);
    --yb-ring: 0 0 0 0.22rem rgba(var(--yb-accent-rgb), 0.18);

    /* Motion */
    --yb-ease: cubic-bezier(0.4, 0, 0.2, 1);
    --yb-dur: 0.22s;

    /* Fonts (already preloaded in App.razor) */
    --yb-font-display: "Fraunces", "Georgia", serif;
    --yb-font-body: "Hanken Grotesk", "Segoe UI", system-ui, sans-serif;
}

[data-theme="dark"] {
    --yb-page: #0e1117;
    --yb-surface: #171b22;
    --yb-surface-2: #1c212b;
    --yb-surface-sunken: #11151c;
    --yb-card: #181d26;

    --yb-border: rgba(148, 170, 205, 0.16);
    --yb-border-strong: rgba(148, 170, 205, 0.26);
    --yb-text: #e7ecf5;
    --yb-text-muted: #a3b0c7;
    --yb-text-soft: #7f8da6;

    /* Lighter red so the small required asterisk keeps its contrast on dark surfaces (#147) */
    --yb-required: #ff8b83;

    /* Lighter violet so the inherited tint stays legible on dark surfaces */
    --yb-inherit: #b3a4ef;
    --yb-inherit-rgb: 179, 164, 239;
    /* --yb-counselor (#7c5cff) is already light enough to read on dark surfaces
       AND to carry white badge text, so it is kept identical across themes. */

    --yb-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.4);
    --yb-shadow-sm: 0 2px 10px rgba(0, 0, 0, 0.45);
    --yb-shadow-md: 0 12px 30px rgba(0, 0, 0, 0.5);
    --yb-shadow-lg: 0 24px 55px rgba(0, 0, 0, 0.6);
}

/* Calmer page canvas so elevated white cards read as foreground */
body,
.page-container {
    font-family: var(--yb-font-body);
}

/* ==================== 2. TYPOGRAPHY & PAGE HEADERS ==================== */
.page-header-section {
    margin-bottom: 1.1rem;
}

.yb-header__row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
}

.page-title-div {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 0.3rem;
    min-width: 0;
}

.page-title-heading {
    font-family: var(--yb-font-display);
    font-optical-sizing: auto;
    font-size: clamp(1.5rem, 1.1rem + 1.4vw, 2.1rem) !important;
    font-weight: 600 !important;
    letter-spacing: -0.01em;
    line-height: 1.15;
    color: var(--yb-text) !important;
    margin: 0 !important;
}

/* Hairline accent under every page title — quiet brand signature */
.page-title-div::after {
    content: "";
    width: 48px;
    height: 3px;
    border-radius: var(--yb-radius-pill);
    background: linear-gradient(90deg, var(--yb-accent), var(--yb-brand-400));
    opacity: 0.9;
}

.page-subtitle {
    font-family: var(--yb-font-body);
    font-size: 0.95rem !important;
    font-weight: 400 !important;
    line-height: 1.5;
    color: var(--yb-text-muted) !important;
    max-width: 78ch;
    margin: 0.55rem auto 0 !important;
    text-align: center;
}

[data-theme="dark"] .page-title-heading {
    color: var(--yb-text) !important;
}

/* --- Compact mode: smaller title, subtitle behind the info toggle --- */
.yb-header--compact {
    margin-bottom: 0.75rem;
}

.yb-header--compact .page-title-heading {
    font-size: clamp(1.15rem, 0.95rem + 0.7vw, 1.45rem) !important;
}

.yb-header--compact .page-title-div {
    gap: 0.2rem;
}

.yb-header--compact .page-title-div::after {
    width: 34px;
    height: 2px;
}

.yb-header--compact .page-subtitle {
    font-size: 0.88rem !important;
    margin-top: 0.4rem !important;
}

/* The ⓘ subtitle toggle */
.yb-header__info {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.7rem;
    height: 1.7rem;
    flex: 0 0 auto;
    padding: 0;
    border: 1px solid var(--yb-border-strong);
    border-radius: var(--yb-radius-pill);
    background: var(--yb-surface);
    color: var(--yb-text-soft);
    font-size: 0.9rem;
    line-height: 1;
    cursor: pointer;
    transition: color var(--yb-dur) var(--yb-ease), border-color var(--yb-dur) var(--yb-ease), background var(--yb-dur) var(--yb-ease);
}

.yb-header__info:hover,
.yb-header__info.is-active {
    color: var(--yb-accent);
    border-color: rgba(var(--yb-accent-rgb), 0.5);
    background: rgba(var(--yb-accent-rgb), 0.08);
}

[data-theme="dark"] .yb-header__info {
    background: var(--yb-card);
}

/* ==================== 3. SEARCH PANELS + FORM ROWS ==================== */
/* Elevate every search form (.search-container is on all 11 search pages
   and the KPI filter panel) into a single cohesive card surface. */
.search-container {
    /* Full-width: occupy the whole content column on large screens instead of
       a centered 1180px measure (looked cramped on 4K). */
    max-width: none;
    margin-inline: 0;
    padding: clamp(0.75rem, 0.5rem + 0.9vw, 1.05rem) clamp(0.9rem, 0.6rem + 1.1vw, 1.35rem);
    background: var(--yb-surface);
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-lg);
    box-shadow: var(--yb-shadow-sm);
    text-align: left;
    transition: box-shadow var(--yb-dur) var(--yb-ease), border-color var(--yb-dur) var(--yb-ease);
}

.search-container:focus-within {
    border-color: rgba(var(--yb-accent-rgb), 0.4);
    box-shadow: var(--yb-shadow-md);
}

[data-theme="dark"] .search-container {
    background: var(--yb-card);
    border-color: var(--yb-border);
}

/* The KPI dashboard already wraps its panel in a Bootstrap .card; avoid a
   double frame by flattening the inner card chrome there. */
.search-container.card,
.kpi-search-panel.card {
    box-shadow: var(--yb-shadow-sm);
}

/* Form rows — consistent rhythm, aligned labels, refined inputs */
.form-group-flex {
    gap: 0.6rem;
    margin-bottom: 0.5rem;
}

.form-label-fixed,
.search-container .form-label {
    min-width: 132px;
    font-weight: 600;
    font-size: 0.86rem;
    letter-spacing: 0.01em;
    color: var(--yb-text-muted) !important;
}

/* Inputs: Bootstrap + Syncfusion share one calm, rounded, focus-ring look */
.search-container .form-control,
.search-container .form-select,
.search-container .e-input-group,
.search-container .e-input-group.e-control-wrapper {
    border-radius: var(--yb-radius-sm);
    border-color: var(--yb-border-strong);
    /* Clip the inner (square-cornered) Syncfusion input fill to the rounded
       wrapper — without this the corners overlap, most visibly in dark mode.
       The focus ring is the wrapper's own outer shadow, so it is not clipped. */
    overflow: hidden;
    transition: border-color var(--yb-dur) var(--yb-ease), box-shadow var(--yb-dur) var(--yb-ease);
}

/* Ensure the inner input/value elements follow the rounded wrapper too */
.search-container .e-input-group input.e-input,
.search-container .e-input-group .e-input,
.search-container .e-input-group.e-control-wrapper input {
    border-radius: inherit;
    background: transparent;
}

.search-container .form-control:focus,
.search-container .form-select:focus,
.search-container .e-input-group.e-input-focus {
    border-color: rgba(var(--yb-accent-rgb), 0.55);
    box-shadow: var(--yb-ring);
}
.search-container .d-flex.justify-content-end {
    margin-top: 1.1rem;
    padding-top: 0.9rem;
    border-top: 1px solid var(--yb-border);
}

/* Always-visible actions footer (toolbar left, buttons right) — tight top gap */
.search-container .yb-search-footer {
    margin-top: 0.4rem;
    padding-top: 0.45rem;
    border-top: 1px solid var(--yb-border);
}

/* Stack label over field on small screens (matches KPI panel behaviour) */
@media (max-width: 767.98px) {
    .form-group-flex {
        flex-direction: column;
        align-items: stretch;
        gap: 0.35rem;
    }

    .form-label-fixed {
        min-width: 0;
    }
}

/* --- Filter toolbar (now lives in the search footer) + collapsible body --- */

/* Toolbar: two icon groups separated by a rule — [filter+show/hide] | [pin] */
.yb-filter-toolbar {
    display: inline-flex;
    align-items: center;
    gap: 0.15rem;
    padding: 0.2rem 0.3rem;
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius);
    background: var(--yb-surface-2);
    box-shadow: var(--yb-shadow-sm);
}

/* Big icon buttons */
.yb-tool {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
    height: 2.1rem;
    min-width: 2.1rem;
    padding: 0 0.55rem;
    border: none;
    border-radius: var(--yb-radius-sm);
    background: transparent;
    color: var(--yb-text-soft);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
    transition: background var(--yb-dur) var(--yb-ease), color var(--yb-dur) var(--yb-ease);
}

.yb-tool:hover {
    background: rgba(var(--yb-accent-rgb), 0.12);
    color: var(--yb-accent);
}

.yb-tool.is-active {
    color: var(--yb-accent);
}

.yb-tool__glyph {
    font-size: 1rem;
}

/* Leading "Filters:" label with funnel glyph */
.yb-tool__label {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0 0.15rem 0 0.25rem;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--yb-text-soft);
    white-space: nowrap;
    user-select: none;
}

/* Colorful state glyphs — keep their hue regardless of button hover/active */
.yb-glyph--funnel {
    color: var(--yb-accent);
}

.yb-glyph--show {
    color: var(--yb-success);
}

.yb-glyph--hide {
    color: var(--yb-warning);
}

.yb-glyph--pin {
    color: var(--yb-text-soft);
}

.yb-glyph--pin.is-pinned {
    color: var(--yb-warning);
}

.yb-tool__sep {
    width: 1px;
    height: 1.5rem;
    margin: 0 0.15rem;
    background: var(--yb-border-strong);
}

[data-theme="dark"] .yb-filter-toolbar {
    background: var(--yb-card);
    border-color: var(--yb-border);
}

/* Collapsible body — just shows/hides the form; stays mounted when hidden */
.yb-cpanel {
    margin-top: 0.2rem;
}

.yb-cpanel__body {
    animation: ybFadeUp 0.25s var(--yb-ease) both;
}

/* Hidden body stays in the DOM (mounted) so selections are never lost */
.yb-cpanel__body[hidden] {
    display: none;
}

/* ==================== 4. DASHBOARD ==================== */
/* Two regions side by side: a flexible cards grid (left) and a fixed recent-orgs rail
   (right). align-items:flex-start is the fix for the old bug where the summary cards
   stretched vertically to match the tall org list — they were siblings in one stretch
   row. Now the cards relate only to each other. */
.dashboard-layout {
    display: flex;
    gap: 1.25rem;
    align-items: flex-start;
    margin-top: 0.25rem;
}

.dashboard-cards {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    align-content: flex-start;
}

/* Each tile gets a sensible min so cards wrap into a tidy grid instead of
   stretching edge-to-edge. */
.dashboard-tile {
    flex: 1 1 200px;
    min-width: 190px;
    display: flex;
}

.dashboard-tile .dashboard-card {
    width: 100%;
}

/* Summary tiles — KPI cards. Each carries its own brand-adjacent accent (--card-accent,
   set per metric below) that drives the icon badge + hover rail, so every metric reads as
   its own thing while the set stays cohesive. */
.dashboard-card,
.default-summary-card.dashboard-card {
    --card-accent: var(--yb-accent-rgb); /* default; overridden per metric */
    position: relative;
    overflow: hidden;
    background: var(--yb-card) !important;
    color: var(--yb-text) !important;
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-lg) !important;
    box-shadow: var(--yb-shadow-sm);
    padding: 1.5rem 1.35rem !important;
    transition: transform var(--yb-dur) var(--yb-ease), box-shadow var(--yb-dur) var(--yb-ease), border-color var(--yb-dur) var(--yb-ease);
}

/* Per-metric accent (R,G,B) — curated, brand-adjacent, not neon. */
.summary-readers { --card-accent: 0, 122, 255; }
.summary-wearables { --card-accent: 14, 165, 164; }
.summary-organizations { --card-accent: 124, 92, 255; }
.summary-branches { --card-accent: 99, 102, 241; }
.summary-itemgroups { --card-accent: 245, 158, 11; }
.summary-lookups { --card-accent: 6, 182, 212; }
.summary-uptime { --card-accent: 34, 197, 94; }

/* Top accent rail in the card's own colour, revealed on hover. */
.dashboard-card::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 3px;
    background: linear-gradient(90deg, rgb(var(--card-accent)), rgba(var(--card-accent), 0.35));
    opacity: 0;
    transition: opacity var(--yb-dur) var(--yb-ease);
}

.clickable-card:hover,
.dashboard-card:hover {
    background: var(--yb-card) !important;
    transform: translateY(-3px);
    box-shadow: var(--yb-shadow-md);
    border-color: rgba(var(--card-accent), 0.4);
}

.dashboard-card:hover::before {
    opacity: 1;
}

/* Icon sits in a soft tinted badge in the metric's colour (was a bare 2rem glyph). */
.dashboard-card .icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3.25rem;
    height: 3.25rem;
    margin-bottom: 0.75rem;
    border-radius: 14px;
    background: rgba(var(--card-accent), 0.12);
    border: 1px solid rgba(var(--card-accent), 0.22);
    transition: background var(--yb-dur) var(--yb-ease), transform var(--yb-dur) var(--yb-ease);
}

.dashboard-card .icon i {
    font-size: 1.5rem;
    line-height: 1;
    color: rgb(var(--card-accent));
}

.dashboard-card:hover .icon {
    background: rgba(var(--card-accent), 0.2);
    transform: translateY(-1px);
}

.dashboard-card h5 {
    font-size: 0.78rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--yb-text-muted);
    margin-bottom: 0.3rem;
}

.dashboard-card h2 {
    font-family: var(--yb-font-display);
    font-weight: 700;
    font-size: clamp(1.9rem, 1.4rem + 1.3vw, 2.5rem);
    line-height: 1.05;
    letter-spacing: -0.015em;
    font-variant-numeric: tabular-nums;
    color: var(--yb-text);
    margin: 0;
}

[data-theme="dark"] .dashboard-card,
[data-theme="dark"] .default-summary-card.dashboard-card {
    background: var(--yb-card) !important;
    border-color: var(--yb-border);
}

[data-theme="dark"] .dashboard-card:hover {
    background: var(--yb-card) !important;
}

[data-theme="dark"] .dashboard-card h2 {
    color: var(--yb-text);
}

/* Recent-organizations rail: fixed width, pinned right, top-aligned and sticky so it
   follows the cards as the page scrolls. Stacks full-width below the cards on narrow
   screens. The rail itself is unstyled — the YbCollapsibleCard inside is the surface,
   so we avoid stacking card-on-card. */
.org-rail {
    flex: 0 0 320px;
    align-self: flex-start;
    position: sticky;
    top: 1rem;
}

@media (max-width: 991.98px) {
    .dashboard-layout {
        flex-direction: column;
    }

    .org-rail {
        flex-basis: auto;
        width: 100%;
        position: static;
    }
}

/* Recent-org entries adopt the app's compact left-accent rail motif (brand tokens)
   rather than the heavy bootstrap bordered card. !important overrides the .border /
   .border-secondary / .shadow-sm utilities on the shared OrganizationLinks card. */
.org-rail .card {
    border: 1px solid var(--yb-border) !important;
    border-left: 3px solid rgba(var(--yb-accent-rgb), 0.5) !important;
    border-radius: var(--yb-radius-sm) !important;
    box-shadow: none !important;
    margin-bottom: 0.6rem !important;
    transition: border-color var(--yb-dur) var(--yb-ease), box-shadow var(--yb-dur) var(--yb-ease);
}

.org-rail .card:last-child {
    margin-bottom: 0 !important;
}

.org-rail .card:hover {
    border-left-color: var(--yb-accent) !important;
    box-shadow: var(--yb-shadow-sm) !important;
}

.org-rail .card-body {
    padding: 0.7rem 0.85rem;
}

.org-rail .card-title {
    font-size: 0.95rem;
    font-weight: 600;
    margin-bottom: 0.15rem;
    color: var(--yb-text);
}

/* ==================== 5. KPI / ANALYTICS SURFACES ==================== */
.analytics-kpi-dashboard .analytics-group {
    border-left: 4px solid rgba(var(--yb-accent-rgb), 0.35);
    padding-left: 1rem;
}

.analytics-kpi-dashboard .analytics-group h4 {
    font-family: var(--yb-font-display);
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--yb-text);
}

/* KPI value cards (AnalyticsKpiCard) + chart cards share one refined card */
.analytics-kpi-card.card,
.analytics-kpi-dashboard .card {
    background: var(--yb-card);
    border: 1px solid var(--yb-border) !important;
    border-radius: var(--yb-radius) !important;
    box-shadow: var(--yb-shadow-xs);
    transition: transform var(--yb-dur) var(--yb-ease), box-shadow var(--yb-dur) var(--yb-ease);
}

.analytics-kpi-card.card:hover {
    transform: translateY(-2px);
    box-shadow: var(--yb-shadow-md);
}

.analytics-kpi-card h3 {
    font-family: var(--yb-font-display);
    font-weight: 600;
    letter-spacing: -0.01em;
}

.analytics-kpi-card .card-body {
    padding: 1.05rem 1.1rem;
}

[data-theme="dark"] .analytics-kpi-card.card,
[data-theme="dark"] .analytics-kpi-dashboard .card {
    background: var(--yb-card);
    border-color: var(--yb-border) !important;
}

.analytics-kpi-card__subtext {
    font-size: 0.75rem;
    line-height: 1.3;
}

/* --- KPI search panel: stacked labels on narrow viewports --- */
.kpi-search-panel .form-label-fixed {
    min-width: 130px;
}

@media (max-width: 575.98px) {
    .kpi-search-panel .ms-auto {
        margin-left: 0 !important;
    }
}

@media (max-width: 767.98px) {
    .kpi-search-panel .form-group-flex {
        align-items: flex-start;
        flex-direction: column;
        gap: 0.35rem;
    }

    .kpi-search-panel .form-label-fixed {
        min-width: 0;
    }
}

/* .kpi-state removed — the KPI dashboard now uses YbSkeletonCards + YbStateBlock. This block was
   the ancestor of .yb-state: it modelled loading/empty/error for one screen, and .yb-state
   generalised it for the app. Keeping both would have left two answers to the same question. (#233) */

/* ── .yb-state — the shared loading / empty / error block ─────────────────────────────────────
   One block for all three answers a surface can give while it has nothing to show: "still
   working", "nothing here", "it failed". Before this the app carried ELEVEN separate treatments
   (yb-tw-*, yb-gov-*, yb-sd-*, yb-acad-*, yb-exam-*, yb-bge-*, nbr-*, sa-tl-*, yb-counsel-*,
   kpi-state, auth-context-gate) across eight CSS files, from a bordered card down to bare muted
   text with px padding and no ARIA at all.

   IT IS A CARD IN THE SAME FAMILY AS THE CONTENT IT STANDS IN FOR. The first version of this was
   a centred icon over a bold line over a muted subline — the empty state every product ships,
   which says nothing about this one. This app already had its own grammar and that version
   ignored it: a state spine, a 4px rounded rail down the left edge carrying the record's state
   in colour (temp-wearable.css .yb-tw-card::before, and ~30 more left rails across nine
   stylesheets). A state block sits in the slot the real records occupy, so it should read as one
   of them — left-aligned, same padding rhythm, same spine.

   Three decisions worth keeping:

   1. THE SPINE CARRIES THE STATE, in colour: accent working, neutral empty, danger failed. That
      is structure encoding meaning rather than decorating it, and it is why no icon is needed to
      tell the three apart.
   2. THE SPINE IS ALSO THE LOADING INDICATOR — it travels while work is in flight, so "loading"
      is the same object as every other state rather than a foreign spinner dropped on top of it.
      Under prefers-reduced-motion it simply stops; the wording and role="status" carry it.
   3. THE HEIGHT IS RESERVED. --yb-state-min-h keeps loading → loaded/empty from shifting the
      layout under the reader's eye.

   Consumed via <YbStateBlock>; prefer that over hand-writing the markup. */
.yb-state {
    --yb-state-min-h: 8.5rem;
    --yb-state-spine: var(--yb-border-strong);
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.3rem;
    min-height: var(--yb-state-min-h);
    padding: 1.35rem 1.35rem 1.35rem 1.6rem;
    margin-top: 1rem;
    /* Stated, not inherited: several page shells centre their text, which left the title and the
       shorter hint ragged against each other. A shared block must not depend on where it lands. */
    text-align: left;
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius);
    background: var(--yb-card, var(--yb-surface));
    box-shadow: var(--yb-shadow-xs);
    color: var(--yb-text-muted);
}

/* The spine. Same geometry as .yb-tw-card::before so a state block and a device card line up. */
.yb-state::before {
    content: "";
    position: absolute;
    inset: 0.5rem auto 0.5rem 0.4rem;
    width: 4px;
    border-radius: 2px;
    background: var(--yb-state-spine);
}

.yb-state__head {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
}

/* Demoted from a 1.7rem centred ornament to an inline mark. With a coloured spine and a display
   face on the title, a large glyph was a third signal for the same fact. */
.yb-state__icon {
    font-size: 1rem;
    line-height: 1;
    color: var(--yb-state-spine);
}

/* The display face is where this block stops being anonymous — it is the same Fraunces the
   device cards set their code in (.yb-tw-card__code), so the block sounds like the screen. */
.yb-state__title {
    margin: 0;
    font-family: var(--yb-font-display);
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--yb-text);
}

.yb-state__hint {
    margin: 0;
    font-size: 0.86rem;
    max-width: 52ch;
}

.yb-state__actions {
    margin-top: 0.65rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Working. The spine runs a travelling gradient rather than sitting still; the block is otherwise
   identical to the settled states, so nothing moves except the one element that means "moving". */
.yb-state--loading {
    --yb-state-spine: var(--yb-accent);
}

.yb-state--loading::before {
    background: linear-gradient(
        to bottom,
        rgba(var(--yb-accent-rgb, 79, 70, 229), 0.15) 0%,
        var(--yb-accent) 45%,
        rgba(var(--yb-accent-rgb, 79, 70, 229), 0.15) 100%);
    background-size: 100% 220%;
    animation: yb-state-spine-travel 1.4s linear infinite;
}

@keyframes yb-state-spine-travel {
    from { background-position: 0 -120%; }
    to   { background-position: 0 120%; }
}

/* Motion is the whole signature here, so honouring the preference means stopping it outright
   rather than slowing it — the title already says the block is working. */
@media (prefers-reduced-motion: reduce) {
    .yb-state--loading::before {
        animation: none;
        background: var(--yb-accent);
    }
}

.yb-state--error {
    --yb-state-spine: var(--yb-danger);
    border-color: rgba(216, 68, 60, 0.4);
    background: rgba(216, 68, 60, 0.07);
}

.yb-state--error .yb-state__title {
    color: var(--yb-danger);
}

[data-theme="dark"] .yb-state--error {
    background: rgba(216, 68, 60, 0.12);
}

/* An empty state that is good news — the tray is full, the queue is clear — reads wrong in the
   same neutral grey as "nothing found". */
.yb-state--calm {
    --yb-state-spine: var(--yb-success);
}

/* Inside a dialog or a narrow panel, where the page-level reserved height would dominate the body
   it sits in. Same block, less of it. */
.yb-state--compact {
    --yb-state-min-h: 4.5rem;
    padding: 1rem 1rem 1rem 1.35rem;
    margin-top: 0;
}

/* ── .yb-skel — skeletons, for surfaces whose shape is known before its content ───────────────
   A state block is a NOTICE: static text saying a thing is true. That is right for "nothing here"
   and "it failed", which are settled answers — and wrong for "still working", which the first pass
   of this got wrong by making loading a near-twin of empty. The only moving part was a 4px spine
   at the far edge of a ~1400px card, while the text it sat beside never moved, so the screen read
   as a message rather than as work in progress (#208 review).

   A skeleton does not say "loading". It shows the SHAPE of what is arriving, so the wait reads as
   content materialising. Use it wherever the layout is known in advance; keep .yb-state for empty,
   error, and for dialogs whose content shape is not fixed.

   THE STAGGER IS THE POINT. Rows resolve one after another rather than pulsing in unison —
   --yb-skel-i sets the position and delays that item's pulse. On a loan desk this is literal: the
   tray is being counted, and the devices report in one at a time. It also avoids the diagonal
   shimmer sweep, which is the skeleton every product ships regardless of what it is loading. */
.yb-skel {
    --yb-skel-i: 0;
    display: block;
    border-radius: var(--yb-radius-sm, 6px);
    background: var(--yb-border);
    opacity: 0.55;
    animation: yb-skel-pulse 1.6s ease-in-out infinite;
    /* NEGATIVE, deliberately. A positive delay leaves each shape frozen at its base opacity until
       its turn comes — with the board's last cards sitting at 810ms, a quick load showed a
       completely motionless skeleton, which is the very thing this replaced. A negative delay
       starts every shape already partway through the cycle: motion from the first frame, and the
       offset turns the stagger into a wave travelling through the board instead of dead time. */
    animation-delay: calc(var(--yb-skel-i) * -90ms);
}

@keyframes yb-skel-pulse {
    0%, 100% { opacity: 0.35; }
    50%      { opacity: 0.75; }
}

/* Sizes. Named for what they stand in for, so the markup reads as the content it replaces. */
.yb-skel--line   { height: 0.72rem; }
.yb-skel--strong { height: 1.05rem; }
.yb-skel--chip   { height: 1.35rem; border-radius: var(--yb-radius-sm, 6px); }
.yb-skel--w25 { width: 25%; }
.yb-skel--w40 { width: 40%; }
.yb-skel--w60 { width: 60%; }
.yb-skel--w75 { width: 75%; }
.yb-skel--w100 { width: 100%; }

/* The whole skeleton region stops moving, rather than each piece slowing down — partial motion
   reads as a stutter. The shapes stay, so the layout still reserves what is coming. */
@media (prefers-reduced-motion: reduce) {
    .yb-skel {
        animation: none;
        opacity: 0.5;
    }
}

/* ── .yb-skel-page — the generic page skeleton ────────────────────────────────────────────────
   For the moment before the app knows which page is coming: the shell (sidebar, top bar) is
   already painted, and what is missing is a page. Every page in this app opens the same way — a
   YbPageHeader title, then a band of controls, then rows — so a skeleton of that shape is an
   honest promise rather than a guess, and it hands over to a page's own skeleton in the same
   visual language instead of switching languages mid-load.

   Replaces the workspace gate's bespoke treatment: two counter-rotating rings, a diagonal sheen
   sweep, a pulsing dot and an indeterminate progress bar, all in ~240 lines of inline <style>
   using hardcoded Tailwind blues (#2563eb / #60a5fa) rather than the app's tokens. The progress
   bar was the worst of it — it animated a position that represented nothing. (#208 review) */
.yb-skel-page {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    width: 100%;
    padding: 0.5rem 0 1rem;
    /* Stated, not inherited: .center-form-container centres its text. */
    text-align: left;
}

.yb-skel-page__head {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.yb-skel-page__band {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 0.35rem;
}

.yb-skel-page__band .yb-skel {
    width: 104px;
    height: 2.15rem;
}

.yb-skel-page__rows {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

/* ── .yb-skel-table / .yb-skel-cards — the two shapes most surfaces load into ─────────────────
   Most loading states in this app are waiting on either a grid of rows or a grid of cards. These
   two give them a skeleton without every page hand-rolling one, so the shapes stay consistent and
   the stagger stays correct (see .yb-skel — the delay is negative on purpose).

   Column and row counts are passed in rather than assumed: a skeleton that does not match the
   table it precedes reintroduces the layout shift it exists to prevent. */
.yb-skel-table {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    width: 100%;
    padding: 0.75rem 0;
    text-align: left;
}

.yb-skel-table__row {
    display: grid;
    grid-template-columns: repeat(var(--yb-skel-cols, 5), minmax(0, 1fr));
    gap: 0.9rem;
    align-items: center;
}

/* The header row reads a shade heavier than the body, as a real table header does. */
.yb-skel-table__row--head .yb-skel {
    height: 0.85rem;
    opacity: 0.6;
}

.yb-skel-table__row--head + .yb-skel-table__row {
    margin-top: 0.35rem;
}

.yb-skel-cards {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(var(--yb-skel-card-min, 240px), 1fr));
    gap: 0.85rem;
    width: 100%;
    padding: 0.5rem 0;
    text-align: left;
}

.yb-skel-cards__card {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    min-height: 8.5rem;
    padding: 1rem 1.1rem;
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius);
    background: var(--yb-card, var(--yb-surface));
    box-shadow: var(--yb-shadow-xs);
}

/* --- Counselor case list table: token-driven, denser --- */
.kpi-cases-table {
    color: var(--yb-text);
    border-color: var(--yb-border);
    margin-bottom: 0;
}

.kpi-cases-table > :not(caption) > * > * {
    color: var(--yb-text) !important;
    background-color: var(--yb-card) !important;
    border-bottom-color: var(--yb-border) !important;
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
    vertical-align: middle;
}

.kpi-cases-table thead th {
    background-color: var(--yb-surface-2) !important;
    color: var(--yb-text-muted) !important;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    border-bottom-color: var(--yb-border) !important;
}

.kpi-cases-table tbody tr:hover > * {
    background-color: var(--yb-surface-2) !important;
}

.kpi-status-badge {
    font-weight: 600;
    color: #fff;
}

.kpi-status-high { background-color: var(--yb-danger); }
.kpi-status-intervention { background-color: var(--yb-warning); color: #1b1f24; }
.kpi-status-required { background-color: var(--yb-counselor); }

/* ==================== 5b. CARE-STATUS HERO + SECTION IDENTITY ==================== */
/* Signature element: a cohort ribbon that shows the whole student population's
   wellbeing split at a glance, with counseling-pending as the violet CTA. */
.kpi-hero {
    position: relative;
    overflow: hidden;
    background: var(--yb-card);
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-lg);
    box-shadow: var(--yb-shadow-sm);
    padding: 1.4rem 1.5rem;
    margin-bottom: 1.75rem;
}

/* severity ramp on the leading edge: cool (fine) → warm (concern) */
.kpi-hero::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: 4px;
    background: linear-gradient(180deg, var(--yb-success), var(--yb-info) 35%, var(--yb-warning) 70%, var(--yb-danger));
}

.kpi-hero__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 1rem;
    margin-bottom: 1rem;
}

.kpi-hero__eyebrow {
    display: block;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--yb-text-muted);
    margin-bottom: 0.15rem;
}

.kpi-hero__title {
    font-family: var(--yb-font-display);
    font-weight: 600;
    font-size: clamp(1.35rem, 1.1rem + 1vw, 1.85rem);
    letter-spacing: -0.02em;
    line-height: 1.1;
    color: var(--yb-text);
    margin: 0;
}

.kpi-hero__period {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.82rem;
    font-weight: 600;
    white-space: nowrap;
    color: var(--yb-text-muted);
    background: var(--yb-surface-2);
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-pill);
    padding: 0.3rem 0.75rem;
}

.kpi-ribbon {
    --kpi-ribbon-sep: rgba(255, 255, 255, 0.45);
    display: flex;
    height: 14px;
    margin-bottom: 1.1rem;
    border-radius: var(--yb-radius-pill);
    overflow: hidden;
    background: var(--yb-surface-2);
    box-shadow: inset 0 0 0 1px var(--yb-border);
}

[data-theme="dark"] .kpi-ribbon {
    --kpi-ribbon-sep: rgba(0, 0, 0, 0.35);
}

.kpi-ribbon__seg {
    height: 100%;
    min-width: 0;
    transition: width var(--yb-dur) var(--yb-ease);
}

.kpi-ribbon__seg + .kpi-ribbon__seg {
    box-shadow: inset 1px 0 0 var(--kpi-ribbon-sep);
}

@media (prefers-reduced-motion: reduce) {
    .kpi-ribbon__seg {
        transition: none;
    }
}

.kpi-ribbon__seg--stable { background: var(--yb-success); }
.kpi-ribbon__seg--moderate { background: var(--yb-info); }
.kpi-ribbon__seg--elevated { background: var(--yb-warning); }
.kpi-ribbon__seg--high { background: var(--yb-danger); }
.kpi-ribbon__seg--muted { background: var(--yb-surface-2); }

.kpi-hero__stats {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 0.6rem 2rem;
}

.kpi-hero__stat {
    display: flex;
    flex-direction: column;
    gap: 0.12rem;
    min-width: 82px;
}

.kpi-hero__stat--action {
    margin-left: auto;
    padding-left: 1.25rem;
    border-left: 1px solid var(--yb-border);
}

.kpi-hero__num {
    font-family: var(--yb-font-display);
    font-weight: 700;
    font-size: 1.65rem;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    color: var(--yb-text);
}

.kpi-hero__num--high { color: var(--yb-danger); }
.kpi-hero__num--action { color: var(--yb-counselor); }

.kpi-hero__lbl {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--yb-text-muted);
}

.kpi-hero__sub {
    font-size: 0.72rem;
    color: var(--yb-text-muted);
    margin-top: 0.1rem;
}

.kpi-dot {
    width: 0.55rem;
    height: 0.55rem;
    border-radius: 50%;
    flex: 0 0 auto;
}

.kpi-dot--stable { background: var(--yb-success); }
.kpi-dot--moderate { background: var(--yb-info); }
.kpi-dot--elevated { background: var(--yb-warning); }
.kpi-dot--high { background: var(--yb-danger); }
.kpi-dot--action { background: var(--yb-counselor); }

/* Below ~768px the five stats can no longer share one line; drop the right-align
   + divider so the wrapped action stat sits flush-left instead of stranded. */
@media (max-width: 767.98px) {
    .kpi-hero__stat--action {
        margin-left: 0;
        padding-left: 0;
        border-left: none;
    }
}

@media (max-width: 575.98px) {
    .kpi-hero__stat--action {
        flex-basis: 100%;
    }
}

/* Section identity — each analytics group gets its own accent chip so Student /
   Staff / Counselor read as distinct but cohesive. */
.kpi-section-head {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.kpi-section-head--wrap { flex-wrap: wrap; }

.kpi-section-head__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2.4rem;
    height: 2.4rem;
    border-radius: 12px;
    font-size: 1.1rem;
    background: rgba(var(--sect-accent, var(--yb-accent-rgb)), 0.12);
    border: 1px solid rgba(var(--sect-accent, var(--yb-accent-rgb)), 0.24);
    color: rgb(var(--sect-accent, var(--yb-accent-rgb)));
}

.kpi-section-head__text {
    display: flex;
    flex-direction: column;
    gap: 0.05rem;
}

.kpi-section-head__title {
    font-family: var(--yb-font-display);
    font-weight: 600;
    font-size: 1.15rem;
    letter-spacing: -0.01em;
    line-height: 1.1;
    color: var(--yb-text);
    margin: 0;
}

.kpi-section-head__focus {
    font-size: 0.78rem;
    color: var(--yb-text-muted);
}

.kpi-section-head__tools {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin-left: auto;
}

.kpi-section-head__hint {
    font-size: 0.76rem;
    color: var(--yb-text-muted);
}

/* Per-section accent (R,G,B) drives the icon chip AND the group's left rule. */
.analytics-group--student { --sect-accent: var(--yb-indigo-rgb); }
.analytics-group--staff { --sect-accent: var(--yb-warning-rgb); }
.analytics-group--counselor { --sect-accent: var(--yb-counselor-rgb); }

.analytics-kpi-dashboard .analytics-group--student,
.analytics-kpi-dashboard .analytics-group--staff,
.analytics-kpi-dashboard .analytics-group--counselor {
    border-left-color: rgba(var(--sect-accent), 0.4);
    /* clear the pinned jump-nav (top offset + its height) when scrolled to */
    scroll-margin-top: 4rem;
}

/* Same clearance for the other jump targets (Filters panel + Wellbeing hero). */
.analytics-kpi-dashboard .kpi-search-panel,
.analytics-kpi-dashboard .kpi-hero {
    scroll-margin-top: 4rem;
}

/* Sticky mini-nav — jumps between the three analytics sections; each link mirrors
   its section's icon + accent. Pinned to the viewport by kpi-scrollspy.js (an
   overflow-y:auto layout ancestor breaks native position:sticky here). */
.kpi-jumpnav {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.3rem 0.4rem;
    margin-bottom: 1.5rem;
    padding: 0.3rem 0.4rem;
    background: var(--yb-card);
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius);
    box-shadow: var(--yb-shadow-sm);
}

/* Pinned state — JS sets inline left/width to match the nav's normal slot; the
   spacer it inserts reserves that vertical space so content doesn't jump. */
.kpi-jumpnav.is-pinned {
    position: fixed;
    top: 8px;
    z-index: 100;
    margin-bottom: 0;
    box-shadow: var(--yb-shadow-md);
}

.kpi-jumpnav__spacer {
    display: none;
}

.kpi-jumpnav__label {
    padding-inline: 0.4rem 0.1rem;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--yb-text-muted);
}

.kpi-jumpnav__link {
    --nav-accent: var(--yb-accent-rgb);
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.24rem 0.6rem;
    font-size: 0.8rem;
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
    color: var(--yb-text);
    background: rgba(var(--nav-accent), 0.08);
    border: 1px solid rgba(var(--nav-accent), 0.2);
    border-radius: var(--yb-radius-sm);
    transition: background var(--yb-dur) var(--yb-ease), border-color var(--yb-dur) var(--yb-ease), transform var(--yb-dur) var(--yb-ease);
}

.kpi-jumpnav__link i {
    font-size: 0.9rem;
    color: rgb(var(--nav-accent));
}

.kpi-jumpnav__link:hover,
.kpi-jumpnav__link:focus-visible {
    color: var(--yb-text);
    background: rgba(var(--nav-accent), 0.16);
    border-color: rgba(var(--nav-accent), 0.42);
    transform: translateY(-1px);
}

.kpi-jumpnav__link:focus-visible {
    outline: 2px solid rgb(var(--nav-accent));
    outline-offset: 2px;
}

.kpi-jumpnav__link--filters { --nav-accent: var(--yb-accent-rgb); }
.kpi-jumpnav__link--wellbeing { --nav-accent: var(--yb-success-rgb); }
.kpi-jumpnav__link--student { --nav-accent: var(--yb-indigo-rgb); }
.kpi-jumpnav__link--staff { --nav-accent: var(--yb-warning-rgb); }
.kpi-jumpnav__link--counselor { --nav-accent: var(--yb-counselor-rgb); }

/* Active section (set by kpi-scrollspy.js). Label stays --yb-text for legibility
   across all three accents/themes; the solid accent border + stronger fill + weight
   mark it — avoids the white-on-amber contrast trap a filled pill would hit. */
.kpi-jumpnav__link.is-active {
    color: var(--yb-text);
    font-weight: 700;
    background: rgba(var(--nav-accent), 0.2);
    border-color: rgb(var(--nav-accent));
}

/* Applied-filter summary — fills the empty right side of the jump bar so the
   active scope stays visible after the filter panel auto-collapses. */
.kpi-jumpnav__applied {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 0.4rem;
    margin-left: auto;
    padding-left: 0.5rem;
    min-width: 0;
}

.kpi-jumpnav__applied-label {
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--yb-text-soft);
}

/* Each chip stacks a tiny superscript label over the value to save width. */
.kpi-jumpnav__chip {
    display: inline-flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 0;
    max-width: 18ch;
    padding: 0.1rem 0.5rem;
    color: var(--yb-text);
    background: var(--yb-surface-2);
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-sm);
}

.kpi-jumpnav__chip b {
    font-size: 0.56rem;
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--yb-text-muted);
}

.kpi-jumpnav__chip-val {
    max-width: 100%;
    font-size: 0.76rem;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* On phones the bar is already tight — drop the scope summary rather than wrap. */
@media (max-width: 767.98px) {
    .kpi-jumpnav__applied {
        display: none;
    }
}

@media (prefers-reduced-motion: no-preference) {
    html { scroll-behavior: smooth; }
}

/* ==================== 6. RESULT SUMMARY BAR + CHIPS ==================== */
/* YbSearchResultSummary sits atop every Result page. One compact, single-line
   toolbar: status + count + active filter chips, all inline. */
.yb-results-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem 0.5rem;
    margin-bottom: 0.6rem;
    padding: 0.3rem 0.6rem;
    background: var(--yb-surface-2);
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-pill);
    font-size: 0.8rem;
    line-height: 1.2;
}

.yb-results-summary--ok {
    border-color: rgba(31, 157, 97, 0.28);
    background: rgba(31, 157, 97, 0.07);
}

.yb-results-summary--empty {
    border-color: rgba(224, 161, 6, 0.32);
    background: rgba(224, 161, 6, 0.08);
}

[data-theme="dark"] .yb-results-summary--ok {
    background: rgba(31, 157, 97, 0.12);
}

[data-theme="dark"] .yb-results-summary--empty {
    background: rgba(224, 161, 6, 0.12);
}

.yb-results-count {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-weight: 600;
    color: var(--yb-text);
}

.yb-results-count .bi-check2-circle {
    color: var(--yb-success);
}

.yb-results-count--empty {
    color: #9a6f04;
}

[data-theme="dark"] .yb-results-count--empty {
    color: #e6b53d;
}

.yb-results-count .badge {
    font-size: 0.72rem;
    padding: 0.2rem 0.45rem;
}

.yb-results-hint {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    color: var(--yb-text-soft);
    font-size: 0.72rem;
}

/* Thin separator between status and filters on the same line */
.yb-results-divider {
    width: 1px;
    height: 0.95rem;
    background: var(--yb-border-strong);
    margin-inline: 0.15rem;
}

.yb-filters-label {
    color: var(--yb-text-soft);
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

/* Filter chips — refined pill that works in both themes */
.search-tag {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    background: rgba(var(--yb-accent-rgb), 0.08);
    color: var(--yb-text);
    border: 1px solid rgba(var(--yb-accent-rgb), 0.22);
    padding: 0.32rem 0.7rem;
    border-radius: var(--yb-radius-pill);
    font-size: 0.82rem;
    font-weight: 500;
    margin: 0;
}

/* Very-compact variant used inside the results toolbar */
.search-tag--sm {
    padding: 0.1rem 0.5rem;
    font-size: 0.72rem;
    gap: 0.2rem;
}

.search-tag strong {
    color: var(--yb-text-muted);
    font-weight: 600;
}

[data-theme="dark"] .search-tag {
    background: rgba(var(--yb-accent-rgb), 0.16);
    color: var(--yb-text);
    border-color: rgba(var(--yb-accent-rgb), 0.32);
}

[data-theme="dark"] .search-tag strong {
    color: var(--yb-text-muted);
}

/* ==================== 7. RESULT GRIDS (Syncfusion) ==================== */
/* Rounded, bordered container with comfortable density. */
.e-grid {
    border: 1px solid var(--yb-border) !important;
    border-radius: var(--yb-radius) !important;
    overflow: hidden;
    box-shadow: var(--yb-shadow-xs);
}

/* Header gets a brand accent underline so it reads as a distinct, branded band
   rather than a flat grey strip. */
.e-grid .e-gridheader {
    border-top: 0 !important;
    border-bottom: 2px solid var(--yb-accent) !important;
}

/* Override the theme's white header background so the scrollbar-filler cell
   (see .e-lastcell below) doesn't expose a white square at the top-right. */
.e-grid .e-gridheader,
.e-grid .e-gridheader .e-headercontent {
    background: #e2eaf6 !important;
}

/* Branded header text (was a calm muted grey; site.css paints it loud red #c62828) */
.e-grid .e-headercell .e-headertext {
    color: var(--yb-brand-700) !important;
    font-weight: 700 !important;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-size: 0.78rem;
}

/* Soft vertical gradient gives the header subtle depth instead of a flat fill */
.e-grid .e-headercell {
    background: linear-gradient(180deg, #eef3fc 0%, #e2eaf6 100%) !important;
}

/* Round the first/last header cells to match the grid's rounded top corners, so a
   sorted (tinted) corner column follows the frame instead of showing a square edge.
   Slightly less than the grid radius so it nests cleanly inside the 1px frame. */
.e-grid .e-gridheader .e-headercell:first-child {
    border-top-left-radius: calc(var(--yb-radius) - 1px) !important;
}

.e-grid .e-gridheader .e-headercell:last-child {
    border-top-right-radius: calc(var(--yb-radius) - 1px) !important;
}

/* When a grid has a vertical scrollbar, Syncfusion appends an empty filler
   header cell (.e-lastcell) at the row end to keep the header aligned with the
   scrolled body. It renders white over the branded header band — paint it to
   match so the top-right corner isn't a white square. */
.e-grid .e-gridheader .e-headercell.e-lastcell {
    background: linear-gradient(180deg, #eef3fc 0%, #e2eaf6 100%) !important;
    border-top-right-radius: calc(var(--yb-radius) - 1px) !important;
}

/* Catch EVERY header cell by element (not class): the scrollbar-filler cell
   that appears only when the grid scrolls is a bare <th> our .e-headercell
   selectors miss, so it exposed white. Element-level selector covers it. */
.e-grid .e-gridheader th {
    background: linear-gradient(180deg, #eef3fc 0%, #e2eaf6 100%) !important;
}

.e-grid .e-rowcell {
    padding-top: 0.55rem !important;
    padding-bottom: 0.55rem !important;
    font-size: 0.9rem;
    color: var(--yb-text);
    /* Ease hover / selection fills + the feathered cell-selection border in smoothly */
    transition: background-color var(--yb-dur) var(--yb-ease),
                box-shadow var(--yb-dur) var(--yb-ease);
}

/* Softer row separators — a brand hairline instead of Syncfusion's flat grey line */
.e-grid .e-row .e-rowcell {
    border-top-color: var(--yb-border) !important;
}

/* Single-colour rows — no zebra striping. Alternate rows render the same as base rows;
   only hover and selection change a row's background (rules further below). */
.e-grid .e-altrow .e-rowcell {
    background-color: transparent !important;
}

[data-theme="dark"] .e-grid {
    border-color: var(--yb-border) !important;
}

[data-theme="dark"] .e-grid .e-gridheader {
    border-bottom-color: var(--yb-brand-400) !important;
    background: #171c26 !important;
}

[data-theme="dark"] .e-grid .e-headercell,
[data-theme="dark"] .e-grid .e-gridheader .e-headercell.e-lastcell,
[data-theme="dark"] .e-grid .e-gridheader th {
    background: linear-gradient(180deg, #1d2433 0%, #171c26 100%) !important;
}

[data-theme="dark"] .e-grid .e-headercell .e-headertext {
    color: #6ea8ff !important;
}

/* Analytics detail header — keep its row of badges / back button off the page
   edges (they sat flush against the border, most visible in dark mode). */
.student-header {
    padding: 0.25rem 0.75rem 0;
}

/* ---- Header sorting: accent the asc/desc icon + highlight the active sort column ---- */
/* Sort direction arrows in the brand accent, a touch larger for legibility */
.e-grid .e-gridheader .e-sortfilterdiv.e-icon-ascending,
.e-grid .e-gridheader .e-sortfilterdiv.e-icon-descending,
.e-grid .e-gridheader .e-icon-ascending,
.e-grid .e-gridheader .e-icon-descending {
    color: var(--yb-accent) !important;
    font-size: 0.95rem !important;
}

/* The sorted column header stands out (stronger accent wash + darker brand text)
   so it's obvious which column drives the order. aria-sort is the reliable hook;
   the .e-ascending/.e-descending classes are a fallback. */
.e-grid .e-gridheader .e-headercell[aria-sort="ascending"],
.e-grid .e-gridheader .e-headercell[aria-sort="descending"],
.e-grid .e-gridheader .e-headercell.e-ascending,
.e-grid .e-gridheader .e-headercell.e-descending {
    background: linear-gradient(180deg, #e6eefb 0%, #d7e4f7 100%) !important;
}

/* Very high specificity (.e-gridheader + .e-columnheader ancestors) so the dark brand
   text wins over Syncfusion's own sorted-header text colour — fixes the unreadable
   light-mode sort text. Uses the same readable dark brand as normal headers. */
.e-grid .e-gridheader .e-columnheader .e-headercell[aria-sort="ascending"] .e-headertext,
.e-grid .e-gridheader .e-columnheader .e-headercell[aria-sort="descending"] .e-headertext,
.e-grid .e-gridheader .e-columnheader .e-headercell.e-ascending .e-headertext,
.e-grid .e-gridheader .e-columnheader .e-headercell.e-descending .e-headertext,
.e-grid .e-gridheader .e-headercell[aria-sort="ascending"] .e-headertext,
.e-grid .e-gridheader .e-headercell[aria-sort="descending"] .e-headertext,
.e-grid .e-gridheader .e-headercell.e-ascending .e-headertext,
.e-grid .e-gridheader .e-headercell.e-descending .e-headertext {
    color: var(--yb-text) !important;
}

/* Multi-sort order number → small accent pill */
.e-grid .e-gridheader .e-sortnumber {
    background: var(--yb-accent) !important;
    color: #fff !important;
    border-radius: var(--yb-radius-pill) !important;
}

/* Dark */
[data-theme="dark"] .e-grid .e-gridheader .e-sortfilterdiv.e-icon-ascending,
[data-theme="dark"] .e-grid .e-gridheader .e-sortfilterdiv.e-icon-descending,
[data-theme="dark"] .e-grid .e-gridheader .e-icon-ascending,
[data-theme="dark"] .e-grid .e-gridheader .e-icon-descending {
    color: var(--yb-brand-400) !important;
}

[data-theme="dark"] .e-grid .e-headercell[aria-sort="ascending"],
[data-theme="dark"] .e-grid .e-headercell[aria-sort="descending"],
[data-theme="dark"] .e-grid .e-headercell.e-ascending,
[data-theme="dark"] .e-grid .e-headercell.e-descending {
    background: linear-gradient(180deg, #243248 0%, #1b2433 100%) !important;
}

[data-theme="dark"] .e-grid .e-gridheader .e-columnheader .e-headercell[aria-sort="ascending"] .e-headertext,
[data-theme="dark"] .e-grid .e-gridheader .e-columnheader .e-headercell[aria-sort="descending"] .e-headertext,
[data-theme="dark"] .e-grid .e-headercell[aria-sort="ascending"] .e-headertext,
[data-theme="dark"] .e-grid .e-headercell[aria-sort="descending"] .e-headertext,
[data-theme="dark"] .e-grid .e-headercell.e-ascending .e-headertext,
[data-theme="dark"] .e-grid .e-headercell.e-descending .e-headertext {
    color: var(--yb-text) !important;
}

/* Empty-results body in dark mode — Syncfusion paints the content area and the
   "No records to display" row white, which reads as a big patch on a dark page. */
[data-theme="dark"] .e-grid .e-content,
[data-theme="dark"] .e-grid .e-emptyrow,
[data-theme="dark"] .e-grid .e-emptyrow td {
    background-color: var(--yb-surface) !important;
}

[data-theme="dark"] .e-grid .e-emptyrow td {
    color: var(--yb-text-muted) !important;
}

/* ---- Row & cell states: hover, selected, active, cell-selection (both themes) ----
   site.css ships ad-hoc colours (dusty-pink selection, light-blue hover, maroon +
   bright-yellow dark hover) that clash with the brand. Re-tint every state with the
   accent ramp using SOLID fills (not low-alpha washes, which were near-invisible on
   the dark surface), as a clear visual ladder — base → hover → selected → active
   cell — and give the selected cell a crisp accent border. Selectors mirror site.css
   / Syncfusion's own long hover selector so this sheet (loaded last) wins. */

/* ===================== Light ===================== */
/* Hover (Syncfusion's own long selector — targets the cells) */
.e-grid.e-gridhover:not(.e-rowdrag)
.e-row:not(.e-disable-gridhover):not(.e-editedrow):not(.e-detailrow):hover
.e-rowcell:not(.e-cellselectionbackground):not(.e-active):not(.e-updatedtd):not(.e-indentcell) {
    background-color: #eef2f8 !important;
    /* Signal hover with COLOUR only. Force normal weight to OVERRIDE site.css's
       `font-weight: bold !important` on this same hover selector — that bold was
       widening the glyphs on hover and causing the reflow flicker. */
    color: var(--yb-brand-600) !important;
    font-weight: 400 !important;
}

/* Selected / active row — paint the row AND its cells. The highlight class can sit
   on the <tr> (.e-row.e-selectionbackground) while the cells stay transparent, so we
   must colour the descendant .e-rowcell too, not only the cell-level classes.
   Muted slate-blue (desaturated) so it doesn't glare on HDR/4K. */
.e-grid .e-row.e-selectionbackground,
.e-grid .e-row.e-active,
.e-grid .e-row.e-selectionbackground .e-rowcell,
.e-grid .e-row.e-active .e-rowcell,
.e-grid .e-rowcell.e-selectionbackground,
.e-grid .e-rowcell.e-active {
    background-color: #dde4ef !important;
    color: var(--yb-brand-700) !important;
    font-weight: 600 !important;
}

/* Premium left accent bar marking the selected / active ROW — a clean "you are here"
   indicator on the row's first cell (eased in via the .e-rowcell box-shadow transition).
   Placed before the cell-hero rules so the teal cell ring still wins on the first cell. */
.e-grid .e-row.e-selectionbackground .e-rowcell:first-child,
.e-grid .e-row.e-active .e-rowcell:first-child {
    box-shadow: inset 3px 0 0 0 var(--yb-accent) !important;
}

[data-theme="dark"] .e-grid .e-row.e-selectionbackground .e-rowcell:first-child,
[data-theme="dark"] .e-grid .e-row.e-active .e-rowcell:first-child {
    box-shadow: inset 3px 0 0 0 var(--yb-brand-400) !important;
}

/* Selected / active CELL (cell-selection mode + focused cell) — the FOCAL hero.
   Deliberately a DIFFERENT hue from the blue rows (soft teal / emerald) so the
   active cell pops as its own accent: gentle gradient fill, crisp 2px teal ring,
   soft inner glow. Cells are overflow:hidden, so the frame is an inset box-shadow;
   it eases in via the .e-rowcell transition. */
.e-grid .e-row.e-selectionbackground .e-rowcell.e-cellselectionbackground,
.e-grid .e-row .e-rowcell.e-cellselectionbackground,
.e-grid .e-rowcell.e-cellselectionbackground,
.e-grid .e-cellselectionbackground {
    background-image: linear-gradient(180deg, #e3f7f1 0%, #c9efe3 100%) !important;
    color: #0a5f48 !important;
    box-shadow: inset 0 0 0 2px #0fae84,
                inset 0 0 12px rgba(15, 174, 132, 0.20) !important;
}

/* Accessible focus ring in the brand accent (replaces a stray light-blue) */
.e-grid .e-row:focus,
.e-grid .e-rowcell:focus {
    outline: 2px solid var(--yb-accent) !important;
    outline-offset: -2px !important;
}

/* ===================== Dark ===================== */
/* Base rows on the themed surface (site.css paints them with a flat --card-bg grey) */
[data-theme="dark"] .e-grid td.e-rowcell {
    background-color: var(--yb-surface) !important;
    color: var(--yb-text) !important;
}

/* Hover — clearly lighter blue-grey than the base row */
[data-theme="dark"] .e-grid.e-gridhover:not(.e-rowdrag)
.e-row:not(.e-disable-gridhover):not(.e-editedrow):not(.e-detailrow):hover
.e-rowcell:not(.e-cellselectionbackground):not(.e-active):not(.e-updatedtd):not(.e-indentcell) {
    background-color: #222a37 !important;
    /* Colour-only hover; force normal weight to override site.css's bold-on-hover */
    color: #9fc0f5 !important;
    font-weight: 400 !important;
}

/* Selected / active row — mirror the LIGHT selectors (row + descendant cells),
   dark-qualified so it wins in dark mode and paints over the base cell colour.
   This is the fix for the "light row + white text = unreadable" dark bug: the
   earlier rules only targeted cell-level classes, but the highlight is on the <tr>. */
[data-theme="dark"] .e-grid .e-row.e-selectionbackground,
[data-theme="dark"] .e-grid .e-row.e-active,
[data-theme="dark"] .e-grid .e-row.e-selectionbackground .e-rowcell,
[data-theme="dark"] .e-grid .e-row.e-active .e-rowcell,
[data-theme="dark"] .e-grid .e-rowcell.e-selectionbackground,
[data-theme="dark"] .e-grid .e-rowcell.e-active {
    background-color: #2a3954 !important;
    color: var(--yb-text) !important;
    font-weight: 600 !important;
}

/* Selected / active CELL — focal hero in dark: soft teal / emerald (distinct from
   the blue rows), gradient fill, crisp 2px teal ring, soft inner glow. */
[data-theme="dark"] .e-grid .e-row.e-selectionbackground .e-rowcell.e-cellselectionbackground,
[data-theme="dark"] .e-grid .e-row .e-rowcell.e-cellselectionbackground,
[data-theme="dark"] .e-grid .e-rowcell.e-cellselectionbackground,
[data-theme="dark"] .e-grid .e-cellselectionbackground {
    background-image: linear-gradient(180deg, #1e4d44 0%, #16403a 100%) !important;
    color: #eafaf5 !important;
    box-shadow: inset 0 0 0 2px #2fd6ad,
                inset 0 0 13px rgba(47, 214, 173, 0.30) !important;
}

/* Action buttons inside grids stay compact */
.e-grid .e-rowcell .btn.btn-sm {
    padding: 0.2rem 0.6rem;
    border-radius: var(--yb-radius-sm);
}

/* ---- Pager polish ----
   Syncfusion's default pager is flat and its parts (numbers, nav arrows, the
   message, the page-size dropdown) sit on mixed baselines. Lay it out as one
   vertically-centered row: page numbers on the left, message + size selector
   pushed right; give items a rounded hover and the active page an accent pill. */
.e-grid .e-gridpager {
    display: flex !important;
    align-items: center !important;
    flex-wrap: wrap;
    gap: 0.15rem 0.3rem;
    padding: 0.4rem 0.65rem !important;
    border: 0 !important;
    border-top: 1px solid var(--yb-border) !important;
    background: var(--yb-surface-2) !important;
}

.e-grid .e-gridpager .e-pagercontainer,
.e-grid .e-gridpager .e-numericcontainer {
    display: inline-flex !important;
    align-items: center !important;
    margin: 0 !important;
    /* Let the pager bar's surface show through — Syncfusion paints these
       containers white by default, which reads as a patch in dark mode. */
    background: transparent !important;
    border: 0 !important;
}

/* Message bar + page-size selector → right edge, quiet text, v-centered */
.e-grid .e-gridpager .e-parentmsgbar {
    display: inline-flex !important;
    align-items: center !important;
    height: 2rem !important;
    margin-left: auto !important;
    float: none !important;
    line-height: 1 !important;
    color: var(--yb-text-soft) !important;
    font-size: 0.8rem !important;
}

/* Reset the inner message spans so their text shares the exact baseline as the
   "items per page" label (kills the slight vertical offset). */
.e-grid .e-gridpager .e-parentmsgbar .e-pagenomsg,
.e-grid .e-gridpager .e-parentmsgbar .e-pagecountmsg {
    line-height: 1 !important;
    margin: 0 !important;
    padding: 0 !important;
    vertical-align: middle !important;
}

.e-grid .e-gridpager .e-pagesizes {
    display: inline-flex !important;
    align-items: center !important;
    float: none !important;
    margin-left: 0.5rem !important;
}

/* Numeric pages + nav arrows — uniform size, rounded, calm, with hover.
   Flex-centering (not line-height) so the digits/icons are both v- and
   h-centered inside each cell. */
.e-grid .e-gridpager .e-numericitem,
.e-grid .e-gridpager .e-pagerbutton,
.e-grid .e-gridpager .e-first,
.e-grid .e-gridpager .e-prev,
.e-grid .e-gridpager .e-next,
.e-grid .e-gridpager .e-last {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    min-width: 2rem !important;
    height: 2rem !important;
    line-height: 1 !important;
    margin: 0 0.1rem !important;
    padding: 0 !important;
    border: 0 !important;
    border-radius: var(--yb-radius-sm) !important;
    background: transparent !important;
    color: var(--yb-text-muted) !important;
    transition: background var(--yb-dur) var(--yb-ease), color var(--yb-dur) var(--yb-ease);
}

.e-grid .e-gridpager .e-numericitem:hover,
.e-grid .e-gridpager .e-pagerbutton:hover:not(.e-disable),
.e-grid .e-gridpager .e-first:hover:not(.e-disable),
.e-grid .e-gridpager .e-prev:hover:not(.e-disable),
.e-grid .e-gridpager .e-next:hover:not(.e-disable),
.e-grid .e-gridpager .e-last:hover:not(.e-disable) {
    background: rgba(var(--yb-accent-rgb), 0.12) !important;
    color: var(--yb-accent) !important;
}

/* Active page → filled accent pill */
.e-grid .e-gridpager .e-numericitem.e-currentitem,
.e-grid .e-gridpager .e-numericitem.e-active {
    background: var(--yb-accent) !important;
    color: #fff !important;
    font-weight: 600 !important;
}

/* Page-size dropdown — match the 2rem control height, align its label */
.e-grid .e-gridpager .e-pagerdropdown {
    display: inline-flex !important;
    align-items: center !important;
    height: 2rem !important;
    margin: 0 0.4rem 0 0 !important;
    vertical-align: middle !important;
}

.e-grid .e-gridpager .e-pagerdropdown .e-input-group,
.e-grid .e-gridpager .e-pagerdropdown .e-input-group.e-control-wrapper {
    height: 2rem !important;
    min-height: 2rem !important;
}

.e-grid .e-gridpager .e-pagerconstant {
    display: inline-flex !important;
    align-items: center !important;
    height: 2rem !important;
    margin: 0 !important;
    line-height: 1 !important;
    color: var(--yb-text-soft) !important;
    font-size: 0.8rem !important;
    white-space: nowrap;
}

[data-theme="dark"] .e-grid .e-gridpager {
    background: var(--yb-surface-2) !important;
    border-top-color: var(--yb-border) !important;
}

/* ---- Row action buttons (Edit / Delete in a grid's Actions column) ----
   One shared, tokenized action language for every result grid, replacing the
   raw Bootstrap btn-primary / btn-danger ovals. Rounded-rect (radius-sm, not a
   999px pill — house rule), quiet tinted fills that escalate on hover, and full
   dark-mode parity. Apply on every *Results.razor Actions column. */
.yb-row-actions {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
}

.yb-row-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.32rem;
    padding: 0.3rem 0.66rem;
    font-size: 0.8rem;
    font-weight: 600;
    line-height: 1;
    border-radius: var(--yb-radius-sm);
    border: 1px solid transparent;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color var(--yb-dur) var(--yb-ease),
                border-color var(--yb-dur) var(--yb-ease),
                color var(--yb-dur) var(--yb-ease),
                box-shadow var(--yb-dur) var(--yb-ease),
                transform var(--yb-dur) var(--yb-ease);
}

.yb-row-btn i {
    font-size: 0.86rem;
    line-height: 1;
}

.yb-row-btn:hover {
    transform: translateY(-1px);
    box-shadow: var(--yb-shadow-xs);
}

.yb-row-btn:active {
    transform: translateY(0);
    box-shadow: none;
}

.yb-row-btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px rgba(var(--yb-accent-rgb), 0.35);
}

/* Edit — quiet brand-tinted */
.yb-row-btn--edit {
    color: var(--yb-brand-700);
    background: rgba(var(--yb-accent-rgb), 0.10);
    border-color: rgba(var(--yb-accent-rgb), 0.22);
}

.yb-row-btn--edit:hover {
    background: rgba(var(--yb-accent-rgb), 0.16);
    border-color: rgba(var(--yb-accent-rgb), 0.34);
    color: var(--yb-brand-700);
}

/* Delete — quiet danger-tinted; escalates on hover */
.yb-row-btn--danger {
    color: #b42318;
    background: rgba(214, 45, 32, 0.09);
    border-color: rgba(214, 45, 32, 0.20);
}

.yb-row-btn--danger:hover {
    background: rgba(214, 45, 32, 0.15);
    border-color: rgba(214, 45, 32, 0.34);
    color: #912018;
}

/* Dark parity */
[data-theme="dark"] .yb-row-btn--edit {
    color: #9cc4ff;
    background: rgba(74, 144, 255, 0.16);
    border-color: rgba(74, 144, 255, 0.28);
}

[data-theme="dark"] .yb-row-btn--edit:hover {
    background: rgba(74, 144, 255, 0.24);
    border-color: rgba(74, 144, 255, 0.40);
    color: #bcd7ff;
}

[data-theme="dark"] .yb-row-btn--danger {
    color: #ff9c8f;
    background: rgba(255, 92, 74, 0.15);
    border-color: rgba(255, 92, 74, 0.28);
}

[data-theme="dark"] .yb-row-btn--danger:hover {
    background: rgba(255, 92, 74, 0.22);
    border-color: rgba(255, 92, 74, 0.42);
    color: #ffb7ac;
}

/* Info — quiet cyan-tinted; read-only audit/metadata view (#144). Distinct hue from the
   brand-indigo Edit and the red Delete so the three row actions stay visually separable. */
.yb-row-btn--info {
    color: #0b6b78;
    background: rgba(14, 116, 144, 0.09);
    border-color: rgba(14, 116, 144, 0.20);
}

.yb-row-btn--info:hover {
    background: rgba(14, 116, 144, 0.15);
    border-color: rgba(14, 116, 144, 0.34);
    color: #0b5560;
}

[data-theme="dark"] .yb-row-btn--info {
    color: #7fd7e3;
    background: rgba(34, 197, 214, 0.15);
    border-color: rgba(34, 197, 214, 0.28);
}

[data-theme="dark"] .yb-row-btn--info:hover {
    background: rgba(34, 197, 214, 0.22);
    border-color: rgba(34, 197, 214, 0.42);
    color: #a5e6ef;
}

/* ==================== 8. SHARED STATES + MOTION ==================== */
/* Unified empty / info / warning result states */
.search-container ~ * .alert,
.yb-results-summary + .alert {
    border-radius: var(--yb-radius);
}

/* Gentle staggered reveal for primary content surfaces on load */
@media (prefers-reduced-motion: no-preference) {
    .dashboard-card,
    .analytics-kpi-card.card,
    .search-container {
        animation: ybFadeUp 0.4s var(--yb-ease) both;
    }

    .dashboard-cards > *:nth-child(2) .dashboard-card { animation-delay: 0.04s; }
    .dashboard-cards > *:nth-child(3) .dashboard-card { animation-delay: 0.08s; }
    .dashboard-cards > *:nth-child(4) .dashboard-card { animation-delay: 0.12s; }
    .dashboard-cards > *:nth-child(5) .dashboard-card { animation-delay: 0.16s; }
}

@keyframes ybFadeUp {
    from {
        opacity: 0;
        transform: translateY(10px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* ===================================================================
   9. Add / Edit form pages — scoped to .yb-form-page ONLY.
   IMPORTANT: .center-form-container is the GLOBAL layout shell (MainLayout
   wraps every routed page in it), so it must NOT be styled here. The seven
   Actions/*AddEdit pages carry an extra .yb-form-page hook for this polish.
   Tokens auto-adapt to dark mode, so no theme-specific overrides needed.
   =================================================================== */

/* Contain the form into a centered column (base .center-form-container is
   width:100%, which sprawls edge-to-edge on wide screens) */
.yb-form-page {
    max-width: 780px;
    margin-inline: auto;
}

/* The SfDataForm <form> becomes the primary card surface (one form per page) */
.yb-form-page form {
    text-align: left;
    margin-top: 0.6rem;
    padding: clamp(1rem, 0.7rem + 1vw, 1.5rem);
    background: var(--yb-surface);
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-lg);
    box-shadow: var(--yb-shadow-sm);
}

/* Each field is wrapped in .e-label-position-top (label + control). Put the
   EQUAL separation between groups here — every field, template or LabelText,
   uses this same wrapper, so the rhythm is uniform. */
.yb-form-page .e-label-position-top {
    margin: 0 0 0.4rem;
}

/* The label hugs its own control (tight proximity → they read as one unit).
   The DataForm grid inherits an oversized line-height (36px) onto labels, which
   is what floats them away from their control — pin it to a tight value.
   Dark-mode-safe color (!important beats site.css's hardcoded color:black). */
.yb-form-page .e-label-position-top > label {
    display: block;
    margin: 0 0 0.2rem;
    line-height: 1.25;
    color: var(--yb-text-muted) !important;
    font-weight: 600;
    font-size: 0.84rem;
    letter-spacing: 0.01em;
}

/* Strip any default margin on the control itself so the only vertical gaps are
   the two above (label→control, and group→group). */
.yb-form-page .e-label-position-top > .e-input-group {
    margin-top: 0;
    margin-bottom: 0;
}

/* Footer action row: a hairline-separated zone, right-aligned with even spacing,
   so Save / Clear / Back read as a distinct action bar under the fields. */
.yb-form-page .e-button-right {
    display: flex;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 1rem;
    padding-top: 0.9rem;
    border-top: 1px solid var(--yb-border);
}

/* Action buttons — one filled primary (Save) + quiet ghost secondaries (Clear /
   Back), replacing the loud Bootstrap primary / warning / info trio that clashed
   with the design language. Bootstrap 5.1 → override colour props directly. */
.yb-form-page .btn {
    border-radius: var(--yb-radius-sm);
    margin-right: 0;
    font-weight: 600;
    font-size: 0.88rem;
    padding: 0.44rem 1.1rem;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    transition: background-color var(--yb-dur) var(--yb-ease),
                border-color var(--yb-dur) var(--yb-ease),
                color var(--yb-dur) var(--yb-ease),
                box-shadow var(--yb-dur) var(--yb-ease),
                transform var(--yb-dur) var(--yb-ease);
}

.yb-form-page .btn:hover { transform: translateY(-1px); }
.yb-form-page .btn:active { transform: translateY(0); }

/* Save — primary brand fill */
.yb-form-page .btn-primary {
    color: #fff;
    background-color: var(--yb-brand-600);
    border-color: var(--yb-brand-600);
    box-shadow: var(--yb-shadow-xs);
}

.yb-form-page .btn-primary:hover,
.yb-form-page .btn-primary:focus {
    color: #fff;
    background-color: var(--yb-brand-700);
    border-color: var(--yb-brand-700);
    box-shadow: var(--yb-shadow-sm);
}

/* Clear & Back — quiet ghost secondaries */
.yb-form-page .btn-warning,
.yb-form-page .btn-info {
    color: var(--yb-text-muted);
    background-color: var(--yb-surface);
    border-color: var(--yb-border-strong);
    box-shadow: none;
}

.yb-form-page .btn-info:hover,
.yb-form-page .btn-info:focus {
    color: var(--yb-text);
    background-color: var(--yb-surface-2);
    border-color: var(--yb-border-strong);
}

/* Clear is a reset — a faint amber tint on hover hints at "discard" without a loud fill. */
.yb-form-page .btn-warning:hover,
.yb-form-page .btn-warning:focus {
    color: #8a5d00;
    background-color: rgba(217, 119, 6, 0.08);
    border-color: rgba(217, 119, 6, 0.4);
}

[data-theme="dark"] .yb-form-page .btn-warning:hover,
[data-theme="dark"] .yb-form-page .btn-warning:focus {
    color: #f0a23b;
    background-color: rgba(240, 162, 59, 0.12);
    border-color: rgba(240, 162, 59, 0.4);
}

/* ===================================================================
   9b. FIELD VALIDATION MESSAGES — one tokenized, dark-aware treatment (#120)
   Blazor <ValidationMessage> and <ValidationSummary> both emit .validation-message
   (summaries wrap them in .validation-errors); this brings them onto --yb-danger
   with a dark variant. (Syncfusion DataForm's own .e-data-form .validation-message
   is retinted in site.css.) Presentation only — no change to what is validated.
   =================================================================== */
/* Standalone per-field message (rendered under an input by <ValidationMessage> or
   Syncfusion) — quiet inline red text. */
.validation-message {
    color: var(--yb-danger);
    font-size: 0.8rem;
    font-weight: 500;
    font-style: normal;
}

[data-theme="dark"] .validation-message {
    color: #ff9c8f;
}

/* Validation SUMMARY (<ValidationSummary> → ul.validation-errors > li.validation-message).
   Was a flat, centre-inheriting bullet list — bullet stranded at the card edge, text
   drifting far from it. Rework it into a designed danger callout: a tinted panel with a
   left accent rail, a directive label, and tight error rows whose marker hugs the text. */
.validation-errors:empty { display: none; }   /* no empty red box when the form is valid */

.validation-errors {
    list-style: none;
    text-align: left;
    margin: 0.5rem 0 1rem;
    padding: 0.7rem 0.9rem 0.75rem;
    background: rgba(var(--yb-danger-rgb), 0.07);
    border: 1px solid rgba(var(--yb-danger-rgb), 0.22);
    border-left: 3px solid var(--yb-danger);
    border-radius: var(--yb-radius);
    box-shadow: var(--yb-shadow-xs);
}

/* Directive label so the block reads as a prompt to act, not loose red text. */
.validation-errors::before {
    content: "Please fix the following";
    display: block;
    margin-bottom: 0.4rem;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--yb-danger);
}

.validation-errors .validation-message,
.validation-errors li {
    position: relative;
    list-style: none;
    margin: 0.12rem 0;
    padding-left: 1.05rem;
    color: var(--yb-danger);
    font-size: 0.84rem;
    font-weight: 500;
    line-height: 1.5;
}

/* Marker sits right beside its text (replaces the stranded default disc). */
.validation-errors .validation-message::before,
.validation-errors li::before {
    content: "";
    position: absolute;
    left: 0.15rem;
    top: 0.72em;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--yb-danger);
    transform: translateY(-50%);
}

[data-theme="dark"] .validation-errors {
    background: rgba(var(--yb-danger-rgb), 0.14);
    border-color: rgba(var(--yb-danger-rgb), 0.32);
    border-left-color: #ff9c8f;
}

[data-theme="dark"] .validation-errors::before,
[data-theme="dark"] .validation-errors .validation-message,
[data-theme="dark"] .validation-errors li {
    color: #ff9c8f;
}

[data-theme="dark"] .validation-errors .validation-message::before,
[data-theme="dark"] .validation-errors li::before {
    background: #ff9c8f;
}

/* ===================================================================
   9c. BOOTSTRAP ALERTS — dark-mode theming (app-wide)
   Bootstrap's .alert-* variants ship no dark treatment, so every raw alert
   (~80 across the app incl. YbStatusMessage toasts) rendered as a light/cream
   box on the dark surface. Retint them to soft token-based panels. Light mode
   is untouched (these rules are dark-scoped only).
   =================================================================== */
[data-theme="dark"] .alert-info {
    color: #8fbcff;
    background-color: rgba(var(--yb-accent-rgb), 0.13);
    border-color: rgba(var(--yb-accent-rgb), 0.30);
}

[data-theme="dark"] .alert-success {
    color: #62d39b;
    background-color: rgba(var(--yb-success-rgb), 0.14);
    border-color: rgba(var(--yb-success-rgb), 0.32);
}

[data-theme="dark"] .alert-warning {
    color: #f0b02f;
    background-color: rgba(var(--yb-warning-rgb), 0.14);
    border-color: rgba(var(--yb-warning-rgb), 0.32);
}

[data-theme="dark"] .alert-danger {
    color: #ff9c8f;
    background-color: rgba(var(--yb-danger-rgb), 0.13);
    border-color: rgba(var(--yb-danger-rgb), 0.30);
}

[data-theme="dark"] .alert-secondary {
    color: var(--yb-text-muted);
    background-color: var(--yb-surface-2);
    border-color: var(--yb-border-strong);
}

/* Links inside alerts follow the panel's text tone. */
[data-theme="dark"] .alert-info .alert-link { color: #b3d3ff; }
[data-theme="dark"] .alert-success .alert-link { color: #8ee6b8; }
[data-theme="dark"] .alert-warning .alert-link { color: #f7c65a; }
[data-theme="dark"] .alert-danger .alert-link { color: #ffb7ac; }

/* Dismiss (×) button is a dark SVG by default — invert it so it's visible on
   the dark alert (Bootstrap's own fix is .btn-close-white, which these lack). */
[data-theme="dark"] .alert .btn-close {
    filter: invert(1) grayscale(1) brightness(1.6);
}

/* ===================================================================
   10. SETTINGS PAGE — scoped to .yb-settings-page
   Config-settings management: toolbar, group nav, setting cards,
   inheritance panel, custom-setting dialog. Visual only — the RBAC
   gating (Edit / Save / Clear-override / Add disabled states) is
   untouched; tokens auto-adapt to dark mode.
   =================================================================== */

/* Full-width settings page: toolbar + content share the page's full measure
   (was a centered 1180px column that wasted space on large/4K screens). */
.yb-settings-page {
    max-width: none;
    margin-inline: 0;
}

/* The toolbar reuses .search-container chrome; tighten its inner rhythm and
   keep it full-width inside the already-centered page wrapper. */
.yb-settings-toolbar.search-container {
    max-width: none;
}

/* Branded segmented control for the Effective / Available scope filter
   (replaces the btn-primary / btn-outline-secondary pair). */
.yb-seg {
    display: inline-flex;
    gap: 0.2rem;
    padding: 0.2rem;
    background: var(--yb-surface-sunken);
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-pill);
}

.yb-seg__btn {
    border: none;
    background: transparent;
    color: var(--yb-text-muted);
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    padding: 0.32rem 0.95rem;
    border-radius: var(--yb-radius-pill);
    cursor: pointer;
    transition: background var(--yb-dur) var(--yb-ease), color var(--yb-dur) var(--yb-ease), box-shadow var(--yb-dur) var(--yb-ease);
}

.yb-seg__btn:hover {
    color: var(--yb-text);
}

.yb-seg__btn.is-active {
    background: var(--yb-surface);
    color: var(--yb-accent);
    box-shadow: var(--yb-shadow-xs);
}

[data-theme="dark"] .yb-seg__btn.is-active {
    background: var(--yb-card);
}

/* Inline scope filter (now a field in the toolbar row): stretch to the column
   and read as a proper inset segmented control — the active pill fills its
   half as a tidy rounded rect, not an oversized pill/oval. */
.yb-settings-toolbar .yb-seg {
    display: flex;
    width: 100%;
    align-items: stretch;
    gap: 0.22rem;
    padding: 0.22rem;
    border-radius: var(--yb-radius);
}

.yb-settings-toolbar .yb-seg__btn {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.3rem;
    padding: 0 0.5rem;
    border-radius: var(--yb-radius-sm);
    font-size: 0.78rem;
}

/* Tick on the selected segment — an explicit "this one is chosen" cue beyond
   colour, so the active scope is obvious at a glance. */
.yb-seg__check {
    font-size: 0.85rem;
    line-height: 1;
}

/* Uniform control height — every filter (native <select>/<input>, Syncfusion
   dropdown, segmented control) sits on one horizon in the toolbar row. */
.yb-settings-toolbar .form-control,
.yb-settings-toolbar .input-group,
.yb-settings-toolbar .e-input-group.e-control-wrapper,
.yb-settings-toolbar .yb-seg {
    height: 38px;
    min-height: 38px;
}

.yb-settings-toolbar .input-group .form-control {
    height: auto;
}

.yb-settings-toolbar .e-input-group.e-control-wrapper input.e-input {
    height: 100%;
}

/* Dark mode: the native Bootstrap search <input> stayed white (the Syncfusion
   dropdowns theme themselves). Give it the same surface as the rest. */
[data-theme="dark"] .yb-settings-toolbar .form-control {
    background-color: var(--yb-surface-2);
    color: var(--yb-text);
    border-color: var(--yb-border-strong);
}

/* The branded "Custom" add button (was raw btn-success) */
.yb-settings-toolbar .yb-btn-custom {
    border-radius: var(--yb-radius-sm);
    font-weight: 600;
    border: 1px solid transparent;
    background: linear-gradient(180deg, var(--yb-success), #18895280);
    box-shadow: var(--yb-shadow-xs);
}

/* ── Group navigation list (left rail) ─────────────────────────────── */
.settings-group-list {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    border: none;
    background: transparent;
}

.settings-group-list .settings-group-item {
    min-height: 2.4rem;
    border: 1px solid var(--yb-border) !important;
    border-radius: var(--yb-radius-sm) !important;
    background: var(--yb-surface) !important;
    color: var(--yb-text-muted) !important;
    font-weight: 600;
    position: relative;
    overflow: hidden;
    transition: background-color var(--yb-dur) var(--yb-ease), border-color var(--yb-dur) var(--yb-ease), color var(--yb-dur) var(--yb-ease);
}

.settings-group-list .settings-group-item:hover {
    border-color: var(--yb-border-strong) !important;
    color: var(--yb-text) !important;
    background: var(--yb-surface-2) !important;
}

.settings-group-list .settings-group-item:focus-visible {
    outline: none;
    border-color: rgba(var(--yb-accent-rgb), 0.5) !important;
    box-shadow: var(--yb-ring);
    z-index: 2;
}

/* Active group: accent left bar + accent text + tinted surface */
.settings-group-list .settings-group-active {
    color: var(--yb-accent) !important;
    border-color: rgba(var(--yb-accent-rgb), 0.4) !important;
    background: rgba(var(--yb-accent-rgb), 0.07) !important;
}

.settings-group-list .settings-group-active::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: 3px;
    background: linear-gradient(180deg, var(--yb-accent), var(--yb-brand-400));
}

/* Count pill — branded, replaces bg-secondary */
.settings-group-list .settings-group-count {
    background: var(--yb-surface-sunken) !important;
    color: var(--yb-text-muted) !important;
    font-weight: 700;
    font-size: 0.7rem;
}

.settings-group-list .settings-group-item:hover .settings-group-count,
.settings-group-list .settings-group-active .settings-group-count {
    background: rgba(var(--yb-accent-rgb), 0.16) !important;
    color: var(--yb-accent) !important;
}

/* ── Setting cards ─────────────────────────────────────────────────── */
.yb-settings-page .setting-card {
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius);
    background: var(--yb-surface);
    box-shadow: var(--yb-shadow-xs);
    overflow: hidden;
    transition: box-shadow var(--yb-dur) var(--yb-ease), border-color var(--yb-dur) var(--yb-ease);
}

.yb-settings-page .setting-card:hover {
    border-color: var(--yb-border-strong);
    box-shadow: var(--yb-shadow-sm);
}

.yb-settings-page .setting-card .card-header {
    background: var(--yb-surface-2);
    border-bottom: 1px solid var(--yb-border);
}

.yb-settings-page .setting-card .card-header .fw-semibold {
    color: var(--yb-text);
    font-size: 0.95rem;
}

.yb-settings-page .setting-card code {
    color: var(--yb-brand-500);
    background: rgba(var(--yb-accent-rgb), 0.07);
    padding: 0.05rem 0.35rem;
    border-radius: var(--yb-radius-sm);
    font-size: 0.78rem;
}

[data-theme="dark"] .yb-settings-page .setting-card code {
    color: var(--yb-brand-400);
}

.yb-settings-page .setting-card .card-header .btn {
    border-radius: var(--yb-radius-sm);
    font-size: 0.78rem;
}

/* ── Collapsible header (default collapsed for density) ─────────────── */
.yb-settings-page .setting-card__header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    cursor: pointer;
    user-select: none;
}

/* Collapsed cards drop the header divider so they read as a single row */
.yb-settings-page .setting-card.is-collapsed .card-header {
    border-bottom: none;
}

.yb-settings-page .setting-card__headline {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    min-width: 0;
    flex: 0 1 auto;
}

.yb-settings-page .setting-card__name {
    color: var(--yb-text);
    font-size: 0.95rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.yb-settings-page .setting-card__chevron {
    flex: 0 0 auto;
    color: var(--yb-text-soft);
    font-size: 0.8rem;
    transition: transform var(--yb-dur) var(--yb-ease), color var(--yb-dur) var(--yb-ease);
}

.yb-settings-page .setting-card__chevron.is-open {
    transform: rotate(90deg);
}

.yb-settings-page .setting-card__header:hover .setting-card__chevron {
    color: var(--yb-accent);
}

.yb-settings-page .setting-card__header:focus-visible {
    outline: 2px solid rgba(var(--yb-accent-rgb), 0.5);
    outline-offset: -2px;
}

/* Collapsed peek — "Effective: value" flows inline after the name (left
   aligned, not centered); actions stay pushed right. Neutral (not blue). */
.yb-settings-page .setting-card__peek {
    flex: 0 1 auto;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    min-width: 0;
}

/* Accent ⚡ label — mirrors the expanded hero's "Effective" so collapsed and
   expanded read the same; the colour also lifts the row out of flatness. */
.yb-settings-page .setting-card__peek-eff {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--yb-accent);
    white-space: nowrap;
}

/* Plain bold mono value (no pill) — reads right for a single "8" as well as a
   long string; matches the expanded hero's value treatment. */
.yb-settings-page .setting-card code.setting-card__peek-value {
    max-width: 22ch;
    padding: 0;
    border: none;
    background: transparent;
    box-shadow: none;
    color: var(--yb-text);
    font-weight: 700;
    font-size: 0.9rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.yb-settings-page .setting-card__peek-source {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    color: var(--yb-text-muted);
    font-size: 0.78rem;
    white-space: nowrap;
}

.yb-settings-page .setting-card__peek-empty {
    color: var(--yb-text-soft);
    font-style: italic;
    font-size: 0.8rem;
}

.yb-settings-page .setting-card__actions {
    flex: 0 0 auto;
    margin-left: auto;
}

/* Meta row — three typed chips (identifier · data type · category). Borders,
   a surface fill, a micro-shadow and leading glyphs give them dimension
   instead of the old flat, dotted text. */
.yb-settings-page .setting-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
}

.yb-settings-page .setting-meta__chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.12rem 0.55rem;
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-pill);
    background: var(--yb-surface);
    box-shadow: var(--yb-shadow-xs);
    font-size: 0.74rem;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
    color: var(--yb-text-muted);
}

.yb-settings-page .setting-meta__chip i {
    font-size: 0.78rem;
}

/* Identifier chip — monospace, brand-tinted. Extra specificity (.setting-card
   code.…) so it wins over the generic `.setting-card code` rule above. */
.yb-settings-page .setting-card code.setting-meta__code {
    display: inline-flex;
    align-items: center;
    padding: 0.12rem 0.55rem;
    border: 1px solid rgba(var(--yb-accent-rgb), 0.18);
    border-radius: var(--yb-radius-pill);
    background: rgba(var(--yb-accent-rgb), 0.06);
    box-shadow: var(--yb-shadow-xs);
    color: var(--yb-brand-500);
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: 0.02em;
}

[data-theme="dark"] .yb-settings-page .setting-card code.setting-meta__code {
    color: var(--yb-brand-400);
}

/* Data-type chip — teal glyph reads as "this is the value's type" */
.yb-settings-page .setting-meta__chip--type i {
    color: var(--yb-info);
}

/* Category chip — quiet neutral tag glyph */
.yb-settings-page .setting-meta__chip--cat i {
    color: var(--yb-text-soft);
}

.yb-settings-page .setting-desc {
    line-height: 1.45;
}

/* Effective value — full-width accent hero band so the live value pops */
.yb-settings-page .setting-effective {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.55rem;
    padding: 0.55rem 0.8rem;
    border: 1px solid var(--yb-border);
    border-left: 3px solid var(--yb-accent);
    border-radius: var(--yb-radius-sm);
    /* Accent lives in the left edge + label + source pill — the band itself is
       a calm wash so the value is the hero (and it doesn't slab over in dark). */
    background: rgba(var(--yb-accent-rgb), 0.05);
}

[data-theme="dark"] .yb-settings-page .setting-effective {
    background: var(--yb-surface-sunken);
    border-color: var(--yb-border);
    border-left-color: var(--yb-accent);
}

.yb-settings-page .setting-effective__label {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--yb-accent);
    white-space: nowrap;
}

.yb-settings-page .setting-effective__value {
    flex: 1 1 auto;
    min-width: 0;
    max-width: 100%;
    color: var(--yb-text);
    background: transparent;
    padding: 0;
    font-weight: 700;
    font-size: 0.95rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: help;
}

.yb-settings-page .setting-effective__source {
    flex: 0 0 auto;
    margin-left: auto;
    padding: 0.12rem 0.55rem;
    border-radius: var(--yb-radius-pill);
    background: rgba(var(--yb-accent-rgb), 0.14);
    color: var(--yb-accent);
    font-size: 0.72rem;
    font-weight: 600;
    white-space: nowrap;
}

.yb-settings-page .setting-effective__empty {
    color: var(--yb-text-soft);
    font-style: italic;
}

/* ── Collapsible group sections (YbCollapsibleCard, scoped) ────────── */
.yb-settings-section > .card {
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius);
    background: var(--yb-surface);
    box-shadow: var(--yb-shadow-xs);
    margin-bottom: 0.75rem !important;
}

.yb-settings-section > .card > .card-header {
    background: var(--yb-surface-2);
    border-bottom: 1px solid var(--yb-border);
    border-radius: var(--yb-radius) var(--yb-radius) 0 0;
}

.yb-settings-section > .card > .card-header .fw-semibold {
    color: var(--yb-text);
    font-size: 0.95rem;
}

.yb-settings-section > .card > .card-header .badge {
    background: rgba(var(--yb-accent-rgb), 0.14) !important;
    color: var(--yb-accent) !important;
    font-weight: 700;
}

/* ── Inheritance cascade (Product → Organisation → Branch) ─────────── */
.yb-settings-page .inheritance-cascade__label {
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--yb-text-soft);
    margin-bottom: 0.35rem;
}

/* Three equal scope nodes separated by flow arrows */
.yb-settings-page .inheritance-cascade__track {
    display: grid;
    grid-template-columns: 1fr auto 1fr auto 1fr;
    align-items: stretch;
    gap: 0.3rem;
}

.yb-settings-page .cascade-node {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    min-width: 0;
    padding: 0.5rem 0.65rem;
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-sm);
    background: var(--yb-surface-2);
    transition: border-color var(--yb-dur) var(--yb-ease), background var(--yb-dur) var(--yb-ease);
}

/* Inherited (no own record) flows down from above — a distinct dashed VIOLET
   node so it never gets mistaken for the accent-blue scope that actually wins. */
.yb-settings-page .cascade-node.is-inherited {
    border-style: dashed;
    border-width: 1.5px;
    border-color: rgba(var(--yb-inherit-rgb), 0.55);
    background: rgba(var(--yb-inherit-rgb), 0.07);
}

.yb-settings-page .cascade-node.is-inherited .cascade-node__scope {
    color: var(--yb-inherit);
}

.yb-settings-page .cascade-node.is-inherited .cascade-node__value.is-inherited-text {
    color: var(--yb-inherit);
    opacity: 0.9;
}

[data-theme="dark"] .yb-settings-page .cascade-node.is-inherited {
    border-color: rgba(var(--yb-inherit-rgb), 0.5);
    background: rgba(var(--yb-inherit-rgb), 0.12);
}

/* The scope that actually wins — accent frame + tint + ring */
.yb-settings-page .cascade-node.is-effective {
    border-color: rgba(var(--yb-accent-rgb), 0.5);
    background: rgba(var(--yb-accent-rgb), 0.08);
    box-shadow: 0 0 0 1px rgba(var(--yb-accent-rgb), 0.25) inset;
}

[data-theme="dark"] .yb-settings-page .cascade-node.is-effective {
    background: rgba(var(--yb-accent-rgb), 0.14);
}

.yb-settings-page .cascade-node__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.35rem;
}

.yb-settings-page .cascade-node__scope {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    color: var(--yb-text-muted);
    white-space: nowrap;
}

.yb-settings-page .cascade-node.is-effective .cascade-node__scope {
    color: var(--yb-accent);
}

.yb-settings-page .cascade-node__flag {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    font-size: 0.64rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--yb-accent);
    white-space: nowrap;
}

.yb-settings-page .cascade-node__flag--off {
    color: var(--yb-warning);
}

.yb-settings-page .cascade-node__value {
    min-width: 0;
    font-weight: 600;
    font-size: 0.85rem;
    color: var(--yb-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: help;
}

.yb-settings-page .cascade-node__value.is-inherited-text {
    color: var(--yb-text-soft);
    font-style: italic;
    font-weight: 500;
    cursor: default;
}

.yb-settings-page .cascade-node.is-inactive .cascade-node__value {
    text-decoration: line-through;
    color: var(--yb-text-soft);
}

/* Flow arrows between the scope nodes */
.yb-settings-page .inheritance-cascade__arrow {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--yb-text-soft);
    font-size: 0.9rem;
}

/* Stack vertically on narrow screens; arrows rotate to point downward */
@media (max-width: 575.98px) {
    .yb-settings-page .inheritance-cascade__track {
        grid-template-columns: 1fr;
    }

    .yb-settings-page .inheritance-cascade__arrow {
        transform: rotate(90deg);
        height: 1.1rem;
    }
}

/* ── Awaiting-context info banner ──────────────────────────────────── */
.settings-context-info {
    border: 1px solid rgba(var(--yb-accent-rgb), 0.3);
    border-radius: var(--yb-radius);
    background: rgba(var(--yb-accent-rgb), 0.06);
    color: var(--yb-text);
}

.settings-context-info i {
    color: var(--yb-accent);
}

/* ── Empty / loading states ────────────────────────────────────────── */
.yb-settings-empty {
    background: var(--yb-surface-2);
    border: 1px dashed var(--yb-border-strong);
    border-radius: var(--yb-radius);
    color: var(--yb-text-muted);
    padding: 2.25rem 1rem;
}

.yb-settings-empty .bi {
    color: var(--yb-text-soft);
}

/* ── Custom-setting dialog ─────────────────────────────────────────── */
.yb-settings-dialog .form-label {
    color: var(--yb-text-muted);
    font-weight: 600;
    font-size: 0.84rem;
    letter-spacing: 0.01em;
}

/* The auto-generated code field uses bg-light, which is invisible in dark
   mode — give it a token surface that reads in both themes. */
.yb-settings-dialog .form-control.bg-light {
    background: var(--yb-surface-sunken) !important;
    border-color: var(--yb-border-strong);
    color: var(--yb-text);
    border-radius: var(--yb-radius-sm);
}

/* ===================================================================
   11. ASSIGN / DEVICE-MAPPING PAGES — scoped to .yb-assign-page
   The Reader & Wearable assignment screens (/assign-reader,
   /assign-wearable) carry a .yb-assign-page wrapper. This brings their
   raw Bootstrap cards, form rows, Syncfusion inputs and action row into
   the shared token language. Dark mode rides on the tokens, plus a few
   explicit fixes for Bootstrap utility classes that aren't theme-aware
   (.bg-light / .text-dark / .text-primary). Visual only.
   =================================================================== */

/* Panel + mapping cards → elevated token surface (beats .border-0 / .shadow-sm) */
.yb-assign-page .card {
    background: var(--yb-surface);
    border: 1px solid var(--yb-border) !important;
    border-radius: var(--yb-radius-lg);
    box-shadow: var(--yb-shadow-sm) !important;
    transition: transform var(--yb-dur) var(--yb-ease), box-shadow var(--yb-dur) var(--yb-ease), border-color var(--yb-dur) var(--yb-ease);
}

.yb-assign-page .card:hover {
    box-shadow: var(--yb-shadow-md) !important;
    border-color: rgba(var(--yb-accent-rgb), 0.25) !important;
}

[data-theme="dark"] .yb-assign-page .card {
    background: var(--yb-card);
}

/* Card section heading — centered, branded, with a short accent underline */
.yb-assign-page .yb-assign-card__title {
    position: relative;
    margin-bottom: 1rem;
    padding-bottom: 0.55rem;
    text-align: center;
    font-size: 0.98rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    color: var(--yb-text);
}

.yb-assign-page .yb-assign-card__title::after {
    content: "";
    position: absolute;
    left: 50%;
    bottom: 0;
    transform: translateX(-50%);
    width: 38px;
    height: 2px;
    border-radius: 2px;
    background: linear-gradient(90deg, var(--yb-accent), var(--yb-brand-400));
}

/* Mapping-row labels — calm muted weight (beats Bootstrap .text-primary) */
.yb-assign-page .col-form-label {
    color: var(--yb-text-muted) !important;
    font-weight: 600;
    font-size: 0.86rem;
    letter-spacing: 0.01em;
}

/* Syncfusion inputs — same rounded, focus-ring look as the search panels */
.yb-assign-page .e-input-group,
.yb-assign-page .e-input-group.e-control-wrapper,
.yb-assign-page .e-ddl.e-input-group {
    border-radius: var(--yb-radius-sm);
    border-color: var(--yb-border-strong);
    overflow: hidden;
    transition: border-color var(--yb-dur) var(--yb-ease), box-shadow var(--yb-dur) var(--yb-ease);
}

.yb-assign-page .e-input-group input.e-input,
.yb-assign-page .e-input-group .e-input {
    border-radius: inherit;
    background: transparent;
}

.yb-assign-page .e-input-group.e-input-focus {
    border-color: rgba(var(--yb-accent-rgb), 0.55);
    box-shadow: var(--yb-ring);
}

/* Read-only (disabled) inputs read as sunken so they're clearly not editable */
.yb-assign-page .e-input-group.e-disabled {
    background: var(--yb-surface-sunken);
}

/* YbInfoView nested inside a panel card: flatten its own frame so surfaces
   don't stack three deep — the panel card is the surface and the field tiles
   (.dashboard-card, already tokenized in §4) are the inner cards. This also
   undoes the dark-mode-broken .bg-light / .text-dark utilities on its wrapper. */
.yb-assign-page .row.justify-content-center > .border.bg-light {
    background: transparent !important;
    border: 0 !important;
    box-shadow: none !important;
    padding: 0 !important;
    color: var(--yb-text) !important;
}

.yb-assign-page .bg-light.text-dark {
    color: var(--yb-text) !important;
}

/* Compact "fact" tiles inside the nested YbInfoView — mirror the density of the
   safety-alert .sa-fact cards (stacked label + value, left accent bar, small
   radius) so the Location / Reader panels stay short and free up vertical
   space, instead of the tall centered fs-5/py-4 tiles. */
.yb-assign-page .row.g-4 {
    --bs-gutter-x: 0.5rem;
    --bs-gutter-y: 0.5rem;
}

/* One info tile per row inside the Location / Reader panels (was 2-up col-md-6).
   These panels live in a narrow ~⅓-width column now, so a single column reads
   cleanly and each fact stays on one short line. */
.yb-assign-page .row.g-4 > [class*="col-"] {
    flex: 0 0 100%;
    max-width: 100%;
}

/* Info tiles rendered by YbInfoView (device / location / entity facts). They use their
   OWN class (.yb-info-tile), NOT .dashboard-card, so they stay visually independent from
   the KPI dashboard cards (which keep their own top-rail hover). Compact sa-fact-style
   fact tiles with a left accent rail that brightens on hover. */
.yb-assign-page .yb-info-tile {
    position: relative;
    background: var(--yb-card);
    color: var(--yb-text);
    border: 1px solid var(--yb-border);
    border-left: 3px solid rgba(var(--yb-accent-rgb), 0.5);
    border-radius: var(--yb-radius-sm);
    box-shadow: var(--yb-shadow-sm);
    padding: 0.4rem 0.65rem 0.5rem;
    text-align: left;
    transition: border-color var(--yb-dur) var(--yb-ease), box-shadow var(--yb-dur) var(--yb-ease);
}

/* Read-only tiles — no lift, but the left rail brightens and the shadow lifts on hover. */
.yb-assign-page .yb-info-tile:hover {
    border-left-color: var(--yb-accent);
    box-shadow: var(--yb-shadow-md);
}

/* Label: static block on top, tiny uppercase (was an absolute corner badge) */
.yb-assign-page .yb-info-tile > .position-absolute {
    position: static !important;
    padding: 0 !important;
    background: transparent;
    color: var(--yb-text-soft);
    font-size: 0.62rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    line-height: 1.3;
    margin-bottom: 0.1rem;
}

/* Value: left-aligned, calm weight (was centered, fs-5, py-4) */
.yb-assign-page .yb-info-tile > .d-flex {
    display: block !important;
    height: auto !important;
    padding: 0 !important;
    font-size: 0.9rem !important;
    font-weight: 600 !important;
    text-align: left;
}

/* Three columns side-by-side (Location/Reader + Mapping) read as one screen.
   Equal-height cards via .h-100 on the card so the row tops/bottoms line up. */
.yb-assign-page .yb-assign-grid > [class*="col-"] {
    margin-bottom: 0;
}

/* Mapping card: stacked label-over-control fields (the column is too narrow for
   the old col-sm-2 / col-sm-10 horizontal split). All card content is left-aligned;
   only the action buttons (.yb-assign-form-actions) are pushed to the right. */
.yb-assign-page .yb-assign-grid .card {
    text-align: left;
}

.yb-assign-page .yb-assign-field {
    margin-bottom: 0.7rem;
}

.yb-assign-page .yb-assign-field__label {
    display: block;
    margin-bottom: 0.25rem;
    color: var(--yb-text-muted);
    font-weight: 600;
    font-size: 0.84rem;
    letter-spacing: 0.01em;
}

/* Read-only mapping fields read as plain values (not disabled input boxes):
   a quiet underline echoes the form-field baseline without the input chrome. */
.yb-assign-page .yb-assign-field__value {
    display: block;
    color: var(--yb-text);
    font-weight: 600;
    font-size: 0.92rem;
    line-height: 1.45;
    word-break: break-word;
    padding: 0.1rem 0 0.4rem;
    border-bottom: 1px solid var(--yb-border);
}

/* Action row — a clear commit zone: divider above, right-aligned, rounded btns */
.yb-assign-page .yb-assign-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    align-items: center;
    gap: 0.5rem;
    margin-top: 1.25rem;
    padding-top: 1rem;
    border-top: 1px solid var(--yb-border);
}

.yb-assign-page .btn {
    border-radius: var(--yb-radius-sm);
}

/* The primary "Assign" button now lives at the foot of the Mapping card (mirrors
   the Save button at the bottom of the add/edit form). A hairline sets it apart
   from the fields above. */
.yb-assign-page .yb-assign-form-actions {
    margin-top: 1rem;
    padding-top: 0.85rem;
    border-top: 1px solid var(--yb-border);
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 0.5rem;
}

.yb-assign-page .yb-assign-status {
    margin-top: 0.75rem;
    text-align: center;
}

/* Allocation-availability pill inside the Reader/Wearable + Location/Entity
   dropdowns. NOTE: the Syncfusion dropdown popup (.e-ddl.e-popup) is rendered at
   <body> level, OUTSIDE the .yb-assign-page wrapper — so these rules MUST stay
   global (unscoped) or the item template silently loses its styling. */
/* Force our templated list rows to left-align and vertically centre regardless of
   any inherited centring on .e-list-item, and let them grow for the 2-line rows. */
.e-dropdownbase .e-list-item:has(.yb-ddl-item) {
    display: flex;
    align-items: center;
    text-align: left;
    height: auto;
    line-height: 1.3;
    padding-top: 0.34rem;
    padding-bottom: 0.34rem;
}

.yb-ddl-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    width: 100%;
    text-align: left;
}

.yb-ddl-item__text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    gap: 0.12rem;
}

.yb-ddl-item__main {
    display: flex;
    align-items: baseline;
    gap: 0.45rem;
    min-width: 0;
}

/* NOTE: the SfDropDownList popup always uses the LIGHT Syncfusion theme (only
   bootstrap5.css is loaded; the .e-list-item popup is not dark-styled anywhere), even
   when the app is in dark mode. So these item styles must use fixed light-surface
   colours — NOT the theme-flipping --yb-* vars, which turn light text invisible on the
   light popup. Do not add [data-theme="dark"] overrides here. */

/* MAC id: monospace, quiet, in a subtle chip so it reads as an identifier, not a name. */
.yb-ddl-mac {
    flex: 0 0 auto;
    font-family: ui-monospace, SFMono-Regular, "Cascadia Code", Menlo, Consolas, monospace;
    font-size: 0.76rem;
    color: #475569;
    background: #f1f5f9;
    border: 1px solid #e2e8f0;
    border-radius: 0.3rem;
    padding: 0.04rem 0.34rem;
}

/* Assigned name / entity label: the human-readable primary text. Inherit the popup's
   own (dark-on-light) item colour so it stays readable in both app themes. */
.yb-ddl-name {
    font-weight: 600;
    color: inherit;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Cross-reference sub-line ("→ who/where it is mapped to"): smaller, blue-tinted,
   with a leading glyph so it reads as a relationship, not part of the name. */
.yb-ddl-item__sub {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.72rem;
    color: #2563eb;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.yb-ddl-item__sub i {
    font-size: 0.74rem;
    opacity: 0.85;
}

/* Inactive-device flag inside the dropdown row (popup is light-only — fixed colours). */
.yb-ddl-devstatus {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    font-size: 0.68rem;
    font-weight: 600;
    color: #b91c1c;
    background: rgba(239, 68, 68, 0.12);
    border: 1px solid rgba(239, 68, 68, 0.3);
    border-radius: 999px;
    padding: 0.02rem 0.4rem;
}

/* Selected-device status badge on the assign-page device card (in-page → theme-aware). */
.yb-assign-page .yb-device-status {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0.55rem 0 0.1rem;
    font-size: 0.82rem;
    font-weight: 600;
    padding: 0.28rem 0.65rem;
    border-radius: 999px;
    border: 1px solid transparent;
}

.yb-assign-page .yb-device-status--ok {
    color: #15803d;
    background: rgba(34, 197, 94, 0.12);
    border-color: rgba(34, 197, 94, 0.3);
}

.yb-assign-page .yb-device-status--danger {
    color: #b91c1c;
    background: rgba(239, 68, 68, 0.12);
    border-color: rgba(239, 68, 68, 0.35);
}

[data-theme="dark"] .yb-assign-page .yb-device-status--ok {
    color: #4ade80;
    background: rgba(34, 197, 94, 0.16);
    border-color: rgba(34, 197, 94, 0.36);
}

[data-theme="dark"] .yb-assign-page .yb-device-status--danger {
    color: #f87171;
    background: rgba(239, 68, 68, 0.18);
    border-color: rgba(239, 68, 68, 0.4);
}

.yb-alloc-pill {
    flex: 0 0 auto;
    font-size: 0.7rem;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.02em;
    padding: 0.2rem 0.5rem;
    border-radius: 999px;
    border: 1px solid transparent;
}

.yb-alloc-pill--available {
    color: #15803d;
    background: rgba(34, 197, 94, 0.14);
    border-color: rgba(34, 197, 94, 0.35);
}

.yb-alloc-pill--assigned {
    color: #b45309;
    background: rgba(245, 158, 11, 0.14);
    border-color: rgba(245, 158, 11, 0.38);
}

/* ==================== 12. GROUP LOOKUPS (reference browser) ====================
   A read-only reference of seed-controlled config: item groups are the navigation
   (left rail), each group's lookup values read like a small data dictionary on the
   right. Token-based, so it adapts to dark mode without overrides. */
.yb-group-lookups {
    max-width: 1080px;
    margin: 0 auto;
}

/* Refresh lives in the values toolbar (after the sort select) as a square icon button
   matching the filter/sort control height. It's a hard refresh — force-reloads groups
   and values from the server, bypassing the cache. */
.yb-gl-refresh {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.15rem;
    height: 2.15rem;
    color: var(--yb-text-muted);
    background: var(--yb-card);
    border: 1px solid var(--yb-border-strong);
    border-radius: var(--yb-radius-sm);
    cursor: pointer;
    transition: color var(--yb-dur) var(--yb-ease), border-color var(--yb-dur) var(--yb-ease), background var(--yb-dur) var(--yb-ease);
}

.yb-gl-refresh:hover:not(:disabled) {
    color: var(--yb-accent);
    border-color: rgba(var(--yb-accent-rgb), 0.5);
    background: rgba(var(--yb-accent-rgb), 0.06);
}

.yb-gl-refresh:focus-visible {
    outline: none;
    border-color: rgba(var(--yb-accent-rgb), 0.55);
    box-shadow: var(--yb-ring);
}

.yb-gl-refresh:disabled {
    opacity: 0.6;
    cursor: default;
}

.yb-spin {
    display: inline-block;
    animation: yb-spin 0.8s linear infinite;
}

@keyframes yb-spin {
    to { transform: rotate(360deg); }
}

/* ONE surface: the rail and the value panel live inside a single bordered card,
   divided by a hairline — so the screen reads as one page, not two floating sections.
   The card's height is locked to the viewport; the rail list and the values list each
   scroll independently inside it. */
.yb-gl-body {
    display: flex;
    align-items: stretch;
    margin-top: 0.75rem;
    background: var(--yb-card);
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-lg);
    box-shadow: var(--yb-shadow-sm);
    overflow: hidden;
    height: calc(100vh - 13rem);
    min-height: 360px;
}

/* Left rail — item groups as vertical tabs; divided from the panel by a hairline. */
.yb-gl-rail {
    flex: 0 0 250px;
    display: flex;
    flex-direction: column;
    min-height: 0;
    padding: 0.85rem;
    border-right: 1px solid var(--yb-border);
}

/* Scrollable group list (the filter/sort row above it stays put). */
.yb-gl-raillist {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    margin: 0 -0.35rem;
    padding: 0 0.35rem;
}

.yb-gl-tab {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.6rem;
    width: 100%;
    text-align: left;
    background: transparent;
    border: 1px solid transparent;
    border-left: 3px solid transparent;
    border-radius: var(--yb-radius-sm);
    padding: 0.5rem 0.7rem;
    color: var(--yb-text);
    font-size: 0.9rem;
    font-weight: 500;
    cursor: pointer;
    transition: background var(--yb-dur) var(--yb-ease), border-color var(--yb-dur) var(--yb-ease), color var(--yb-dur) var(--yb-ease);
}

.yb-gl-tab:hover {
    background: rgba(var(--yb-accent-rgb), 0.06);
    border-left-color: rgba(var(--yb-accent-rgb), 0.4);
}

.yb-gl-tab.is-active {
    background: rgba(var(--yb-accent-rgb), 0.1);
    border-color: rgba(var(--yb-accent-rgb), 0.25);
    border-left-color: var(--yb-accent);
    color: var(--yb-accent);
    font-weight: 600;
}

.yb-gl-tab__name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.yb-gl-tab__count {
    flex: 0 0 auto;
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--yb-text-muted);
    background: var(--yb-surface-sunken);
    border-radius: 999px;
    padding: 0.05rem 0.45rem;
    min-width: 1.6rem;
    text-align: center;
}

.yb-gl-tab.is-active .yb-gl-tab__count {
    color: var(--yb-accent);
    background: rgba(var(--yb-accent-rgb), 0.14);
}

/* Right panel — the selected group's values. No own surface; the .yb-gl-body card
   is the surface. Header stays put; the values list scrolls below it. */
.yb-gl-panel {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: 1rem 1.25rem 0;
}

.yb-gl-panel__head {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.6rem;
    row-gap: 0.5rem;
    padding-bottom: 0.6rem;
    margin-bottom: 0;
    border-bottom: 1px solid var(--yb-border);
}

/* Scrollable values area. */
.yb-gl-panelbody {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 0.3rem 0 1rem;
}

/* Filter + sort controls (rail and panel share the input/select styling). */
.yb-gl-railtools {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 0.6rem;
}

.yb-gl-panel__tools {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.yb-gl-panel__tools .yb-gl-search {
    flex: 0 1 200px;
}

.yb-gl-search {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
}

.yb-gl-search > i {
    position: absolute;
    left: 0.55rem;
    top: 50%;
    transform: translateY(-50%);
    font-size: 0.8rem;
    color: var(--yb-text-muted);
    pointer-events: none;
}

/* Filter input and sort select share one fixed control height so they line up. */
.yb-gl-search input {
    width: 100%;
    height: 2.15rem;
    box-sizing: border-box;
    padding: 0 0.5rem 0 1.7rem;
    font-size: 0.85rem;
    color: var(--yb-text);
    background: var(--yb-card);
    border: 1px solid var(--yb-border-strong);
    border-radius: var(--yb-radius-sm);
    transition: border-color var(--yb-dur) var(--yb-ease), box-shadow var(--yb-dur) var(--yb-ease);
}

.yb-gl-search input::placeholder {
    color: var(--yb-text-muted);
}

.yb-gl-sort {
    flex: 0 0 auto;
    height: 2.15rem;
    box-sizing: border-box;
    font-size: 0.82rem;
    color: var(--yb-text);
    background: var(--yb-card);
    border: 1px solid var(--yb-border-strong);
    border-radius: var(--yb-radius-sm);
    padding: 0 0.4rem;
    cursor: pointer;
}

.yb-gl-search input:focus,
.yb-gl-sort:focus {
    outline: none;
    border-color: rgba(var(--yb-accent-rgb), 0.55);
    box-shadow: var(--yb-ring);
}

.yb-gl-norail {
    color: var(--yb-text-muted);
    font-size: 0.82rem;
    font-style: italic;
    padding: 0.4rem 0.2rem;
}

.yb-gl-panel__title {
    font-family: var(--yb-font-display);
    font-size: 1.15rem;
    font-weight: 600;
    margin: 0;
    color: var(--yb-text);
}

.yb-gl-panel__meta {
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--yb-text-muted);
}

/* Values read like a data dictionary: a quiet monospace sequence index + the term. */
.yb-gl-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.yb-gl-row {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    padding: 0.5rem 0.4rem;
    border-bottom: 1px solid var(--yb-border);
}

.yb-gl-row:last-child {
    border-bottom: 0;
}

.yb-gl-row:hover {
    background: rgba(var(--yb-accent-rgb), 0.04);
}

.yb-gl-row__seq {
    flex: 0 0 auto;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.78rem;
    color: var(--yb-text-muted);
    min-width: 1.8rem;
    text-align: right;
}

.yb-gl-row__name {
    font-size: 0.92rem;
    font-weight: 500;
    color: var(--yb-text);
}

.yb-gl-empty {
    color: var(--yb-text-muted);
    font-style: italic;
    padding: 0.6rem 0.4rem;
}

/* Fallback when no groups are loaded at all — a centered card with a Refresh action
   (the toolbar Refresh isn't reachable since the master-detail panel doesn't render). */
.yb-gl-emptystate {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.65rem;
    text-align: center;
    color: var(--yb-text-muted);
    padding: 3rem 1rem;
    margin-top: 0.75rem;
    background: var(--yb-card);
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-lg);
    box-shadow: var(--yb-shadow-sm);
}

.yb-gl-emptystate > i {
    font-size: 1.7rem;
    opacity: 0.7;
}

.yb-gl-emptystate p {
    margin: 0;
    font-size: 0.95rem;
}

/* Slim scrollbars for the two internal scroll regions — the default OS bars read as
   bulky inside these compact panels (most noticeable on small screens). */
.yb-gl-raillist,
.yb-gl-panelbody {
    scrollbar-width: thin;                                       /* Firefox */
    scrollbar-color: var(--yb-border-strong) transparent;
}

.yb-gl-raillist::-webkit-scrollbar,
.yb-gl-panelbody::-webkit-scrollbar {
    width: 6px;
}

.yb-gl-raillist::-webkit-scrollbar-track,
.yb-gl-panelbody::-webkit-scrollbar-track {
    background: transparent;
}

.yb-gl-raillist::-webkit-scrollbar-thumb,
.yb-gl-panelbody::-webkit-scrollbar-thumb {
    background: var(--yb-border-strong);
    border-radius: 999px;
}

.yb-gl-raillist::-webkit-scrollbar-thumb:hover,
.yb-gl-panelbody::-webkit-scrollbar-thumb:hover {
    background: var(--yb-text-muted);
}

@media (max-width: 767.98px) {
    /* Stack on small screens and release the locked height so the page scrolls
       normally instead of trapping two scroll regions in a short viewport. */
    .yb-gl-body {
        flex-direction: column;
        height: auto;
    }
    .yb-gl-rail {
        flex: 0 0 auto;
        width: 100%;
        border-right: 0;
        border-bottom: 1px solid var(--yb-border);
    }
    .yb-gl-raillist {
        max-height: 220px;
    }
    .yb-gl-panelbody {
        overflow-y: visible;
    }
}

/* ==================== 13. CLASS & SECTIONS / ASSIGN SECTIONS & CONTACTS ====================
   Reuses the Group Lookups language (.yb-gl-body/-rail/-panel/-list/-tab/search/sort/refresh
   + slim scrollbars). This section adds only the bits unique to these two screens: the
   read-only catalog's twin panes, the assign screen's scope bar, the assigned indicator,
   and the SPOC detail form. Token-based → adapts to dark mode. */
.yb-cs {
    max-width: 1100px;
    margin: 0 auto;
}

/* Catalog: two equal panes inside the single card, split by a hairline. */
.yb-cs-pane {
    flex: 1 1 0;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    padding: 1rem 1.25rem 0;
}

.yb-cs-pane + .yb-cs-pane {
    border-left: 1px solid var(--yb-border);
}

@media (max-width: 767.98px) {
    .yb-cs-pane + .yb-cs-pane {
        border-left: 0;
        border-top: 1px solid var(--yb-border);
    }
}

/* Class/Section code reads as a distinct identifier chip (monospace). It picks up the
   stage colour (--stage, set on the group) so each code is colour-coded by stage; falls
   back to the brand accent outside a stage group (e.g. the Sections pane). */
.yb-cs-code {
    flex: 0 0 auto;
    align-self: center;
    font-family: ui-monospace, SFMono-Regular, "Cascadia Code", Menlo, Consolas, monospace;
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: rgb(var(--stage, var(--yb-accent-rgb)));
    background: rgba(var(--stage, var(--yb-accent-rgb)), 0.1);
    border: 1px solid rgba(var(--stage, var(--yb-accent-rgb)), 0.25);
    border-radius: var(--yb-radius-sm);
    padding: 0.1rem 0.45rem;
    min-width: 2.6rem;
    text-align: center;
}

/* Stage group in the catalog Classes pane. --stage (R,G,B) is set per group and inherits
   to the code chips + the header below. */
.yb-cs-grouphdr {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    appearance: none;
    border: 0;
    border-radius: var(--yb-radius-sm);
    font: inherit;
    text-align: left;
    cursor: pointer;
    padding: 0.5rem 0.35rem;
    position: sticky;
    top: 0;
    background: var(--yb-card);
    z-index: 1;
    transition: background var(--yb-dur) var(--yb-ease);
}

.yb-cs-grouphdr:hover {
    background: rgba(var(--stage, var(--yb-accent-rgb)), 0.07);
}

.yb-cs-groupchev {
    flex: 0 0 auto;
    font-size: 0.7rem;
    color: var(--yb-text-muted);
}

.yb-cs-group:first-child .yb-cs-grouphdr {
    padding-top: 0.2rem;
}

.yb-cs-groupdot {
    flex: 0 0 auto;
    width: 0.6rem;
    height: 0.6rem;
    border-radius: 50%;
    background: rgb(var(--stage, var(--yb-accent-rgb)));
}

.yb-cs-grouplabel {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: rgb(var(--stage, var(--yb-accent-rgb)));
}

.yb-cs-groupcount {
    margin-left: auto;
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--yb-text-muted);
    background: var(--yb-surface-sunken);
    border-radius: 999px;
    padding: 0.02rem 0.45rem;
}

/* Stage dot inside the grouped class picker (popup is light-only → fixed rgb is fine). */
.yb-cs-ddl-item {
    display: inline-flex;
    align-items: center;
}

.yb-cs-ddl-dot {
    flex: 0 0 auto;
    width: 0.55rem;
    height: 0.55rem;
    border-radius: 50%;
    margin-right: 0.5rem;
    background: rgb(var(--stage, var(--yb-accent-rgb)));
}

/* ============================================================
   Assign Section & SPOC — scope ribbon + section board
   ============================================================ */

/* Single page surface: scope ribbon, toolbar, and board all live inside ONE card
   so the screen reads as one continuous page rather than stacked blocks. */
.yb-cs-shell {
    margin-top: 0.5rem;
    background: var(--yb-card);
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-lg);
    box-shadow: var(--yb-shadow-sm);
    overflow: hidden;
}

/* Scope ribbon: the three selectors read as ONE connected control (chevrons between),
   sitting as the shell's header strip. Background follows the search-panel styling. */
.yb-cs-ribbon {
    display: flex;
    align-items: stretch;
    flex-wrap: wrap;
    gap: 0;
    padding: 0.7rem 0.6rem;
    background: var(--yb-surface);
    border-bottom: 1px solid var(--yb-border);
}

[data-theme="dark"] .yb-cs-ribbon {
    background: var(--yb-card);
}

.yb-cs-seg {
    flex: 1 1 200px;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    padding: 0.15rem 0.7rem;
}

.yb-cs-seg__label {
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--yb-text-muted);
}

.yb-cs-sep {
    align-self: center;
    color: var(--yb-text-muted);
    opacity: 0.45;
    font-size: 0.85rem;
    flex: 0 0 auto;
}

/* Summary strip: directly under the scope ribbon, count right-aligned below Class. */
.yb-cs-summarybar {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 0.6rem;
    padding: 0.55rem 1rem;
    border-bottom: 1px solid var(--yb-border);
}

.yb-cs-summary {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.9rem;
    color: var(--yb-text-muted);
}

.yb-cs-summary i {
    color: #16a34a;
    font-size: 1rem;
}

.yb-cs-summary strong {
    color: var(--yb-text);
    font-weight: 700;
}

/* Inline help text under the summary. */
.yb-cs-helptext {
    display: flex;
    align-items: flex-start;
    gap: 0.45rem;
    margin: 0;
    padding: 0.7rem 1rem 0.3rem;
    font-size: 0.82rem;
    line-height: 1.45;
    color: var(--yb-text-muted);
}

.yb-cs-helptext > i {
    flex: 0 0 auto;
    margin-top: 0.12rem;
    color: var(--yb-accent);
    font-size: 0.95rem;
}

.yb-cs-helptext strong {
    color: var(--yb-text);
    font-weight: 600;
}

.yb-cs-status:not(:empty) {
    padding: 0 1rem;
}

/* The board is a table: a header row + one row per section. Section, Status, Primary,
   Secondary, Actions. Each row carries its section's --sec colour (left bar + tint). */
.yb-cs-table {
    --cols: minmax(130px, 1.1fr) minmax(120px, 0.9fr) minmax(150px, 1.5fr) minmax(150px, 1.5fr) minmax(112px, auto);
    padding: 0.4rem 0.5rem 0.6rem;
}

.yb-cs-thead,
.yb-cs-row {
    display: grid;
    grid-template-columns: var(--cols);
    align-items: center;
    gap: 0.6rem;
}

/* Header row reads as a real table header: filled strip, hairline under it. */
.yb-cs-thead {
    padding: 0.55rem 0.85rem;
    background: var(--yb-surface-sunken);
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-sm);
    margin-bottom: 0.35rem;
}

.yb-cs-th {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--yb-text-muted);
}

.yb-cs-th--actions {
    text-align: right;
}

/* A section row: a soft self-contained card — smooth full border, rounded corners,
   a section-coloured left bar, and gentle shading. Assigned rows get a faint colour
   wash; hover deepens the wash + ring and lifts the row. */
.yb-cs-row {
    padding: 0.55rem 0.85rem;
    border: 1px solid var(--yb-border);
    border-left: 4px solid rgb(var(--sec, var(--yb-accent-rgb)));
    border-radius: var(--yb-radius-md, 10px);
    background: var(--yb-card);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
    transition: background var(--yb-dur) var(--yb-ease),
                border-color var(--yb-dur) var(--yb-ease),
                box-shadow var(--yb-dur) var(--yb-ease),
                transform var(--yb-dur) var(--yb-ease);
}

.yb-cs-row + .yb-cs-row {
    margin-top: 0.4rem;
}

.yb-cs-row.is-assigned {
    background: linear-gradient(90deg, rgba(var(--sec, var(--yb-accent-rgb)), 0.08), rgba(var(--sec, var(--yb-accent-rgb)), 0.02) 40%, var(--yb-card));
}

.yb-cs-row.is-unassigned {
    border-left-color: rgba(var(--sec, var(--yb-accent-rgb)), 0.4);
}

.yb-cs-row:hover {
    background: linear-gradient(90deg, rgba(var(--sec, var(--yb-accent-rgb)), 0.16), rgba(var(--sec, var(--yb-accent-rgb)), 0.05));
    border-color: rgba(var(--sec, var(--yb-accent-rgb)), 0.4);
    border-left-color: rgb(var(--sec, var(--yb-accent-rgb)));
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
    transform: translateY(-1px);
}

.yb-cs-cell {
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Section name cell: colour swatch + name. */
.yb-cs-cell--sec {
    font-weight: 700;
    font-size: 0.92rem;
    color: var(--yb-text);
}

.yb-cs-secbar {
    flex: 0 0 auto;
    width: 0.85rem;
    height: 0.85rem;
    border-radius: 4px;
    background: rgb(var(--sec, var(--yb-accent-rgb)));
}

.yb-cs-secname {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Status badge — a tidy chip. Assigned = soft green badge with a filled check. */
.yb-cs-statepill {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex: 0 0 auto;
    font-size: 0.74rem;
    font-weight: 600;
    line-height: 1.2;
    padding: 0.2rem 0.55rem;
    border-radius: 999px;
    color: var(--yb-text-muted);
    background: var(--yb-surface-sunken);
    border: 1px solid var(--yb-border);
}

.yb-cs-statepill.is-on {
    color: #15803d;
    background: rgba(34, 197, 94, 0.12);
    border-color: rgba(34, 197, 94, 0.3);
}

.yb-cs-statepill.is-on i {
    color: #22c55e;
    font-size: 0.8rem;
}

[data-theme="dark"] .yb-cs-statepill.is-on {
    color: #4ade80;
}

/* "Assign to class" action shown in the Status cell of an unassigned row. */
.yb-cs-assignbtn {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.32rem 0.7rem;
    border-radius: var(--yb-radius-sm);
    border: 1px dashed rgba(var(--yb-accent-rgb), 0.5);
    background: rgba(var(--yb-accent-rgb), 0.06);
    color: var(--yb-accent);
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--yb-dur) var(--yb-ease), border-color var(--yb-dur) var(--yb-ease);
}

.yb-cs-assignbtn:hover:not(:disabled) {
    background: rgba(var(--yb-accent-rgb), 0.12);
    border-style: solid;
}

.yb-cs-assignbtn:disabled {
    opacity: 0.6;
    cursor: default;
}

/* Contact cells host the staff dropdowns (full width) or a read-only name. */
.yb-cs-cell--contact .e-input-group,
.yb-cs-cell--contact .e-ddl,
.yb-cs-cell--contact .e-control-wrapper {
    width: 100%;
    height: 2.375rem; /* keep dropdowns + row action buttons the same height */
}

.yb-cs-readonly {
    font-weight: 600;
    color: var(--yb-text);
}

/* Placeholder shown in contact cells before the section is assigned. */
.yb-cs-locked {
    color: var(--yb-text-muted);
    font-size: 0.82rem;
    font-style: italic;
    opacity: 0.8;
}

.yb-cs-locked i {
    font-size: 0.78rem;
}

/* Actions cell: per-row Save (lit only when dirty) + remove-from-class. */
.yb-cs-cell--actions {
    justify-content: flex-end;
    gap: 0.35rem;
}

/* Clear + Save share the dropdown height so the row lines up cleanly.
   Save is a simple solid button in the row's section colour; Clear is a quiet outline. */
.yb-cs-clear,
.yb-cs-save {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.3rem;
    height: 2.375rem;
    box-sizing: border-box;
    padding: 0 0.8rem;
    border-radius: var(--yb-radius-sm);
    border: 1px solid var(--yb-border);
    font-size: 0.8rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--yb-dur) var(--yb-ease), color var(--yb-dur) var(--yb-ease), border-color var(--yb-dur) var(--yb-ease), box-shadow var(--yb-dur) var(--yb-ease);
}

.yb-cs-clear {
    background: transparent;
    color: var(--yb-text-muted);
}

.yb-cs-clear:hover:not(:disabled) {
    background: var(--yb-surface-sunken);
    color: var(--yb-text);
    border-color: var(--yb-border-strong);
}

.yb-cs-save {
    background: var(--yb-surface-sunken);
    color: var(--yb-text-muted);
}

.yb-cs-save.is-dirty {
    background: rgb(var(--sec, var(--yb-accent-rgb)));
    border-color: rgb(var(--sec, var(--yb-accent-rgb)));
    color: #fff;
    box-shadow: 0 1px 4px rgba(var(--sec, var(--yb-accent-rgb)), 0.4);
}

.yb-cs-save.is-dirty:hover {
    filter: brightness(1.06);
}

.yb-cs-clear:disabled,
.yb-cs-save:disabled {
    opacity: 0.55;
    cursor: default;
    box-shadow: none;
}

.yb-cs-iconbtn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.9rem;
    height: 1.9rem;
    border-radius: var(--yb-radius-sm);
    border: 1px solid transparent;
    background: transparent;
    color: var(--yb-text-muted);
    cursor: pointer;
    transition: background var(--yb-dur) var(--yb-ease), color var(--yb-dur) var(--yb-ease);
}

.yb-cs-iconbtn--danger:hover:not(:disabled) {
    background: rgba(220, 53, 69, 0.1);
    color: #dc3545;
}

.yb-cs-iconbtn:disabled {
    opacity: 0.5;
    cursor: default;
}

.yb-cs-table__empty {
    padding: 2.5rem 1rem;
    text-align: center;
    color: var(--yb-text-muted);
    font-size: 0.9rem;
}

/* Type-to-confirm removal body. Hosted inside the shared YbConfirmDialog
   (badge + eyebrow + title header), whose .yb-confirm-body already provides the
   air below the header divider — no padding of its own on top. */
.yb-cs-confirm-body {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding: 0 0.15rem 0.25rem;
}

.yb-cs-confirm-warn {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 0.7rem 0.8rem;
    border-radius: var(--yb-radius-sm);
    background: rgba(220, 53, 69, 0.08);
    border: 1px solid rgba(220, 53, 69, 0.25);
}

.yb-cs-confirm-warn > i {
    flex: 0 0 auto;
    margin-top: 0.1rem;
    color: #dc3545;
    font-size: 1.1rem;
}

.yb-cs-confirm-warn p {
    margin: 0;
    font-size: 0.88rem;
    line-height: 1.45;
    color: var(--yb-text);
}

.yb-cs-confirm-warn__sub {
    margin-top: 0.3rem !important;
    color: var(--yb-text-muted) !important;
    font-size: 0.82rem !important;
}

.yb-cs-confirm-label {
    font-size: 0.84rem;
    font-weight: 600;
    color: var(--yb-text-muted);
}

/* The exact phrase to type, shown as a monospace code chip. */
.yb-cs-confirm-target {
    font-family: var(--bs-font-monospace, ui-monospace, SFMono-Regular, Menlo, monospace);
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--yb-text);
    padding: 0.45rem 0.7rem;
    border-radius: var(--yb-radius-sm);
    background: var(--yb-surface-sunken);
    border: 1px dashed var(--yb-border-strong);
    user-select: all;
    word-break: break-word;
}

.yb-cs-confirm-input {
    width: 100%;
    height: 2.375rem;
    padding: 0 0.7rem;
    border-radius: var(--yb-radius-sm);
    border: 1px solid var(--yb-border-strong);
    background: var(--yb-card);
    color: var(--yb-text);
    font-size: 0.9rem;
    transition: border-color var(--yb-dur) var(--yb-ease), box-shadow var(--yb-dur) var(--yb-ease);
}

.yb-cs-confirm-input:focus {
    outline: none;
    border-color: rgba(220, 53, 69, 0.55);
    box-shadow: 0 0 0 3px rgba(220, 53, 69, 0.15);
}

/* Responsive: collapse the table into stacked, self-labelled rows. */
@media (max-width: 820px) {
    .yb-cs-thead {
        display: none;
    }
    .yb-cs-row {
        grid-template-columns: 1fr;
        gap: 0.4rem;
        padding: 0.7rem 0.85rem;
    }
    .yb-cs-cell[data-label]::before {
        content: attr(data-label);
        flex: 0 0 7.5rem;
        font-size: 0.68rem;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: 0.04em;
        color: var(--yb-text-muted);
    }
    .yb-cs-cell--sec {
        font-size: 1rem;
    }
    .yb-cs-cell--actions {
        justify-content: flex-start;
    }
    .yb-cs-locked:empty {
        display: none;
    }
}

@media (max-width: 575.98px) {
    .yb-cs-ribbon {
        flex-direction: column;
        padding: 0.6rem;
    }
    .yb-cs-sep {
        display: none;
    }
    .yb-cs-summary {
        margin-left: 0;
    }
}

/* ============================================================
   Service Dashboard (/services) — API health hero + data cards
   ============================================================ */
.yb-svc {
    max-width: 1080px;
    margin: 0 auto;
}

/* API health hero — colour driven by --st (green healthy / red down). */
.yb-svc-hero {
    --st: 100, 116, 139;
    position: relative;
    overflow: hidden;
    margin-top: 0.75rem;
    padding: 1.1rem 1.25rem;
    background: linear-gradient(180deg, rgba(var(--st), 0.06), var(--yb-card) 55%);
    border: 1px solid var(--yb-border);
    border-left: 4px solid rgb(var(--st));
    border-radius: var(--yb-radius-lg);
    box-shadow: var(--yb-shadow-sm);
}

.yb-svc-hero.is-healthy { --st: 34, 197, 94; }
.yb-svc-hero.is-down    { --st: 220, 53, 69; }

.yb-svc-hero__main {
    display: flex;
    align-items: center;
    gap: 0.9rem;
}

.yb-svc-hero__icon {
    flex: 0 0 auto;
    width: 3rem;
    height: 3rem;
    border-radius: 14px;
    display: grid;
    place-items: center;
    font-size: 1.4rem;
    color: rgb(var(--st));
    background: rgba(var(--st), 0.12);
    border: 1px solid rgba(var(--st), 0.25);
}

.yb-svc-hero__id {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.yb-svc-hero__name {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--yb-text);
}

.yb-svc-hero__sub {
    font-size: 0.82rem;
    color: var(--yb-text-muted);
}

.yb-svc-status {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.85rem;
    font-weight: 700;
    color: rgb(var(--st));
    padding: 0.3rem 0.7rem;
    border-radius: 999px;
    background: rgba(var(--st), 0.12);
    border: 1px solid rgba(var(--st), 0.3);
}

.yb-svc-dot {
    width: 0.6rem;
    height: 0.6rem;
    border-radius: 50%;
    background: rgb(var(--st));
}

.yb-svc-hero.is-healthy .yb-svc-dot {
    animation: yb-svc-pulse 2.2s ease-out infinite;
}

@keyframes yb-svc-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(var(--st), 0.45); }
    70%  { box-shadow: 0 0 0 6px rgba(var(--st), 0); }
    100% { box-shadow: 0 0 0 0 rgba(var(--st), 0); }
}

/* Hero refresh button. */
.yb-svc-refresh {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    height: 2.2rem;
    padding: 0 0.85rem;
    border-radius: var(--yb-radius-sm);
    border: 1px solid var(--yb-border-strong);
    background: var(--yb-card);
    color: var(--yb-text);
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--yb-dur) var(--yb-ease), border-color var(--yb-dur) var(--yb-ease), color var(--yb-dur) var(--yb-ease);
}

.yb-svc-refresh:hover:not(:disabled) {
    background: var(--yb-surface-sunken);
    border-color: rgb(var(--st));
    color: rgb(var(--st));
}

.yb-svc-refresh:disabled {
    opacity: 0.65;
    cursor: default;
}

/* Hero meta facts: Service / Version / Last checked. */
.yb-svc-facts {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.75rem;
    margin-top: 1rem;
    padding-top: 0.9rem;
    border-top: 1px solid var(--yb-border);
}

.yb-svc-fact {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}

.yb-svc-fact__label {
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: 700;
    color: var(--yb-text-muted);
}

.yb-svc-fact__value {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--yb-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Hero quick links. */
.yb-svc-links {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.9rem;
}

.yb-svc-link {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--yb-accent);
    text-decoration: none;
    padding: 0.35rem 0.7rem;
    border-radius: var(--yb-radius-sm);
    border: 1px solid var(--yb-border);
    background: var(--yb-surface-sunken);
    transition: background var(--yb-dur) var(--yb-ease), border-color var(--yb-dur) var(--yb-ease);
}

.yb-svc-link:hover {
    background: rgba(var(--yb-accent-rgb), 0.1);
    border-color: rgba(var(--yb-accent-rgb), 0.4);
}

.yb-svc-config-warn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.82rem;
    font-weight: 600;
    color: #b45309;
}

/* Shared error strip. */
.yb-svc-error {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.9rem;
    padding: 0.6rem 0.8rem;
    border-radius: var(--yb-radius-sm);
    background: rgba(220, 53, 69, 0.08);
    border: 1px solid rgba(220, 53, 69, 0.25);
    color: #b02a37;
    font-size: 0.85rem;
}

.yb-svc-error i { color: #dc3545; }

[data-theme="dark"] .yb-svc-error { color: #f1a7ad; }

/* Reference-data cards grid. */
.yb-svc-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 1rem;
    margin-top: 1rem;
}

.yb-svc-card {
    --accent: var(--yb-accent-rgb);
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    padding: 1rem 1.1rem;
    background: var(--yb-card);
    border: 1px solid var(--yb-border);
    border-top: 3px solid rgb(var(--accent));
    border-radius: var(--yb-radius-lg);
    box-shadow: var(--yb-shadow-sm);
}

.yb-svc-card__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.yb-svc-card__title {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.98rem;
    font-weight: 700;
    color: var(--yb-text);
}

.yb-svc-card__title i { color: rgb(var(--accent)); }

.yb-svc-iconrefresh {
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    display: inline-grid;
    place-items: center;
    border-radius: var(--yb-radius-sm);
    border: 1px solid transparent;
    background: transparent;
    color: var(--yb-text-muted);
    cursor: pointer;
    transition: background var(--yb-dur) var(--yb-ease), color var(--yb-dur) var(--yb-ease);
}

.yb-svc-iconrefresh:hover:not(:disabled) {
    background: rgba(var(--accent), 0.12);
    color: rgb(var(--accent));
}

.yb-svc-iconrefresh:disabled {
    opacity: 0.6;
    cursor: default;
}

/* Stat blocks. */
.yb-svc-stats {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.75rem;
}

.yb-svc-stat {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 0.7rem 0.85rem;
    border-radius: var(--yb-radius-md, 10px);
    background: rgba(var(--accent), 0.07);
    border: 1px solid rgba(var(--accent), 0.18);
}

.yb-svc-stat__num {
    font-size: 1.6rem;
    font-weight: 800;
    line-height: 1;
    color: var(--yb-text);
}

.yb-svc-stat__label {
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    font-weight: 700;
    color: var(--yb-text-muted);
}

/* Coverage chips. */
.yb-svc-coverage {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
}

.yb-svc-coverage__label {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: 700;
    color: var(--yb-text-muted);
}

.yb-svc-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.yb-svc-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.78rem;
    font-weight: 600;
    padding: 0.22rem 0.55rem;
    border-radius: 999px;
    border: 1px solid var(--yb-border);
    background: var(--yb-surface-sunken);
    color: var(--yb-text);
}

.yb-svc-chip i { font-size: 0.78rem; }
.yb-svc-chip b { margin-left: 0.15rem; font-weight: 800; }

.yb-svc-chip.is-ok {
    color: #15803d;
    background: rgba(34, 197, 94, 0.1);
    border-color: rgba(34, 197, 94, 0.3);
}
.yb-svc-chip.is-ok i { color: #22c55e; }

.yb-svc-chip.is-missing {
    color: #b02a37;
    background: rgba(220, 53, 69, 0.08);
    border-color: rgba(220, 53, 69, 0.28);
}
.yb-svc-chip.is-missing i { color: #dc3545; }

[data-theme="dark"] .yb-svc-chip.is-ok { color: #4ade80; }
[data-theme="dark"] .yb-svc-chip.is-missing { color: #f1a7ad; }

.yb-svc-cardnote {
    margin: 0;
    font-size: 0.8rem;
    line-height: 1.45;
    color: var(--yb-text-muted);
}

@media (max-width: 600px) {
    .yb-svc-hero__main {
        flex-wrap: wrap;
    }
    .yb-svc-status {
        margin-left: 0;
    }
    .yb-svc-facts {
        grid-template-columns: 1fr 1fr;
    }
}

/* ============================================================
   Governance (/governance hub + sub-pages) — Issue #38 rework
   Posture hero, summary cards, status pills, theme-aware audit.
   ============================================================ */
.yb-gov {
    max-width: 1120px;
    margin: 0 auto;
}

/* ---- Posture hero — colour driven by --st (amber action / green clear) ---- */
.yb-gov-hero {
    --st: 34, 197, 94;
    position: relative;
    overflow: hidden;
    margin-top: 0.75rem;
    padding: 1.1rem 1.25rem;
    background: linear-gradient(180deg, rgba(var(--st), 0.06), var(--yb-card) 55%);
    border: 1px solid var(--yb-border);
    border-left: 4px solid rgb(var(--st));
    border-radius: var(--yb-radius-lg);
    box-shadow: var(--yb-shadow-sm);
}

.yb-gov-hero.is-clear  { --st: 34, 197, 94; }
.yb-gov-hero.is-action { --st: 245, 158, 11; }

.yb-gov-hero__main {
    display: flex;
    align-items: center;
    gap: 0.9rem;
}

.yb-gov-hero__icon {
    flex: 0 0 auto;
    width: 3rem;
    height: 3rem;
    border-radius: 14px;
    display: grid;
    place-items: center;
    font-size: 1.4rem;
    color: rgb(var(--st));
    background: rgba(var(--st), 0.12);
    border: 1px solid rgba(var(--st), 0.25);
}

.yb-gov-hero__id {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.yb-gov-hero__name {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--yb-text);
}

.yb-gov-hero__sub {
    font-size: 0.82rem;
    color: var(--yb-text-muted);
}

.yb-gov-posture {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.85rem;
    font-weight: 700;
    color: rgb(var(--st));
    padding: 0.3rem 0.7rem;
    border-radius: 999px;
    background: rgba(var(--st), 0.12);
    border: 1px solid rgba(var(--st), 0.3);
    white-space: nowrap;
}

.yb-gov-dot {
    width: 0.6rem;
    height: 0.6rem;
    border-radius: 50%;
    background: rgb(var(--st));
}

.yb-gov-hero.is-action .yb-gov-dot {
    animation: yb-gov-pulse 2.2s ease-out infinite;
}

@keyframes yb-gov-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(var(--st), 0.45); }
    70%  { box-shadow: 0 0 0 6px rgba(var(--st), 0); }
    100% { box-shadow: 0 0 0 0 rgba(var(--st), 0); }
}

/* Audit-log link in the hero / sub-page toolbars. */
.yb-gov-auditlink {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    height: 2.1rem;
    padding: 0 0.8rem;
    font-size: 0.82rem;
    font-weight: 600;
    text-decoration: none;
    color: var(--yb-text-muted);
    background: var(--yb-card);
    border: 1px solid var(--yb-border);
    border-radius: 999px;
    transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

.yb-gov-auditlink:hover {
    color: var(--yb-brand-600);
    border-color: var(--yb-brand-400);
    background: rgba(31, 111, 229, 0.06);
}

/* ---- Summary cards ---- */
.yb-gov-grid {
    margin-top: 1rem;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(245px, 1fr));
    gap: 0.9rem;
}

.yb-gov-card {
    --accent: 31, 111, 229;
    display: flex;
    flex-direction: column;
    gap: 0.65rem;
    padding: 1.05rem 1.1rem;
    text-decoration: none;
    background: var(--yb-card);
    border: 1px solid var(--yb-border);
    border-top: 3px solid rgb(var(--accent));
    border-radius: var(--yb-radius-lg);
    box-shadow: var(--yb-shadow-sm);
    transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

.yb-gov-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--yb-shadow-md, 0 8px 24px rgba(2, 12, 38, 0.12));
    border-color: rgba(var(--accent), 0.55);
}

.yb-gov-card.is-hot  { background: linear-gradient(180deg, rgba(245, 158, 11, 0.09), var(--yb-card) 60%); }
.yb-gov-card.is-warn { background: linear-gradient(180deg, rgba(217, 70, 160, 0.07), var(--yb-card) 60%); }

.yb-gov-card__head {
    display: flex;
    align-items: center;
    gap: 0.55rem;
}

.yb-gov-card__icon {
    flex: 0 0 auto;
    width: 2.1rem;
    height: 2.1rem;
    border-radius: 10px;
    display: grid;
    place-items: center;
    font-size: 1rem;
    color: rgb(var(--accent));
    background: rgba(var(--accent), 0.12);
    border: 1px solid rgba(var(--accent), 0.22);
}

.yb-gov-card__title {
    font-size: 0.92rem;
    font-weight: 700;
    color: var(--yb-text);
}

.yb-gov-card__go {
    margin-left: auto;
    color: var(--yb-text-muted);
    font-size: 0.85rem;
    transition: transform 0.15s ease, color 0.15s ease;
}

.yb-gov-card:hover .yb-gov-card__go {
    transform: translateX(3px);
    color: rgb(var(--accent));
}

.yb-gov-card__metric {
    display: flex;
    align-items: baseline;
    gap: 0.45rem;
}

.yb-gov-card__num {
    font-size: 2rem;
    font-weight: 800;
    line-height: 1;
    color: rgb(var(--accent));
}

.yb-gov-card__unit {
    font-size: 0.8rem;
    color: var(--yb-text-muted);
}

.yb-gov-card__note {
    margin: 0;
    font-size: 0.8rem;
    line-height: 1.45;
    color: var(--yb-text-muted);
}

/* ---- Status / type pills (shared across hub + sub-pages) ---- */
.yb-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.18rem 0.55rem;
    font-size: 0.74rem;
    font-weight: 700;
    line-height: 1.2;
    border-radius: 999px;
    white-space: nowrap;
    border: 1px solid transparent;
}

.yb-pill.is-approved { color: #15803d; background: rgba(34, 197, 94, 0.13);  border-color: rgba(34, 197, 94, 0.3); }
.yb-pill.is-rejected { color: #b91c1c; background: rgba(220, 53, 69, 0.12);  border-color: rgba(220, 53, 69, 0.3); }
.yb-pill.is-pending  { color: #b45309; background: rgba(245, 158, 11, 0.14); border-color: rgba(245, 158, 11, 0.32); }
.yb-pill.is-neutral  { color: var(--yb-text-muted); background: rgba(100, 116, 139, 0.12); border-color: rgba(100, 116, 139, 0.28); }
.yb-pill.is-type     { color: var(--yb-text); background: rgba(100, 116, 139, 0.08); border-color: var(--yb-border); font-weight: 600; }
.yb-pill.is-warn     { color: #a16207; background: rgba(234, 179, 8, 0.16);  border-color: rgba(234, 179, 8, 0.34); }

[data-theme="dark"] .yb-pill.is-approved { color: #4ade80; }
[data-theme="dark"] .yb-pill.is-rejected { color: #f1a7ad; }
[data-theme="dark"] .yb-pill.is-pending  { color: #fcd34d; }
[data-theme="dark"] .yb-pill.is-warn     { color: #fcd34d; }

/* Inline pill used inside a card note. */
.yb-gov-inlinepill {
    display: inline-flex;
    align-items: center;
    padding: 0.14rem 0.5rem;
    font-size: 0.74rem;
    font-weight: 700;
    border-radius: 999px;
}
.yb-gov-inlinepill.is-pending { color: #b45309; background: rgba(245, 158, 11, 0.14); border: 1px solid rgba(245, 158, 11, 0.32); }
[data-theme="dark"] .yb-gov-inlinepill.is-pending { color: #fcd34d; }

/* ---- Shared states ---- */
/* .yb-gov-loading removed — the four governance surfaces now use YbSkeletonTable /
   YbSkeletonCards and YbStateBlock (#233). */

.yb-gov-empty {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-top: 0.75rem;
    padding: 1.1rem 1.2rem;
    font-size: 0.88rem;
    color: var(--yb-text-muted);
    background: linear-gradient(180deg, rgba(31, 111, 229, 0.05), var(--yb-card) 60%);
    border: 1px dashed var(--yb-border);
    border-radius: var(--yb-radius-lg);
}
.yb-gov-empty i { font-size: 1.1rem; color: var(--yb-brand-500); }

.yb-gov-note {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.75rem;
    padding: 0.65rem 0.9rem;
    font-size: 0.82rem;
    border-radius: 10px;
}
.yb-gov-note.is-warn  { color: #92660b; background: rgba(245, 158, 11, 0.1); border: 1px solid rgba(245, 158, 11, 0.28); }
.yb-gov-note.is-error { color: #b91c1c; background: rgba(220, 53, 69, 0.08); border: 1px solid rgba(220, 53, 69, 0.26); }
.yb-gov-note.is-info  { color: var(--yb-text-muted); background: rgba(var(--yb-info-rgb), 0.07); border: 1px solid rgba(var(--yb-info-rgb), 0.24); align-items: flex-start; }
.yb-gov-note.is-info i { color: var(--yb-info); margin-top: 0.15rem; }
[data-theme="dark"] .yb-gov-note.is-warn  { color: #fcd34d; }
[data-theme="dark"] .yb-gov-note.is-error { color: #f1a7ad; }

/* ── Approval review: what exactly is being authorized (#169) ─────────────────
   A reviewer approving one batch needs the batch, not a summary of it. The fact
   table is the dialog's spine; the consequence block is the blast radius, and it
   holds the tick that unlocks Approve. */
/* The decision dialog's notes/expiry are native Bootstrap controls, which carry no dark-mode
   token of their own — left alone they render as white slabs in a dark dialog. */
[data-theme="dark"] .yb-gov-dialog .form-control {
    color: var(--yb-text);
    background: var(--yb-surface-2);
    border-color: var(--yb-border-strong);
}

[data-theme="dark"] .yb-gov-dialog .form-control::placeholder { color: var(--yb-text-muted); }

/* The native date picker's calendar glyph is a black icon on a now-dark field. */
[data-theme="dark"] .yb-gov-dialog input[type="date"]::-webkit-calendar-picker-indicator {
    filter: invert(1) opacity(0.7);
}

/* NB: the surrounding .modal-body centres its text. A centred label/value table and a centred
   paragraph of consequences are both unreadable, so these blocks opt out explicitly rather than
   restyling the shared modal and disturbing every other dialog. */
.yb-gov-facts {
    margin: 0 0 1rem;
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-sm);
    background: var(--yb-surface-2);
    overflow: hidden;
    text-align: left;
}

.yb-gov-fact {
    display: grid;
    grid-template-columns: 8.5rem 1fr;
    gap: 0.75rem;
    padding: 0.5rem 0.8rem;
    border-bottom: 1px solid var(--yb-border);
}

.yb-gov-fact:last-child { border-bottom: 0; }

.yb-gov-fact dt {
    margin: 0;
    font-size: 0.76rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--yb-text-muted);
    align-self: center;
}

.yb-gov-fact dd {
    margin: 0;
    font-size: 0.86rem;
    color: var(--yb-text);
    overflow-wrap: anywhere;
}

.yb-gov-fact dd.is-danger {
    font-weight: 700;
    color: var(--yb-danger);
}

.yb-gov-consequence {
    margin-bottom: 1rem;
    padding: 0.85rem 1rem;
    border: 1px solid rgba(var(--yb-danger-rgb), 0.32);
    border-left: 3px solid var(--yb-danger);
    border-radius: var(--yb-radius-sm);
    background: rgba(var(--yb-danger-rgb), 0.07);
    text-align: left;
}

.yb-gov-consequence__head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: 700;
    color: var(--yb-text);
}

.yb-gov-consequence__head i { color: var(--yb-danger); }

.yb-gov-consequence__body {
    margin: 0.4rem 0 0.75rem;
    font-size: 0.83rem;
    line-height: 1.55;
    color: var(--yb-text-muted);
}

.yb-gov-consequence__ack {
    display: flex;
    align-items: flex-start;
    gap: 0.55rem;
    padding-top: 0.7rem;
    border-top: 1px dashed rgba(var(--yb-danger-rgb), 0.32);
    font-size: 0.83rem;
    line-height: 1.45;
    color: var(--yb-text);
    cursor: pointer;
}

.yb-gov-consequence__ack input {
    margin-top: 0.15rem;
    flex: 0 0 auto;
    accent-color: var(--yb-danger);
}

/* Destructive marker in the request grid. A rounded-rect, not an oval — a full load
   is a warning, and it should not read as one more decorative status chip. */
.yb-gov-flag {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.14rem 0.45rem;
    font-size: 0.72rem;
    font-weight: 700;
    line-height: 1.2;
    white-space: nowrap;
    color: var(--yb-danger);
    background: rgba(var(--yb-danger-rgb), 0.1);
    border: 1px solid rgba(var(--yb-danger-rgb), 0.3);
    border-radius: var(--yb-radius-sm);
}

.yb-gov-details {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
}

/* Status cell on My Requests: the badge, plus what the request still needs from you. */
.yb-gov-status {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.25rem;
}

.yb-gov-status__link,
.yb-gov-status__cta {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.76rem;
    font-weight: 600;
    text-decoration: none;
}

.yb-gov-status__link { color: var(--yb-text-muted); }
.yb-gov-status__link:hover { color: var(--yb-text); text-decoration: underline; }

/* Approved-but-unspent is the state operators misread as "done". Make it look like work. */
.yb-gov-status__cta {
    padding: 0.16rem 0.45rem;
    color: var(--yb-brand-600);
    background: rgba(var(--yb-info-rgb), 0.09);
    border: 1px solid rgba(var(--yb-info-rgb), 0.3);
    border-radius: var(--yb-radius-sm);
}

.yb-gov-status__cta:hover {
    color: #fff;
    background: var(--yb-brand-600);
    border-color: var(--yb-brand-600);
}

[data-theme="dark"] .yb-gov-status__cta { color: var(--yb-brand-400); }
[data-theme="dark"] .yb-gov-status__cta:hover { color: #fff; }

/* Sub-page surface wrapper + toolbar */
.yb-gov-surface {
    margin-top: 0.75rem;
    padding: 1.1rem 1.2rem;
    background: var(--yb-card);
    border: 1px solid var(--yb-border);
    border-radius: var(--yb-radius-lg);
    box-shadow: var(--yb-shadow-sm);
}

.yb-gov-toolbar {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin-bottom: 0.9rem;
}
.yb-gov-toolbar__spacer { margin-left: auto; }

/* ---- Theme-aware audit table (break-glass) ---- */
.yb-gov-table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: 0.85rem;
}
.yb-gov-table thead th {
    text-align: left;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--yb-text-muted);
    padding: 0.55rem 0.75rem;
    border-bottom: 1px solid var(--yb-border);
}
.yb-gov-table tbody td {
    padding: 0.6rem 0.75rem;
    color: var(--yb-text);
    border-bottom: 1px solid var(--yb-border);
    vertical-align: middle;
}
.yb-gov-table tbody tr:last-child td { border-bottom: 0; }
.yb-gov-table tbody tr:hover td { background: rgba(31, 111, 229, 0.05); }
.yb-gov-table .yb-gov-muted { color: var(--yb-text-muted); }

@media (max-width: 600px) {
    .yb-gov-hero__main { flex-wrap: wrap; }
    .yb-gov-posture { margin-left: 0; }
}
