/*
   Metropolis Entertainment — brand overrides for the TrendyAdmin theme.
   Loaded AFTER the theme's main.css, so anything here wins. Keeping our overrides in this
   one file means re-pulling a theme update never clobbers the branding (see docs/conventions.md).

   TrendyAdmin brands entirely through CSS custom properties, so rebranding is just re-declaring
   the tokens below. Swap the placeholder values for the real Metropolis palette the moment the
   brand hex + logo land — no rebuild needed.
*/

:root {
    /* --- Metropolis brand standard (Adobe palette, 2026-08) ---

       Every semantic colour in the app is one of these. Bootstrap's stock blue/green/red are mapped
       onto them further down rather than left showing through, because a screen that mixes a purple
       header with a stock-green button reads as two products.

       Two stops per role. The *hue* is the brand colour, used for text, borders and subtle badges.
       The *fill* is what a solid button uses, deepened where the brand hue cannot carry white text
       at 4.5:1 — pink at #D256A4 manages 3.7, which is fine behind a badge and not fine under button
       text. `ink` is what sits on the fill. */
    --brand-primary: #742896;         /* purple — the accent */
    --brand-primary-fill: #742896;
    --brand-primary-hover: #5f2079;
    --brand-primary-ink: #fff;
    --brand-primary-soft: rgba(116, 40, 150, 0.10);

    --brand-secondary: #2167c0;       /* blue */
    --brand-secondary-fill: #2167c0;
    --brand-secondary-hover: #1b559f;
    --brand-secondary-ink: #fff;
    --brand-secondary-soft: rgba(33, 103, 192, 0.12);

    --brand-tertiary: #072040;        /* deep navy — chrome and dark surfaces, not an accent */
    --brand-tertiary-soft: rgba(7, 32, 64, 0.10);

    /* Deep logo cyan. Kept dark deliberately — a pale cyan reads as disabled, and this has to carry
       white text on a button (4.9:1). */
    --brand-success: #0e7c8f;
    --brand-success-fill: #0e7c8f;
    --brand-success-hover: #0b6474;
    --brand-success-ink: #fff;
    --brand-success-soft: rgba(14, 124, 143, 0.12);

    --brand-danger: #d256a4;          /* pink */
    --brand-danger-fill: #a93c80;     /* deepened: white text on the brand pink is only 3.7:1 */
    --brand-danger-hover: #8e326c;
    --brand-danger-ink: #fff;
    --brand-danger-soft: rgba(210, 86, 164, 0.14);

    --brand-warning: #fda62b;         /* orange */
    --brand-warning-fill: #fda62b;
    --brand-warning-hover: #e8910f;
    --brand-warning-ink: #2b1a00;     /* orange takes dark ink; white on it is unreadable */
    --brand-warning-soft: rgba(253, 166, 43, 0.16);

    /* Map the primary onto the theme's accent so buttons/links/highlights pick it up. */
    --accent-color: var(--brand-primary-fill);
    --accent-hover: var(--brand-primary-hover);
    --accent-soft: var(--brand-primary-soft);
    --heading-color: #1a1029;

    /* The theme carries its own semantic tokens and paints buttons and badges from them directly,
       rather than through Bootstrap's variables. Both paths have to land on the brand or a screen
       ends up with a purple header and a stock-green button. */
    --success-color: var(--brand-success-fill);
    --warning-color: var(--brand-warning-fill);
    --danger-color: var(--brand-danger-fill);
    --info-color: var(--brand-secondary-fill);
}

/* Intentional brand-accent utilities. */
.text-brand-secondary { color: var(--brand-secondary) !important; }
.bg-brand-secondary   { background-color: var(--brand-secondary) !important; }
.text-brand-tertiary  { color: var(--brand-tertiary) !important; }
.bg-brand-tertiary    { background-color: var(--brand-tertiary) !important; }

/* Dark mode — the theme flips via data-theme="dark" on <html>. Metropolis uses a warm mid-tone
   base (#594f58) instead of the theme's near-black, so the logo art and content read comfortably. */
:root[data-theme="dark"] {
    /* Near-black canvas with only a faint warm lean toward the #594f58 mauve — not the theme's
       cool blue-black, and nowhere near as light as #594f58 itself. */
    --background-color: #171417;   /* root canvas */
    --surface-color: #221f22;      /* panels lifted a step off the canvas */
    --card-bg: #221f22;            /* cards use --card-bg, not --surface-color */
    --sidebar-bg: #141114;         /* chrome a hair darker than the canvas */
    --header-bg: #171417;
    --border-color: #322c32;
    --border-color-light: #221f22;
    --border-color-dark: #3c353c;

    --heading-color: #f3eef6;      /* headings must flip light on the dark base (card titles, etc.) */

    /* One value has to serve as both link colour and the theme's own accent fill, so it sits in the
       middle: readable as text on the dark canvas, still purple enough to be the brand. Solid
       buttons take --brand-primary-fill instead, via the rules below. */
    --accent-color: #a259c4;
    --accent-hover: #b678d6;
    --accent-soft: rgba(196, 137, 214, 0.16);

    --success-color: #0f8598;
    --warning-color: #fdb750;
    --danger-color: #b8478e;
    --info-color: #2167c0;

    /* The roles lift on the dark base: the hue brightens so text and borders read, while the fills
       stay close to the brand so a button is recognisably the same button in either theme. */
    --brand-primary: #c489d6;
    --brand-primary-fill: #7f2ca3;
    --brand-primary-hover: #96379f;
    --brand-primary-soft: rgba(196, 137, 214, 0.16);

    --brand-secondary: #6fa8e8;
    --brand-secondary-fill: #2167c0;
    --brand-secondary-hover: #3b81d6;
    --brand-secondary-soft: rgba(111, 168, 232, 0.16);

    --brand-tertiary: #8fb4e0;
    --brand-tertiary-soft: rgba(143, 180, 224, 0.14);

    --brand-success: #35b7cf;
    --brand-success-fill: #0f8598;
    --brand-success-hover: #1499af;
    --brand-success-soft: rgba(53, 183, 207, 0.16);

    --brand-danger: #e884c2;
    --brand-danger-fill: #b8478e;
    --brand-danger-hover: #c9569e;
    --brand-danger-soft: rgba(232, 132, 194, 0.16);

    --brand-warning: #fdb750;
    --brand-warning-fill: #fdb750;
    --brand-warning-hover: #f5a733;
    --brand-warning-soft: rgba(253, 183, 80, 0.16);
}

/* ── Bootstrap's semantics, mapped onto the brand ───────────────────────────
   Bootstrap 5.3 reads utilities (.text-success, .bg-danger-subtle, .badge) from these custom
   properties at runtime, so remapping them here reaches every one without touching a view. Buttons
   and alerts are the exception — they compile literal colours into their own --bs-btn-* / --bs-alert-*
   properties, so those are restated below. */
:root {
    --bs-primary: var(--brand-primary);
    --bs-primary-rgb: 116, 40, 150;
    --bs-secondary: var(--brand-secondary);
    --bs-secondary-rgb: 33, 103, 192;
    --bs-success: var(--brand-success);
    --bs-success-rgb: 14, 124, 143;
    --bs-danger: var(--brand-danger);
    --bs-danger-rgb: 169, 60, 128;
    --bs-warning: var(--brand-warning);
    --bs-warning-rgb: 176, 106, 4;      /* readable as text; the fill keeps the brand orange */
    --bs-info: var(--brand-secondary);
    --bs-info-rgb: 33, 103, 192;

    --bs-link-color: var(--brand-primary);
    --bs-link-color-rgb: 116, 40, 150;
    --bs-link-hover-color: var(--brand-primary-hover);

    --bs-primary-bg-subtle: rgba(116, 40, 150, 0.10);
    --bs-primary-border-subtle: rgba(116, 40, 150, 0.30);
    --bs-primary-text-emphasis: #5f2079;

    --bs-secondary-bg-subtle: rgba(33, 103, 192, 0.10);
    --bs-secondary-border-subtle: rgba(33, 103, 192, 0.30);
    --bs-secondary-text-emphasis: #1b559f;

    --bs-success-bg-subtle: rgba(14, 124, 143, 0.12);
    --bs-success-border-subtle: rgba(14, 124, 143, 0.30);
    --bs-success-text-emphasis: #0b6474;

    --bs-danger-bg-subtle: rgba(210, 86, 164, 0.14);
    --bs-danger-border-subtle: rgba(210, 86, 164, 0.35);
    --bs-danger-text-emphasis: #8e326c;

    --bs-warning-bg-subtle: rgba(253, 166, 43, 0.16);
    --bs-warning-border-subtle: rgba(253, 166, 43, 0.40);
    --bs-warning-text-emphasis: #8a5410;

    --bs-info-bg-subtle: rgba(33, 103, 192, 0.10);
    --bs-info-border-subtle: rgba(33, 103, 192, 0.30);
    --bs-info-text-emphasis: #1b559f;
}

:root[data-theme="dark"] {
    --bs-primary-rgb: 196, 137, 214;
    --bs-secondary-rgb: 111, 168, 232;
    --bs-success-rgb: 53, 183, 207;
    --bs-danger-rgb: 232, 132, 194;
    --bs-warning-rgb: 253, 183, 80;
    --bs-info-rgb: 111, 168, 232;

    --bs-link-color-rgb: 196, 137, 214;

    --bs-primary-text-emphasis: #d5a9e2;
    --bs-secondary-text-emphasis: #9cc4ef;
    --bs-success-text-emphasis: #6fcede;
    --bs-danger-text-emphasis: #f0a8d3;
    --bs-warning-text-emphasis: #fdc47f;
    --bs-info-text-emphasis: #9cc4ef;
}

/* Solid buttons. Two things paint a button here: Bootstrap, through its --bs-btn-* variables, and
   the theme, which sets background-color directly from its own tokens. Both are set — the variables
   so Bootstrap's own machinery agrees, and the properties because a direct declaration beats a
   variable the theme has already resolved. This file loads last, so these win. */
.btn-primary,
.btn-secondary,
.btn-success,
.btn-danger,
.btn-warning {
    background-color: var(--btn-fill);
    border-color: var(--btn-fill);
    color: var(--btn-ink);
}

.btn-primary:hover,
.btn-primary:focus,
.btn-primary:active,
.btn-secondary:hover,
.btn-secondary:focus,
.btn-secondary:active,
.btn-success:hover,
.btn-success:focus,
.btn-success:active,
.btn-danger:hover,
.btn-danger:focus,
.btn-danger:active,
.btn-warning:hover,
.btn-warning:focus,
.btn-warning:active {
    background-color: var(--btn-hover);
    border-color: var(--btn-hover);
    color: var(--btn-ink);
}

.btn-primary { --btn-fill: var(--brand-primary-fill); --btn-hover: var(--brand-primary-hover); --btn-ink: var(--brand-primary-ink); }
.btn-secondary { --btn-fill: var(--brand-secondary-fill); --btn-hover: var(--brand-secondary-hover); --btn-ink: var(--brand-secondary-ink); }
.btn-success { --btn-fill: var(--brand-success-fill); --btn-hover: var(--brand-success-hover); --btn-ink: var(--brand-success-ink); }
.btn-danger { --btn-fill: var(--brand-danger-fill); --btn-hover: var(--brand-danger-hover); --btn-ink: var(--brand-danger-ink); }
.btn-warning { --btn-fill: var(--brand-warning-fill); --btn-hover: var(--brand-warning-hover); --btn-ink: var(--brand-warning-ink); }

/* Outline buttons: the hue on the border and the label, the fill once you commit. */
.btn-outline-primary,
.btn-outline-secondary,
.btn-outline-success,
.btn-outline-danger,
.btn-outline-warning {
    background-color: transparent;
    border-color: var(--btn-hue);
    color: var(--btn-hue);
}

.btn-outline-primary:hover,
.btn-outline-primary:focus,
.btn-outline-primary:active,
.btn-outline-secondary:hover,
.btn-outline-secondary:focus,
.btn-outline-secondary:active,
.btn-outline-success:hover,
.btn-outline-success:focus,
.btn-outline-success:active,
.btn-outline-danger:hover,
.btn-outline-danger:focus,
.btn-outline-danger:active,
.btn-outline-warning:hover,
.btn-outline-warning:focus,
.btn-outline-warning:active {
    background-color: var(--btn-fill);
    border-color: var(--btn-fill);
    color: var(--btn-ink);
}

.btn-outline-primary { --btn-hue: var(--brand-primary); --btn-fill: var(--brand-primary-fill); --btn-ink: var(--brand-primary-ink); }
.btn-outline-secondary { --btn-hue: var(--brand-secondary); --btn-fill: var(--brand-secondary-fill); --btn-ink: var(--brand-secondary-ink); }
.btn-outline-success { --btn-hue: var(--brand-success); --btn-fill: var(--brand-success-fill); --btn-ink: var(--brand-success-ink); }
.btn-outline-danger { --btn-hue: var(--brand-danger); --btn-fill: var(--brand-danger-fill); --btn-ink: var(--brand-danger-ink); }
.btn-outline-warning { --btn-hue: var(--bs-warning-text-emphasis); --btn-fill: var(--brand-warning-fill); --btn-ink: var(--brand-warning-ink); }

/* Bootstrap's own variables, kept in step so focus rings and disabled states agree. */
.btn-primary {
    --bs-btn-bg: var(--brand-primary-fill);
    --bs-btn-border-color: var(--brand-primary-fill);
    --bs-btn-color: var(--brand-primary-ink);
    --bs-btn-hover-bg: var(--brand-primary-hover);
    --bs-btn-hover-border-color: var(--brand-primary-hover);
    --bs-btn-hover-color: var(--brand-primary-ink);
    --bs-btn-active-bg: var(--brand-primary-hover);
    --bs-btn-active-border-color: var(--brand-primary-hover);
    --bs-btn-active-color: var(--brand-primary-ink);
    --bs-btn-disabled-bg: var(--brand-primary-fill);
    --bs-btn-disabled-border-color: var(--brand-primary-fill);
    --bs-btn-disabled-color: var(--brand-primary-ink);
}

.btn-secondary {
    --bs-btn-bg: var(--brand-secondary-fill);
    --bs-btn-border-color: var(--brand-secondary-fill);
    --bs-btn-color: var(--brand-secondary-ink);
    --bs-btn-hover-bg: var(--brand-secondary-hover);
    --bs-btn-hover-border-color: var(--brand-secondary-hover);
    --bs-btn-hover-color: var(--brand-secondary-ink);
    --bs-btn-active-bg: var(--brand-secondary-hover);
    --bs-btn-active-border-color: var(--brand-secondary-hover);
    --bs-btn-disabled-bg: var(--brand-secondary-fill);
    --bs-btn-disabled-border-color: var(--brand-secondary-fill);
    --bs-btn-disabled-color: var(--brand-secondary-ink);
}

.btn-success {
    --bs-btn-bg: var(--brand-success-fill);
    --bs-btn-border-color: var(--brand-success-fill);
    --bs-btn-color: var(--brand-success-ink);
    --bs-btn-hover-bg: var(--brand-success-hover);
    --bs-btn-hover-border-color: var(--brand-success-hover);
    --bs-btn-hover-color: var(--brand-success-ink);
    --bs-btn-active-bg: var(--brand-success-hover);
    --bs-btn-active-border-color: var(--brand-success-hover);
    --bs-btn-disabled-bg: var(--brand-success-fill);
    --bs-btn-disabled-border-color: var(--brand-success-fill);
    --bs-btn-disabled-color: var(--brand-success-ink);
}

.btn-danger {
    --bs-btn-bg: var(--brand-danger-fill);
    --bs-btn-border-color: var(--brand-danger-fill);
    --bs-btn-color: var(--brand-danger-ink);
    --bs-btn-hover-bg: var(--brand-danger-hover);
    --bs-btn-hover-border-color: var(--brand-danger-hover);
    --bs-btn-hover-color: var(--brand-danger-ink);
    --bs-btn-active-bg: var(--brand-danger-hover);
    --bs-btn-active-border-color: var(--brand-danger-hover);
    --bs-btn-disabled-bg: var(--brand-danger-fill);
    --bs-btn-disabled-border-color: var(--brand-danger-fill);
    --bs-btn-disabled-color: var(--brand-danger-ink);
}

.btn-warning {
    --bs-btn-bg: var(--brand-warning-fill);
    --bs-btn-border-color: var(--brand-warning-fill);
    --bs-btn-color: var(--brand-warning-ink);
    --bs-btn-hover-bg: var(--brand-warning-hover);
    --bs-btn-hover-border-color: var(--brand-warning-hover);
    --bs-btn-hover-color: var(--brand-warning-ink);
    --bs-btn-active-bg: var(--brand-warning-hover);
    --bs-btn-active-border-color: var(--brand-warning-hover);
    --bs-btn-disabled-bg: var(--brand-warning-fill);
    --bs-btn-disabled-border-color: var(--brand-warning-fill);
    --bs-btn-disabled-color: var(--brand-warning-ink);
}

/* Outline buttons: the hue on the border and the label, the fill once you commit. */
.btn-outline-primary {
    --bs-btn-color: var(--brand-primary);
    --bs-btn-border-color: var(--brand-primary);
    --bs-btn-hover-bg: var(--brand-primary-fill);
    --bs-btn-hover-border-color: var(--brand-primary-fill);
    --bs-btn-hover-color: var(--brand-primary-ink);
    --bs-btn-active-bg: var(--brand-primary-hover);
    --bs-btn-active-border-color: var(--brand-primary-hover);
    --bs-btn-active-color: var(--brand-primary-ink);
    --bs-btn-disabled-color: var(--brand-primary);
    --bs-btn-disabled-border-color: var(--brand-primary);
}

.btn-outline-secondary {
    --bs-btn-color: var(--brand-secondary);
    --bs-btn-border-color: var(--brand-secondary);
    --bs-btn-hover-bg: var(--brand-secondary-fill);
    --bs-btn-hover-border-color: var(--brand-secondary-fill);
    --bs-btn-hover-color: var(--brand-secondary-ink);
    --bs-btn-active-bg: var(--brand-secondary-hover);
    --bs-btn-active-border-color: var(--brand-secondary-hover);
    --bs-btn-active-color: var(--brand-secondary-ink);
    --bs-btn-disabled-color: var(--brand-secondary);
    --bs-btn-disabled-border-color: var(--brand-secondary);
}

.btn-outline-success {
    --bs-btn-color: var(--brand-success);
    --bs-btn-border-color: var(--brand-success);
    --bs-btn-hover-bg: var(--brand-success-fill);
    --bs-btn-hover-border-color: var(--brand-success-fill);
    --bs-btn-hover-color: var(--brand-success-ink);
    --bs-btn-active-bg: var(--brand-success-hover);
    --bs-btn-active-border-color: var(--brand-success-hover);
    --bs-btn-active-color: var(--brand-success-ink);
    --bs-btn-disabled-color: var(--brand-success);
    --bs-btn-disabled-border-color: var(--brand-success);
}

.btn-outline-danger {
    --bs-btn-color: var(--brand-danger);
    --bs-btn-border-color: var(--brand-danger);
    --bs-btn-hover-bg: var(--brand-danger-fill);
    --bs-btn-hover-border-color: var(--brand-danger-fill);
    --bs-btn-hover-color: var(--brand-danger-ink);
    --bs-btn-active-bg: var(--brand-danger-hover);
    --bs-btn-active-border-color: var(--brand-danger-hover);
    --bs-btn-active-color: var(--brand-danger-ink);
    --bs-btn-disabled-color: var(--brand-danger);
    --bs-btn-disabled-border-color: var(--brand-danger);
}

.btn-outline-warning {
    --bs-btn-color: var(--bs-warning-text-emphasis);
    --bs-btn-border-color: var(--brand-warning);
    --bs-btn-hover-bg: var(--brand-warning-fill);
    --bs-btn-hover-border-color: var(--brand-warning-fill);
    --bs-btn-hover-color: var(--brand-warning-ink);
    --bs-btn-active-bg: var(--brand-warning-hover);
    --bs-btn-active-border-color: var(--brand-warning-hover);
    --bs-btn-active-color: var(--brand-warning-ink);
    --bs-btn-disabled-color: var(--brand-warning);
    --bs-btn-disabled-border-color: var(--brand-warning);
}

/* Alerts — the tint, the border and the text, all from the same role. */
.alert-primary {
    --bs-alert-color: var(--bs-primary-text-emphasis);
    --bs-alert-bg: var(--bs-primary-bg-subtle);
    --bs-alert-border-color: var(--bs-primary-border-subtle);
}

.alert-info {
    --bs-alert-color: var(--bs-info-text-emphasis);
    --bs-alert-bg: var(--bs-info-bg-subtle);
    --bs-alert-border-color: var(--bs-info-border-subtle);
}

.alert-success {
    --bs-alert-color: var(--bs-success-text-emphasis);
    --bs-alert-bg: var(--bs-success-bg-subtle);
    --bs-alert-border-color: var(--bs-success-border-subtle);
}

.alert-warning {
    --bs-alert-color: var(--bs-warning-text-emphasis);
    --bs-alert-bg: var(--bs-warning-bg-subtle);
    --bs-alert-border-color: var(--bs-warning-border-subtle);
}

.alert-danger {
    --bs-alert-color: var(--bs-danger-text-emphasis);
    --bs-alert-bg: var(--bs-danger-bg-subtle);
    --bs-alert-border-color: var(--bs-danger-border-subtle);
}

/* Form controls that carry the accent. */
.form-check-input:checked {
    background-color: var(--brand-primary-fill);
    border-color: var(--brand-primary-fill);
}

.form-check-input:focus,
.form-control:focus,
.form-select:focus {
    border-color: var(--brand-primary);
    box-shadow: 0 0 0 0.2rem var(--brand-primary-soft);
}

/* Logo mark: the SkyScape art carries its own transparency, so drop the theme's
   circular gradient chip and let the logo sit directly on the surface. */
.sidebar-logo-mark,
.header-logo-mark {
    background: none !important;
    border-radius: 0;
    width: auto;
    height: 34px;
}

.sidebar-logo-mark img,
.header-logo-mark img {
    width: auto;
    height: 100%;
    object-fit: contain;
    display: block;
}

/* Brand wordmark in the sidebar/header (until the real logo asset is dropped in). */
.sidebar-logo-text,
.header-logo-text {
    font-family: var(--heading-font);
    font-weight: 700;
    letter-spacing: -0.01em;
}

/* Weekly Ops secondary navigation — the in-section pipeline tabs (Dashboard, Lines,
   Availability, Staffing Grid, Schedule, Publish). Kept in our overrides file so a theme
   update never clobbers it. */
.weekly-ops-nav {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
    border-bottom: 1px solid var(--border-color);
    padding-bottom: 0.75rem;
}

.weekly-ops-tab {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.45rem 0.85rem;
    border-radius: 0.5rem;
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--bs-secondary-color, #6c757d);
    text-decoration: none;
    line-height: 1;
    transition: background-color 0.12s ease, color 0.12s ease;
}

.weekly-ops-tab i {
    font-size: 1.05rem;
}

.weekly-ops-tab:hover {
    background: var(--accent-soft);
    color: var(--accent-color);
}

.weekly-ops-tab.active {
    background: var(--accent-color);
    color: #fff;
}

/* ── Staffing grid ──────────────────────────────────────────────────────────
   Roles down, nights across (ADR-0012), ported from BasecampTools' week grid — the part of the
   prototype that works best. Everything here is a token so both themes come out of one rule set;
   the dark values are re-declared with the other tokens further up. */
:root {
    /* Booked, and a night that has landed on a configuration: the success role, which is the deep
       logo cyan rather than a green. */
    --grid-booked: var(--brand-success-fill);
    --grid-booked-hover: var(--brand-success-hover);

    /* A night still being worked — the secondary blue. Not orange and not red: a night that has not
       yet reached a known configuration is the ordinary state of a grid being staffed, not a fault,
       and the warning colours are needed for things that actually are. */
    --grid-open: var(--brand-secondary-fill);
    --grid-open-ink: var(--brand-secondary-ink);

    /* A night the contract does not run. Flat, where unavailable is hatched. */
    --grid-hatch: rgba(0, 0, 0, 0.06);

    /* Someone who cannot work that night. Dense enough to read as a wall at a glance across seven
       columns — the whole point of the column is to be skipped over. */
    --grid-unavailable: rgba(0, 0, 0, 0.22);
    --grid-unavailable-base: rgba(0, 0, 0, 0.07);
}

:root[data-theme="dark"] {
    /* The role tokens have already lifted for the dark base, so the grid only restates the greys. */
    --grid-hatch: rgba(255, 255, 255, 0.07);
    --grid-unavailable: rgba(255, 255, 255, 0.22);
    --grid-unavailable-base: rgba(255, 255, 255, 0.06);
}

.staffing-grid-wrap {
    overflow-x: auto;
    border: 1px solid var(--border-color);
    border-radius: 0.5rem;
    background: var(--card-bg);
}

.staffing-grid {
    border-collapse: separate;
    border-spacing: 0;
    width: 100%;
    font-size: 0.9rem;
}

.staffing-grid th,
.staffing-grid td {
    border-right: 1px solid var(--border-color-light, var(--border-color));
    border-bottom: 1px solid var(--border-color-light, var(--border-color));
    padding: 0.3rem 0.5rem;
    text-align: center;
    vertical-align: middle;
}

/* ── Role bands ─────────────────────────────────────────────────────────────
   A contract names its own roles (ADR-0011's second amendment), so the tints cannot be keyed to
   role names the way BasecampTools keyed them to its five fixed positions. They are positional
   instead: six stops walking the Metropolis logo's purple → blue → cyan → amber → orange, cycled
   if a contract ever names more than six roles.

   The tint is carried as a custom property on the row so it inherits into the cells, which is what
   lets a cell's own state composite over it — a hatched unavailable square still reads as part of
   its role's band. */
.staffing-grid {
    --tint-body: 0.09;
    --tint-head: 0.22;
}

:root[data-theme="dark"] .staffing-grid {
    --tint-body: 0.15;
    --tint-head: 0.30;
}

.staffing-grid .tint-0 { --row-tint: rgb(127 42 149 / var(--tint-body)); --row-tint-head: rgb(127 42 149 / var(--tint-head)); }
.staffing-grid .tint-1 { --row-tint: rgb(91 63 176 / var(--tint-body)); --row-tint-head: rgb(91 63 176 / var(--tint-head)); }
.staffing-grid .tint-2 { --row-tint: rgb(47 111 196 / var(--tint-body)); --row-tint-head: rgb(47 111 196 / var(--tint-head)); }
.staffing-grid .tint-3 { --row-tint: rgb(36 184 209 / var(--tint-body)); --row-tint-head: rgb(36 184 209 / var(--tint-head)); }
.staffing-grid .tint-4 { --row-tint: rgb(240 180 41 / var(--tint-body)); --row-tint-head: rgb(240 180 41 / var(--tint-head)); }
.staffing-grid .tint-5 { --row-tint: rgb(252 159 54 / var(--tint-body)); --row-tint-head: rgb(252 159 54 / var(--tint-head)); }

.staffing-grid tbody tr {
    background-color: var(--row-tint, transparent);
}

/* The name column stays put while the week scrolls sideways — a cell is meaningless without it.
   Being sticky it has to be opaque, so the band arrives as a layer over the surface rather than as
   a see-through colour. */
.staffing-grid .name-col {
    position: sticky;
    left: 0;
    z-index: 2;
    background-color: var(--card-bg);
    background-image: linear-gradient(var(--row-tint, transparent), var(--row-tint, transparent));
    border-right-color: var(--border-color);
    text-align: left;
    min-width: 13rem;
    font-weight: 600;
    white-space: nowrap;
}

.staffing-grid thead th {
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--surface-color, var(--card-bg));
}

.staffing-grid thead .name-col {
    z-index: 4;
}

.staffing-grid .day-col {
    min-width: 5.5rem;
}

.staffing-grid .day-name {
    font-size: 0.7rem;
    letter-spacing: 0.05em;
    color: var(--bs-secondary-color, #6c757d);
}

.staffing-grid .day-num {
    font-size: 1.05rem;
    font-weight: 700;
    line-height: 1.1;
}

.staffing-grid .day-mark {
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--bs-secondary-color, #6c757d);
}

.staffing-grid .day-col.dark,
.staffing-grid .group-cell.dark {
    background: var(--grid-hatch);
}

/* Counters: the night's headcount, and each role's count within it. */
.night-count,
.role-count {
    display: inline-block;
    margin-top: 0.15rem;
    padding: 0 0.45rem;
    border-radius: 0.75rem;
    font-size: 0.75rem;
    font-weight: 700;
    line-height: 1.45;
    background: var(--accent-soft);
    color: var(--bs-body-color);
}

.night-count .of,
.role-count .of {
    opacity: 0.65;
    font-weight: 500;
}

/* Settled — what is staffed is a configuration this contract has a name for, and the counter says
   which one instead of counting. */
.night-count.set,
.role-count.set {
    background: var(--grid-booked);
    color: #fff;
    letter-spacing: 0.04em;
}

/* Still being worked. Not a warning: a weekday's format is a default, and a night off it is
   ordinary — so this is the calm colour, and nothing in the grid goes red for a headcount. */
.night-count.open,
.role-count.open {
    background: var(--grid-open);
    color: var(--grid-open-ink);
}

.night-count.none,
.role-count.none {
    background: transparent;
    color: var(--bs-secondary-color, #6c757d);
}

/* Role group header row — the band's own colour, a shade up from its people. */
.staffing-grid .group-head {
    font-size: 0.75rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--bs-body-color);
    font-weight: 700;
}

.staffing-grid tbody tr.group-row {
    background-color: var(--row-tint-head, var(--surface-color, var(--card-bg)));
}

.staffing-grid .group-row .name-col,
.staffing-grid .group-row .total-col {
    background-image: linear-gradient(var(--row-tint-head, transparent), var(--row-tint-head, transparent));
}

/* The band opens on a firmer line than the rows inside it carry. */
.staffing-grid tbody tr.group-row td,
.staffing-grid tbody tr.group-row th {
    border-top: 1px solid var(--border-color);
}

/* Cells. Each square is drawn as a square: a grid line on every side, firmer than the light rules
   the header and the name column use, so a night reads as a box to click rather than as a gap. */
.staffing-grid .cell {
    height: 2.1rem;
    cursor: default;
    border-right-color: var(--border-color);
    border-bottom-color: var(--border-color);
    background-clip: padding-box;
}

.staffing-grid .cell.dark {
    background-color: var(--grid-hatch);
}

.staffing-grid .cell.unavailable {
    background-color: var(--grid-unavailable-base);
    background-image: repeating-linear-gradient(
        45deg,
        transparent, transparent 4px,
        var(--grid-unavailable) 4px, var(--grid-unavailable) 8px);
    cursor: context-menu;
}

.staffing-grid .cell.available {
    cursor: pointer;
}

.staffing-grid .cell.available:hover {
    background: var(--accent-soft);
    box-shadow: inset 0 0 0 2px var(--accent-color);
}

.staffing-grid .cell:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: -2px;
}

/* The ring keeps the edge visible where booked squares run together — four greens in a row should
   still read as four nights, not one block. */
.staffing-grid .cell.booked {
    background-color: var(--grid-booked);
    background-image: none;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.25);
}

.staffing-grid .cell.booked::after {
    content: "✓";
    color: #fff;
    font-weight: 700;
}

.staffing-grid .cell.booked:hover {
    background: var(--grid-booked-hover);
    box-shadow: inset 0 0 0 2px var(--grid-booked-hover);
}

/* Closed: Basecamp holds the night, so the grid is done with it (ADR-0012's 2026-08-26 amendment).
   The corner flag stays as the mark; the cell keeps its colours as the record of how the night was
   built, but stops inviting a click — the night is managed on View Schedule now. */
.staffing-grid .cell.published {
    position: relative;
}

.staffing-grid .cell.published::before {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    border-top: 0.45rem solid var(--brand-secondary);
    border-left: 0.45rem solid transparent;
}

.staffing-grid .cell.published,
.staffing-grid .cell.published.available,
.staffing-grid .cell.published.unavailable {
    cursor: default;
}

.staffing-grid .cell.published.available:hover {
    background: inherit;
    box-shadow: none;
}

.staffing-grid .cell.published.booked:hover {
    background-color: var(--grid-booked);
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.25);
}

/* The mark doubles as the way to where the night is managed now. */
a.day-mark.published {
    display: inline-block;
    color: var(--brand-secondary);
    text-decoration: none;
}

a.day-mark.published:hover {
    text-decoration: underline;
}

.staffing-grid .cell.busy {
    opacity: 0.5;
}

/* The totals column is opaque like the name column, so it takes the band the same way — a stripe
   that stopped short of the week total would read as the band ending. */
.staffing-grid .total-col {
    min-width: 4rem;
    font-weight: 700;
    background-color: var(--surface-color, var(--card-bg));
    background-image: linear-gradient(var(--row-tint, transparent), var(--row-tint, transparent));
}

.staffing-grid .name-col.not-submitted {
    font-style: italic;
    color: var(--bs-secondary-color, #6c757d);
}

.grid-flag {
    display: inline-block;
    margin-left: 0.3rem;
    padding: 0 0.4rem;
    border-radius: 0.6rem;
    font-size: 0.65rem;
    font-weight: 700;
    text-transform: uppercase;
    cursor: help;
}

/* Never answered — the one flag on the grid that is genuinely a "chase this", so it takes warning. */
.grid-flag.no-submission {
    background: var(--brand-warning-soft);
    color: var(--bs-warning-text-emphasis);
}

/* Something they wrote. Information, so it takes the secondary blue rather than a warning colour. */
.grid-flag.note {
    background: var(--brand-secondary-soft);
    color: var(--bs-secondary-text-emphasis);
}

/* Legend */
.grid-legend {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.8rem;
    color: var(--bs-secondary-color, #6c757d);
}

.grid-legend .swatch {
    width: 1rem;
    height: 1rem;
    border-radius: 0.2rem;
    border: 1px solid var(--border-color);
}

.grid-legend .swatch.available { background: var(--card-bg); }
.grid-legend .swatch.booked { background: var(--grid-booked); }
.grid-legend .swatch.dark { background: var(--grid-hatch); }

.grid-legend .swatch.unavailable {
    background-color: var(--grid-unavailable-base);
    background-image: repeating-linear-gradient(
        45deg,
        transparent, transparent 3px,
        var(--grid-unavailable) 3px, var(--grid-unavailable) 6px);
}

/* Right-click menu — opening or closing one person's night by hand. */
.cell-menu {
    display: none;
    position: absolute;
    z-index: 1000;
    min-width: 14rem;
    padding: 0.25rem;
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 0.375rem;
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.18);
}

.cell-menu button {
    display: block;
    width: 100%;
    padding: 0.4rem 0.6rem;
    border: 0;
    border-radius: 0.25rem;
    background: none;
    color: var(--bs-body-color);
    text-align: left;
    font-size: 0.85rem;
    cursor: pointer;
}

.cell-menu button:hover,
.cell-menu button:focus-visible {
    background: var(--accent-soft);
    color: var(--accent-color);
}

/* ── Cast picker motion ─────────────────────────────────────────────────────
   Adding someone moves their row from the candidate list into the cast without
   a reload, which is fast enough to be invisible. The motion is there to make
   the move legible: the row tints, slides out to the left, and the list closes
   the gap behind it, so it is obvious which person went and that the list did
   not simply reorder itself under the cursor. */

/* Not scoped to either list: a row leaves the same way whichever direction it is going. */
.js-candidate,
.cap-row {
    transition: background-color 0.12s ease;
}

.is-leaving {
    background-color: var(--brand-primary-soft);
    transform: translateX(-14%);
    opacity: 0;
    height: 0 !important;
    padding-top: 0 !important;
    padding-bottom: 0 !important;
    border-bottom-width: 0 !important;
    /* Four phases, deliberately staggered rather than simultaneous. Run together, the fade
       finishes before the tint has registered and the collapse happens behind an already
       invisible row, so all you see is the swipe.

         0.00 – 0.16   tint            the row acknowledges the click
         0.10 – 0.38   slide out       overlaps the tint just enough to feel like one motion
         0.18 – 0.38   fade            starts late, so the row is still visible while it travels
         0.36 – 0.58   collapse        only once the row has actually gone

       Total ~0.58s. Anything faster and the phases read as a single blur. If this is retimed,
       the completion fallback in Cast.cshtml has to stay longer than the total. */
    transition:
        background-color 0.16s ease,
        transform 0.28s ease 0.10s,
        opacity 0.20s ease 0.18s,
        height 0.22s ease 0.36s,
        padding 0.22s ease 0.36s;
}

/* Where it landed. Fades out on its own so it does not become permanent noise. */
.is-arriving {
    animation: cast-arrive 1s ease-out;
}

@keyframes cast-arrive {
    from { background-color: var(--brand-primary-soft); }
    to   { background-color: transparent; }
}

@media (prefers-reduced-motion: reduce) {
    .js-candidate,
    .cap-row,
    .is-leaving {
        transition: none;
    }

    .is-arriving {
        animation: none;
    }
}
