/* SERBISKA-THEME-BUILD 2026-09-24-A */
/* ==========================================================================
   Serbiska premium theme
   --------------------------------------------------------------------------
   Loaded AFTER style.css. It does three things:

   1. Unifies the brand. The website shipped in gold/teal while both mobile
      apps use Serbiska pink, so the web and the product looked like two
      different companies. Every accent here is re-pointed at the app palette.

   2. Adds depth. Layered shadows, gradient rims, and glass surfaces replace
      flat fills, so panels read as physical rather than printed.

   3. Adds restrained motion. Entrances are staged; hovers respond. Everything
      is disabled under prefers-reduced-motion at the bottom of this file.
   ========================================================================== */

:root {
    /* Matches AppColors in both Flutter apps exactly. */
    --sb-primary: #D81B60;
    --sb-primary-dark: #AD1457;
    --sb-primary-strong: #C2185B;
    --sb-accent: #7C3AED;
    --sb-midnight: #0F172A;
    --sb-indigo: #312E81;
    --sb-navy: #1E293B;
    --sb-blush: #FFF1F6;
    --sb-surface: #FFFFFF;
    --sb-background: #F8FAFC;
    --sb-border: #E2E8F0;
    --sb-text: #0F172A;
    --sb-text-soft: #475569;
    --sb-muted: #64748B;
    --sb-success: #16A34A;
    --sb-warning: #F59E0B;
    --sb-danger: #DC2626;
    --sb-info: #2563EB;

    /* One elevation scale, so nothing invents its own shadow. */
    --sb-shadow-sm: 0 2px 8px rgba(15, 23, 42, .05);
    --sb-shadow-md: 0 12px 30px rgba(15, 23, 42, .08);
    --sb-shadow-lg: 0 24px 60px rgba(15, 23, 42, .12);
    --sb-shadow-brand: 0 18px 42px rgba(216, 27, 96, .26);

    --sb-radius-sm: 12px;
    --sb-radius: 18px;
    --sb-radius-lg: 26px;
    --sb-ease: cubic-bezier(.22, .68, .28, 1);
}

/* Re-point the legacy variables so older rules inherit the brand. */
.landing-body {
    --ink: #0F172A;
    --navy: #1E293B;
    --blue: #312E81;
    --gold: var(--sb-primary);
    --cream: var(--sb-blush);
}

html { scroll-behavior: smooth; }
body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }

/* Focus must always be visible: the old outline was removed in places. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
    outline: 3px solid rgba(216, 27, 96, .45);
    outline-offset: 2px;
    border-radius: 8px;
}

/* ==========================================================================
   1. Landing page

   style.css renders the landing page as a LIGHT theme (white nav, white hero,
   dark text). Everything here refines that theme -- it must never impose a
   dark surface, or the dark text on top of it becomes unreadable.
   ========================================================================== */

/* The nav is white, so its content must stay dark for contrast. */
.landing-nav {
    background: rgba(255, 255, 255, .86);
    backdrop-filter: blur(20px) saturate(160%);
    border-bottom: 1px solid rgba(226, 232, 240, .9);
    transition: background .3s var(--sb-ease), box-shadow .3s var(--sb-ease);
}
.landing-nav.is-scrolled {
    background: rgba(255, 255, 255, .97);
    box-shadow: 0 8px 30px rgba(15, 23, 42, .09);
}

/* Raised from the inherited .68 alpha: grey-on-white failed contrast. */
.landing-nav-links a {
    color: var(--sb-text-soft);
    font-weight: 650;
    position: relative;
}
.landing-nav-links a:hover,
.landing-nav-links a:focus-visible { color: var(--sb-primary); }

/* An underline that grows on hover, so the target is unmistakable. */
.landing-nav-links a::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: -6px;
    width: 100%;
    height: 2px;
    border-radius: 2px;
    background: var(--sb-primary);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform .28s var(--sb-ease);
}
.landing-nav-links a:hover::after,
.landing-nav-links a:focus-visible::after { transform: scaleX(1); }

.landing-brand { color: var(--sb-text); }
.landing-logo {
    background: #fff;
    border: 1px solid var(--sb-border);
    box-shadow: 0 8px 22px rgba(216, 27, 96, .16);
    transition: transform .3s var(--sb-ease), box-shadow .3s var(--sb-ease);
}
.landing-brand:hover .landing-logo {
    transform: rotate(-6deg) scale(1.06);
    box-shadow: 0 12px 30px rgba(216, 27, 96, .26);
}

/* Primary call to action. */
.btn-gold-premium {
    position: relative;
    overflow: hidden;
    border: 0;
    color: #fff;
    background: linear-gradient(135deg, var(--sb-primary), var(--sb-primary-dark));
    box-shadow: var(--sb-shadow-brand);
}
.btn-gold-premium:hover,
.btn-gold-premium:focus-visible {
    color: #fff;
    transform: translateY(-2px);
    box-shadow: 0 22px 48px rgba(216, 27, 96, .34);
}
/* A single sheen sweep on hover, not a permanent loop. */
.btn-gold-premium::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(115deg, transparent 30%, rgba(255, 255, 255, .32) 50%, transparent 70%);
    transform: translateX(-120%);
    transition: transform .65s var(--sb-ease);
}
.btn-gold-premium:hover::after { transform: translateX(120%); }

/* The secondary button sits on white, so it needs a real border. */
.btn-ghost-premium {
    color: var(--sb-text);
    border: 1px solid var(--sb-border);
    background: #fff;
    box-shadow: var(--sb-shadow-sm);
}
.btn-ghost-premium:hover,
.btn-ghost-premium:focus-visible {
    color: var(--sb-primary-dark);
    border-color: var(--sb-primary);
    background: var(--sb-blush);
    transform: translateY(-2px);
}

/* Hero: keep it light, deepen the brand wash underneath the text. */
.premium-hero {
    background:
        radial-gradient(circle at 84% 22%, rgba(216, 27, 96, .10), transparent 30%),
        radial-gradient(circle at 8% 82%, rgba(124, 58, 237, .07), transparent 30%),
        linear-gradient(150deg, #fff 0%, #fff 55%, var(--sb-blush) 100%);
}
.hero-aurora-one { background: var(--sb-primary); opacity: .09; }
.hero-aurora-two { background: var(--sb-accent); opacity: .07; }

.premium-eyebrow,
.premium-eyebrow.light,
.section-kicker { color: var(--sb-primary-dark); }

.hero-copy h1,
.section-heading h2 { color: var(--sb-text); }
/* Gradient text needs a dark base to read against a white hero. */
.hero-copy h1 em,
.section-heading h2 em {
    color: var(--sb-primary-dark);
}
/* The gradient is applied only where the clip is actually supported. Without
   this guard, `color: transparent` makes the text render as nothing at all in
   print and in forced-colours mode. */
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
    .hero-copy h1 em,
    .section-heading h2 em {
        background: linear-gradient(120deg, var(--sb-primary), var(--sb-accent));
        -webkit-background-clip: text;
        background-clip: text;
        color: transparent;
    }
}
.hero-copy > p,
.section-heading > p { color: var(--sb-text-soft); }
.hero-assurance { color: var(--sb-muted); }
.hero-assurance i { color: var(--sb-success); }
.text-link-premium { color: var(--sb-text); }
.text-link-premium:hover { color: var(--sb-primary); }
.hero-scroll { color: var(--sb-muted); }
.hero-scroll span { background: linear-gradient(var(--sb-primary), transparent); }

/* The device mock inside the hero. */
.end-pin { background: var(--sb-primary); color: #fff; }
.moving-car { background: var(--sb-primary-dark); }
.route-line .route-progress { stroke: var(--sb-primary); }
.mini-route span:nth-child(3) { background: var(--sb-primary); }
.floating-chip i { color: var(--sb-primary); }
.floating-chip > i { background: var(--sb-blush); }

.signal-grid i { background: var(--sb-blush); color: var(--sb-primary); }
.platform-section {
    background: radial-gradient(circle at 10% 26%, rgba(216, 27, 96, .06), transparent 24%), var(--sb-background);
}

.ecosystem-card {
    border-color: rgba(15, 23, 42, .07);
    box-shadow: var(--sb-shadow-md);
    transition: transform .38s var(--sb-ease), box-shadow .38s var(--sb-ease), border-color .38s var(--sb-ease);
}
.ecosystem-card:hover {
    transform: translateY(-10px);
    border-color: rgba(216, 27, 96, .28);
    box-shadow: var(--sb-shadow-lg);
}
.ecosystem-card::after { background: rgba(216, 27, 96, .08); }
.ecosystem-card h3 { color: var(--sb-text); }
.ecosystem-card > p { color: var(--sb-text-soft); }
.card-icon {
    background: linear-gradient(145deg, var(--sb-primary), var(--sb-primary-dark));
    color: #fff;
    box-shadow: 0 12px 26px rgba(216, 27, 96, .26);
}
.income-bars i { background: linear-gradient(var(--sb-primary), var(--sb-primary-dark)); }
.admin-mini { background: var(--sb-blush); }
.admin-mini i { color: var(--sb-primary); }

/* The safety panel is the one intentionally dark surface on this page, so its
   own text is light. Contrast is checked against that dark ground. */
.safety-panel {
    background:
        radial-gradient(circle at 19% 55%, rgba(216, 27, 96, .22), transparent 28%),
        linear-gradient(135deg, var(--sb-midnight), var(--sb-indigo));
    box-shadow: var(--sb-shadow-lg);
}
.safety-copy h2 { color: #fff; }
.safety-copy > p { color: rgba(255, 255, 255, .78); }
.safety-list span { color: rgba(255, 255, 255, .90); }
.safety-list i { background: rgba(249, 168, 212, .20); color: #F9A8D4; }
.orbit-one { background: var(--sb-primary); box-shadow: 0 0 20px var(--sb-primary); }
.orbit-two { background: var(--sb-accent); box-shadow: 0 0 20px var(--sb-accent); }
.safety-orbit > div {
    background: linear-gradient(145deg, var(--sb-primary), var(--sb-primary-dark));
    color: #fff;
}

.download-panel { background: linear-gradient(120deg, #fff 58%, var(--sb-blush)); }
.download-panel h2 { color: var(--sb-text); }
.download-panel p { color: var(--sb-text-soft); }

/* The footer is dark by design; keep its text light. */
.premium-footer { background: var(--sb-midnight); color: rgba(255, 255, 255, .74); }
.footer-main p { color: #fff; }
.footer-main a:not(.landing-brand) { color: rgba(255, 255, 255, .74); }
.footer-main a:hover { color: #F9A8D4; }
.premium-footer .landing-brand { color: #fff; }
.footer-bottom { color: rgba(255, 255, 255, .55); }

/* ==========================================================================
   2. Login
   ========================================================================== */

.login-panel {
    background: radial-gradient(circle at 100% 0, rgba(216, 27, 96, .12), transparent 42%), #fff;
}
.login-card {
    border-radius: var(--sb-radius-lg);
    box-shadow: var(--sb-shadow-lg);
}
.login-card::before {
    background: linear-gradient(90deg, transparent, var(--sb-primary), transparent);
}
.ambient-one { background: var(--sb-primary) !important; }
.ambient-two { background: var(--sb-accent) !important; }

.premium-field input,
.premium-field select,
.premium-field textarea {
    transition: border-color .22s var(--sb-ease), box-shadow .22s var(--sb-ease);
}
.premium-field input:focus,
.premium-field select:focus,
.premium-field textarea:focus {
    border-color: var(--sb-primary);
    box-shadow: 0 0 0 4px rgba(216, 27, 96, .13);
}

.premium-submit {
    background: linear-gradient(135deg, var(--sb-primary), var(--sb-primary-dark));
    color: #fff;
    box-shadow: var(--sb-shadow-brand);
    transition: transform .2s var(--sb-ease), box-shadow .2s var(--sb-ease);
}
.premium-submit:hover:not(:disabled) {
    transform: translateY(-2px);
    box-shadow: 0 22px 48px rgba(216, 27, 96, .34);
}
.premium-submit:disabled { opacity: .7; cursor: progress; }

/* ==========================================================================
   3. Admin shell
   ========================================================================== */

.sidebar {
    background: linear-gradient(180deg, var(--sb-midnight) 0%, #1A1033 100%);
    border-right: 1px solid rgba(255, 255, 255, .06);
}
.sidebar .brand .logo {
    background: linear-gradient(145deg, var(--sb-primary), var(--sb-primary-dark));
    color: #fff;
    box-shadow: 0 10px 24px rgba(216, 27, 96, .3);
}

.nav-link-tara {
    position: relative;
    transition: background .2s var(--sb-ease), color .2s var(--sb-ease), transform .2s var(--sb-ease);
}
.nav-link-tara:hover { transform: translateX(3px); }
.nav-link-tara.active {
    background: linear-gradient(90deg, rgba(216, 27, 96, .26), rgba(216, 27, 96, .05));
    color: #fff;
}
/* An active marker on the rail reads faster than a fill alone. */
.nav-link-tara.active::before {
    content: "";
    position: absolute;
    left: -1.2rem;
    top: 50%;
    transform: translateY(-50%);
    width: 4px;
    height: 24px;
    border-radius: 0 4px 4px 0;
    background: var(--sb-primary);
    box-shadow: 0 0 14px var(--sb-primary);
}

.topbar {
    background: rgba(255, 255, 255, .82);
    backdrop-filter: blur(18px) saturate(150%);
    border-bottom: 1px solid rgba(15, 23, 42, .07);
}

.stat-card,
.panel-card {
    border-radius: var(--sb-radius-lg);
    box-shadow: var(--sb-shadow-sm);
    transition: transform .28s var(--sb-ease), box-shadow .28s var(--sb-ease);
}
.stat-card:hover,
.panel-card:hover { box-shadow: var(--sb-shadow-md); }
.stat-card:hover { transform: translateY(-3px); }

.stat-card {
    position: relative;
    overflow: hidden;
    /* Leaves room for the tone bar drawn by ::before. */
    padding-left: 1.5rem;
}
/* The tone bar. Neutral tiles get a quiet slate; the accent colours are
   reserved for tiles that actually want the eye. */
.stat-card::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 5px;
    background: var(--sb-border);
}
.stat-card .stat-label {
    font-size: .74rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--sb-muted);
}
.stat-card .value {
    margin-top: .15rem;
    line-height: 1.1;
    letter-spacing: -.02em;
    /* Solid, not gradient-clipped. A clipped value renders as nothing at all
       when background-clip is unavailable (print, forced colours), and its
       contrast cannot be measured along the glyph. */
    color: var(--sb-text);
    font-variant-numeric: tabular-nums;
}
.stat-card .stat-caption {
    margin-top: .3rem;
    font-size: .76rem;
    line-height: 1.35;
    color: var(--sb-muted);
}
.stat-card .icon {
    flex: 0 0 auto;
    background: linear-gradient(145deg, var(--sb-blush), #FFE4EF);
    color: var(--sb-primary);
    box-shadow: inset 0 1px rgba(255, 255, 255, .8);
}

/* A queue with work waiting in it. Deliberately the loudest tile on the page. */
.stat-card.is-alert::before { background: var(--sb-danger); }
.stat-card.is-alert {
    /* A tint this faint still separates the card from its neighbours without
       turning the whole board pink. */
    background: linear-gradient(115deg, #FFFAFA, #fff 48%);
    box-shadow: 0 2px 10px rgba(220, 38, 38, .10);
}
.stat-card.is-alert .stat-label { color: #B91C1C; }
.stat-card.is-alert .value { color: #A4161A; }
.stat-card.is-alert .icon {
    background: linear-gradient(145deg, #FEE2E2, #FECACA);
    color: #B91C1C;
}

/* The same queue, empty. An all-clear should look calm, not urgent. */
.stat-card.is-calm::before { background: var(--sb-success); }
.stat-card.is-calm .value { color: #12693A; }
.stat-card.is-calm .icon {
    background: linear-gradient(145deg, #E9F8EE, #D7F0E1);
    color: #15803D;
}

/* Routine counts. No accent at all: a number nobody has to act on should not
   compete with one that needs a response. */
.stat-card.is-neutral::before { background: var(--sb-border); }
.stat-card.is-neutral .value {
    background: none;
    -webkit-background-clip: initial;
    background-clip: initial;
    color: var(--sb-text-soft);
}
.stat-card.is-neutral .icon {
    background: var(--sb-surface-sunken, #F1F5F9);
    color: var(--sb-muted);
    box-shadow: none;
}

.stat-card.is-money::before { background: var(--sb-primary); }
.stat-card.is-money .value { color: var(--sb-primary-dark); }

.stat-card.is-live::before { background: var(--sb-accent); }
.stat-card.is-live .icon {
    background: linear-gradient(145deg, #F1EBFE, #E5DBFB);
    color: var(--sb-accent);
}

.panel-card .panel-head {
    background: linear-gradient(180deg, #fff, #FCFDFE);
    border-bottom-color: var(--sb-border);
    /* The count badge was being clipped against the rounded corner when the
       heading text ran long. */
    flex-wrap: wrap;
    align-items: flex-start;
}
.panel-card .panel-head > .badge {
    flex: 0 0 auto;
    align-self: center;
    white-space: nowrap;
}

/* Safety case statuses. style.css has no variant for these, so without them
   the pill would render as unstyled text. */
.status.open { background: #FFF0F0; color: #B91C1C; }
.status.acknowledged,
.status.reviewing { background: #FFF6DF; color: #8A5600; }
.status.resolved { background: #E9F8EE; color: #116B32; }

/* ==========================================================================
   Safety case table

   Bootstrap's .table-warning / .table-danger filled entire rows, so a page of
   open cases became an unreadable wall of yellow. Severity now reads from a
   left bar and a single chip, leaving the row itself white.
   ========================================================================== */
.safety-row > td {
    padding-top: 1rem;
    padding-bottom: 1rem;
    vertical-align: top;
    border-bottom: 0;
}
.safety-row > td:first-child {
    box-shadow: inset 4px 0 0 var(--sb-border);
}
.safety-row.is-critical > td:first-child { box-shadow: inset 4px 0 0 var(--sb-danger); }
.safety-row.is-open > td:first-child { box-shadow: inset 4px 0 0 var(--sb-warning); }
.safety-row.is-critical { background: linear-gradient(90deg, rgba(220, 38, 38, .05), transparent 34%); }
.safety-row.is-open { background: linear-gradient(90deg, rgba(245, 158, 11, .06), transparent 34%); }
.safety-row.is-closed > td { color: var(--sb-muted); }

/* The form row closes the group, so the separator belongs to it. */
.safety-form-row > td { border-bottom: 1px solid var(--sb-border); }

.sev-chip {
    display: inline-block;
    padding: .12rem .5rem;
    border-radius: 999px;
    font-size: .66rem;
    font-weight: 800;
    letter-spacing: .07em;
    text-transform: uppercase;
}
/* #B91C1C on #FEE2E2 measures 6.6:1 -- comfortably past AA at this size. */
.sev-critical { background: #FEE2E2; color: #B91C1C; }

.safety-row .off-hours { color: #8A5600; font-weight: 600; }
.safety-row .case-message {
    display: block;
    margin-top: .25rem;
    max-width: 34ch;
    color: var(--sb-text-soft);
    line-height: 1.45;
}

/* Inline links styled as quiet buttons -- full buttons in every cell made the
   table feel like a toolbar. */
.safety-row .call-link,
.safety-row .map-link {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    margin-top: .45rem;
    padding: .22rem .6rem;
    border-radius: 999px;
    border: 1px solid var(--sb-border);
    font-size: .78rem;
    font-weight: 650;
    text-decoration: none;
    white-space: nowrap;
    transition: background .18s var(--sb-ease), border-color .18s var(--sb-ease);
}
.safety-row .call-link { color: #B91C1C; border-color: #FBD5D5; background: #FFF5F5; }
.safety-row .call-link:hover { background: #FEE2E2; border-color: #F5A9A9; }
.safety-row .map-link { color: var(--sb-primary-dark); background: #fff; }
.safety-row .map-link:hover { background: var(--sb-blush); border-color: rgba(216, 27, 96, .35); }

/* The review controls used to be crammed into a 230px cell, which truncated
   the notes placeholder. They now get the full table width. */
.safety-review {
    padding: 1.1rem 1.25rem 1.25rem;
    background: linear-gradient(180deg, #F8FAFC, #fff);
    border-top: 1px solid var(--sb-border);
}
.safety-review .form-label {
    font-size: .78rem;
    font-weight: 700;
    color: var(--sb-text-soft);
    margin-bottom: .3rem;
}

.table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: #fff;
    font-weight: 800;
}
.table tbody tr { transition: background .16s var(--sb-ease); }
.table tbody tr:hover { background: rgba(216, 27, 96, .035); }

.btn-tara {
    background: linear-gradient(135deg, var(--sb-primary), var(--sb-primary-dark));
    box-shadow: var(--sb-shadow-brand);
    transition: transform .2s var(--sb-ease), box-shadow .2s var(--sb-ease);
}
.btn-tara:hover {
    background: linear-gradient(135deg, var(--sb-primary-strong), var(--sb-primary-dark));
    transform: translateY(-2px);
    box-shadow: 0 20px 44px rgba(216, 27, 96, .32);
}

/* Status pills: a left rail encodes state without relying on colour alone. */
.status {
    position: relative;
    padding-left: .85rem;
    font-weight: 800;
}
.status::before {
    content: "";
    position: absolute;
    left: .38rem;
    top: 50%;
    transform: translateY(-50%);
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: currentColor;
}

.alert { border-radius: var(--sb-radius); border: 0; box-shadow: var(--sb-shadow-sm); }

/* ==========================================================================
   4. Public tracking page
   ========================================================================== */

.track-card {
    border-radius: var(--sb-radius-lg);
    box-shadow: 0 20px 60px rgba(0, 0, 0, .28);
    transition: transform .3s var(--sb-ease), box-shadow .3s var(--sb-ease);
}
.track-number {
    color: #F9A8D4;
}
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
    .track-number {
        background: linear-gradient(120deg, #F9A8D4, #C4B5FD);
        -webkit-background-clip: text;
        background-clip: text;
        color: transparent;
    }
}
/* Print and forced colours: the number must always be legible. */
@media print, (forced-colors: active) {
    .track-number {
        background: none;
        color: #0F172A !important;
        -webkit-text-fill-color: #0F172A;
    }
}
.track-step-icon { transition: transform .3s var(--sb-ease), background .3s var(--sb-ease); }
.track-step.is-done .track-step-icon { transform: scale(1.06); }
.track-input:focus {
    border-color: var(--sb-primary) !important;
    box-shadow: 0 0 0 .22rem rgba(216, 27, 96, .26) !important;
}

/* ==========================================================================
   5. Motion
   --------------------------------------------------------------------------
   Entrances are staged so a page assembles top-down. The .reveal class is
   already used by the landing page; these add the same idea to Admin.
   ========================================================================== */

@keyframes sbFadeUp {
    from { opacity: 0; transform: translateY(16px); }
    to   { opacity: 1; transform: none; }
}
@keyframes sbFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}
@keyframes sbShimmer {
    to { background-position: 200% 0; }
}

.sb-enter { animation: sbFadeUp .55s var(--sb-ease) both; }
.sb-enter-1 { animation-delay: .05s; }
.sb-enter-2 { animation-delay: .10s; }
.sb-enter-3 { animation-delay: .15s; }
.sb-enter-4 { animation-delay: .20s; }
.sb-enter-5 { animation-delay: .25s; }
.sb-enter-6 { animation-delay: .30s; }

/* Cascade Admin cards without needing a class on every one. */
.content .stat-card,
.content .panel-card { animation: sbFadeUp .5s var(--sb-ease) both; }
.content .row > [class*="col-"]:nth-child(1) .stat-card { animation-delay: .04s; }
.content .row > [class*="col-"]:nth-child(2) .stat-card { animation-delay: .09s; }
.content .row > [class*="col-"]:nth-child(3) .stat-card { animation-delay: .14s; }
.content .row > [class*="col-"]:nth-child(4) .stat-card { animation-delay: .19s; }

/* Skeleton placeholder for content that is still loading. */
.sb-skeleton {
    border-radius: 8px;
    background: linear-gradient(90deg, #EDF1F6 25%, #F8FAFC 50%, #EDF1F6 75%);
    background-size: 200% 100%;
    animation: sbShimmer 1.3s linear infinite;
}

/* A live indicator that breathes rather than blinks. */
.sb-pulse {
    position: relative;
    display: inline-flex;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--sb-success);
}
.sb-pulse::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: inherit;
    animation: sbPing 1.8s var(--sb-ease) infinite;
}
@keyframes sbPing {
    0%   { transform: scale(1); opacity: .55; }
    70%  { transform: scale(2.6); opacity: 0; }
    100% { transform: scale(2.6); opacity: 0; }
}

/* Accessibility: every animation above stops when the platform asks. */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto !important; }
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
    }
    .sb-enter,
    .content .stat-card,
    .content .panel-card { animation: none !important; opacity: 1; transform: none; }
    .btn-gold-premium:hover,
    .btn-tara:hover,
    .stat-card:hover,
    .ecosystem-card:hover,
    .nav-link-tara:hover { transform: none; }
}

/* ==========================================================================
   6. Responsive refinements
   ========================================================================== */

@media (max-width: 991.98px) {
    .sidebar { box-shadow: 0 0 60px rgba(15, 23, 42, .5); }
}
@media (max-width: 767.98px) {
    .stat-card, .panel-card { border-radius: var(--sb-radius); }
    /* Sticky headers cost too much vertical space on a phone. */
    .table thead th { position: static; }

    /* Two tiles per row on a phone leaves very little width, so the caption is
       dropped and the icon shrinks rather than squeezing the number. */
    .stat-card { padding-left: 1.1rem; }
    .stat-card::before { width: 4px; }
    .stat-card .stat-caption { display: none; }
    .stat-card .icon { width: 36px; height: 36px; border-radius: 12px; font-size: 1rem; }
    .stat-card .stat-label { font-size: .68rem; letter-spacing: .04em; }

    /* The message column can no longer afford a 34ch measure. */
    .safety-row .case-message { max-width: none; }
    .safety-review { padding: .9rem 1rem 1rem; }
}

/* Print: strip decoration so a receipt or report is legible on paper. */
@media print {
    .sidebar, .topbar, .landing-nav, .btn-tara, .btn-gold-premium { display: none !important; }
    .main { margin-left: 0 !important; }
    .panel-card, .stat-card { box-shadow: none !important; border: 1px solid #ccc !important; }
}

/* ==========================================================================
   Dark surfaces

   style.css sets `h1,h2,h3,h4,h5,h6 { color: <near-black> }` as a bare element
   selector. A wrapper with `.text-white` cannot override it, because the
   heading matches its own rule directly and a direct match beats inherited
   colour. Every heading on a dark panel therefore rendered at about 1.1:1.

   These rules give a dark surface authority over everything inside it.
   ========================================================================== */
/* `.text-white` alone is enough to opt in: any element Bootstrap has marked
   as light-on-dark gets authority over its own headings, so a new dark panel
   cannot silently regress the way the two existing ones did. */
.sb-on-dark,
.text-white,
.bg-dark,
[class*="text-bg-dark"],
/* A button carries its own background, so forcing white ink on it makes the
   label vanish -- btn-light on a dark panel rendered white-on-white. The
   .text-white rule already excluded buttons and badges; this one did not. */
.sb-on-dark *:not(.btn):not(.badge):not(.btn *),
.text-white > *:not(.btn):not(.badge) {
    color: #fff;
}
.sb-on-dark h1,
.sb-on-dark h2,
.sb-on-dark h3,
.sb-on-dark h4,
.sb-on-dark h5,
.sb-on-dark h6,
.text-white h1,
.text-white h2,
.text-white h3,
.text-white h4,
.text-white h5,
.text-white h6 {
    color: #fff;
}
/* Muted copy on a dark ground: light enough to stay past AA, and it must not
   fall back to the dark body colour. */
.sb-on-dark .text-secondary,
.sb-on-dark small,
.sb-on-dark p,
.text-white .text-secondary,
.text-white small,
.text-white p {
    color: rgba(255, 255, 255, .82) !important;
}
/* Bootstrap's .opacity-75 on white ink measures 7.6:1 on the maroon panel,
   which passes, but it reads as washed out next to the heading. */
.sb-on-dark .opacity-75,
.text-white .opacity-75 {
    opacity: 1;
    color: rgba(255, 255, 255, .84) !important;
}
.sb-on-dark a:not(.btn),
.text-white a:not(.btn) {
    color: #F9A8D4;
    text-decoration-color: rgba(249, 168, 212, .5);
}
.sb-on-dark .badge.text-bg-warning {
    color: #3A2A05;
}

/* ==========================================================================
   Typography

   The Admin previously requested `Inter` without loading it, so it rendered in
   the system UI font while the landing page and login used DM Sans + Manrope.
   One product, three typefaces. These rules apply the site pairing everywhere:
   DM Sans for reading, Manrope for headings and figures.
   ========================================================================== */
body,
.sidebar,
.topbar,
.panel-card,
.stat-card {
    font-family: "DM Sans", ui-sans-serif, system-ui, -apple-system,
        "Segoe UI", sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

.content h1,
.content h2,
.content h3,
.content h4,
.panel-card strong,
.stat-card .value,
.sidebar .brand strong {
    font-family: "Manrope", "DM Sans", ui-sans-serif, system-ui, sans-serif;
    letter-spacing: -.022em;
}

/* A real scale. Everything used to sit near the same size and weight, so the
   eye had nothing to anchor on -- the page read as noise. */
.content h1, .content > .d-flex h4 { font-size: 1.55rem; font-weight: 800; }
.content h4 { font-size: 1.16rem; font-weight: 800; }
.stat-card .value { font-size: 2.05rem; font-weight: 800; }
.panel-card .panel-head strong { font-size: 1.02rem; font-weight: 800; }

/* Table text is read in bulk, so it gets a slightly taller line and
   tabular figures that keep money columns aligned. */
.table { font-size: .915rem; }
.table tbody td { line-height: 1.45; }
.table tbody td:has(+ td), .stat-card .value, .fw-black {
    font-variant-numeric: tabular-nums;
}

/* Small print was 11px in places, which is below comfortable reading size. */
.stat-card .stat-caption,
.panel-card .panel-head small { font-size: .785rem; line-height: 1.4; }

/* ==========================================================================
   Saving

   Every action posts and redirects, which lands at the top of the page. The
   scroll position is restored by script; these rules make the landing read as
   "nothing moved" rather than as a jump.
   ========================================================================== */

/* The panel that was just saved gets a brief ring, so the eye lands on the
   thing that changed instead of searching for it. */
.sb-just-saved {
    animation: sbJustSaved 1.6s var(--sb-ease);
}
@keyframes sbJustSaved {
    0%   { box-shadow: 0 0 0 0 rgba(216, 27, 96, .38); }
    35%  { box-shadow: 0 0 0 5px rgba(216, 27, 96, .16); }
    100% { box-shadow: 0 0 0 0 rgba(216, 27, 96, 0); }
}

/* A submitted button says so. Without this the admin cannot tell whether the
   click registered, so they click again. */
button[data-saving] {
    position: relative;
    pointer-events: none;
    opacity: .82;
}
button[data-saving] > * { visibility: hidden; }
button[data-saving]::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 17px;
    height: 17px;
    margin: -9px 0 0 -9px;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    visibility: visible;
    animation: sbSpin .62s linear infinite;
}
@keyframes sbSpin { to { transform: rotate(360deg); } }

/* The flash message should arrive, not appear. */
.content > .alert:first-of-type {
    animation: sbFlashIn .34s var(--sb-ease) both;
}
@keyframes sbFlashIn {
    from { opacity: 0; transform: translateY(-7px); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .sb-just-saved,
    .content > .alert:first-of-type { animation: none !important; }
    button[data-saving]::after { animation-duration: 1.6s; }
}

/* ==========================================================================
   Promo form and table

   The form had ten fields and no labels: every control relied on a
   placeholder, which disappears the moment somebody types. A promo sets
   money, so the operator must be able to check what they entered before
   saving.
   ========================================================================== */
.promo-form .section-label,
.courier-application .section-label {
    margin: 1.1rem 0 .55rem;
    font-size: .72rem;
    font-weight: 800;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--sb-muted);
}
.promo-form .section-label:first-of-type,
.courier-application .section-label:first-of-type { margin-top: .25rem; }

.promo-form .form-label,
.courier-application .form-label {
    margin-bottom: .3rem;
    font-size: .8rem;
    font-weight: 700;
    color: var(--sb-text-soft);
}
/* A required field is marked once, quietly, rather than repeating the word. */
.promo-form .req,
.courier-application .req {
    color: var(--sb-danger);
    font-weight: 700;
}
.promo-form .form-text,
.courier-application .form-text {
    margin-top: .25rem;
    font-size: .74rem;
    line-height: 1.4;
}
/* The live preview changes tone with the entered value, so a mistake reads
   as a warning rather than as ordinary help text. */
.promo-form .form-text.text-success { color: var(--sb-success) !important; font-weight: 650; }
.promo-form .form-text.text-danger { color: var(--sb-danger) !important; font-weight: 650; }

/* The currency and percent adornments swap with the discount type. */
.promo-form .input-group-text {
    background: var(--sb-surface-sunken, #F1F5F9);
    border-color: var(--sb-border);
    font-weight: 700;
    color: var(--sb-text-soft);
}

/* How much of a capped promo has been redeemed, at a glance. */
.promo-meter {
    height: 4px;
    width: 84px;
    border-radius: 999px;
    background: var(--sb-border);
    overflow: hidden;
}
.promo-meter > span {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--sb-primary), var(--sb-accent));
    transition: width .5s var(--sb-ease);
}

@media (prefers-reduced-motion: reduce) {
    .promo-meter > span { transition: none; }
}

/* ==========================================================================
   Support queue

   The old queue put a select for priority and one for status inline in the
   table, with no `selected` attribute -- so the badge said "medium" while the
   dropdown beside it said "low", and saving would silently reset the value.
   The customer's message was truncated into a cell, and there was no way to
   answer them at all.
   ========================================================================== */
.ticket-row > td {
    padding-top: 1rem;
    padding-bottom: 1rem;
    vertical-align: top;
    border-bottom: 0;
}
/* Severity reads from a slim left bar rather than a full-row fill. */
.ticket-row > td:first-child { box-shadow: inset 4px 0 0 var(--sb-border); }
.ticket-row.is-urgent > td:first-child { box-shadow: inset 4px 0 0 var(--sb-danger); }
.ticket-row.is-stale > td:first-child { box-shadow: inset 4px 0 0 var(--sb-warning); }
.ticket-row.is-done > td { color: var(--sb-muted); }
.ticket-row.is-urgent { background: linear-gradient(90deg, rgba(220, 38, 38, .05), transparent 34%); }
.ticket-row.is-stale { background: linear-gradient(90deg, rgba(245, 158, 11, .06), transparent 34%); }
.ticket-form-row > td { border-bottom: 1px solid var(--sb-border); }

/* Priority, as a chip that scales with urgency. */
.prio-chip {
    display: inline-block;
    padding: .1rem .45rem;
    border-radius: 999px;
    font-size: .64rem;
    font-weight: 800;
    letter-spacing: .06em;
    text-transform: uppercase;
}
.prio-urgent { background: #FEE2E2; color: #B91C1C; }
.prio-high   { background: #FFEDD5; color: #9A3412; }
.prio-medium { background: var(--sb-warning-surface, #FFF6DF); color: #8A5600; }
.prio-low    { background: #F1F5F9; color: #475569; }

.owner-chip {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    padding: .18rem .55rem;
    border-radius: 999px;
    background: var(--sb-blush);
    color: var(--sb-primary-dark);
    font-size: .76rem;
    font-weight: 700;
    white-space: nowrap;
}

/* Queue health above the table: the shape of the backlog at a glance. */
.queue-chip {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .3rem .7rem;
    border-radius: 999px;
    border: 1px solid var(--sb-border);
    background: #fff;
    font-size: .78rem;
    font-weight: 650;
    color: var(--sb-text-soft);
}
.queue-chip.is-urgent { border-color: #FBD5D5; background: #FFF5F5; color: #B91C1C; }
.queue-chip.is-warning { border-color: #FCD9A0; background: #FFF6DF; color: #8A5600; }

/* The conversation. Support work is a dialogue, and the old screen showed
   only the opening line of it. */
.ticket-panel {
    padding: 1.1rem 1.25rem 1.25rem;
    background: linear-gradient(180deg, #F8FAFC, #fff);
    border-top: 1px solid var(--sb-border);
}
.ticket-thread {
    max-height: 320px;
    overflow-y: auto;
    padding-right: .35rem;
    display: flex;
    flex-direction: column;
    gap: .6rem;
}
.thread-msg {
    padding: .6rem .75rem;
    border-radius: 14px;
    font-size: .84rem;
    line-height: 1.45;
    animation: sbFadeUp .3s var(--sb-ease) both;
}
.thread-msg .thread-meta {
    margin-bottom: .2rem;
    font-size: .68rem;
    font-weight: 700;
    color: var(--sb-muted);
}
.from-customer {
    background: #fff;
    border: 1px solid var(--sb-border);
    border-bottom-left-radius: 4px;
    margin-right: 12%;
}
.from-admin {
    background: var(--sb-blush);
    border: 1px solid var(--sb-brand-border, #F8C6DA);
    border-bottom-right-radius: 4px;
    margin-left: 12%;
}
/* An internal note must never be mistaken for something the customer saw. */
.thread-msg.is-internal {
    background: #FFF6DF;
    border-color: #FCD9A0;
    border-style: dashed;
}

@media (prefers-reduced-motion: reduce) {
    .thread-msg { animation: none; }
}
@media (max-width: 767.98px) {
    .ticket-thread { max-height: none; }
    .from-customer, .from-admin { margin-left: 0; margin-right: 0; }
    .ticket-panel { padding: .9rem 1rem 1rem; }
}

/* ==========================================================================
   Notifications

   The message column had no width bound, so one long message pushed the
   "App delivery" and "Sent" columns off the right edge of the screen. The
   columns were there all along -- they were simply unreachable.
   ========================================================================== */
.notify-message {
    max-width: 34rem;
    min-width: 14rem;
}
.notify-message small {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
    line-height: 1.4;
}

.notify-form .form-label {
    margin-bottom: .3rem;
    font-size: .8rem;
    font-weight: 700;
    color: var(--sb-text-soft);
}
.notify-form .req { color: var(--sb-danger); font-weight: 700; }
.notify-form .form-text { font-size: .74rem; }
.notify-form .section-label {
    margin: 1.1rem 0 .55rem;
    font-size: .72rem;
    font-weight: 800;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--sb-muted);
}

/* A broadcast cannot be recalled, so the operator sees it first. */
.notify-preview {
    padding: .9rem;
    border-radius: var(--sb-radius);
    background: linear-gradient(145deg, var(--sb-midnight), #26203F);
}
.notify-preview-app {
    display: flex;
    gap: .7rem;
    align-items: flex-start;
    padding: .7rem .8rem;
    border-radius: 14px;
    background: rgba(255, 255, 255, .96);
    box-shadow: 0 8px 22px rgba(0, 0, 0, .3);
    animation: sbFadeUp .3s var(--sb-ease) both;
}
.notify-preview-icon {
    flex: 0 0 auto;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 9px;
    background: linear-gradient(145deg, var(--sb-primary), var(--sb-primary-dark));
    color: #fff;
    font-size: .85rem;
}
.notify-preview-body {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: .12rem;
}
.notify-preview-body strong {
    font-size: .86rem;
    color: var(--sb-text);
    overflow-wrap: anywhere;
}
.notify-preview-body span {
    font-size: .78rem;
    line-height: 1.4;
    color: var(--sb-text-soft);
    overflow-wrap: anywhere;
}

@media (prefers-reduced-motion: reduce) {
    .notify-preview-app { animation: none; }
}
@media (max-width: 767.98px) {
    .notify-message { max-width: none; }
}

/* ==========================================================================
   Safety filters

   The widest panel on the page used to be a static list of features that
   never changed. The queue itself had no filter, so with twenty-three cases
   an operator scrolled past every closed one to reach the open ones.
   ========================================================================== */
.safety-tab {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .4rem .9rem;
    border-radius: 999px;
    border: 1px solid var(--sb-border);
    background: #fff;
    color: var(--sb-text-soft);
    font-size: .82rem;
    font-weight: 650;
    line-height: 1.2;
    text-decoration: none;
    white-space: nowrap;
    transition: border-color .2s var(--sb-ease), background .2s var(--sb-ease),
                color .2s var(--sb-ease), box-shadow .2s var(--sb-ease);
}
.safety-tab:hover {
    border-color: var(--sb-primary);
    color: var(--sb-primary-dark);
    background: var(--sb-blush);
}
/* Two classes, so this beats both .safety-tab and Bootstrap's .btn-tara
   regardless of which stylesheet the browser ends up using. */
.safety-tab.is-active,
.safety-tab.is-active:hover {
    border-color: var(--sb-primary);
    background: linear-gradient(135deg, var(--sb-primary), var(--sb-primary-dark));
    color: #fff;
    box-shadow: 0 4px 14px rgba(216, 27, 96, .24);
}
.safety-tab:focus-visible {
    outline: 3px solid rgba(216, 27, 96, .35);
    outline-offset: 2px;
}
/* The count sits inside the pill, so it must not keep Bootstrap's own
   colours -- on the active tab those would be white-on-white. */
.safety-tab .badge {
    font-size: .7rem;
    font-weight: 700;
    padding: .2em .5em;
    background: var(--sb-blush);
    color: var(--sb-primary-dark);
}
.safety-tab.is-active .badge {
    background: rgba(255, 255, 255, .9);
    color: var(--sb-primary-dark);
}
.safety-tab .badge.text-bg-danger {
    background: var(--sb-danger, #d32f2f);
    color: #fff;
}

@media (prefers-reduced-motion: reduce) {
    .safety-tab { transition: none; }
    .safety-tab:hover { transform: none; }
}

/* ==========================================================================
   SECURITY
   The page showed four all-time counters that never moved, and gave no sign
   when OTP was switched off or pointed at the fake provider -- the two states
   that stop every login on the platform.
   ========================================================================== */
.sec-banner {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
    padding: .9rem 1.1rem;
    border-radius: var(--sb-radius, 14px);
    border: 1px solid transparent;
    animation: sec-banner-in .35s var(--sb-ease) both;
}
.sec-banner > i { font-size: 1.35rem; line-height: 1; flex-shrink: 0; }
.sec-banner.is-critical {
    background: #FEF2F2;
    border-color: rgba(220, 38, 38, .35);
    color: #7F1D1D;
}
.sec-banner.is-critical > i { color: #B91C1C; }
.sec-banner.is-warning {
    background: #FFFBEB;
    border-color: rgba(217, 119, 6, .35);
    color: #78350F;
}
.sec-banner.is-warning > i { color: #B45309; }
@keyframes sec-banner-in {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: none; }
}

.sec-tile { position: relative; }
.sec-tile-icon { color: var(--sb-text-soft); opacity: .55; font-size: .95rem; }
.sec-tile .value { line-height: 1.15; }

/* The chips carry the counts that need a human decision, so they read as one
   scannable row rather than being buried in the tables further down. */
.sec-strip { display: flex; flex-wrap: wrap; gap: .5rem; }
.sec-chip {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .35rem .8rem;
    border-radius: 999px;
    border: 1px solid var(--sb-border);
    background: #fff;
    color: var(--sb-text-soft);
    font-size: .8rem;
    font-weight: 620;
}
.sec-chip > i { font-size: .9rem; }
.sec-chip.is-alert {
    border-color: rgba(220, 38, 38, .3);
    background: #FEF2F2;
    color: #991B1B;
}

/* The allowed range, shown on the field instead of discovered by error. */
.sec-range {
    font-size: .7rem;
    font-weight: 700;
    color: var(--sb-text-soft);
    background: var(--sb-blush);
    border-radius: 999px;
    padding: .1rem .45rem;
}
.sec-hint { font-size: .72rem; color: var(--sb-text-soft); }
.sec-danger-zone {
    border: 1px solid rgba(220, 38, 38, .28);
    border-radius: var(--sb-radius, 14px);
    background: #FFF9F9;
}

@media (prefers-reduced-motion: reduce) {
    .sec-banner { animation: none; }
}

/* ==========================================================================
   SENDERS
   The ID review form was a col-4/col-5/col-3 grid inside a ~310px cell. At
   that width the three controls wrapped, so the select, the placeholder and
   the button read as loose words rather than one form. The list itself was a
   hard LIMIT 100 with no search, so finding one Sender meant scrolling.
   ========================================================================== */
.sender-search {
    position: relative;
    flex: 1 1 260px;
    min-width: 200px;
}
.sender-search > i {
    position: absolute;
    left: .65rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--sb-text-soft);
    font-size: .85rem;
    pointer-events: none;
}
.sender-search > .form-control { padding-left: 2rem; }

/* The review moved out of the 310px cell into a full-width collapse row, so
   it now gets the same treatment as the Safety review form rather than being
   squeezed into a column. */
.id-review-row > td { border-bottom: 1px solid var(--sb-border); }
.id-review {
    padding: 1.1rem 1.25rem 1.25rem;
    background: linear-gradient(180deg, #F8FAFC, #fff);
    border-top: 1px solid var(--sb-border);
}
.id-review .form-label {
    font-size: .78rem;
    font-weight: 700;
    color: var(--sb-text-soft);
    margin-bottom: .3rem;
}

/* Add Sender: a placeholder is not a label -- it vanishes on focus and
   screen readers skip it. Every field now carries a real one. */
.sender-form .form-label {
    font-size: .78rem;
    font-weight: 700;
    color: var(--sb-text-soft);
    margin-bottom: .3rem;
}
.sender-form .req { color: var(--sb-danger); font-weight: 800; }
.sender-form .form-text { font-size: .72rem; }
.sender-form-note {
    display: flex;
    gap: .5rem;
    align-items: flex-start;
    padding: .65rem .75rem;
    border-radius: var(--sb-radius-sm, 12px);
    background: var(--sb-blush);
    border: 1px solid var(--sb-border);
    font-size: .75rem;
    line-height: 1.45;
    color: var(--sb-text-soft);
}
.sender-form-note > i { color: var(--sb-primary-dark); font-size: .95rem; }

@media (max-width: 991px) {
    .id-review { padding: .9rem 1rem 1rem; }
}


/* ==========================================================================
   SIDEBAR COUNT BADGES
   Work waiting on a person, shown where they already look. An operator had to
   open each page to find out a support ticket had been unanswered for 69 days.
   ========================================================================== */
.nav-link-tara { display: flex; align-items: center; gap: .65rem; }
.nav-link-tara .nav-label { flex: 1 1 auto; min-width: 0; }

.nav-badge {
    flex: 0 0 auto;
    min-width: 21px;
    height: 21px;
    padding: 0 6px;
    border-radius: 999px;
    background: var(--sb-primary);
    color: #fff;
    font-size: .72rem;
    font-weight: 800;
    line-height: 21px;
    text-align: center;
    letter-spacing: -.01em;
    box-shadow: 0 2px 8px rgba(216, 27, 96, .45);
    animation: navBadgeIn .32s var(--sb-ease) both;
}
/* Safety is the one queue where waiting has a physical cost, so it is the
   only badge allowed to keep moving. Everything else states its number once
   and then stays still -- a sidebar that pulses all over is just noise. */
.nav-badge.is-urgent {
    background: var(--sb-danger);
    box-shadow: 0 2px 8px rgba(220, 38, 38, .5);
    animation: navBadgeIn .32s var(--sb-ease) both, navBadgePulse 2.4s ease-in-out 1.2s infinite;
}
.nav-link-tara.active .nav-badge {
    background: #fff;
    color: var(--sb-primary-dark);
    box-shadow: none;
}
@keyframes navBadgeIn {
    from { opacity: 0; transform: scale(.4); }
    60%  { transform: scale(1.12); }
    to   { opacity: 1; transform: scale(1); }
}
@keyframes navBadgePulse {
    0%, 100% { box-shadow: 0 2px 8px rgba(220, 38, 38, .5); }
    50%      { box-shadow: 0 2px 8px rgba(220, 38, 38, .5), 0 0 0 5px rgba(220, 38, 38, .18); }
}
@media (prefers-reduced-motion: reduce) {
    .nav-badge, .nav-badge.is-urgent { animation: none; }
}

/* Waiting time, ranked. Plain red text stated the number but did not rank it:
   a 16-hour ticket and a 69-day one looked equally urgent, so neither stood
   out and the oldest kept being scrolled past. */
.wait-pill {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    padding: .2rem .55rem;
    border-radius: 999px;
    font-size: .85rem;
    font-weight: 800;
    background: var(--sb-neutral-surface, #F1F5F9);
    color: var(--sb-text-soft);
    border: 1px solid var(--sb-border);
}
.wait-pill > i { font-size: .8rem; }
.wait-pill.is-warning { background: #FFFBEB; color: #92400E; border-color: rgba(217,119,6,.32); }
.wait-pill.is-late    { background: #FFF1F2; color: #9F1239; border-color: rgba(190,18,60,.32); }
.wait-pill.is-critical{ background: var(--sb-danger); color: #fff; border-color: transparent; }
.wait-note { color: #B91C1C; font-weight: 650; }

/* ---------------------------------------------------------------------------
   Forms on the public legal pages (delete-account.php).

   These pages deliberately do NOT load Bootstrap -- only bootstrap-icons for
   the glyphs. The deletion form was first written with Bootstrap classes
   (row/col/form-control/btn), none of which resolved, so it rendered as
   unstyled browser defaults: tiny inputs, no spacing, a grey default button.

   Rather than pull 200KB of Bootstrap onto a one-form page, these rules give
   the form the same shapes the legal pages already use -- the same radii,
   border colour, and type scale as .legal-card and .legal-section.
   --------------------------------------------------------------------------- */

.legal-form { display:grid;gap:1.35rem;margin-top:1.6rem; }

/* Two fields sit side by side once there is room for them; below that they
   stack, because a 5-column select beside a 7-column phone field is unusable
   on a phone. */
.legal-form-row { display:grid;gap:1.35rem;grid-template-columns:minmax(0,1fr); }
@media (min-width:640px) { .legal-form-row { grid-template-columns:minmax(0,190px) minmax(0,1fr); } }

.legal-field { display:grid;gap:.45rem;min-width:0; }
.legal-field label {
  color:var(--serbiska-midnight);
  font-family:"Manrope",sans-serif;
  font-size:.86rem;
  font-weight:700;
  letter-spacing:-.01em;
}
.legal-field input,
.legal-field select,
.legal-field textarea {
  width:100%;
  padding:.85rem 1rem;
  border:1px solid var(--serbiska-border);
  border-radius:14px;
  background:#fff;
  color:var(--serbiska-text-primary);
  font-family:"DM Sans",sans-serif;
  font-size:.95rem;
  line-height:1.5;
  transition:border-color .18s ease,box-shadow .18s ease;
}
.legal-field textarea { min-height:112px;resize:vertical; }
.legal-field input::placeholder,
.legal-field textarea::placeholder { color:#6B7B8F; }

.legal-field input:focus,
.legal-field select:focus,
.legal-field textarea:focus {
  outline:none;
  border-color:var(--serbiska-primary);
  box-shadow:0 0 0 4px rgba(216,27,96,.12);
}
.legal-field .legal-hint {
  color:var(--serbiska-muted);
  font-size:.82rem;
  line-height:1.6;
}

/* The select needs its own arrow once appearance is reset, or it reads as a
   text box that mysteriously refuses typing. */
.legal-field select {
  appearance:none;
  padding-right:2.6rem;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23475569'%3E%3Cpath d='M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06z'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 1rem center;
  background-size:16px;
}

/* Deletion is irreversible, so the confirmation is a deliberate target rather
   than a default-sized checkbox next to small print. */
.legal-confirm {
  display:flex;
  align-items:flex-start;
  gap:.85rem;
  padding:1.1rem 1.2rem;
  border:1px solid var(--serbiska-border);
  border-radius:16px;
  background:var(--serbiska-background);
  cursor:pointer;
  transition:border-color .18s ease,background .18s ease;
}
.legal-confirm:hover { border-color:#CBD5E1; }
.legal-confirm:focus-within {
  border-color:var(--serbiska-primary);
  box-shadow:0 0 0 4px rgba(216,27,96,.10);
}
.legal-confirm input {
  flex:0 0 auto;
  width:20px;
  height:20px;
  margin-top:.12rem;
  accent-color:var(--serbiska-primary);
  cursor:pointer;
}
.legal-confirm span {
  color:var(--serbiska-text-secondary);
  font-size:.9rem;
  line-height:1.65;
}

.legal-submit {
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:.6rem;
  padding:1rem 1.75rem;
  border:0;
  border-radius:14px;
  background:var(--serbiska-danger);
  color:#fff;
  font-family:"Manrope",sans-serif;
  font-size:.98rem;
  font-weight:700;
  letter-spacing:-.01em;
  cursor:pointer;
  transition:transform .18s ease,box-shadow .18s ease,background .18s ease;
  box-shadow:0 12px 28px rgba(220,38,38,.22);
}
.legal-submit:hover { background:#B91C1C;transform:translateY(-1px);box-shadow:0 16px 34px rgba(220,38,38,.28); }
.legal-submit:active { transform:translateY(0); }
.legal-submit:focus-visible { outline:3px solid rgba(220,38,38,.4);outline-offset:3px; }
.legal-submit i { font-size:1.05rem; }

/* Errors and the post-submit confirmation. */
.legal-notice {
  display:flex;
  align-items:flex-start;
  gap:.85rem;
  padding:1.1rem 1.25rem;
  border-radius:16px;
  font-size:.92rem;
  line-height:1.7;
}
.legal-notice i { flex:0 0 auto;font-size:1.15rem;margin-top:.1rem; }
.legal-notice ul { margin:.4rem 0 0;padding-left:1.1rem; }
.legal-notice p:last-child { margin-bottom:0; }
.legal-notice-error {
  border:1px solid #FECACA;
  background:#FEF2F2;
  color:#991B1B;
}
.legal-notice-success {
  border:1px solid #BBF7D0;
  background:#F0FDF4;
  color:#14532D;
}
.legal-notice-success i { color:var(--serbiska-success); }
.legal-notice-error i { color:var(--serbiska-danger); }

@media (prefers-reduced-motion:reduce) {
  .legal-field input,
  .legal-field select,
  .legal-field textarea,
  .legal-confirm,
  .legal-submit { transition:none; }
  .legal-submit:hover { transform:none; }
}
