/* ShowRunner Portal — dark-default theme with opt-in light override.
 * Set HTML[data-theme="light"] to activate light mode. That attribute is
 * set by an inline pre-boot script in bootstrap.php, before CSS parses,
 * so there's no flash of the wrong theme.
 */

:root {
    /* surfaces */
    --bg-body:     #1a2332;
    --bg-card:     #243044;
    --bg-elevated: #2d3b50;
    --bg-hover:    #354560;
    --bg-topbar:   #0f1923;
    --bg-input:    #1a2332;

    /* text */
    --text-primary: #e0e6ed;
    --text-soft:    #8899aa;
    --text-dim:     #5a6a7a;
    --text-onbrand: #ffffff;

    /* brand */
    --brand-primary:   #5a7a9b;
    --brand-secondary: #7a9abb;
    --brand-accent:    #b0c4d8;
    --brand-dark:      #2c4257;

    /* borders */
    --border:       #3d5a73;
    --border-light: #2d4560;

    /* semantic — soft backgrounds tuned for dark surfaces */
    --success:      #28a745;
    --success-soft: rgba(40, 167, 69, 0.18);
    --success-ink:  #6fdc8c;
    --danger:       #dc3545;
    --danger-soft:  rgba(220, 53, 69, 0.18);
    --danger-ink:   #f77a85;
    --warning:      #ffc107;
    --warning-soft: rgba(255, 193, 7, 0.18);
    --warning-ink:  #ffd866;
    --info-soft:    rgba(90, 122, 155, 0.18);
    --info-ink:     #b0c4d8;

    --shadow-card:    0 2px 8px rgba(0, 0, 0, 0.35);
    --shadow-card-lg: 0 4px 16px rgba(0, 0, 0, 0.45);
}

[data-theme="light"] {
    --bg-body:     #eef0f3;
    --bg-card:     #ffffff;
    --bg-elevated: #f8f9fa;
    --bg-hover:    #dce1e8;
    --bg-topbar:   #3d5a73;
    --bg-input:    #ffffff;

    --text-primary: #1e2a3a;
    --text-soft:    #556677;
    --text-dim:     #999999;
    --text-onbrand: #ffffff;

    --brand-primary:   #3d5a73;
    --brand-secondary: #5a7a9b;
    /* In dark mode --brand-accent is #b0c4d8 (light blue) — works as text
       on a dark page body. In light mode the body becomes near-white, so
       the same pale accent washes out. Use the darker mid-blue here so
       headings/links/badges stay legible. The topbar stays dark-bg in
       both themes; we re-override --brand-accent below for that scope so
       its nav text keeps the light tint. */
    --brand-accent:    #5a7a9b;
    --brand-dark:      #2c4257;

    --border:       #cfd8dc;
    --border-light: #e0e6ed;

    --success:      #28a745;
    --success-soft: #e9f7ef;
    --success-ink:  #155724;
    --danger:       #dc3545;
    --danger-soft:  #fdecea;
    --danger-ink:   #721c24;
    --warning:      #ffc107;
    --warning-soft: #fff3cd;
    --warning-ink:  #856404;
    --info-soft:    #e9f3fb;
    --info-ink:     #0c5460;

    --shadow-card:    0 2px 8px rgba(0, 0, 0, 0.06);
    --shadow-card-lg: 0 4px 16px rgba(0, 0, 0, 0.08);
}

/* Topbar stays dark-bg in BOTH themes (--bg-topbar=#3d5a73). The light-
   mode --brand-accent override above made on-card text readable on white
   but would've made the topbar's nav text invisible on its dark blue.
   Re-scope --brand-accent back to its light-blue value for elements
   nested inside the topbar so text/icons there keep the right contrast. */
[data-theme="light"] .topbar,
[data-theme="light"] .topbar * {
    --brand-accent: #b0c4d8;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { height: 100%; }
body { min-height: 100%; }
body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    background: var(--bg-body);
    color: var(--text-primary);
    line-height: 1.5;
}
a { color: var(--brand-secondary); text-decoration: none; }
a:hover { text-decoration: underline; color: var(--brand-accent); }

/* --- Auth card (login, forgot, reset, create-account) --- */
.auth-wrap {
    min-height: 100vh;
    display: flex; align-items: center; justify-content: center;
    padding: 24px;
    position: relative;
}
.auth-card {
    background: var(--bg-card);
    border-radius: 12px;
    box-shadow: var(--shadow-card-lg);
    padding: 32px;
    width: 100%;
    max-width: 420px;
    border: 1px solid var(--border-light);
}
.auth-card .auth-pasoi-mark {
    display: block;
    /* Carl-tuned: wordmark sized at ~94px so it reads as a brand badge
       above the "ShowRunner" title rather than dominating the card. */
    width: 94px; height: auto;
    margin: 0 auto 14px;
    opacity: 0.95;
}
[data-theme="light"] .auth-card .auth-pasoi-mark {
    /* Recolor the cream PNG to brand-primary in light mode so it stays
       legible on the white card. CSS filter approach avoids a second asset.
       Selector was `body.light` historically — current theme switch sets
       data-theme on <html>, not a class on body, so the override silently
       broke when that refactor landed. */
    filter: brightness(0.35) sepia(1) hue-rotate(170deg) saturate(2.2);
    opacity: 0.9;
}
.auth-card h1 {
    color: var(--brand-accent);
    font-size: 28px;
    font-style: italic;
    font-weight: 700;
    margin-bottom: 4px;
    text-align: center;
    letter-spacing: 0.2px;
}
.auth-card h1.auth-card-title {
    /* h1 wrapper around the logo image — strip text-only styling so the
       image sits cleanly. Kept as h1 for semantics + screen readers (alt). */
    margin: 0 0 6px;
    line-height: 0;
}
.auth-card .auth-showrunner-logo {
    display: inline-block;
    height: 34px;
    width: auto;
    vertical-align: middle;
}
[data-theme="light"] .auth-card .auth-showrunner-logo {
    /* Same recolor trick as the PASOI wordmark — brand-primary blue on
       the white card. Single PNG works for both themes. Selector fixed
       from `body.light` to match the data-theme="light" attribute the
       theme switcher actually sets. */
    filter: brightness(0.35) sepia(1) hue-rotate(170deg) saturate(2.2);
    opacity: 0.95;
}
.auth-card .subtitle {
    text-align: center;
}
.auth-card .subtitle {
    color: var(--text-soft);
    font-size: 13px;
    margin-bottom: 24px;
}
.auth-card label {
    display: block;
    font-size: 13px;
    font-weight: 600;
    margin: 12px 0 6px;
    color: var(--text-soft);
}
.auth-card input[type="email"],
.auth-card input[type="password"],
.auth-card input[type="text"] {
    width: 100%;
    padding: 12px;
    background: var(--bg-input);
    color: var(--text-primary);
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 15px;
}
.auth-card input:focus {
    outline: none;
    border-color: var(--brand-secondary);
    box-shadow: 0 0 0 2px rgba(122, 154, 187, 0.25);
}
.auth-card input:disabled {
    opacity: 0.6;
    background: var(--bg-hover);
    cursor: not-allowed;
}
.auth-card .checkbox-row {
    display: flex; align-items: center; gap: 10px;
    margin: 14px 0;
    font-size: 14px;
    color: var(--text-soft);
    min-height: 44px;  /* whole row acts as tap target on mobile */
}
.auth-card .checkbox-row input[type="checkbox"] {
    width: 20px; height: 20px; margin: 0; flex-shrink: 0;
}
.auth-card .checkbox-row label { margin: 0; cursor: pointer; }

/* Show/hide password toggle — meets 44px tap target */
.auth-pw-toggle {
    position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
    background: transparent; border: 1px solid var(--border);
    color: var(--text-soft); border-radius: 4px;
    padding: 8px 12px; font-size: 13px; font-family: inherit;
    cursor: pointer; min-height: 36px;
}
.auth-pw-toggle:hover { color: var(--text-primary); border-color: var(--brand-secondary); }

.auth-card button[type="submit"] {
    width: 100%;
    padding: 12px;
    min-height: 44px;
    background: var(--brand-primary);
    color: var(--text-onbrand);
    border: none;
    border-radius: 6px;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    margin-top: 8px;
}
.auth-card button:focus-visible,
.auth-card .auth-pw-toggle:focus-visible {
    outline: 2px solid var(--brand-secondary);
    outline-offset: 2px;
}
.auth-card button[type="submit"]:hover { background: var(--brand-secondary); }
.auth-card .auth-links {
    margin-top: 18px;
    font-size: 13px;
    text-align: center;
    color: var(--text-soft);
}

/* --- Alerts --- */
.alert {
    padding: 10px 14px;
    border-radius: 6px;
    font-size: 13px;
    margin-bottom: 14px;
    border: 1px solid transparent;
}
.alert-error   { background: var(--danger-soft);  color: var(--danger-ink);  border-color: var(--danger); }
.alert-info    { background: var(--info-soft);    color: var(--info-ink);    border-color: var(--brand-primary); }
.alert-success { background: var(--success-soft); color: var(--success-ink); border-color: var(--success); }
.alert-warning { background: var(--warning-soft); color: var(--warning-ink); border-color: var(--warning); }

/* Unsubmitted-days pill on the worker home / "My shows" view. Less
   urgent than the 48h reminder modal — surfaces the moment they have ANY
   draft with content, training the daily-submit habit. */
.psheet-unsub-pill {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding: 14px 18px;
}
.psheet-unsub-pill__head {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1 1 240px;
}
.psheet-unsub-pill__amt {
    font-size: 13px;
    font-weight: 700;
    color: var(--warning-ink);
}
.psheet-unsub-pill__hint {
    font-size: 12px;
    color: var(--warning-ink);
    opacity: 0.85;
    font-weight: 400;
}
.psheet-unsub-pill__btn {
    background: var(--brand-secondary);
    color: #fff;
    padding: 10px 18px;
    font-size: 14px;
    font-weight: 700;
    text-decoration: none;
    border-radius: 6px;
    white-space: nowrap;
}
@media (max-width: 480px) {
    .psheet-unsub-pill__btn { width: 100%; text-align: center; }
}

/* Day-of-action submit CTA at the top of paysheet.php. Same visual
   weight as a warning alert but with the action button inline so
   workers can submit without scrolling past time entries + adjustments. */
.psheet-submit-cta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding: 14px 18px;
}
.psheet-submit-cta__head {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1 1 240px;
}
.psheet-submit-cta__hint {
    font-size: 12px;
    color: var(--warning-ink);
    opacity: 0.85;
    font-weight: 400;
}
.psheet-submit-cta__form { margin: 0; }
.psheet-submit-cta__btn {
    background: var(--brand-secondary);
    color: #fff;
    padding: 10px 18px;
    font-size: 14px;
    font-weight: 700;
    white-space: nowrap;
}
@media (max-width: 480px) {
    .psheet-submit-cta__btn { width: 100%; }
    .psheet-submit-cta__form { width: 100%; }
}

/* --- Top bar (authenticated pages) --- */
.topbar {
    background: linear-gradient(180deg, var(--bg-topbar) 0%, color-mix(in srgb, var(--bg-topbar) 88%, var(--brand-secondary) 12%) 100%);
    color: var(--text-onbrand);
    padding: 12px 24px;
    display: flex; align-items: center; justify-content: space-between;
    border-bottom: 1px solid color-mix(in srgb, var(--brand-secondary) 38%, transparent);
    box-shadow: 0 1px 0 color-mix(in srgb, var(--brand-secondary) 14%, transparent), 0 4px 14px rgba(0,0,0,0.18);
    position: relative;
}

/* Admin topbar — module title gets the full left half, ShowRunner brand
   sits flush against the hamburger drawer on the right side.
   Layout: [Module title.................][ShowRunner][☰]
   The `margin-left: auto` on the center pushes it to the right edge of
   the available space, and the right column's `flex: 0 0 auto` keeps the
   hamburger sized to its own content (no extra gap eating into the left). */
.topbar.topbar--admin { gap: 8px; }
.topbar__left  { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; }
.topbar__center { flex: 0 0 auto; margin-left: auto; display: flex; align-items: center; }
.topbar__right { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }

/* Center brand-mark — actual ShowRunner identity (3 racing lines + the
   "ShowRunner" wordmark + the star overlay). Static by default; .is-running
   class toggles on briefly via JS every 20-60 seconds so the racing lines
   streak in + the star shimmers, then settles back. Tap to go home. */
.topbar-brand-mini {
    display: inline-flex;
    align-items: center;
    height: 30px;
    padding: 2px 10px;
    border-radius: 999px;
    text-decoration: none;
    transition: background 0.15s;
}
.topbar-brand-mini:hover {
    background: rgba(255,255,255,0.04);
    text-decoration: none;
}
.topbar-brand-mini__svg {
    height: 100%;
    width: auto;
    overflow: visible;
}
.topbar-brand-mini__name {
    font-family: 'Helvetica Neue', 'Arial Black', Arial, sans-serif;
    font-weight: 900;
    font-style: italic;
    font-size: 24px;
    fill: var(--brand-accent, #5a7a9b);
    letter-spacing: -0.5px;
}
.topbar-brand-mini__line {
    fill: var(--brand-secondary, #3d5a73);
    opacity: 1;
    transform-origin: 0 50%;
}
.topbar-brand-mini__star {
    fill: #e8eef5;
    transform-origin: center;
    transform-box: fill-box;
    filter: drop-shadow(0 0 2px rgba(168, 197, 221, 0.55));
}
/* Animation only fires when JS toggles `.is-running` on the parent.
   Lines streak left-to-right + star shimmers once, then settles. */
.topbar-brand-mini.is-running .topbar-brand-mini__line {
    animation: srSpeedLine 1.2s ease-out;
}
.topbar-brand-mini.is-running .topbar-brand-mini__line--mid { animation-delay: 0.15s; }
.topbar-brand-mini.is-running .topbar-brand-mini__line--bot { animation-delay: 0.30s; }
.topbar-brand-mini.is-running .topbar-brand-mini__star {
    animation: srStarShimmer 2.0s ease-in-out;
}
@media (prefers-reduced-motion: reduce) {
    .topbar-brand-mini.is-running .topbar-brand-mini__line,
    .topbar-brand-mini.is-running .topbar-brand-mini__star {
        animation: none;
    }
}

@media (max-width: 520px) {
    /* On phones, smaller brand mark. Keep the SVG visible — Carl wants
       the actual logo + word everywhere, not collapse to icon. */
    .topbar-brand-mini { height: 26px; padding: 2px 6px; }
    /* Drop the LEFT wordmark on mobile so the right mini-brand's SVG
       "ShowRunner" text isn't a visual duplicate. Left keeps the play
       icon as a tap target; right keeps the animated wordmark. */
    .topbar-brand-word { display: none; }
}
@media (max-width: 380px) {
    .topbar-brand-mini { height: 22px; padding: 1px 4px; }
}

/* Visually hidden mirror — holds the canonical theme + layout-toggle
   buttons that the hamburger entries dispatch to. Out of the visual
   layout but still in the DOM for click targets. */
.topbar-mirror {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
    pointer-events: none;
}
.topbar::after {
    /* hairline accent — gives the bar a sense of depth without competing with content */
    content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
    background: linear-gradient(90deg, transparent 0%, var(--brand-secondary) 18%, var(--brand-accent) 50%, var(--brand-secondary) 82%, transparent 100%);
    opacity: 0.55;
}
.topbar-brand {
    display: inline-flex; align-items: center; gap: 9px;
    color: var(--text-onbrand); text-decoration: none;
    padding: 4px 6px; margin-left: -6px; border-radius: 8px;
    transition: background 0.15s, color 0.15s;
}
.topbar-brand:hover { color: var(--text-onbrand); text-decoration: none; background: rgba(255,255,255,0.04); }
.topbar-brand-mark { color: var(--brand-accent); flex-shrink: 0; }
.topbar-brand-word { font-size: 18px; font-weight: 700; font-style: italic; letter-spacing: 0.2px; }
.topbar h1 { font-size: 18px; font-weight: 600; }  /* legacy fallback */

/* Per-page module title — replaces the global ShowRunner brand on admin
   pages so the topbar reads as the actual module ("Payroll" / "Roster"
   / "CRMS Templates"). Same hover affordance as the legacy brand block.
   No max-width constraint — the parent .topbar__left already has
   `min-width: 0` + `flex: 1 1 0` so the title naturally shrinks via
   ellipsis when the left column gets squeezed by the centered brand. */
.topbar-module {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    color: var(--text-onbrand);
    text-decoration: none;
    padding: 4px 8px;
    margin-left: -6px;
    border-radius: 8px;
    font-weight: 700;
    transition: background 0.15s, color 0.15s;
    min-width: 0;
    max-width: 100%;
}
.topbar-module:hover {
    background: rgba(255,255,255,0.04);
    color: var(--text-onbrand);
    text-decoration: none;
}
.topbar-module__icon { color: var(--brand-accent); flex-shrink: 0; }
.topbar-module__title {
    font-size: 16px;
    letter-spacing: 0.2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
@media (max-width: 767px) {
    .topbar-module__title { font-size: 14px; }
    /* Below 520px the center decorative brand mark hogs space the page
     * title needs (e.g. "My shows" was ellipsizing to "My sh…"). Hide
     * the center mark so the title has room — the topbar still says
     * where the user is via the page title + icon on the left.
     * Two selectors because the admin topbar wraps the brand in
     * .topbar__center, while the worker topbar drops it as a direct
     * child of <header class="topbar">. Both branches need the same
     * rule. */
    .topbar__center,
    .topbar > .topbar-brand-mini--worker { display: none; }
}
@media (max-width: 380px) {
    /* Cramped phones: hide the title text, keep the icon. The center
       brand still tells you "ShowRunner"; the module name is one tap
       away in the hamburger's Pages list. */
    .topbar-module__title { display: none; }
}

/* Topbar utility group — wraps Theme + Refresh + Profile + Layout + Sign
   out. Hidden in modern + mobile so the hamburger menu becomes the only
   path for those actions. Classic mode + desktop both render the group
   inline (existing behavior preserved). */
.topbar-utility-group {
    display: inline-flex;
    align-items: center;
    gap: 10px;
}

/* App drawer hamburger — ALWAYS visible on admin pages (mobile + desktop,
   classic + modern). Single discoverable surface for cross-platform
   modules (LaborGrid / Intake / Templates / StagePlot), tools, account,
   and sign out. The classic-mode utility-group inline pills are gone
   entirely — the hamburger replaced them. Categorized panel below the
   button mirrors the subnav-overflow visual language. */
.topbar-hamburger { display: inline-flex; position: relative; }
.topbar-hamburger > summary {
    list-style: none;
    cursor: pointer;
    padding: 8px 10px;
    color: var(--text-onbrand);
    border-radius: 6px;
    border: 1px solid transparent;
    display: inline-flex;
    align-items: center;
    transition: background 0.12s, color 0.12s, border-color 0.12s;
    user-select: none;
}
.topbar-hamburger > summary::-webkit-details-marker { display: none; }
.topbar-hamburger > summary:hover,
.topbar-hamburger[open] > summary {
    background: rgba(255,255,255,0.06);
    border-color: var(--border-light);
}
.topbar-hamburger__panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    /* Wider panel + grid layout so apps + pages flow as 2-3 columns.
       Cuts the panel's vertical real estate roughly in half — fits a
       typical phone viewport even with the chat bar reserving ~76px. */
    width: min(440px, calc(100vw - 16px));
    max-height: calc(100dvh - 80px - max(var(--sr-chat-bar-h, 56px), 56px) - 16px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    background: var(--bg-card);
    border: 1px solid var(--border-light);
    border-radius: 10px;
    box-shadow: var(--shadow-card-lg);
    padding: 8px;
    z-index: 200;
    animation: topbar-hamburger-in 0.14s ease-out;
}
@keyframes topbar-hamburger-in {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}
.topbar-hamburger__group {
    /* Grid layout — items flow as 2 columns on phones, 3+ on wider
       drawers. auto-fit + minmax means a section with one item still
       fills the row, sections with many items wrap cleanly. Tightened
       row gap (1px → near-flush items) since each item already has its
       own min-height + padding for a comfortable tap target. */
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 1px 4px;
}
.topbar-hamburger__group + .topbar-hamburger__group {
    margin-top: 4px;
    padding-top: 4px;
    border-top: 1px solid var(--border-light);
}
.topbar-hamburger__group--danger {
    margin-top: 4px;
    padding-top: 4px;
    border-top: 1px solid var(--border-light);
}
.topbar-hamburger__group-title {
    grid-column: 1 / -1;          /* span all grid columns */
    font-size: 9px;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-soft);
    font-weight: 700;
    margin: 2px 4px 1px;
    opacity: 0.75;
}
.topbar-hamburger__item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 10px;
    color: var(--text-primary);
    text-decoration: none;
    background: transparent;
    border: none;
    border-radius: 6px;
    font-size: 12.5px;
    font-weight: 500;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    transition: background 0.12s;
    min-height: 30px;
    min-width: 0;
}
.topbar-hamburger__item span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.topbar-hamburger__item svg { flex-shrink: 0; }
.topbar-hamburger__item:hover {
    background: var(--bg-elevated);
    text-decoration: none;
}
.topbar-hamburger__item--danger {
    color: var(--danger-ink, #e34d5d);
}
.topbar-hamburger__item--danger:hover {
    background: rgba(220,53,69,0.12);
    color: var(--danger, #dc3545);
}

/* (Legacy modern-mobile activation block removed — the hamburger is now
   always visible across both nav modes and both viewport widths.) */

.topbar nav { display: flex; align-items: center; gap: 10px; }
.topbar nav a { color: var(--brand-accent); font-size: 14px; }
.topbar nav a:hover { color: var(--text-onbrand); text-decoration: none; }

/* Cross-app pill (LaborGrid from admin, Admin from worker side). Reads as a
   distinct destination, not just another utility link. */
.topbar-app-pill {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 6px 12px;
    background: rgba(176, 196, 216, 0.10);
    border: 1px solid color-mix(in srgb, var(--brand-secondary) 50%, transparent);
    border-radius: 999px;
    color: var(--brand-accent);
    font-size: 13px; font-weight: 600; letter-spacing: 0.2px;
    transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.12s;
}
.topbar-app-pill:hover {
    background: rgba(176, 196, 216, 0.18);
    border-color: var(--brand-accent);
    color: var(--text-onbrand);
    text-decoration: none;
    transform: translateY(-1px);
}
.topbar-app-pill svg { color: var(--brand-accent); }
.topbar-app-pill:hover svg { color: var(--text-onbrand); }

/* Badge variant — used for the "you are an admin" indicator. Looks like a
   normal pill but is a button instead of a link, with no destination. The
   only thing it does is toggle a rainbow class on click (handled in JS). */
.topbar-app-pill--badge {
    font-family: inherit;
    cursor: pointer;
    user-select: none;
}
.topbar-app-pill--badge:hover { transform: none; }  /* no lift — it's not navigation */

/* Top-of-panel "Admin" pill — replaces the in-list "Admin Status" row.
 * Sits centered at the very top of the hamburger panel so the role
 * indicator reads as a header (not a menu choice). Keeps the
 * data-rainbow-toggle behavior on click for the easter egg. */
.topbar-hamburger__role-row {
    display: flex;
    justify-content: center;
    padding: 0 4px 6px;
    margin-bottom: 4px;
    border-bottom: 1px solid var(--border-light);
}
.topbar-hamburger__role-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-light);
    border-radius: 999px;
    color: var(--text-soft);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    cursor: pointer;
    user-select: none;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.topbar-hamburger__role-pill:hover {
    background: var(--bg-card);
    color: var(--text-primary);
}
.topbar-hamburger__role-pill svg { flex-shrink: 0; opacity: 0.85; }

/* Rainbow easter-egg — same animated gradient as the prior badge row,
 * scoped to the new pill selector so the row's data-rainbow-toggle
 * click still flips it. */
.topbar-hamburger__role-pill.is-rainbow {
    background: linear-gradient(90deg, #ff0064 0%, #ff8a00 18%, #ffd400 36%, #16d39a 54%, #00b6ff 72%, #b14aed 90%, #ff0064 100%);
    background-size: 300% 100%;
    color: #fff;
    border-color: transparent;
    animation: pill-rainbow-shift 3s linear infinite, pill-rainbow-pulse 2s ease-in-out infinite;
}
.topbar-hamburger__role-pill.is-rainbow svg { color: #fff; opacity: 1; }
.topbar-hamburger__role-pill.is-rainbow span { text-shadow: 0 1px 0 rgba(0,0,0,0.25); }
@media (prefers-reduced-motion: reduce) {
    .topbar-hamburger__role-pill.is-rainbow { animation: none; }
}

/* Legacy in-list rainbow rule kept temporarily — removed once the
 * topbar refactor (1.45.x) ships and no remaining callers render
 * `.topbar-hamburger__item--badge`. Safe to delete on the next pass. */
.topbar-hamburger__item--badge.is-rainbow {
    background: linear-gradient(90deg, #ff0064 0%, #ff8a00 18%, #ffd400 36%, #16d39a 54%, #00b6ff 72%, #b14aed 90%, #ff0064 100%);
    background-size: 300% 100%;
    color: #fff;
    border-color: transparent;
    animation: pill-rainbow-shift 3s linear infinite, pill-rainbow-pulse 2s ease-in-out infinite;
}
.topbar-hamburger__item--badge.is-rainbow svg { color: #fff; }
.topbar-hamburger__item--badge.is-rainbow span { text-shadow: 0 1px 0 rgba(0,0,0,0.25); }
@media (prefers-reduced-motion: reduce) {
    .topbar-hamburger__item--badge.is-rainbow { animation: none; }
}

/* Rainbow toggle — pure delight moment. When .is-rainbow is set, the pill's
   background becomes an animated multi-hue gradient and the text/icon flip
   to white for legibility. The animation runs forever until clicked off. */
@keyframes pill-rainbow-shift {
    0%   { background-position:   0% 50%; }
    100% { background-position: 200% 50%; }
}
@keyframes pill-rainbow-pulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.06); }
}
.topbar-app-pill--badge.is-rainbow {
    background: linear-gradient(90deg,
        #ff5e5e, #ffae3a, #ffe83a, #6fe26f, #4ad8ff, #7d6cff, #d96bff, #ff5e5e);
    background-size: 200% 100%;
    border-color: transparent;
    color: #fff;
    box-shadow: 0 0 14px rgba(255, 94, 175, 0.45), 0 0 4px rgba(255, 255, 255, 0.5) inset;
    animation: pill-rainbow-shift 3s linear infinite, pill-rainbow-pulse 2s ease-in-out infinite;
}
.topbar-app-pill--badge.is-rainbow svg { color: #fff; }
.topbar-app-pill--badge.is-rainbow span { text-shadow: 0 1px 0 rgba(0,0,0,0.25); }
@media (prefers-reduced-motion: reduce) {
    .topbar-app-pill--badge.is-rainbow {
        animation: none;
        background-position: 0% 50%;
    }
}

.topbar-signout {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 6px 10px; border-radius: 6px;
    color: var(--brand-accent);
    transition: background 0.15s, color 0.15s;
}
.topbar-signout:hover { background: rgba(255,255,255,0.06); color: var(--text-onbrand); text-decoration: none; }

/* Generic top-bar icon-only button — used by the refresh button. Stays
   square-ish so it lines up cleanly with the theme-toggle next door. */
.topbar-iconbtn {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px;
    background: transparent; border: 1px solid transparent;
    color: var(--brand-accent); cursor: pointer;
    border-radius: 6px;
    transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.topbar-iconbtn:hover, .topbar-iconbtn:focus-visible {
    background: rgba(255,255,255,0.06);
    border-color: rgba(255,255,255,0.10);
    color: var(--text-onbrand);
    outline: none;
}

.topbar-divider {
    width: 1px; height: 22px;
    background: rgba(255,255,255,0.14);
    margin: 0 4px;
    flex-shrink: 0;
}

/* --- Page content ---
 *  Desktop canvas is generous — 1280px is the modern SaaS default for
 *  information-dense dashboards. Below 767px the mobile breakpoint
 *  tightens padding and stacks layout primitives.
 */
.page {
    max-width: 1280px;
    margin: 24px auto;
    padding: 0 24px;
}

/* Narrower pages for auth flows (login, forgot, reset) already handled by
   .auth-card max-width. Worker single-focus pages (paysheet detail, show
   detail) can opt into a narrower comfortable reading width. */
.page--narrow { max-width: 960px; }
.card {
    background: var(--bg-card);
    border-radius: 12px;
    box-shadow: var(--shadow-card);
    padding: 24px;
    margin-bottom: 20px;
    border: 1px solid var(--border-light);
}
.card h2 { color: var(--brand-accent); font-size: 18px; margin-bottom: 12px; }

/* --- Table wrap primitive — used anywhere a table might overflow narrow screens.
 *  Constrains width to parent so inner table scrolls horizontally instead of
 *  expanding its container and pushing the whole page wider.
 */
.invite-table-wrap {
    width: 100%;
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* --- Invite table (admin) --- */
table.invite-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
    color: var(--text-primary);
}
table.invite-table th,
table.invite-table td {
    padding: 10px 12px;
    border-bottom: 1px solid var(--border-light);
    text-align: left;
}
table.invite-table th {
    background: var(--bg-elevated);
    font-weight: 600;
    color: var(--text-soft);
}
table.invite-table button {
    padding: 6px 12px;
    background: var(--brand-primary);
    color: var(--text-onbrand);
    border: none;
    border-radius: 4px;
    font-size: 13px;
    cursor: pointer;
}
table.invite-table button:hover { background: var(--brand-secondary); }
table.invite-table button:disabled { opacity: 0.5; cursor: wait; }
table.invite-table .sent-badge {
    display: inline-block;
    padding: 4px 8px;
    background: var(--success);
    color: #fff;
    border-radius: 3px;
    font-size: 12px;
}

/* --- "My Shows" worker dashboard --- */
.show-card {
    background: var(--bg-card);
    border-radius: 12px;
    box-shadow: var(--shadow-card);
    padding: 20px 24px;
    margin-bottom: 16px;
    border: 1px solid var(--border-light);
    border-left: 4px solid var(--brand-secondary);
}
.show-card--confirmed { border-left-color: var(--success); }
.show-card--declined  { border-left-color: var(--danger); opacity: 0.72; }
.show-card--pending   { border-left-color: var(--warning); }

.show-card__header {
    display: flex; justify-content: space-between; align-items: flex-start; gap: 16px;
    flex-wrap: wrap;
}
.show-card__name {
    font-size: 17px;
    color: var(--brand-accent);
    font-weight: 600;
    margin: 0 0 2px;
    word-break: break-word;     /* long deal names wrap instead of overflowing on phones */
    overflow-wrap: break-word;
}

/* "Pull from CRMS" modal on the Prep page — overrides for CRMS opp #
   and layout ID, with a fallback to manual upload when the CRMS print
   API isn't accessible. Same visual language as the task popup but
   non-blocking (tap backdrop to close). */
.sr-pull-modal-overlay {
    position: fixed; inset: 0; z-index: 5000;
    display: flex; align-items: center; justify-content: center;
    padding: 16px;
    animation: sr-task-popup-fade 0.18s ease-out;
}
.sr-pull-modal__backdrop {
    position: absolute; inset: 0;
    background: rgba(20, 28, 40, 0.78);
    -webkit-backdrop-filter: blur(3px);
            backdrop-filter: blur(3px);
}
.sr-pull-modal__panel {
    position: relative;
    background: var(--bg-card);
    border: 1px solid var(--border-light);
    border-radius: 14px;
    box-shadow: var(--shadow-card-lg);
    padding: 20px 22px 18px;
    max-width: 460px;
    width: 100%;
    color: var(--text-primary);
    animation: sr-task-popup-rise 0.22s ease-out;
}
.sr-pull-modal__x {
    position: absolute; top: 8px; right: 10px;
    background: transparent; border: none; cursor: pointer;
    color: var(--text-soft); font-size: 22px; line-height: 1;
    padding: 4px 8px; border-radius: 6px;
}
.sr-pull-modal__x:hover { background: var(--bg-elevated); color: var(--text-primary); }
.sr-pull-modal__field {
    margin-bottom: 12px;
}
.sr-pull-modal__row {
    display: flex; gap: 8px; flex-wrap: wrap;
    margin-bottom: 8px;
}
.sr-pull-modal__row .sr-pull-modal__field {
    margin-bottom: 0;
    min-width: 100px;
    flex: 1;
}
/* Filters row — date range + search + Find button on one line on
   desktop, wraps cleanly on narrow widths. Cleaner than stacking
   each filter into its own row with a separate Find pill below. */
.sr-pull-modal__filters {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    align-items: flex-end;
    margin-bottom: 12px;
}
.sr-pull-modal__filters .sr-pull-modal__field {
    margin-bottom: 0;
}
.sr-pull-modal__field--date {
    flex: 0 0 130px;
}
@media (max-width: 540px) {
    .sr-pull-modal__field--date { flex: 1 1 calc(50% - 4px); }
    .sr-pull-modal__filters > .btn-secondary { width: 100%; }
}

/* Date / search inputs — match the theme. Browser-native date picker
   styling is dark-theme-hostile; explicit color-scheme: dark fixes
   the calendar icon and day-cell legibility on Chromium / Safari. */
.sr-pull-modal__field input[type="date"],
.sr-pull-modal__field input[type="text"],
.sr-pull-modal__field input[type="number"] {
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--border-light);
    border-radius: 6px;
    background: var(--bg-body);
    color: var(--text-primary);
    font-size: 14px;
    font-family: inherit;
    box-sizing: border-box;
    color-scheme: dark light;
}
.sr-pull-modal__field input[type="date"]::-webkit-calendar-picker-indicator {
    filter: invert(0.6);
    cursor: pointer;
}

/* Opp picker — clickable button list (replaces native <select size>
   which Chrome won't fully highlight a selection on). Tap a row →
   selected state lights up + we know which opp is picked. */
.sr-pull-modal__opp-list {
    border: 1px solid var(--border-light);
    border-radius: 6px;
    background: var(--bg-body);
    max-height: 220px;
    overflow-y: auto;
    padding: 4px;
}
.sr-pull-modal__opp {
    display: block;
    width: 100%;
    text-align: left;
    padding: 8px 10px;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 4px;
    color: var(--text-primary);
    font-size: 13px;
    font-family: inherit;
    cursor: pointer;
    line-height: 1.35;
    transition: background 0.1s, border-color 0.1s;
}
.sr-pull-modal__opp:hover {
    background: var(--bg-hover);
}
.sr-pull-modal__opp.is-selected {
    background: rgba(122,154,187,0.18);
    border-color: var(--brand-accent);
    color: var(--text-primary);
}
.sr-pull-modal__opp__date {
    color: var(--text-soft);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    font-weight: 600;
    margin-right: 8px;
}
.sr-pull-modal__opp__num {
    color: var(--brand-accent);
    font-weight: 700;
    margin-right: 6px;
}
.sr-pull-modal__opp__name { font-weight: 500; }
.sr-pull-modal__opp__meta {
    display: block;
    color: var(--text-soft);
    font-size: 11px;
    margin-top: 2px;
}
.sr-pull-modal__opp-empty,
.sr-pull-modal__opp-loading {
    padding: 14px 10px;
    color: var(--text-soft);
    font-size: 13px;
    text-align: center;
}

/* "Selected: <opp>" pill below the list — clear at-a-glance signal of
   which opp will be pulled when the admin clicks the primary action. */
.sr-pull-modal__selected-bar {
    margin-top: 8px;
    padding: 6px 10px;
    border-radius: 6px;
    background: rgba(122,154,187,0.10);
    border: 1px solid color-mix(in srgb, var(--brand-secondary) 35%, transparent);
    color: var(--text-primary);
    font-size: 12px;
    line-height: 1.4;
}
.sr-pull-modal__selected-bar[hidden] { display: none; }
.sr-pull-modal__selected-bar strong { color: var(--brand-accent); }
.sr-pull-modal__field label {
    display: block;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--text-soft);
    margin-bottom: 4px;
}
.sr-pull-modal__field input {
    width: 100%;
    padding: 8px 10px;
    border: 1px solid var(--border-light);
    border-radius: 6px;
    background: var(--bg-body);
    color: var(--text-primary);
    font-size: 14px;
    font-family: inherit;
    box-sizing: border-box;
}
.sr-pull-modal__field small {
    display: block; margin-top: 4px; line-height: 1.4;
}
.sr-pull-modal__error {
    padding: 10px 12px;
    border-radius: 6px;
    background: rgba(220, 53, 69, 0.12);
    border: 1px solid rgba(220, 53, 69, 0.30);
    color: var(--text-primary);
    font-size: 13px;
    line-height: 1.5;
    margin-bottom: 12px;
}
.sr-pull-modal__foot {
    display: flex; justify-content: space-between; align-items: center;
    gap: 12px; flex-wrap: wrap;
    margin-top: 4px;
}
.sr-pull-modal__fallback {
    color: var(--text-soft);
    font-size: 12px;
    text-decoration: none;
}
.sr-pull-modal__fallback:hover { color: var(--brand-accent); }
.sr-pull-modal__actions {
    display: flex; gap: 8px;
}

/* Task popup modal — pops on every authed page when the user has unread
   task assignments. Modeled after the system-message modal but with
   task-themed pill + a "Mark complete" inline action. Pops one task at
   a time; "I've read this" advances to the next, × closes the queue
   without acknowledging (it pops again on the next page load). */
.sr-task-popup[hidden] { display: none; }
.sr-task-popup {
    position: fixed; inset: 0;
    z-index: 5000;
    display: flex; align-items: center; justify-content: center;
    padding: 16px;
    animation: sr-task-popup-fade 0.18s ease-out;
}
@keyframes sr-task-popup-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.sr-task-popup__backdrop {
    position: absolute; inset: 0;
    background: rgba(20, 28, 40, 0.78);
    -webkit-backdrop-filter: blur(3px);
            backdrop-filter: blur(3px);
}
.sr-task-popup__panel {
    position: relative;
    background: var(--bg-card);
    border: 1px solid var(--border-light);
    border-radius: 14px;
    box-shadow: var(--shadow-card-lg);
    padding: 20px 22px 18px;
    max-width: 480px;
    width: 100%;
    color: var(--text-primary);
    animation: sr-task-popup-rise 0.22s ease-out;
}
@keyframes sr-task-popup-rise {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: translateY(0); }
}
.sr-task-popup__x {
    position: absolute; top: 8px; right: 10px;
    background: transparent; border: none; cursor: pointer;
    color: var(--text-soft); font-size: 22px; line-height: 1;
    padding: 4px 8px; border-radius: 6px;
}
.sr-task-popup__x:hover { background: var(--bg-elevated); color: var(--text-primary); }
.sr-task-popup__pill {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 4px 10px; border-radius: 999px;
    background: rgba(122,154,187,0.14);
    color: var(--brand-accent);
    border: 1px solid color-mix(in srgb, var(--brand-secondary) 50%, transparent);
    font-size: 11px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.5px;
}
.sr-task-popup__title {
    font-size: 19px; font-weight: 700;
    margin: 12px 0 6px;
    line-height: 1.25;
}
.sr-task-popup__meta {
    color: var(--text-soft); font-size: 13px;
    margin-bottom: 12px;
}
.sr-task-popup__body {
    font-size: 14px; line-height: 1.5;
    color: var(--text-primary);
    white-space: pre-wrap;
    max-height: 40vh; overflow-y: auto;
    padding: 10px 12px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-light);
    border-radius: 8px;
    margin-bottom: 14px;
}
.sr-task-popup__foot {
    display: flex; align-items: center; justify-content: space-between;
    gap: 12px; flex-wrap: wrap;
}
.sr-task-popup__counter {
    color: var(--text-soft); font-size: 12px;
}
.sr-task-popup__actions {
    display: flex; gap: 8px; flex-wrap: wrap;
}
.sr-task-popup__btn {
    appearance: none; border: 1px solid var(--border-light);
    background: var(--bg-body); color: var(--text-primary);
    padding: 9px 14px; border-radius: 8px;
    font-size: 13px; font-weight: 600;
    font-family: inherit; cursor: pointer;
    transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.sr-task-popup__btn--ghost { color: var(--text-soft); }
.sr-task-popup__btn--ghost:hover {
    background: var(--bg-elevated); color: var(--text-primary);
    border-color: var(--brand-accent);
}
.sr-task-popup__btn--primary {
    background: var(--brand-accent);
    color: var(--bg-body);
    border-color: var(--brand-accent);
}
.sr-task-popup__btn--primary:hover {
    filter: brightness(1.08);
}

/* Reusable chip strip — used by show cards, task cards, and any other
   card surface that wants a compact "label: value" row of metadata
   without burning vertical space. Pattern mirrors the LaborGrid sidebar
   stats strip (.sidebar-detail-stats) but lives here in portal.css so
   any portal page can drop in `<div class="meta-chips"><span class="meta-chip">…</span></div>`. */
.meta-chips {
    display: flex; flex-wrap: wrap; gap: 6px;
    margin: 8px 0 6px;
}
.meta-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 3px 9px; border-radius: 999px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-light);
    line-height: 1.25; font-size: 12px;
    max-width: 100%; min-width: 0;
}
.meta-chip__lbl {
    color: var(--text-soft);
    font-size: 10px; text-transform: uppercase; letter-spacing: 0.4px;
    font-weight: 600;
    flex-shrink: 0;
}
.meta-chip__val {
    color: var(--text-primary); font-weight: 600;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    min-width: 0;
}
/* "Prep sheet ready" chip — fires on show cards when the deal has any
   shop_prep / prep_sheet document in its Documents tab. Subtle green
   tint so it reads as an at-a-glance "yes the sheet is here" without
   competing with the prep-status dot. */
.meta-chip--prep-ready {
    background: rgba(40,167,69,0.14);
    border-color: color-mix(in srgb, #28a745 45%, transparent);
    color: #28a745;
}
.meta-chip--prep-ready .meta-chip__val { color: #28a745; }
.meta-chip--prep-ready svg { color: #28a745; flex-shrink: 0; }

/* Prep-progress chip — replaces the binary "ready" chip whenever the
   show has a persistent checklist (prep_items) attached. Carries the
   actual X/N count so admins and crew can see progress at a glance.
   Two color states: partial = brand-accent (in-flight), done = green
   (so a 100%-checked show pops visually). */
.meta-chip--prep-progress {
    background: rgba(122, 154, 187, 0.14);
    border-color: color-mix(in srgb, #5a7a9b 45%, transparent);
    color: var(--brand-accent);
}
.meta-chip--prep-progress .meta-chip__val { color: var(--brand-accent); font-weight: 700; }
.meta-chip--prep-progress svg { color: var(--brand-accent); flex-shrink: 0; }
.meta-chip--prep-progress--done {
    background: rgba(40, 167, 69, 0.18);
    border-color: color-mix(in srgb, #28a745 55%, transparent);
    color: #28a745;
}
.meta-chip--prep-progress--done .meta-chip__val { color: #28a745; font-weight: 700; }
.meta-chip--prep-progress--done svg { color: #28a745; flex-shrink: 0; }

/* Disclosure pattern for "More info" sections inside cards. Default
   styling is a subtle dashed-top divider with a small clickable label;
   open state rotates the chevron and shows the body. Reusable across
   show cards, task cards, etc. */
.show-card__more {
    margin-top: 10px;
    border-top: 1px dashed var(--border-light);
    padding-top: 6px;
}
.show-card__more > summary {
    cursor: pointer;
    list-style: none;
    color: var(--text-soft);
    font-size: 12px;
    font-weight: 600;
    user-select: none;
    padding: 4px 0;
    display: flex; align-items: center; gap: 6px;
}
.show-card__more > summary::-webkit-details-marker { display: none; }
.show-card__more > summary::after {
    content: '›';
    margin-left: auto;
    font-size: 14px;
    transition: transform 0.15s;
}
.show-card__more[open] > summary::after { transform: rotate(90deg); }
.show-card__more-body { padding-top: 4px; }
/* Prep-stage chip — the at-a-glance "is this show prepped?" badge that
   sits next to each show's date row on the My Shows / admin shows list.
   Carl's spec: green=prepped, yellow=in progress, red=not prepped, red
   flashing=issue. Both admin and field crew see the same chip — shop
   crew toggles status from the Prep page; everybody else reads it.

   Replaces the smaller `.show-card__prep-dot` that previously sat inline
   in the title. The dot's color rules are kept below for any straggler
   callers, with pending updated from gray to red to match the new spec. */
.show-card__prep-stage {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 3px 10px;
    border: 1px solid;
    border-radius: 999px;
    font-size: 10px; font-weight: 800;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    line-height: 1.4;
    flex-shrink: 0;
    white-space: nowrap;
}
.show-card__prep-stage::before {
    content: '';
    display: inline-block;
    width: 7px; height: 7px;
    border-radius: 50%;
    background: currentColor;
    flex-shrink: 0;
}
.show-card__prep-stage--pending {
    background: rgba(220,53,69,0.10);
    border-color: rgba(220,53,69,0.42);
    color: #dc3545;
}
.show-card__prep-stage--in-progress {
    background: rgba(224,168,0,0.12);
    border-color: rgba(224,168,0,0.45);
    color: #d4a300;
}
.show-card__prep-stage--in-progress::before {
    animation: show-card-prep-pulse 1.4s ease-in-out infinite;
}
.show-card__prep-stage--prepped {
    background: rgba(40,167,69,0.14);
    border-color: rgba(40,167,69,0.5);
    color: #28a745;
}
.show-card__prep-stage--issue {
    background: rgba(220,53,69,0.18);
    border-color: rgba(220,53,69,0.65);
    color: #dc3545;
    animation: show-card-prep-flash 0.9s steps(2, start) infinite;
}

/* The wrapping row that holds the prep-stage chip + the date range.
   On wide cards everything sits on one line; on narrow cards the
   chip stays together (white-space: nowrap above) and the dates wrap
   to the next line. */
.show-card__sub {
    display: flex; align-items: center; gap: 10px;
    flex-wrap: wrap;
    margin-top: 4px;
}

/* Legacy dot — kept for any callers we haven't migrated. Pending
   updated from gray to red per the new spec; issue gains the flash
   animation so it matches the chip's behavior. */
.show-card__prep-dot {
    display: inline-block;
    width: 10px; height: 10px;
    border-radius: 50%;
    margin-right: 8px;
    vertical-align: middle;
    border: 1px solid rgba(0,0,0,0.18);
    box-sizing: border-box;
    flex-shrink: 0;
}
.show-card__prep-dot--pending     { background: #dc3545; box-shadow: 0 0 0 2px rgba(220,53,69,0.18); }
.show-card__prep-dot--in-progress {
    background: #e0a800;
    animation: show-card-prep-pulse 1.4s ease-in-out infinite;
}
.show-card__prep-dot--prepped     { background: #28a745; box-shadow: 0 0 0 2px rgba(40,167,69,0.18); }
.show-card__prep-dot--issue       {
    background: #dc3545; box-shadow: 0 0 0 2px rgba(220,53,69,0.22);
    animation: show-card-prep-flash 0.9s steps(2, start) infinite;
}

/* Pulsing yellow for "prep in progress" — Carl's at-a-glance signal for
   crew that the shop is actively prepping their show right now. */
@keyframes show-card-prep-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(224,168,0,0.55); transform: scale(1); }
    50%      { box-shadow: 0 0 0 5px rgba(224,168,0,0); transform: scale(1.12); }
}
/* Steps(2) gives a hard on/off flash (not a smooth fade) — easier to
   pick up peripherally because the eye catches the abrupt change. */
@keyframes show-card-prep-flash {
    0%, 49.99% { opacity: 1; }
    50%, 100%  { opacity: 0.35; }
}
@media (prefers-reduced-motion: reduce) {
    .show-card__prep-dot--in-progress,
    .show-card__prep-dot--issue,
    .show-card__prep-stage--in-progress::before,
    .show-card__prep-stage--issue { animation: none; }
}
.show-card__dates {
    font-size: 13px;
    color: var(--text-soft);
}
.show-card__badge {
    font-size: 12px; font-weight: 600;
    padding: 5px 10px;
    border-radius: 999px;
    white-space: nowrap;
}
.show-card__badge--confirmed { background: var(--success-soft); color: var(--success-ink); }
.show-card__badge--declined  { background: var(--danger-soft);  color: var(--danger-ink); }
.show-card__badge--pending   { background: var(--warning-soft); color: var(--warning-ink); }

.show-card__body {
    margin-top: 14px;
    font-size: 14px;
}
.show-card__row {
    display: flex; gap: 10px;
    padding: 4px 0;
}
.show-card__label {
    min-width: 110px;
    color: var(--text-soft);
    font-size: 13px;
}
.show-card__comment {
    margin-top: 10px;
    padding: 10px 12px;
    background: var(--bg-elevated);
    border-radius: 6px;
    font-size: 13px;
    color: var(--text-primary);
    font-style: italic;
    border: 1px solid var(--border-light);
}

.show-card__actions {
    margin-top: 16px;
    display: flex; gap: 10px;
    flex-wrap: wrap;
}
.show-card__actions form { margin: 0; }

/* Prominent "Show details" navigation button. Lives between the card body
   and the Accept/Decline actions so the path to the full schedule + docs
   is always obvious. Outline style so it doesn't visually compete with the
   primary Accept/Decline actions. */
.show-card__details-btn {
    position: relative;
    isolation: isolate;     /* contain the ::before shimmer in this stacking ctx */
    overflow: hidden;       /* clip the sweep to the rounded button shape */
    display: flex; align-items: center; justify-content: center; gap: 6px;
    margin-top: 14px;
    padding: 11px 18px; min-height: 44px;
    background: var(--bg-elevated);
    color: var(--brand-accent);
    border: 1.5px solid var(--brand-secondary);
    border-radius: 6px;
    font-size: 15px; font-weight: 600;
    text-decoration: none; text-align: center;
    transition: background 0.12s, border-color 0.12s, transform 0.08s;
}
.show-card__details-btn:hover {
    background: var(--bg-hover);
    border-color: var(--brand-accent);
    text-decoration: none;
}
.show-card__details-btn:active { transform: scale(0.99); }
.show-card__details-btn-arrow { font-size: 16px; line-height: 1; }
/* Subtle shimmer sweep — a soft highlight travels across the button every
   ~5s with a long pause between sweeps. Sits at z-index -1 so the label
   text always stays crisp on top. Disabled for users with reduced-motion
   preferences so the page doesn't fight accessibility settings. */
.show-card__details-btn::before {
    content: '';
    position: absolute; inset: 0;
    background: linear-gradient(115deg,
        transparent 35%,
        rgba(127, 169, 207, 0.30) 50%,
        transparent 65%);
    transform: translateX(-110%);
    animation: showCardShimmer 5s ease-in-out infinite;
    pointer-events: none;
    z-index: -1;
}
@keyframes showCardShimmer {
    0%, 55%  { transform: translateX(-110%); }
    100%     { transform: translateX(110%); }
}
@media (prefers-reduced-motion: reduce) {
    .show-card__details-btn::before { animation: none; }
}

/* Generic small back-button — used at the top of inner pages
   (show-detail, etc.) where the user needs an obvious return path.
   Replaces the inline-styled tiny gray text-link pattern. */
.btn-back {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 7px 14px; min-height: 36px;
    background: var(--bg-elevated);
    color: var(--text-primary);
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 13px; font-weight: 500;
    text-decoration: none;
    transition: background 0.12s, border-color 0.12s;
    cursor: pointer;
}
.btn-back:hover {
    background: var(--bg-hover);
    border-color: var(--brand-secondary);
    color: var(--text-primary);
    text-decoration: none;
}

/* Site-wide footer — small, low-contrast, sits below the main content.
   Same markup on every page via portal_footer() in bootstrap.php. */
.sr-footer {
    text-align: center;
    padding: 18px 12px 24px;
    margin-top: 32px;
    font-size: 11px;
    color: var(--text-soft);
    opacity: 0.7;
    letter-spacing: 0.3px;
    border-top: 1px solid var(--border-light);
}
/* Version number is a link to the admin changelog. Underline on hover
   only — no constant link styling so it stays unobtrusive. */
.sr-footer-version,
.sr-footer-link {
    color: inherit;
    text-decoration: none;
    border-bottom: 1px dotted transparent;
}
.sr-footer-version:hover,
.sr-footer-link:hover {
    color: var(--brand-accent);
    border-bottom-color: var(--brand-accent);
    text-decoration: none;
}

/* System-wide message modal. Pops on every authenticated page when the
   current user has at least one undismissed broadcast. Rendered by
   portal_system_message_modal() inside the topbar helpers so it
   appears automatically on every page without per-page wiring. */
.sr-sysmsg-modal {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    box-sizing: border-box;
}
.sr-sysmsg-modal[hidden] { display: none; }
.sr-sysmsg-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(10, 14, 22, 0.72);
    backdrop-filter: blur(3px);
    cursor: pointer;
}
.sr-sysmsg-panel {
    position: relative;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 28px 28px 22px;
    max-width: 520px;
    width: 100%;
    max-height: calc(100vh - 40px);
    overflow-y: auto;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45);
    animation: sr-sysmsg-pop 0.18s ease-out;
}
@keyframes sr-sysmsg-pop {
    from { opacity: 0; transform: translateY(8px) scale(0.98); }
    to   { opacity: 1; transform: translateY(0)   scale(1); }
}
.sr-sysmsg-x {
    position: absolute;
    top: 8px;
    right: 12px;
    background: transparent;
    border: 0;
    color: var(--text-soft);
    font-size: 28px;
    line-height: 1;
    cursor: pointer;
    padding: 4px 10px;
    border-radius: 6px;
}
.sr-sysmsg-x:hover { color: var(--text-primary); background: var(--bg-hover); }
.sr-sysmsg-severity {
    display: inline-block;
    padding: 4px 10px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.6px;
    margin-bottom: 12px;
}
.sr-sysmsg-severity--info {
    background: rgba(90, 122, 155, 0.20);
    color: var(--brand-secondary);
}
.sr-sysmsg-severity--important {
    background: rgba(212, 168, 70, 0.22);
    color: #c89540;
}
.sr-sysmsg-severity--urgent {
    background: rgba(192, 76, 76, 0.22);
    color: #c04c4c;
}
.sr-sysmsg-title {
    font-size: 22px;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0 0 14px;
    line-height: 1.25;
}
.sr-sysmsg-body {
    font-size: 15px;
    line-height: 1.55;
    color: var(--text-primary);
    margin-bottom: 20px;
    white-space: pre-wrap;
}
.sr-sysmsg-body a { color: var(--brand-accent); text-decoration: underline; }
.sr-sysmsg-body strong { color: var(--text-primary); }
.sr-sysmsg-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    border-top: 1px solid var(--border-light);
    padding-top: 16px;
}
.sr-sysmsg-counter {
    font-size: 12px;
    color: var(--text-soft);
}
.sr-sysmsg-confirm {
    background: var(--brand-secondary);
    color: #fff;
    border: 0;
    border-radius: 8px;
    padding: 12px 20px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    min-height: 44px;
    margin-left: auto;
}
.sr-sysmsg-confirm:hover { filter: brightness(1.08); }
@media (max-width: 480px) {
    .sr-sysmsg-panel { padding: 22px 18px 16px; }
    .sr-sysmsg-title { font-size: 19px; }
    .sr-sysmsg-confirm { width: 100%; margin-left: 0; }
}

/* Submit-reminder modal. Reuses the .sr-sysmsg-modal frame for backdrop +
   panel + animation, but replaces the system-message body styling with
   a custom layout: pill, title, lead, calendar-tear-off card, footer.
   The shared body class has white-space: pre-wrap which trips on this
   layout's whitespace, hence the dedicated .sr-submit-* classes. */
.sr-submit-panel { padding: 26px 28px 22px; }
.sr-submit-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 10px 5px 8px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.6px;
    margin-bottom: 14px;
    background: rgba(212, 168, 70, 0.18);
    color: #c89540;
    border: 1px solid rgba(212, 168, 70, 0.4);
}
.sr-submit-pill svg { flex: 0 0 auto; }
.sr-submit-title {
    font-size: 22px;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0 0 8px;
    line-height: 1.25;
}
.sr-submit-lead {
    font-size: 14px;
    color: var(--text-soft);
    line-height: 1.5;
    margin: 0 0 18px;
}

/* Day-preview card. 3-column grid: calendar tear-off | content | amount.
   Mirrors the .pwh-day pattern from paysheet.php's history but a bit
   bigger because it's the focal element of the modal. */
.sr-submit-card {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 14px;
    align-items: center;
    padding: 14px 16px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-left: 3px solid var(--brand-secondary);
    border-radius: 10px;
    margin-bottom: 14px;
}
.sr-submit-card__date {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-width: 56px;
    padding: 6px 8px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: 8px;
    line-height: 1;
}
.sr-submit-card__dow {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.6px;
    color: var(--text-soft);
}
.sr-submit-card__day {
    font-size: 22px;
    font-weight: 800;
    color: var(--text-primary);
    margin: 2px 0;
}
.sr-submit-card__mon {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.6px;
    color: var(--brand-secondary);
}
.sr-submit-card__body { min-width: 0; }
.sr-submit-card__title {
    font-size: 15px;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
}
.sr-submit-card__meta {
    font-size: 12px;
    color: var(--text-soft);
    line-height: 1.4;
}
.sr-submit-card__amt { text-align: right; }
.sr-submit-card__amt-num {
    font-size: 20px;
    font-weight: 800;
    color: var(--success-ink);
    line-height: 1;
    margin-bottom: 2px;
}
.sr-submit-card__amt-lbl {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.5px;
    color: var(--text-soft);
    text-transform: uppercase;
}

.sr-submit-error {
    background: rgba(192, 76, 76, 0.14);
    color: #c04c4c;
    border: 1px solid rgba(192, 76, 76, 0.4);
    border-radius: 6px;
    padding: 8px 12px;
    margin-bottom: 12px;
    font-size: 13px;
}

.sr-submit-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    border-top: 1px solid var(--border-light);
    padding-top: 16px;
}
.sr-submit-counter {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.5px;
    color: var(--text-soft);
    text-transform: uppercase;
}
.sr-submit-actions {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    margin-left: auto;
}
.sr-submit-secondary {
    color: var(--brand-secondary);
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
}
.sr-submit-secondary:hover { text-decoration: underline; }
.sr-submit-primary {
    background: var(--brand-secondary);
    color: #fff;
    border: 0;
    border-radius: 8px;
    padding: 11px 20px;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    font-family: inherit;
    min-height: 42px;
}
.sr-submit-primary:hover:not(:disabled) { filter: brightness(1.1); }
.sr-submit-primary:disabled { opacity: 0.6; cursor: not-allowed; }

@media (max-width: 480px) {
    .sr-submit-panel { padding: 22px 18px 16px; }
    .sr-submit-title { font-size: 19px; }
    .sr-submit-card { grid-template-columns: auto 1fr; row-gap: 8px; }
    .sr-submit-card__amt {
        grid-column: 1 / -1;
        text-align: left;
        padding-top: 4px;
        border-top: 1px dashed var(--border-light);
    }
    .sr-submit-card__amt-num { font-size: 18px; }
    .sr-submit-actions { width: 100%; justify-content: space-between; }
    .sr-submit-primary { flex: 1 1 auto; }
}

/* ShowRunner brand spinner — the full "ShowRunner" wordmark with three
   speed lines streaking past it on the left and a star overlaid on the
   capital R (echoing the original logo's star detail). Recolored to the
   PASOI blue/grey palette; the star is near-white so it shimmers visibly
   against the blue text.
   Used in two contexts:
     1. Full-page navigation overlay (centered on a backdrop)
     2. In-modal loading state (smaller, no backdrop) */
.sr-brand-spinner {
    display: inline-flex; align-items: center;
    width: 200px; height: 44px;
    flex-shrink: 0;
}
.sr-brand-spinner__svg {
    width: 100%; height: 100%;
    overflow: visible;
}
.sr-brand-spinner__name {
    font-family: 'Helvetica Neue', 'Arial Black', Arial, sans-serif;
    font-weight: 900;
    font-style: italic;
    font-size: 24px;
    fill: var(--brand-accent, #5a7a9b);
    letter-spacing: -0.5px;
}
.sr-brand-spinner__line {
    fill: var(--brand-secondary, #3d5a73);
    opacity: 0;
    transform-origin: 0 50%;
    animation: srSpeedLine 1.2s ease-out infinite;
}
.sr-brand-spinner__line--mid { animation-delay: 0.15s; }
.sr-brand-spinner__line--bot { animation-delay: 0.30s; }
@keyframes srSpeedLine {
    0%   { opacity: 0;    transform: translateX(-12px) scaleX(0.4); }
    25%  { opacity: 1;    transform: translateX(0)     scaleX(1);   }
    65%  { opacity: 0.95; transform: translateX(0)     scaleX(1);   }
    100% { opacity: 0;    transform: translateX(14px)  scaleX(0.4); }
}
/* Star overlaid on top of the capital R in "ShowRunner". Shimmer is the
   combo of three things: gentle scale pulse, a slow rotate so the points
   catch the eye, and a brightening glow halo. transform-box: fill-box
   anchors the rotation to the star's own center, not the SVG canvas. */
.sr-brand-spinner__star {
    fill: #e8eef5;
    transform-origin: center;
    transform-box: fill-box;
    filter: drop-shadow(0 0 2px rgba(168, 197, 221, 0.55));
    animation: srStarShimmer 2.0s ease-in-out infinite;
}
@keyframes srStarShimmer {
    0%, 100% {
        transform: scale(0.85) rotate(-10deg);
        fill: #b8c8d8;
        filter: drop-shadow(0 0 1px rgba(168, 197, 221, 0.4));
    }
    50% {
        transform: scale(1.20) rotate(15deg);
        fill: #ffffff;
        filter: drop-shadow(0 0 6px rgba(255, 255, 255, 1));
    }
}
@media (prefers-reduced-motion: reduce) {
    .sr-brand-spinner__line { animation: none; opacity: 0.6; transform: none; }
    .sr-brand-spinner__star { animation: none; fill: #e8eef5; }
}

/* Page-load overlay — used during same-origin navigation. Uses the brand
   spinner above as its centerpiece. */
.sr-loading-overlay {
    position: fixed; inset: 0;
    background: rgba(20, 28, 40, 0.78);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
    display: flex; align-items: center; justify-content: center;
    z-index: 99999;
    animation: srLoadingFadeIn 0.18s ease-out;
}
@keyframes srLoadingFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.sr-loading-card {
    display: flex; flex-direction: column; align-items: center; gap: 12px;
    padding: 24px 32px;
    background: var(--bg-card, #1a2330);
    border: 1px solid var(--border, #2c3543);
    border-radius: 12px;
    box-shadow: 0 16px 48px rgba(0,0,0,0.55);
}
.sr-loading-label {
    color: var(--text-soft, #8c9ba8);
    font-size: 11px; font-weight: 600;
    letter-spacing: 1.5px; text-transform: uppercase;
}
@media (prefers-reduced-motion: reduce) {
    .sr-loading-overlay { animation: none; }
}

/* "Show details" modal — wraps the existing show-detail.php in an iframe
   with embedded=1 so the page content fills the modal without duplicating
   template logic in JS. Single source of truth, single rendering path. */
.show-detail-modal-overlay {
    position: fixed; inset: 0; background: rgba(0,0,0,0.7);
    display: flex; align-items: center; justify-content: center;
    z-index: 9500; padding: 12px;
}
.show-detail-modal {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 10px;
    width: 100%; max-width: 720px;
    height: 100%; max-height: 92vh;
    display: flex; flex-direction: column; overflow: hidden;
    box-shadow: 0 20px 50px rgba(0,0,0,0.5);
}
.show-detail-modal-header {
    display: flex; justify-content: space-between; align-items: center;
    gap: 10px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-light);
    background: var(--bg-elevated);
}
.show-detail-modal-title {
    font-size: 15px; font-weight: 600; color: var(--text-primary);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    flex: 1 1 auto;
}
.show-detail-modal-close {
    background: none; border: none; color: var(--text-soft);
    font-size: 28px; cursor: pointer; line-height: 1;
    width: 36px; height: 36px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 6px;
    flex-shrink: 0;
}
.show-detail-modal-close:hover { color: var(--text-primary); background: var(--bg-hover); }
.show-detail-modal-frame {
    flex: 1 1 auto; width: 100%; border: 0;
    background: var(--bg-card);
}
.show-detail-modal-loading {
    display: flex; align-items: center; justify-content: center;
    flex: 1 1 auto; color: var(--text-soft);
    font-size: 14px;
}
/* When show-detail.php loads in embedded mode, drop body padding-top that
   normally accommodates the topbar/subnav, and tighten the page wrapper. */
body.show-detail--embedded { padding: 0; }
body.show-detail--embedded .page { padding: 12px; max-width: none; }
@media (max-width: 520px) {
    .show-detail-modal-overlay { padding: 0; }
    .show-detail-modal { max-height: 100vh; border-radius: 0; border: none; }
}

/* Readiness dots — green/red status indicators for whether the schedule
   and stage-advance documents are populated for this show. Lives at the
   end of the card body so workers see the signal before scrolling to
   the Show details button. */
.show-card__readiness {
    margin-top: 12px;
    display: flex; flex-direction: column; gap: 4px;
    font-size: 13px;
}
.show-card__ready-row { display: inline-flex; align-items: center; gap: 8px; }
.show-card__ready-dot {
    width: 10px; height: 10px; border-radius: 50%;
    flex-shrink: 0; display: inline-block;
    border: 1px solid rgba(0,0,0,0.18);
}
.show-card__ready-dot--on  { background: var(--success, #2e7d32); }
.show-card__ready-dot--off { background: var(--danger,  #c62828); }
.show-card__ready-label { color: var(--text-soft); }

/* Working with — clean inline list right under "Your role". No
   dropdown — workers see who they're on the call with at a glance.
   Each line: status dot + name + role + tap-to-call phone. */
.show-card__crew-list {
    list-style: none;
    margin: 0;
    padding: 0;
    flex: 1 1 auto;
    min-width: 0;
}
.show-card__crew-line {
    display: flex; align-items: center; gap: 6px;
    flex-wrap: wrap;
    padding: 3px 0;
    font-size: 13px;
    line-height: 1.35;
    color: var(--text-primary);
}
.show-card__crew-bullet {
    width: 7px; height: 7px;
    border-radius: 50%;
    flex-shrink: 0;
    box-shadow: 0 0 0 1px rgba(0,0,0,0.18) inset;
    margin-right: 2px;
}
.show-card__crew-bullet--confirmed { background: var(--success, #2e7d32); }
.show-card__crew-bullet--pending   { background: var(--warning, #f7a73c); }
.show-card__crew-bullet--declined  { background: var(--danger,  #b04040); }
/* Declined partner — crossed out + dimmed so the worker reading the card
   can tell at a glance "we tried to book Jonathan, he can't make it."
   Phone link stays untouched so it remains tap-to-call. */
.show-card__crew-line--declined { opacity: 0.65; }
.show-card__crew-line--declined .show-card__crew-name,
.show-card__crew-line--declined .show-card__crew-role {
    text-decoration: line-through;
    color: var(--text-soft);
}
.show-card__crew-name {
    font-weight: 600;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
.show-card__crew-role {
    font-size: 12px;
    color: var(--text-soft);
}
.show-card__crew-phone {
    margin-left: auto;
    color: var(--brand-accent);
    font-size: 12px;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    padding: 2px 6px;
    border-radius: 4px;
}
.show-card__crew-phone:hover {
    color: var(--brand-secondary);
    background: var(--bg-hover);
    text-decoration: none;
}

.btn {
    padding: 9px 18px;
    border: none;
    border-radius: 6px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
}
.btn-accept  { background: var(--success); color: #fff; }
.btn-accept:hover  { background: #218838; }
.btn-decline { background: var(--danger); color: #fff; }
.btn-decline:hover { background: #c82333; }
.btn--ghost {
    background: transparent;
    color: var(--text-soft);
    border: 1px solid var(--border);
    font-weight: 500;
}
.btn--ghost:hover { background: var(--bg-hover); color: var(--text-primary); }

/* --- Theme toggle — polished icon pill, sun/moon swap --- */
.theme-toggle {
    background: transparent;
    color: var(--brand-accent);
    border: 1px solid var(--border);
    border-radius: 999px;
    width: 32px; height: 32px;
    padding: 0;
    line-height: 1;
    cursor: pointer;
    font-family: inherit;
    display: inline-flex; align-items: center; justify-content: center;
    transition: background 0.18s, color 0.18s, border-color 0.18s, transform 0.15s;
}
.theme-toggle:hover {
    background: color-mix(in srgb, var(--brand-secondary) 14%, transparent);
    border-color: var(--brand-secondary);
    color: var(--brand-accent);
    transform: rotate(-12deg);
}
.theme-toggle__icon { display: block; }
.topbar .theme-toggle {
    border-color: rgba(255, 255, 255, 0.18);
    color: var(--brand-accent);
    background: rgba(255, 255, 255, 0.04);
}
.topbar .theme-toggle:hover {
    background: rgba(255, 255, 255, 0.12);
    border-color: var(--brand-accent);
    color: var(--text-onbrand);
}
.theme-toggle--floating {
    position: fixed;
    top: 16px;
    right: 16px;
    z-index: 10;
    color: var(--text-soft);
}
.theme-toggle--floating:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}

/* --- Sub-nav (worker and admin section tabs) ---
   Pill-tabs with icon + label. Desktop shows them side-by-side; mobile
   stacks icon above a tiny label so all 7 admin tabs fit on ONE row. */
.subnav {
    background: var(--bg-card);
    border-bottom: 1px solid var(--border-light);
    display: flex;
    gap: 4px;
    padding: 6px 12px;
}
.subnav a {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--text-soft);
    padding: 8px 12px;
    font-size: 14px;
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
    border-radius: 6px;
    line-height: 1.2;
    transition: background 0.12s, color 0.12s;
}
.subnav a:hover {
    color: var(--text-primary);
    background: var(--bg-hover);
    text-decoration: none;
}
.subnav a.active {
    color: var(--brand-accent);
    background: var(--bg-elevated);
    font-weight: 600;
}
.subnav-icon { flex-shrink: 0; }
.subnav-label { display: inline; }

/* Pin a tab to the far right of the subnav row.
   Desktop: margin-left:auto eats remaining flex space; a thin left border
   visually separates the pinned tab from the rest of the group.
   Mobile: tabs all share equal width via flex:1, so margin-left:auto is
   a no-op there — the left border is the only separator and we add a
   tiny left margin to amplify it. */
.subnav a.subnav-pin-right {
    margin-left: auto;
    border-left: 1px solid var(--border-light);
    padding-left: 16px;
    margin-left: auto; /* explicit win over any cascaded gap */
}
/* When two pin-right tabs sit side-by-side (e.g. "Calendar" + "My
   shows" in the admin subnav), share one separator before the group
   instead of stacking two dividers. The first pin-right element keeps
   the auto-margin push + border; the second drops both. */
.subnav a.subnav-pin-right + a.subnav-pin-right {
    margin-left: 0;
    border-left: 0;
    padding-left: 8px;
}

/* Phones (portrait + landscape) and small tablets: switch to icon-above-
   label stack, each tab claims equal width so all 8 admin tabs fit on one
   row at 375px AND at landscape phone widths. Ceiling is 1024px so even
   flagship phones in landscape (iPhone 14 Pro Max = 932px, Galaxy S23
   Ultra = 915px, iPad Mini portrait = 768px) get the compact layout. No
   wrap, no scroll. */
@media (max-width: 1024px) {
    .subnav {
        padding: 4px 6px;
        gap: 2px;
        flex-wrap: nowrap;  /* critical — force single row */
    }
    .subnav a {
        flex: 1 1 0;
        min-width: 0;
        flex-direction: column;
        gap: 2px;
        padding: 6px 2px;
        font-size: 10px;
        font-weight: 500;
        text-align: center;
    }
    .subnav-icon { width: 20px; height: 20px; }
    .subnav-label {
        font-size: 10px; line-height: 1;
        overflow: hidden; text-overflow: ellipsis; max-width: 100%;
    }
}
@media (max-width: 360px) {
    .subnav a { padding: 6px 1px; }
    .subnav-label { font-size: 9px; }
}

/* ─── Modern admin nav layout (super_admin opt-in) ───
   When `html[data-admin-nav="modern"]` is set (via the topbar toggle —
   currently super_admin only), secondary subnav items collapse into a
   "More" overflow panel on mobile. Classic mode (the default) shows
   every item in the row, same as before. Desktop (>767px) shows all
   items in either mode — modern only kicks in when there isn't room. */

/* In modern admin nav mode the entire subnav is suppressed — every page
   that used to live in the subnav (Roster, Pending, Payroll, Tasks,
   Documents, Calendar, My shows, Settings) now lives in the topbar
   hamburger drawer's "Pages" group. Classic users still see the subnav
   row inline. Toggle via the topbar hamburger's "Switch layout" entry. */
/* Hide the subnav ONLY on admin-shell pages (those whose topbar is
   .topbar--admin, where the modern hamburger drawer carries every
   navigation entry already). Crew/worker pages use the bare .topbar
   and need their own subnav row visible — the prior universal rule
   was hiding their tabs too. .topbar--admin appears earlier in the
   document tree than .subnav, so the general-sibling combinator
   matches reliably whether or not modals/scripts sit between. */
html[data-admin-nav="modern"] .topbar--admin ~ .subnav { display: none !important; }

/* Default: hide the overflow pill + panel entirely. Classic users never
   see the More button; modern desktop also never sees it because the
   row has room. The mobile-modern @media block below opts back in. */
.subnav-overflow { display: none; }
.subnav-overflow > summary { list-style: none; }
.subnav-overflow > summary::-webkit-details-marker { display: none; }

/* Modern mode + mobile: hide secondary items, reveal the More pill.
   Below the row, the pill's <details>-toggle reveals a categorized
   panel with all the secondary items grouped (Manage / Show tools /
   Setup). One more-pill replaces 5-9 secondary tabs in the row. */
@media (max-width: 767px) {
    html[data-admin-nav="modern"] .subnav a[data-priority="secondary"] {
        display: none;
    }
    html[data-admin-nav="modern"] .subnav-overflow {
        display: inline-flex;
        position: relative;
        flex: 1 1 0;
        min-width: 0;
    }
    html[data-admin-nav="modern"] .subnav-overflow > summary {
        flex: 1 1 0;
        min-height: 44px;
        padding: 7px 2px 9px;
        flex-direction: column;
        gap: 0;
        border-radius: 10px;
        cursor: pointer;
        color: var(--text-soft);
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 10px;
        font-weight: 500;
        text-align: center;
        user-select: none;
        width: 100%;
        transition: background 0.12s, color 0.12s;
    }
    html[data-admin-nav="modern"] .subnav-overflow > summary:hover,
    html[data-admin-nav="modern"] .subnav-overflow[open] > summary {
        background: var(--bg-elevated);
        color: var(--text-primary);
    }
    /* Hide pin-right separator inside modern-mode More pill — it's not
       a pinned admin tab anymore. */
    html[data-admin-nav="modern"] .subnav a.subnav-pin-right { display: none; }
}

/* Overflow panel — slides down under the subnav as a categorized menu.
   Anchored to the right edge so it never clips off-screen on phones. */
.subnav-overflow__panel {
    position: absolute;
    top: calc(100% + 4px);
    right: 4px;
    min-width: 220px;
    max-width: calc(100vw - 16px);
    background: var(--bg-card);
    border: 1px solid var(--border-light);
    border-radius: 10px;
    box-shadow: var(--shadow-card-lg);
    padding: 8px;
    z-index: 100;
    animation: subnav-overflow-in 0.14s ease-out;
}
@keyframes subnav-overflow-in {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}
.subnav-overflow__group + .subnav-overflow__group {
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px solid var(--border-light);
}
.subnav-overflow__group-title {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-soft);
    font-weight: 700;
    margin: 4px 8px 6px;
}
.subnav-overflow__item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 10px;
    color: var(--text-primary);
    text-decoration: none;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 500;
    transition: background 0.12s;
    min-height: 40px;
}
.subnav-overflow__item:hover {
    background: var(--bg-elevated);
    text-decoration: none;
}
.subnav-overflow__item.active {
    background: var(--bg-elevated);
    color: var(--brand-accent);
    font-weight: 600;
}

/* Layout-toggle pill — super_admin only. Sits in the topbar nav next
   to the Profile button. Compact + neutral until activated; lights up
   in the brand-accent color when modern mode is on so Carl can see at
   a glance which mode he's previewing. */
.topbar-nav-mode-toggle {
    appearance: none;
    border: 1px solid var(--border-light);
    background: transparent;
    color: var(--text-soft);
    padding: 6px 10px;
    border-radius: 6px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 600;
    font-family: inherit;
    line-height: 1;
    transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.topbar-nav-mode-toggle:hover {
    background: var(--bg-elevated);
    color: var(--text-primary);
    border-color: var(--brand-accent);
}
.topbar-nav-mode-toggle__label { white-space: nowrap; }
html[data-admin-nav="modern"] .topbar-nav-mode-toggle {
    color: var(--brand-accent);
    border-color: var(--brand-accent);
    background: rgba(122, 154, 187, 0.10);
}
@media (max-width: 767px) {
    .topbar-nav-mode-toggle { padding: 6px 8px; }
    .topbar-nav-mode-toggle__label { display: none; }
}

/* ─── Modern mobile subnav (≤500px): icon-only ───
   Labels are visually hidden (still readable to screen-readers via the
   <span>) so the row stays uncluttered when 10+ admin tabs need to share
   a 375px viewport. Active tab carries a pill background + accent dot
   under the icon for unambiguous "you are here" feedback. Each tap target
   meets Apple HIG's 44px minimum.

   This pattern beats truncating labels to "Pend…" / "Setti…" — admins
   recognize icons faster than 4-character abbreviations. */
@media (max-width: 500px) {
    .subnav {
        padding: 4px 4px 6px;
        gap: 1px;
    }
    .subnav a {
        position: relative;
        min-height: 44px;
        padding: 7px 2px 9px;
        flex-direction: column;
        gap: 0;
        border-radius: 10px;
    }
    .subnav-icon {
        width: 22px;
        height: 22px;
    }
    .subnav-label {
        position: absolute !important;
        width: 1px; height: 1px;
        padding: 0; margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
    }
    .subnav a.active {
        background: var(--bg-elevated);
        color: var(--brand-accent);
    }
    /* The accent dot indicator under the active icon — modern tab-bar
       pattern (iOS / Material) that reads as "selected" without any
       text. Dot is 3px wide / 3px tall, brand-accent color, anchored
       3px below the icon center. */
    .subnav a.active::after {
        content: '';
        position: absolute;
        left: 50%;
        bottom: 4px;
        transform: translateX(-50%);
        width: 4px;
        height: 4px;
        border-radius: 999px;
        background: var(--brand-accent);
    }
    /* Don't let the pinned tab (My Shows) start on a new visual block —
       the gap was set to 4px on mobile pin-right elsewhere; collapse it
       to the same 1px gap as the rest so all 10 tabs read as one row. */
    .subnav a.subnav-pin-right {
        margin-left: 1px;
        border-left-color: transparent;
        padding-left: 2px;
    }
}
/* Landscape phones / small tablets: each tab has 100px+ of room — give
   labels and icons more breathing room than the cramped portrait-phone
   sizes above. Stays equal-width via the inherited flex:1 1 0 rule. */
@media (min-width: 521px) and (max-width: 1024px) {
    .subnav a { padding: 8px 6px; }
    .subnav-icon { width: 22px; height: 22px; }
    .subnav-label { font-size: 12px; }
}

/* Mobile-specific override for the pinned tab: margin-left:auto won't
   right-align inside flex:1 children, so just visually separate via
   an explicit divider gap + left border (already set above). The tab
   sits last in the source order so it's already on the right edge. */
@media (max-width: 1024px) {
    .subnav a.subnav-pin-right {
        margin-left: 4px;
        padding-left: 4px;
        border-left: 1px solid var(--border-light);
    }
}

/* --- Empty-state helper --- */
.empty-state {
    text-align: center;
    padding: 40px 20px;
    color: var(--text-soft);
}
.empty-state h3 { color: var(--brand-accent); font-size: 17px; margin-bottom: 8px; }

/* --- Form primitive (profile, admin actions) --- */
.form-field { margin-bottom: 14px; }
.form-field label {
    display: block;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-soft);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 4px;
}
.form-field input,
.form-field select,
.form-field textarea {
    width: 100%;
    padding: 10px 12px;
    background: var(--bg-input);
    color: var(--text-primary);
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 14px;
    font-family: inherit;
}
.form-field input:focus {
    outline: none;
    border-color: var(--brand-secondary);
    box-shadow: 0 0 0 2px rgba(122, 154, 187, 0.25);
}
.form-field .hint {
    display: block;
    font-size: 12px;
    color: var(--text-dim);
    margin-top: 4px;
}
.btn-primary {
    background: var(--brand-primary);
    color: var(--text-onbrand);
    border: none;
    border-radius: 6px;
    padding: 10px 22px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    line-height: 1.2;
    transition: background 0.12s, color 0.12s, border-color 0.12s, opacity 0.12s;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}
.btn-primary:hover { background: var(--brand-secondary); text-decoration: none; }
.btn-primary:disabled { opacity: 0.55; cursor: not-allowed; }

/* Secondary button — subtle outlined variant. Was being referenced
   throughout the codebase but never defined globally; modals + the
   prep page were falling back to browser defaults (white/grey) which
   broke the dark theme. */
.btn-secondary {
    background: var(--bg-elevated);
    color: var(--text-primary);
    border: 1px solid var(--border-light);
    border-radius: 6px;
    padding: 10px 18px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    line-height: 1.2;
    transition: background 0.12s, border-color 0.12s, color 0.12s, opacity 0.12s;
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}
.btn-secondary:hover {
    background: var(--bg-hover);
    border-color: var(--brand-accent);
    text-decoration: none;
}
.btn-secondary:disabled { opacity: 0.55; cursor: not-allowed; }
.btn-primary:disabled {
    opacity: 0.6;
    cursor: wait;
    color: var(--text-soft);
    background: var(--brand-secondary);
}

/* --- Check-in badge (appears above clock UI when worker has checked in) --- */
.checkin-badge {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px;
    background: var(--success-soft);
    border: 1px solid var(--success);
    border-radius: 8px;
    flex-wrap: wrap;
}

/* --- Clock-in / out widget on worker show cards --- */
.show-card__clock {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px dashed var(--border-light);
}
.clock-active {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    background: var(--success-soft);
    border: 1px solid var(--success);
    border-radius: 8px;
    padding: 12px 14px;
}
.clock-active__label {
    font-weight: 600;
    font-size: 14px;
    color: var(--success-ink);
}
.clock-active__time {
    font-size: 12px;
    color: var(--text-soft);
    font-variant-numeric: tabular-nums;
}
.clock-blocked {
    background: var(--warning-soft);
    color: var(--warning-ink);
    border: 1px solid var(--warning);
    border-radius: 8px;
    padding: 10px 14px;
    font-size: 13px;
}
.clock-form { display: flex; flex-direction: column; gap: 10px; }
.clock-form__row {
    display: flex;
    gap: 14px;
    align-items: flex-end;
    flex-wrap: wrap;
}
.clock-form__label {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-soft);
    text-transform: uppercase;
    letter-spacing: 0.4px;
    flex: 1;
    min-width: 140px;
}
.clock-form__label select {
    padding: 8px 10px;
    background: var(--bg-input);
    color: var(--text-primary);
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 14px;
    font-family: inherit;
}
.clock-form__driver {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    color: var(--text-primary);
    cursor: pointer;
    padding-bottom: 8px;
}
.clock-form .btn-accept { align-self: flex-start; padding: 10px 22px; }

/* --- Admin landing hero ---
   Greeting + role on the left, today's date on the right. Distinct from
   the .card chrome — sits above the stat grid as a warm welcome. */
.admin-landing-hero {
    display: flex; align-items: center; justify-content: space-between;
    gap: 20px; flex-wrap: wrap;
    padding: 22px 24px;
    margin-bottom: 18px;
    background: linear-gradient(135deg, color-mix(in srgb, var(--brand-primary) 22%, var(--bg-card)) 0%, var(--bg-card) 70%);
    border: 1px solid var(--border-light);
    border-radius: 14px;
    box-shadow: var(--shadow-card);
    position: relative;
    overflow: hidden;
}
.admin-landing-hero::after {
    content: ""; position: absolute;
    right: -40px; top: -40px; width: 180px; height: 180px;
    background: radial-gradient(closest-side, color-mix(in srgb, var(--brand-accent) 22%, transparent) 0%, transparent 100%);
    pointer-events: none;
}
.admin-landing-hero__greeting { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.admin-landing-hero__hello {
    font-size: 13px; color: var(--text-soft);
    text-transform: uppercase; letter-spacing: 0.6px; font-weight: 600;
}
.admin-landing-hero__name {
    font-size: 28px; font-weight: 700; color: var(--brand-accent);
    line-height: 1.05; letter-spacing: -0.5px;
    margin: 0;
}
.admin-landing-hero__role {
    margin-top: 4px;
    display: inline-flex; align-self: flex-start;
    padding: 2px 10px; border-radius: 999px;
    font-size: 11px; font-weight: 700; letter-spacing: 0.5px; text-transform: uppercase;
    background: color-mix(in srgb, var(--brand-secondary) 20%, transparent);
    color: var(--brand-accent);
    border: 1px solid color-mix(in srgb, var(--brand-secondary) 50%, transparent);
}
.admin-landing-hero__date {
    text-align: right; display: flex; flex-direction: column; gap: 1px;
    z-index: 1;
}
.admin-landing-hero__day {
    font-size: 18px; font-weight: 700; color: var(--text-primary);
    letter-spacing: -0.2px;
}
.admin-landing-hero__full {
    font-size: 12px; color: var(--text-soft);
    text-transform: uppercase; letter-spacing: 0.5px;
}
@media (max-width: 560px) {
    .admin-landing-hero { padding: 14px 16px; }
    .admin-landing-hero__name { font-size: 22px; }
    .admin-landing-hero__hello { font-size: 11px; }
    .admin-landing-hero__role { font-size: 10px; }
    .admin-landing-hero__date { text-align: right; }
    .admin-landing-hero__day { font-size: 14px; }
    .admin-landing-hero__full { font-size: 11px; }
}

/* --- Stat card grid (admin home dashboard) --- */
.stat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 16px;
    margin-bottom: 24px;
}
.stat-card {
    background: linear-gradient(155deg, var(--bg-card) 0%, color-mix(in srgb, var(--bg-card) 92%, var(--brand-secondary) 8%) 100%);
    border: 1px solid var(--border-light);
    border-radius: 14px;
    padding: 18px 18px 16px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    text-decoration: none;
    color: var(--text-primary);
    position: relative;
    overflow: hidden;
    transition: border-color 0.18s, transform 0.18s, box-shadow 0.18s;
    min-height: 124px;
}
.stat-card::before {
    /* corner accent sliver — tasteful, no clutter */
    content: ""; position: absolute; right: -22px; top: -22px;
    width: 70px; height: 70px;
    background: radial-gradient(closest-side, color-mix(in srgb, var(--brand-secondary) 22%, transparent) 0%, transparent 100%);
    pointer-events: none;
}
.stat-card:hover {
    text-decoration: none;
    border-color: var(--brand-secondary);
    transform: translateY(-3px);
    box-shadow: 0 8px 22px -10px color-mix(in srgb, var(--brand-secondary) 60%, transparent);
}
.stat-card__num {
    font-size: 38px;
    font-weight: 700;
    color: var(--brand-accent);
    line-height: 1;
    letter-spacing: -0.5px;
    margin-top: auto;  /* push number to bottom-area, label below it */
}
.stat-card__label {
    font-size: 12px;
    color: var(--text-soft);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    font-weight: 600;
}
.stat-card--warn { border-color: var(--warning); }
.stat-card--warn .stat-card__num  { color: var(--warning-ink); }
.stat-card--warn::before {
    background: radial-gradient(closest-side, color-mix(in srgb, var(--warning) 28%, transparent) 0%, transparent 100%);
}

/* --- Quicklink list (admin home) ---
   Each row is: a primary-styled button (the destination) + an inline
   description to its right. Mobile drops the description below. */
.quicklink-list {
    list-style: none;
    margin: 0; padding: 0;
    display: flex; flex-direction: column;
    gap: 8px;
}
.quicklink-list li {
    display: flex; align-items: center; gap: 14px;
    flex-wrap: wrap;
}
.quicklink-btn {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 9px 16px;
    min-width: 200px;
    background: var(--brand-primary);
    color: var(--text-onbrand);
    border: 1px solid var(--brand-primary);
    border-radius: 7px;
    font-size: 14px; font-weight: 600;
    text-decoration: none;
    flex-shrink: 0;
    transition: background 0.15s, border-color 0.15s, transform 0.12s, box-shadow 0.18s;
}
.quicklink-btn:hover {
    background: var(--brand-secondary);
    border-color: var(--brand-secondary);
    color: var(--text-onbrand);
    text-decoration: none;
    transform: translateY(-1px);
    box-shadow: 0 4px 14px -8px color-mix(in srgb, var(--brand-secondary) 70%, transparent);
}
.quicklink-btn--external {
    background: transparent;
    color: var(--brand-accent);
    border-color: var(--brand-secondary);
}
.quicklink-btn--external:hover {
    background: color-mix(in srgb, var(--brand-secondary) 16%, transparent);
    border-color: var(--brand-accent);
    color: var(--brand-accent);
}
.quicklink-arrow {
    font-size: 12px; opacity: 0.85;
    transition: transform 0.15s;
    display: inline-block;
}
.quicklink-btn:hover .quicklink-arrow { transform: translate(2px, -2px); }
.quicklink-desc {
    font-size: 13px;
    color: var(--text-soft);
    line-height: 1.4;
    flex: 1;
    min-width: 0;
}
@media (max-width: 560px) {
    .quicklink-list li { gap: 4px; }
    .quicklink-btn { width: 100%; min-width: 0; justify-content: flex-start; }
    .quicklink-desc { padding: 0 4px; }
}

/* --- Mobile breakpoint — progressive upgrade to desktop above 768px ---
   Topbar collapses every secondary action to an icon-only button so the
   row stays single-line: brand on the left, all utility actions on the
   right. Text labels stay in markup (a11y) but visually hide via CSS so
   nothing wraps to a second line. */
@media (max-width: 767px) {
    .topbar {
        padding: 10px 12px;
        flex-wrap: nowrap;          /* force single row */
        gap: 8px;
    }
    .topbar h1 { font-size: 16px; }
    .topbar-brand { min-width: 0; flex: 0 1 auto; }
    .topbar-brand-word { font-size: 16px; }
    .topbar nav {
        gap: 4px;
        font-size: 13px;
        flex-wrap: nowrap;          /* force single row */
        justify-content: flex-end;
        flex: 1 1 auto;
        min-width: 0;
    }
    /* Pill text labels collapse — icon stays. */
    .topbar-app-pill {
        padding: 6px 8px;
        gap: 0;
        font-size: 12px;
    }
    .topbar-app-pill > span { display: none; }
    .topbar-app-pill svg { width: 16px; height: 16px; }
    /* Sign-out becomes an icon-only door button to match the others. */
    .topbar-signout { padding: 6px 8px; gap: 0; }
    .topbar-signout-label { display: none; }
    /* Vertical divider just adds noise on mobile — drop it. */
    .topbar-divider { display: none; }
    .page {
        padding: 0 12px;
        margin: 16px auto;
    }
    .card, .show-card {
        padding: 16px;
        border-radius: 10px;
    }
    .auth-card { padding: 24px 20px; }
    .theme-toggle--floating { top: 10px; right: 10px; }

    /* Worker show cards on mobile — compact, single-column rows, full-
       width action buttons. Tighter than desktop so a confirmed show with
       a full crew list + readiness + clock block still fits a phone
       screen without scrolling past the end of the card. */
    .show-card {
        padding: 14px 14px;     /* was 20px 24px */
        margin-bottom: 12px;
        border-radius: 10px;
    }
    .show-card__header { flex-direction: column; gap: 6px; }
    .show-card__name { font-size: 16px; line-height: 1.25; }
    .show-card__dates { font-size: 12px; }
    .show-card__prep-dot { width: 9px; height: 9px; margin-right: 6px; }
    .show-card__badge { align-self: flex-start; padding: 3px 8px; font-size: 11px; }
    .show-card__body { margin-top: 10px; font-size: 13px; }
    .show-card__row {
        flex-direction: column;
        gap: 1px;
        padding: 5px 0;
        border-bottom: 1px solid var(--border-light);
    }
    .show-card__row:last-child { border-bottom: none; }
    .show-card__label {
        min-width: 0;
        font-size: 10px;
        text-transform: uppercase;
        letter-spacing: 0.5px;
    }
    .show-card__crew-list { gap: 2px; }
    .show-card__crew-line { font-size: 12px; flex-wrap: wrap; gap: 4px; }
    .show-card__crew-name { font-size: 12px; }
    .show-card__crew-role { font-size: 11px; }
    .show-card__crew-phone { font-size: 11px; padding: 1px 6px; }
    .show-card__readiness {
        display: flex; flex-wrap: wrap; gap: 8px 14px;
        margin-top: 8px; font-size: 11px;
    }
    .show-card__comment { font-size: 12px; padding: 8px 10px; margin-top: 6px; }

    .show-card__details-btn {
        margin-top: 10px; padding: 10px 12px;
        font-size: 13px; min-height: 44px;
    }
    .show-card__actions { flex-direction: column; gap: 8px; margin-top: 10px; }
    .show-card__actions form { width: 100%; }
    .show-card__actions .btn { width: 100%; padding: 11px; min-height: 44px; }

    /* Clock block — keep all states visible without dwarfing the rest of
       the card. Notice text wraps cleanly under the button instead of
       sitting next to it. */
    .show-card__clock { margin-top: 10px; }
    .show-card__clock .clock-form { flex-direction: column; align-items: stretch; gap: 6px; }
    .show-card__clock .clock-form .btn { width: 100%; min-height: 44px; }
    .show-card__clock .clock-form span,
    .show-card__clock .clock-blocked,
    .show-card__clock .checkin-badge { font-size: 12px; }
    .show-card__clock .clock-active { padding: 12px; }
    .show-card__clock .clock-blocked { padding: 10px 12px; }
}

/* Extra-tight pass for narrow phones (iPhone SE / older Androids). The
   767px breakpoint above already stacks rows; this trims further so a
   confirmed show with a full crew + readiness + clock notice still fits
   without horizontal overflow at 320–380px viewport widths. */
@media (max-width: 400px) {
    .show-card { padding: 12px 12px; }
    .show-card__name { font-size: 15px; }
    .show-card__row { padding: 4px 0; }
    .show-card__readiness { gap: 6px 12px; }
    .show-card__crew-line { font-size: 11.5px; }
    .show-card__clock .clock-form span { display: block; margin-left: 0 !important; margin-top: 4px; }

    /* Invite table: compact */
    table.invite-table { font-size: 13px; }
    table.invite-table th,
    table.invite-table td { padding: 8px 6px; }

    /* Page-level headings */
    .card h2 { font-size: 16px; }

    /* Stat cards: 2-column grid on mobile so the admin landing fits a
       phone screen without scrolling. Compact column layout — number
       above label. Was previously 1-col stacked rows (each 84px tall),
       which made the page 4× taller than necessary. */
    .stat-grid { grid-template-columns: 1fr 1fr; gap: 8px; }
    .stat-card {
        min-height: 0; padding: 12px;
        flex-direction: column; align-items: flex-start;
        gap: 4px;
    }
    .stat-card__num { font-size: 26px; flex-shrink: 0; }
    .stat-card__label { text-align: left; font-size: 11px; line-height: 1.25; }

    /* Clock widgets stack on mobile */
    .clock-active { flex-direction: column; align-items: stretch; }
    .clock-active form { width: 100%; }
    .clock-active .btn { width: 100%; }
    .clock-form__row { flex-direction: column; align-items: stretch; gap: 10px; }
    .clock-form__label { min-width: 0; width: 100%; }
    .clock-form .btn-accept { width: 100%; }

    /* Invite table: ensure submit buttons meet 44px tap target on mobile */
    table.invite-table button,
    table.invite-table .btn {
        min-height: 44px;
    }
    /* Status labels never wrap (DECLINED / NO RESPONSE / APPROVED pills) */
    .crew-status-label { white-space: nowrap; display: inline-block; }

    /* Admin documents upload form: stack 2-column grid to 1-column on phones */
    .doc-form-grid { grid-template-columns: 1fr !important; }

    /* Admin roster role <select>: fit table cell, ensure tappable */
    table.invite-table select[name="role"] {
        width: 100%; max-width: 140px; min-height: 36px;
    }
}

/* --- Stat-grid 3-column modifier (used by paysheet totals) --- */
@media (min-width: 521px) {
    .stat-grid.stat-grid--3col { grid-template-columns: repeat(3, 1fr); }
}

/* --- Shared card-stack utilities ---------------------------------------
   Used by admin pages (payroll, roster, pending, settings) that render a
   table for wide viewports and a card-stack for phones. Page-specific
   classes (.psc-*, .rst-*, .pnd-*) layer on identity/badge/meta details;
   these utilities only handle the table↔stack swap + common anatomy.
   ----------------------------------------------------------------------- */
.psc-table-view { display: block; }
.psc-card-stack { display: none; }

.psc-stack-card {
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 14px;
    margin-bottom: 10px;
}
.psc-stack-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 10px;
    margin-bottom: 8px;
}
.psc-stack-footer {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 10px;
}
.psc-stack-btn {
    flex: 1 1 auto;
    min-height: 44px;
    padding: 10px 14px;
    font-size: 14px;
    font-family: inherit;
    font-weight: 500;
    border-radius: 6px;
    cursor: pointer;
    text-align: center;
    border: 1px solid var(--border);
    background: var(--bg-input);
    color: var(--text-primary);
    text-decoration: none;
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.psc-stack-btn--primary {
    background: var(--brand-accent);
    color: #fff;
    border-color: var(--brand-accent);
}
.psc-stack-btn--danger {
    color: var(--danger-ink);
    border-color: var(--danger);
    background: transparent;
}

@media (max-width: 520px) {
    .psc-table-view { display: none; }
    .psc-card-stack { display: block; }
}

/* --- Extra-narrow (≤360px): tighten nav + stat cards for old iPhone SE.
       Drop the "ShowRunner" word so the brand is just the logo, freeing
       enough horizontal space for the icon row. --- */
@media (max-width: 360px) {
    .topbar { padding: 8px 10px; }
    .topbar h1 { font-size: 15px; }
    .topbar-brand-word { display: none; }
    .topbar nav { gap: 2px; font-size: 12px; }
    .topbar nav a { padding: 4px 6px; }
    .topbar-app-pill, .topbar-signout, .topbar-iconbtn {
        padding: 6px 6px;
    }
    .topbar-iconbtn { width: 30px; height: 30px; }
    .stat-card__num { font-size: 24px; }
}

/* --- Stage chip on worker show cards and calendar events. Pulls the
       mobile_stage value (SL-100, SC-90 etc.) forward so crew know what
       kind of rig they're showing up to at a glance. -------------------- */
.show-card__stage,
.cal-event__stage,
.cal-agenda__stage {
    display: inline-block;
    padding: 1px 7px;
    border-radius: 10px;
    background: rgba(140, 170, 200, 0.18);
    color: var(--brand-accent, #b0c4d8);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.3px;
    line-height: 1.5;
    vertical-align: middle;
    margin-left: 4px;
    white-space: nowrap;
}
.show-card__stage {
    /* In a stacked show-card row the chip sits inline after the label —
       remove the margin-left since the row already has natural spacing. */
    margin-left: 0;
    font-size: 12px;
    padding: 2px 8px;
}
.cal-event__stage { font-size: 9px; padding: 0 4px; margin-left: 2px; }

/* --- Document stack — responsive card rows (replaces the old table UI).
       Always fits ≥320px; never horizontal-scrolls. Tap the card to open
       inline; tap the ↓ badge to force a download. ---------------------- */
.doc-stack {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.doc-card {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    background: var(--bg-elevated, #1d2935);
    border: 1px solid var(--border, rgba(255,255,255,0.08));
    border-radius: 8px;
    text-decoration: none;
    color: inherit;
    transition: background-color 0.12s ease, border-color 0.12s ease;
    min-height: 48px; /* tap target */
}
.doc-card:hover,
.doc-card:focus-visible {
    background: var(--bg-hover, rgba(255,255,255,0.04));
    border-color: var(--brand-accent, #b0c4d8);
}
.doc-card__body {
    flex: 1 1 auto;
    min-width: 0; /* allows text truncation inside flexbox */
}
.doc-card__label {
    font-weight: 600;
    font-size: 14px;
    line-height: 1.3;
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}
.doc-card__meta {
    margin-top: 3px;
    font-size: 12px;
    color: var(--text-soft, #8aa);
    word-break: break-word;
    /* Clamp to 2 lines with ellipsis — keeps long filenames readable on
       narrow screens without pushing the download button off-card. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.doc-card__dl {
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: rgba(255,255,255,0.06);
    border: 1px solid var(--border, rgba(255,255,255,0.12));
    border-radius: 6px;
    color: var(--text-soft, #8aa);
    font-size: 16px;
    text-decoration: none;
    cursor: pointer;
    user-select: none;
}
.doc-card__dl:hover,
.doc-card__dl:focus-visible {
    background: var(--brand-accent, #b0c4d8);
    color: var(--bg-base, #0f1822);
    border-color: var(--brand-accent, #b0c4d8);
}

/* =====================================================================
   PWB — Payroll Worker Banner  (paysheet.php week-summary strip)
   ===================================================================== */
.pwb-banner {
    margin-bottom: 0; /* sits right above the day-nav card; gap handled by .card margin */
}
.pwb-banner__header {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}
.pwb-banner__title {
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-soft);
}
.pwb-banner__range {
    font-size: 14px;
    color: var(--text-primary);
    font-weight: 600;
}
.pwb-banner__empty {
    color: var(--text-dim);
    font-size: 13px;
    margin: 0;
}
.pwb-banner__nums {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
}
.pwb-num {
    flex: 1 1 120px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-light);
    border-radius: 10px;
    padding: 14px 16px;
    min-width: 100px;
}
.pwb-num__val {
    font-size: 26px;
    font-weight: 700;
    line-height: 1;
    color: var(--brand-accent);
}
.pwb-num__lbl {
    font-size: 12px;
    color: var(--text-soft);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-top: 6px;
}
.pwb-num--paid { border-color: var(--success); background: var(--success-soft); }
.pwb-num--paid .pwb-num__val { color: var(--success-ink); }
.pwb-num--approved .pwb-num__val { color: var(--success-ink); }
.pwb-num--pending { border-color: var(--warning); }
.pwb-num--pending .pwb-num__val { color: var(--warning-ink); }
.pwb-num--zero .pwb-num__val { color: var(--text-dim); }

@media (max-width: 520px) {
    .pwb-banner__nums { flex-direction: column; gap: 10px; }
    .pwb-num { flex: unset; width: 100%; }
}

/* =====================================================================
   PWH — Payroll Worker History  (paysheet.php weekly history section)
   ===================================================================== */
.pwh-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.pwh-week {
    border: 1px solid var(--border-light);
    border-radius: 10px;
    overflow: hidden;
}
.pwh-week--paid {
    border-color: var(--success);
}
.pwh-week__summary {
    list-style: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px;
    padding: 12px 16px;
    cursor: pointer;
    background: var(--bg-elevated);
    user-select: none;
}
.pwh-week__summary::-webkit-details-marker { display: none; }
.pwh-week__summary::marker { display: none; }
.pwh-week__summary:hover { background: var(--bg-hover, rgba(255,255,255,0.04)); }
.pwh-week__range {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-primary);
}
.pwh-week__badges {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
    justify-content: flex-end;
}
.pwh-badge {
    display: inline-block;
    font-size: 12px;
    font-weight: 600;
    padding: 3px 10px;
    border-radius: 20px;
    white-space: nowrap;
}
.pwh-badge--paid {
    background: var(--success-soft);
    color: var(--success-ink);
    border: 1px solid var(--success);
}
.pwh-badge--pending {
    background: rgba(255, 193, 7, 0.14);
    color: var(--warning-ink);
    border: 1px solid var(--warning);
}
.pwh-badge--muted {
    background: var(--bg-card);
    color: var(--text-dim);
    border: 1px solid var(--border);
}
.pwh-week__days {
    background: var(--bg-card);
    border-top: 1px solid var(--border-light);
    padding: 8px 0;
}
.pwh-day {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    padding: 7px 16px;
    font-size: 13px;
    border-bottom: 1px solid var(--border-light);
}
.pwh-day:last-child { border-bottom: none; }
.pwh-day__date {
    flex: 1 1 140px;
    color: var(--text-primary);
}
.pwh-day__amt {
    color: var(--text-soft);
    font-weight: 600;
    min-width: 60px;
    text-align: right;
}
.pwh-day__link {
    font-size: 12px;
    color: var(--brand-secondary);
    text-decoration: none;
    white-space: nowrap;
}
.pwh-day__link:hover { text-decoration: underline; }

/* ────────────────────────────────────────────────────────────
   Mobile safe-area insets (1.31.0.1).
   The Flutter shell + modern Android/iOS browsers draw under the
   OS gesture / home-indicator bar. Without explicit padding,
   trailing content (Save buttons, last list rows, fixed bars)
   tucks behind that ~24-48px band. Every Portal page now carries
   viewport-fit=cover so env(safe-area-inset-bottom) returns the
   actual gesture-bar height; these rules consume it consistently.

   @supports gates the rule so older browsers that don't grok env()
   fall back to no extra padding (which is what they always had —
   they don't render under the bar in the first place).
   ──────────────────────────────────────────────────────────── */
@supports (padding: env(safe-area-inset-bottom)) {
    /* Flowing pages: pad the body so the last footer line + last
       form action button always clear the OS bar. .page already
       has its own bottom margin; the inset adds on top of it. */
    body {
        padding-bottom: env(safe-area-inset-bottom);
    }

    /* Modal panels — the panel max-height accounts for the inset
       so internal scrolling (long forms) doesn't push the bottom
       of the panel under the bar. Internal padding-bottom keeps
       the trailing button (Save / Submit / etc.) visible without
       needing per-modal overrides. Covers:
         .sr-sysmsg-panel — system message modal (broadcast)
         .stg-modal-panel — admin Settings modals (pay rates,
                            payroll, notifications)
         .sr-paysubmit-panel — worker submit-paysheet modal
         .modal-panel — generic/legacy fallback
       Add new modal classes here if you introduce a new modal
       shell — better one place than scattered overrides. */
    .sr-sysmsg-panel,
    .stg-modal-panel,
    .sr-paysubmit-panel,
    .modal-panel {
        max-height: calc(100dvh - 40px - env(safe-area-inset-bottom));
        padding-bottom: calc(22px + env(safe-area-inset-bottom));
    }

    /* Known fixed-position bottom bars across the app. The chat
       dock is the main one today — anchored to viewport bottom on
       both Portal pages and LaborGrid via the shared chat.css.
       Adding the inset here in portal.css means the chat bar pulls
       up off the gesture bar without per-component edits. */
    .chat-dock,
    .chat-bar,
    [data-fixed-bottom] {
        padding-bottom: calc(8px + env(safe-area-inset-bottom));
    }
}

/* ============================================================
   Future-ready polish — accessibility + motion
   ============================================================ */

/* Smooth-scroll for anchor jumps (changelog → version, in-page nav).
   Only when the user hasn't asked to reduce motion. */
@media (prefers-reduced-motion: no-preference) {
    html { scroll-behavior: smooth; }
}

/* Respect prefers-reduced-motion globally. Anyone who has set this
   in their OS settings (vestibular sensitivity, focus disorders) gets
   near-instant transitions instead of our polished animations. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* Global focus-visible default — applies a consistent 2px outline to any
   keyboard-navigated element that doesn't already have its own focus
   treatment. Components that DO style their own focus state (.btn,
   .topnav-pill, .form-field input, etc.) keep their existing rule by
   virtue of CSS specificity. This is the safety net for icon buttons
   and links a future me forgets to style. */
:focus-visible {
    outline: 2px solid var(--brand-accent, #b0c4d8);
    outline-offset: 2px;
    border-radius: 3px;
}

/* --- Notification bell (Tier 1.4) --------------------------------------
 *
 * Lives inside the topbar's right-side nav, before the hamburger drawer
 * button. The button is sized to match .topbar-iconbtn (defined above).
 * The dropdown panel is absolute-positioned under the bell — anchored to
 * the .notif-bell wrapper so it tracks correctly across the three topbar
 * variants without per-variant tweaks.
 *
 * Why position:relative on the wrapper rather than fixed positioning
 * on the panel: the panel is short (max 70vh) and lives directly under
 * the button. Fixed would float over content but forces JS to recompute
 * left/top on every viewport change. Relative wins for our scale.
 */
.notif-bell {
    position: relative;
    display: inline-flex;
    align-items: center;
}
.notif-bell__btn { position: relative; }
.notif-bell__badge {
    position: absolute;
    top: 2px; right: 2px;
    min-width: 16px; height: 16px;
    padding: 0 4px;
    border-radius: 8px;
    background: #d4624c;
    color: #fff;
    font-size: 10px;
    font-weight: 600;
    line-height: 16px;
    text-align: center;
    box-shadow: 0 0 0 2px var(--bg-topbar, #2a3744);
    pointer-events: none;
}
.notif-bell__badge.is-hidden { display: none; }

.notif-bell__panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    width: 360px;
    max-width: calc(100vw - 24px);
    max-height: 70vh;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    background: var(--bg-card, #1f2a36);
    border: 1px solid var(--border-soft, rgba(255,255,255,0.10));
    border-radius: 10px;
    box-shadow: 0 12px 32px rgba(0,0,0,0.35);
    z-index: 1000;
}
.notif-bell__panel.is-hidden { display: none; }

.notif-bell__header {
    display: flex; align-items: center; justify-content: space-between;
    padding: 10px 14px;
    border-bottom: 1px solid var(--border-soft, rgba(255,255,255,0.10));
    background: linear-gradient(to bottom, rgba(255,255,255,0.04), transparent);
}
.notif-bell__header h4 {
    margin: 0;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-strong, #e6eef7);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.notif-bell__markall {
    background: transparent;
    border: none;
    color: var(--brand-accent, #b0c4d8);
    font-size: 11px;
    cursor: pointer;
    padding: 4px 6px;
    border-radius: 4px;
}
.notif-bell__markall:hover { background: rgba(255,255,255,0.06); }

.notif-bell__list {
    list-style: none;
    margin: 0;
    padding: 0;
    overflow-y: auto;
    flex: 1;
}
.notif-bell__empty {
    padding: 22px 14px;
    text-align: center;
    color: var(--text-soft, #8a9aab);
    font-size: 13px;
}

.notif-bell__item {
    display: block;
    padding: 12px 14px;
    border-bottom: 1px solid var(--border-soft, rgba(255,255,255,0.06));
    color: var(--text-strong, #e6eef7);
    text-decoration: none;
    transition: background 0.12s;
}
.notif-bell__item:hover { background: rgba(255,255,255,0.05); }
.notif-bell__item.is-unread {
    background: rgba(176,196,216,0.06);
    border-left: 3px solid var(--brand-accent, #b0c4d8);
    padding-left: 11px;
}
.notif-bell__item-title {
    font-size: 13px;
    font-weight: 600;
    margin-bottom: 2px;
}
.notif-bell__item-body {
    font-size: 12px;
    color: var(--text-soft, #8a9aab);
    line-height: 1.4;
    margin-bottom: 4px;
}
.notif-bell__item-meta {
    font-size: 11px;
    color: var(--text-soft, #6c7c8c);
}

/* Source-specific accents — left edge color tells the user at a glance
 * which surface a notification came from. Subtle; doesn't compete with
 * the unread-indicator color. */
.notif-bell__item--push.is-unread   { border-left-color: #5a9bbe; }
.notif-bell__item--chat.is-unread   { border-left-color: #7aae7a; }
.notif-bell__item--system.is-unread { border-left-color: #c89540; }

/* Light-theme override — match the rest of the portal's data-theme="light"
 * pattern. Topbar is still dark in light mode (per existing
 * [data-theme="light"] .topbar override above), so the panel can stay
 * dark too — but the badge ring needs to track. */
[data-theme="light"] .notif-bell__badge {
    box-shadow: 0 0 0 2px var(--bg-topbar, #2a3744);
}

/* Mobile — the panel switches from "anchor to bell right edge" to
 * "pin to viewport edges". On the worker topbar the bell isn't at the
 * right edge (it sits between the brand and theme toggle), so a
 * panel anchored to the bell with viewport-width would overflow
 * leftward off-screen. position:fixed + right:8px/left:8px decouples
 * the panel from its anchor entirely below 520px. */
@media (max-width: 520px) {
    .notif-bell__panel {
        position: fixed;
        top: 56px;
        right: 8px;
        left: 8px;
        width: auto;
        max-width: none;
    }
}
