/* Back of House — Light mode, spreadsheet-like */

:root {
    --bg: #ffffff;
    --bg-alt: #f8f9fa;
    --bg-hover: #f0f1f3;
    --border: #dee2e6;
    --border-light: #e9ecef;
    --text: #212529;
    --text-muted: #6c757d;
    --text-light: #adb5bd;
    --primary: #3B82F6;
    --primary-hover: #2563EB;
    --success: #22c55e;
    --warning: #eab308;
    --danger: #ef4444;
    --orange: #f97316;
    --sidebar-width: 280px;
    --header-height: 52px;
    --subnav-height: 34px;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    font-size: 14px;
    line-height: 1.5;
    color: var(--text);
    background: var(--bg);
}

/* ---- Header / Nav ---- */

.top-nav {
    display: flex;
    align-items: center;
    height: var(--header-height);
    padding: 0 16px;
    background: var(--bg);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
    z-index: 100;
}

.detail-subnav {
    display: flex;
    gap: 4px;
    align-items: center;
    height: var(--subnav-height);
    padding: 0 16px;
    background: var(--bg-alt);
    border-bottom: 1px solid var(--border-light);
    position: sticky;
    top: var(--header-height);
    z-index: 99;
    overflow-x: auto;
    white-space: nowrap;
    font-size: 12px;
}

.detail-subnav a {
    padding: 4px 8px;
    color: var(--text-muted);
    text-decoration: none;
    border-radius: 3px;
}

.detail-subnav a:hover {
    background: var(--bg-hover);
    color: var(--text);
}

.detail-subnav a.active {
    background: var(--primary);
    color: #fff;
}

.detail-section[id^="section-"] {
    scroll-margin-top: calc(var(--header-height) + var(--subnav-height) + 8px);
}

/* Back of House logo — Variant 3 (left bar + stacked acronym).
   Renders as a two-line block (BOH / BACK·OF·HOUSE) inside the nav. */
.top-nav .logo {
    font-family: 'JetBrains Mono', 'Courier New', monospace;
    font-size: 16px;
    font-weight: 400;
    line-height: 1.15;
    color: var(--text);
    text-decoration: none;
    border-left: 2px solid currentColor;
    padding-left: 10px;
    margin-right: 28px;
    display: inline-block;
}
.top-nav .logo .logo-sub {
    display: block;
    font-size: 9px;
    opacity: 0.55;
    letter-spacing: 0.3em;
    font-weight: 400;
}

/* Reusable logo classes (per style guide). */
.boh-logo-bar {
    font-family: 'JetBrains Mono', 'Courier New', monospace;
    font-size: 18px;
    font-weight: 400;
    line-height: 1.3;
    border-left: 2px solid currentColor;
    padding-left: 12px;
    display: inline-block;
}
.boh-logo-bar__sub {
    display: block;
    font-size: 10px;
    opacity: 0.5;
    letter-spacing: 0.3em;
}

.top-nav .nav-links {
    display: flex;
    gap: 4px;
    list-style: none;
}

.top-nav .nav-links a {
    display: inline-block;
    padding: 6px 12px;
    color: var(--text-muted);
    text-decoration: none;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 500;
    transition: background 0.15s, color 0.15s;
}

.top-nav .nav-links a:hover {
    background: var(--bg-hover);
    color: var(--text);
}

.top-nav .nav-links a.active {
    background: var(--primary);
    color: #fff;
}

.top-nav .nav-right {
    margin-left: auto;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 8px;
}

/* Second line under the nav controls: rwfetch loop "last completed" heartbeats.
   flex-basis:100% forces it onto its own row within the wrapping .nav-right. */
.nav-loop-status {
    flex-basis: 100%;
    text-align: right;
    font-size: 10px;
    line-height: 1.3;
    color: var(--text-muted, #9ca3af);
    margin-top: -2px;
}
.nav-loop { white-space: nowrap; }
.nav-loop-stale { color: #d97706; font-weight: 600; }
.nav-loop-fail { color: #dc2626; font-weight: 700; }

/* ---- Layout ---- */

.page-wrapper {
    display: flex;
    min-height: calc(100vh - var(--header-height));
}

.main-content {
    flex: 1;
    /* min-width: 0 lets the flex item shrink below its content's
     * min-content so wide tables (calendar/schedule spreadsheets)
     * stay constrained to the viewport. Without it the flex item
     * grows to fit the table, the body scrolls horizontally, and
     * inner overflow:auto containers (.spreadsheet-calendar) never
     * actually clip — which means position:sticky inside them has
     * no scroll context and never pins. */
    min-width: 0;
    padding: 16px 24px;
    overflow-x: auto;
}

.sidebar {
    width: var(--sidebar-width);
    border-left: 1px solid var(--border);
    padding: 16px;
    background: var(--bg-alt);
    overflow-y: auto;
    flex-shrink: 0;
    position: sticky;
    top: var(--header-height);
    height: calc(100vh - var(--header-height));
    transition: width 0.2s, padding 0.2s;
}

.sidebar.collapsed {
    width: 32px;
    min-width: 32px;
    padding: 8px 4px;
    overflow: hidden;
}

.sidebar.collapsed .sidebar-content {
    display: none;
}

.sidebar-toggle {
    display: block;
    background: none;
    border: none;
    cursor: pointer;
    font-size: 14px;
    color: var(--text-muted);
    padding: 4px 6px;
    margin-bottom: 8px;
    border-radius: 4px;
}

.sidebar-toggle:hover {
    background: var(--bg-hover);
    color: var(--text);
}

.sidebar h3 {
    font-size: 13px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-muted);
    margin-bottom: 8px;
}

.sidebar .index-list {
    list-style: none;
}

.sidebar .index-list li {
    margin-bottom: 2px;
}

.sidebar .index-list a {
    display: block;
    padding: 4px 8px;
    color: var(--text);
    text-decoration: none;
    border-radius: 4px;
    font-size: 13px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidebar .index-list a:hover {
    background: var(--bg-hover);
}

/* ---- Workload Summary ---- */

.workload-summary {
    background: var(--bg);
    border: 1px solid var(--border-light);
    border-radius: 8px;
    padding: 12px;
    margin-bottom: 16px;
}

.workload-summary .stat-row {
    display: flex;
    justify-content: space-between;
    padding: 2px 0;
    font-size: 13px;
}

.workload-summary .stat-value {
    font-weight: 600;
}

/* ---- Project Row ---- */

.project-group {
    border: 1px solid var(--border-light);
    border-radius: 8px;
    margin-bottom: 8px;
    background: var(--bg);
    transition: border-color 0.15s, box-shadow 0.15s;
    min-width: max-content;
}

.project-group:hover {
    border-color: var(--primary);
    box-shadow: 0 1px 4px rgba(59, 130, 246, 0.1);
}

.project-row {
    padding: 12px 16px;
}

/* My Projects / Watched row highlights */
/* Both "assigned to me" and "watched" share the same soft-yellow highlight
 * background; a thick left border distinguishes them — RED = assigned to me,
 * GREEN = watching. dash-row-mine and dash-row-watched are mutually exclusive
 * in JS (a mine row never also gets the watched class), so a "both" project
 * always renders as assigned/red — assigned is the stronger signal.
 * These rules sit after `.project-group:hover` in source and at equal
 * specificity, so their border-left-color wins on hover too (the accent
 * stays red/green instead of flipping to the hover primary color). */
.project-group:has(.dash-row-mine),
.project-group:has(.dash-row-watched) {
    background: #fffaeb;
}
.project-group:has(.dash-row-mine) {
    border-left: 4px solid #dc2626;
}
.project-group:has(.dash-row-watched) {
    border-left: 4px solid #16a34a;
}

.project-row-header {
    display: flex;
    align-items: baseline;
    gap: 12px;
    margin-bottom: 6px;
}

.project-row-header .project-name {
    font-weight: 600;
    font-size: 15px;
}

.project-row-header .project-number {
    color: var(--text-muted);
    font-size: 13px;
}

.project-row-header .project-color-dot {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    display: inline-block;
    flex-shrink: 0;
}

.project-dates-inline {
    display: flex;
    gap: 12px;
    font-size: 12px;
    color: var(--text-muted);
    margin-bottom: 8px;
    flex-wrap: wrap;
}

.project-dates-inline .date-chip {
    background: var(--bg-alt);
    padding: 2px 8px;
    border-radius: 4px;
    white-space: nowrap;
}

.project-info-block {
    display: flex;
    gap: 24px;
    margin-bottom: 8px;
    flex-wrap: wrap;
}

.project-info-block .info-field {
    flex: 1;
    min-width: 150px;
}

.project-info-block .info-label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    color: var(--text-muted);
    margin-bottom: 2px;
}

.project-info-block .info-value {
    font-size: 13px;
    color: var(--text);
}

/* ---- Dashboard Row Layout ---- */

.dash-filter-warning {
    padding: 12px 16px;
    background: #fef3c7;
    border: 1px solid #f59e0b;
    border-radius: 4px;
    color: #92400e;
    font-size: 13px;
    margin-bottom: 8px;
}
.dash-filter-warning a {
    color: #1e40af;
    font-weight: 600;
}
.dash-row {
    display: flex;
    gap: 0;
    align-items: stretch;
    padding: 0;
    min-width: max-content;
}

#projectList {
    /* Vertical + horizontal scroller for the virtualized project list. The
     * server-rendered `.project-group` rows are detached into a JS array and
     * only the visible window (+buffer) is attached inside #dash-rows. */
    overflow: auto;
    position: relative;
    max-height: calc(100vh - 200px);
}
/* Anti-flash: the template renders every project row unfiltered/unsorted, and
 * that markup can paint before dashboard.js's DOMContentLoaded handler runs,
 * detaches the rows, restores persisted filters (showPast/showCompleted/...)
 * and builds the real filtered+sorted view. Without this, users see a brief
 * flash of the full server list before it snaps to the filtered one.
 * dashboard.html renders #projectList with this class present from the first
 * byte (no JS race); dashboard.js removes it once the first filtered render
 * (or the no-virtualizer fallback) is in place. visibility (not display)
 * keeps the box measurable/scrollable while hidden. */
#projectList.dash-booting {
    visibility: hidden;
}
/* Spacer gives the scrollbar its full range (height = sum of all row heights,
 * set by JS). #dash-rows is lifted out of flow and translated to the first
 * visible row; min-width:max-content keeps horizontal scrolling of wide rows. */
#dash-spacer {
    position: relative;
    width: 1px;
}
#dash-rows {
    position: absolute;
    top: 0;
    left: 0;
    right: auto;
    min-width: max-content;
    will-change: transform;
}

.dash-col {
    padding: 8px 10px;
    border-right: 1px solid var(--border-light);
    flex-shrink: 0;
}

.dash-col:last-child {
    border-right: none;
}

/* Inline edit inputs for dashboard */
.dash-inline {
    border: 1px solid var(--border-light);
    padding: 2px 4px;
    border-radius: 4px;
    background: transparent;
    font-size: 13px;
    font-family: inherit;
    color: var(--text);
    width: 100%;
    transition: border-color 0.15s, background 0.15s;
}

.dash-inline:hover {
    border-color: var(--border);
    background: var(--bg-alt);
}

.dash-inline:focus {
    outline: none;
    border-color: var(--primary);
    background: var(--bg);
    box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.15);
}

.dash-inline-sm {
    font-size: 12px;
    padding: 1px 3px;
    width: 100%;
}

.dash-inline-area {
    resize: none;
    min-height: 36px;
    border: 1px solid var(--border-light);
    padding: 2px 4px;
    border-radius: 4px;
    background: transparent;
    font-size: 12px;
    font-family: inherit;
    color: var(--text);
    width: 100%;
    flex: 1;
    transition: border-color 0.15s, background 0.15s;
}

.dash-inline-area:hover {
    border-color: var(--border);
    background: var(--bg-alt);
}

.dash-inline-area:focus {
    outline: none;
    border-color: var(--primary);
    background: var(--bg);
    box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.15);
}

/* ---- Lazy resting cells + shared editor ----
 * A `.dash-lazy` div renders the field's text at rest (no live input). On
 * click the shared VL editor (input/textarea) is moved INSIDE the div; the
 * editor is chrome-less, so the div's own border/padding stays the field
 * frame — no double border, no layout shift on activate. */
.dash-lazy {
    cursor: text;
    box-sizing: border-box;
    white-space: pre-wrap;        /* textarea variants keep newlines + wrap */
    overflow: hidden;
}
.dash-lazy[data-ctl="input"] {
    white-space: nowrap;          /* input variants: single line, clipped */
    /*text-overflow: ellipsis;*/
    min-height: 1.4em;            /* hold one-line height when empty */
    line-height: 1.4;
}
.dash-lazy[data-ctl="textarea"] {
    display: flex;
    flex-direction: column;
}
/* keep empty cells sized + clickable; spec cells show their label as a hint */
.dash-lazy:empty::before { content: '\200b'; }
.dash-lazy[data-placeholder]:empty::before {
    content: attr(data-placeholder);
    color: var(--text-muted);
}
/* focus-ring parity with the old input/textarea :focus rules */
.dash-inline.dash-lazy:focus-within,
.dash-inline-area.dash-lazy:focus-within {
    outline: none;
    border-color: var(--primary);
    background: var(--bg);
    box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.15);
}
.dash-feed-input.dash-lazy:focus-within { background: #fff; }

/* The shared editor controls: chrome-less, fill the wrapping cell so the
 * caret/text sit exactly where the resting text did. */
.vl-editor {
    font: inherit;
    color: inherit;
    border: none;
    outline: none;
    background: transparent;
    margin: 0;
    padding: 0;
    width: 100%;
    box-sizing: border-box;
}
.vl-editor-area {
    display: block;
    flex: 1;
    resize: none;
    min-height: 1.4em;
}

/* Left block: name/number header spanning over dates + loc/status/desc */
.dash-col-left {
    width: 680px;
    min-width: 680px;
    display: flex;
    flex-direction: column;
}

.dash-left-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--border-light);
    margin-bottom: 6px;
}

.dash-inline-name {
    font-weight: 600;
    font-size: 14px;
    flex: 1;
    min-width: 4em;
}

.dash-detail-link {
    font-size: 16px;
    font-weight: 600;
    color: var(--primary);
    text-decoration: none;
    flex-shrink: 0;
    padding: 0 4px;
    line-height: 1;
}

.dash-detail-link:hover {
    color: var(--primary-hover, #2563eb);
}

.dash-inline-number {
    color: var(--text-muted);
    font-size: 13px;
    width: 100px;
    text-align: right;
    flex-shrink: 0;
}

.dash-left-body {
    display: flex;
    gap: 0;
    flex: 1;
}

.dash-left-dates {
    width: 248px;
    min-width: 248px;
    padding-right: 10px;
    border-right: 1px solid var(--border);
}

.dash-date-input {
    width: 110px !important;
    font-size: 11px !important;
}

.dash-left-fields {
    display: flex;
    flex: 1;
    gap: 0;
    align-items: stretch;
}

.dash-left-field {
    flex: 1;
    padding: 0 8px;
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
}

.dash-left-field:last-child {
    border-right: none;
}

.dash-left-field .dash-inline-area {
    flex: 1;
}

/* Milestone alerts column (conditional) */
.dash-col-ms-alerts {
    width: 160px;
    min-width: 160px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    justify-content: center;
    padding: 4px 8px;
}

.dash-ms-alert {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 4px;
    font-size: 11px;
    padding: 2px 6px;
    border-radius: 3px;
    line-height: 1.3;
}

.dash-ms-alert-name {
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dash-ms-alert-due {
    flex-shrink: 0;
    font-weight: 600;
}

.dash-ms-overdue {
    background: #fee2e2;
    color: #991b1b;
}

.dash-ms-alerting {
    background: #fff7ed;
    color: #9a3412;
}

.dash-ms-upcoming {
    background: #fef9c3;
    color: #854d0e;
}

/* Project row left-edge alert stripe */
.dash-row-ms-overdue,
.dash-row-ms-alerting,
.dash-row-ms-upcoming {
    position: relative;
    overflow: hidden;
}

.dash-row-ms-overdue::before,
.dash-row-ms-alerting::before,
.dash-row-ms-upcoming::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 2em;
    border-radius: 8px 0 0 8px;
}

.dash-row-ms-overdue::before {
    background: #ef4444;
}
.dash-row-ms-alerting::before {
    background: #f97316;
}
.dash-row-ms-upcoming::before {
    background: #eab308;
}

.dash-row-ms-overdue > .dash-col:first-child,
.dash-row-ms-alerting > .dash-col:first-child,
.dash-row-ms-upcoming > .dash-col:first-child {
    padding-left: calc(2em + 10px);
}

.dash-col-people {
    width: 130px;
    min-width: 130px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    justify-content: flex-start;
}

.dash-people-field {
    display: flex;
    flex-direction: column;
}

.dash-people-field .dash-inline-sm {
    width: 100%;
}

.dash-date-stack {
    font-size: 12px;
    line-height: 1.5;
}

.dash-date-row {
    display: flex;
    align-items: center;
    gap: 2px;
    justify-content: space-between;
}

.dash-date-label {
    color: var(--text-muted);
    min-width: 80px;
    max-width: 128px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 11px;
}

.dash-col-reqs {
    /* min-width (not fixed width) so >2 requirement columns widen the block;
     * the row is a flex of flex-shrink:0 columns and scrolls horizontally. */
    min-width: 300px;
    position: relative;
}

.dash-req-grid {
    /* Column-major flow capped at 10 rows tall: items fill DOWN up to 10,
     * then wrap RIGHT into as many implicit columns as needed (25 reqs =
     * 3 columns of <=10). Trailing empty `auto` rows collapse to 0, so short
     * lists don't reserve height. The template's inline --dash-req-rows
     * (ceil(n/2), for the old balanced 2-column layout) is no longer read.
     * Fixed 135px implicit columns reproduce the old column width (300px
     * block - 2*10px padding - 10px gap = 2*135px) and preserve .req-name
     * ellipsis clipping; extra columns widen the block (.dash-col-reqs has
     * min-width, not fixed width) and the dash row already h-scrolls
     * (min-width: max-content in #projectList's overflow:auto). */
    display: grid;
    grid-template-rows: repeat(10, auto);
    grid-auto-flow: column;
    grid-auto-columns: 135px;
    gap: 2px 10px;
}

.dash-req-item {
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 4px;
    position: relative;
}

.dash-req-item:hover {
    background: var(--bg-hover);
}

.dash-col-actions {
    width: 80px;
    min-width: 80px;
    display: flex;
    flex-direction: column;
    gap: 3px;
    justify-content: flex-start;
}

.dash-col-actions .btn-sm {
    width: 100%;
    justify-content: center;
}

.dash-col-notes {
    min-width: 200px;
    display: flex;
}

.dash-notes-strip {
    display: flex;
    gap: 8px;
    padding: 0;
    align-items: stretch;
}

.dash-note-card {
    background: var(--bg-alt);
    border: 1px solid var(--border-light);
    border-radius: 6px;
    padding: 0;
    font-size: 12px;
    width: 160px;
    flex-shrink: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}

.dash-feed-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 2px 6px 2px 10px;
    border-radius: 6px 6px 0 0;
    background: #dbeafe;
}
.dash-feed-label {
    font-weight: 600;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    color: #1e3a5f;
}
.dash-feed-label-open { color: #dc2626; }
.dash-feed-header:has(.dash-feed-label-open) { background: #fde8e8; }
.dash-feed-check {
    display: flex;
    align-items: center;
    cursor: pointer;
    margin: 0;
}
.dash-feed-check input { margin: 0; }
.dash-feed-input {
    flex: 1;
    border: none;
    background: transparent;
    font-size: 12px;
    font-family: inherit;
    padding: 4px 8px;
    resize: none;
    outline: none;
    min-height: 20px;
    width: 100%;
    box-sizing: border-box;
}
.dash-feed-input:focus {
    background: #fff;
}
.dash-feed-done {
    opacity: 0.5;
}
.dash-feed-done .dash-feed-input {
    text-decoration: line-through;
}
.dash-feed-meta { padding: 0 8px 4px; font-size: 11px; color: #888; white-space: nowrap; }

.dash-feed-toggle:not(.active) {
    opacity: 0.5;
}

/* Note/field columns (Next Step, Schedule Notes, Flip, Hardware, Trucking) */
.dash-col-field {
    width: 150px;
    min-width: 120px;
    display: flex;
    flex-direction: column;
}
.dash-col-field .dash-inline-area {
    flex: 1;
}

/* ------------------------------------------------------------------
 * Dashboard row height caps: long content scrolls IN PLACE instead of
 * stretching the row and pushing the rest of the row off-screen.
 * ------------------------------------------------------------------ */

/* (Requirements list height cap lives on .dash-req-grid itself:
 * grid-template-rows: repeat(10, auto) + grid-auto-flow: column makes the
 * list at most 10 items tall, wrapping into extra columns — no scroll.) */

/* Every text display cell: cap at 10 lines (10 * line-height). em-based so
 * the cap tracks font-size changes. Inherited line-height is 1.5, so
 * 10 lines = 15em. These rules sit AFTER `.dash-lazy { overflow:hidden }`,
 * so the overflow-y longhand wins (keeps overflow-x hidden, y scrollable). */
.dash-inline-area,
.dash-feed-input,
.dash-scratch-note {
    max-height: 15em;
    overflow-y: auto;
}
/* Editing state: the shared VL editor moves a chrome-less textarea INTO the
 * resting cell on click and sets NO inline height, so this max-height wins
 * with no !important; the textarea scrolls its own overflow while editing. */
.vl-editor-area {
    max-height: 15em;
    overflow-y: auto;
}

/* Subtle thin scrollbars for the capped scroll areas. */
.dash-req-grid,
.dash-inline-area,
.dash-feed-input,
.dash-scratch-note,
.vl-editor-area {
    scrollbar-width: thin;
    scrollbar-color: var(--border) transparent;
}
.dash-req-grid::-webkit-scrollbar,
.dash-inline-area::-webkit-scrollbar,
.dash-feed-input::-webkit-scrollbar,
.dash-scratch-note::-webkit-scrollbar,
.vl-editor-area::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}
.dash-req-grid::-webkit-scrollbar-thumb,
.dash-inline-area::-webkit-scrollbar-thumb,
.dash-feed-input::-webkit-scrollbar-thumb,
.dash-scratch-note::-webkit-scrollbar-thumb,
.vl-editor-area::-webkit-scrollbar-thumb {
    background: var(--border);
    border-radius: 3px;
}
.dash-req-grid::-webkit-scrollbar-track,
.dash-inline-area::-webkit-scrollbar-track,
.dash-feed-input::-webkit-scrollbar-track,
.dash-scratch-note::-webkit-scrollbar-track,
.vl-editor-area::-webkit-scrollbar-track {
    background: transparent;
}

/* Quick-add dropdown in requirements column */
.dash-req-quickadd {
    display: flex;
    gap: 4px;
    margin-top: 6px;
    align-items: center;
}
select.dash-quickadd-select {
    font-size: 11px;
    padding: 2px 4px;
    max-width: 120px;
    min-width: 0;
}

/* Expand buttons row under each project */
.dash-expand-row {
    display: flex;
    gap: 4px;
    padding: 2px 10px 4px;
    border-bottom: 1px solid var(--border-light);
    background: var(--bg-alt);
    position: sticky;
    left: 0;
    max-width: calc(100vw - 40px);
}
.dash-expand-btn.active {
    background: var(--primary);
    color: #fff;
}
.dash-expand-panel {
    border-bottom: 1px solid var(--border-light);
    background: #fafbfc;
    overflow-x: auto;
    position: sticky;
    left: 0;
    max-width: calc(100vw - 40px);
}
.dash-expand-table {
    font-size: 12px;
    margin: 0;
}
.dash-expand-loading {
    padding: 8px 12px;
    color: var(--text-muted);
    font-size: 12px;
}

/* Project search bar (inline with header) */
.dash-search-bar {
    font-size: 13px;
    padding: 4px 8px;
    width: 200px;
}

/* Requirement Popover */
.req-popover {
    position: fixed;
    z-index: 300;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 8px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
    padding: 10px 14px;
    min-width: 200px;
    white-space: nowrap;
}

.req-pop-label {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    padding: 3px 0;
    cursor: pointer;
    white-space: nowrap;
}

/* Milestone popover (dashboard) */
.ms-popover {
    position: absolute;
    z-index: 300;
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 8px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
    padding: 10px 14px;
    min-width: 180px;
    white-space: nowrap;
}

.ms-pop-title {
    font-weight: 600;
    font-size: 13px;
    margin-bottom: 2px;
}

.ms-pop-due {
    font-size: 12px;
    color: var(--text-muted);
}

.ms-pop-repeat {
    font-size: 11px;
    color: var(--text-muted);
    font-style: italic;
}

/* ---- Requirements Grid ---- */

.req-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 4px 16px;
    margin: 8px 0;
}

.req-item {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 2px 0;
    font-size: 12px;
}

.req-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
}

.req-dot.green { background: var(--success); }
.req-dot.yellow { background: var(--warning); }
.req-dot.red { background: var(--danger); }
.req-dot.orange { background: var(--orange); }

/* Fully-completed requirement rows: greyed and sunk to the bottom (toggle in
   the Requirements section header, default on). Dot keeps its green color. */
.req-row-done { opacity: 0.5; }
.req-row-done td { color: var(--text-muted); }
.req-row-done .inline-edit { color: var(--text-muted); }

.req-sink-toggle {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    color: var(--text-muted);
    white-space: nowrap;
    cursor: pointer;
}

.req-checks-inline {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    align-items: center;
}

.req-check-label {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-size: 11px;
    color: var(--text-muted);
    white-space: nowrap;
    cursor: pointer;
}

.req-name {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ---- Specs List (horizontal scroll) ---- */

.specs-row {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    padding: 4px 0;
}

.spec-chip {
    background: var(--bg-alt);
    border: 1px solid var(--border-light);
    border-radius: 6px;
    padding: 4px 10px;
    font-size: 12px;
    white-space: nowrap;
    flex-shrink: 0;
}

.spec-chip .spec-label {
    font-weight: 600;
    color: var(--text-muted);
}

/* ---- Row Actions ---- */

.row-actions {
    display: flex;
    gap: 4px;
    margin-top: 8px;
}

/* ---- Buttons ---- */

.btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 5px 12px;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--bg);
    color: var(--text);
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
    text-decoration: none;
}

.btn:hover {
    background: var(--bg-hover);
    border-color: var(--text-light);
}

.btn-sm {
    padding: 3px 8px;
    font-size: 11px;
}

.btn-primary {
    background: var(--primary);
    color: #fff;
    border-color: var(--primary);
}

.btn-primary:hover {
    background: var(--primary-hover);
    border-color: var(--primary-hover);
}

.btn-danger {
    color: var(--danger);
    border-color: var(--danger);
}

.btn-danger:hover {
    background: var(--danger);
    color: #fff;
}

/* ---- Drawers ---- */

.drawer-overlay {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.3);
    z-index: 200;
}

.drawer-overlay.active {
    display: block;
}

.drawer {
    position: fixed;
    top: 0;
    right: -420px;
    width: 420px;
    height: 100vh;
    background: var(--bg);
    border-left: 1px solid var(--border);
    z-index: 201;
    transition: right 0.25s ease;
    display: flex;
    flex-direction: column;
    box-shadow: -4px 0 12px rgba(0, 0, 0, 0.1);
}

.drawer.active {
    right: 0;
}

.drawer-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px;
    border-bottom: 1px solid var(--border);
}

.drawer-header h3 {
    font-size: 16px;
    font-weight: 600;
}

.drawer-close {
    background: none;
    border: none;
    font-size: 20px;
    cursor: pointer;
    color: var(--text-muted);
    padding: 4px;
}

.drawer-body {
    flex: 1;
    padding: 16px;
    overflow-y: auto;
}

.drawer-footer {
    padding: 12px 16px;
    border-top: 1px solid var(--border);
}

/* ---- Forms ---- */

.form-group {
    margin-bottom: 12px;
}

.form-group label {
    display: block;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-muted);
    margin-bottom: 4px;
}

.form-control {
    width: 100%;
    padding: 6px 10px;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 13px;
    font-family: inherit;
    transition: border-color 0.15s;
}

.form-control:focus {
    outline: none;
    border-color: var(--primary);
    box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.15);
}

textarea.form-control {
    min-height: 80px;
    resize: vertical;
}

select.form-control {
    appearance: auto;
}

.inline-edit {
    border: 1px solid var(--border-light);
    padding: 2px 6px;
    border-radius: 4px;
    background: transparent;
    font-size: inherit;
    font-family: inherit;
    color: inherit;
    width: 100%;
    transition: border-color 0.15s, background 0.15s;
}

.inline-edit:hover {
    border-color: var(--border-light);
    background: var(--bg-alt);
}

.inline-edit:focus {
    outline: none;
    border-color: var(--primary);
    background: var(--bg);
    box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.15);
}

/* ---- Todo / Note items ---- */

.todo-item, .note-item {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 10px 12px;
    border: 1px solid var(--border-light);
    border-radius: 6px;
    margin-bottom: 8px;
    background: var(--bg);
}

.todo-checkbox {
    margin-top: 3px;
    cursor: pointer;
    width: 16px;
    height: 16px;
    accent-color: var(--primary);
}

.todo-text.completed {
    text-decoration: line-through;
    color: var(--text-muted);
}

.todo-meta {
    display: flex;
    gap: 8px;
    font-size: 11px;
    color: var(--text-muted);
    margin-top: 2px;
}

/* Due date urgency backgrounds */
.todo-due-week {
    background: #fefce8;
    padding-left: 8px;
    padding-right: 8px;
    margin-left: -8px;
    margin-right: -8px;
    border-radius: 4px;
}
.todo-due-soon {
    background: #fff7ed;
    padding-left: 8px;
    padding-right: 8px;
    margin-left: -8px;
    margin-right: -8px;
    border-radius: 4px;
}
.todo-due-today {
    background: #fef2f2;
    padding-left: 8px;
    padding-right: 8px;
    margin-left: -8px;
    margin-right: -8px;
    border-radius: 4px;
}
.todo-due-overdue {
    background: #fef2f2;
    border: 3px solid #fca5a5;
    padding-left: 8px;
    padding-right: 8px;
    margin-left: -8px;
    margin-right: -8px;
    border-radius: 4px;
}

.priority-badge {
    display: inline-block;
    padding: 1px 6px;
    border-radius: 3px;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
}

.priority-badge.low { background: #e0f2fe; color: #0369a1; }
.priority-badge.medium { background: #fef3c7; color: #92400e; }
.priority-badge.high { background: #fee2e2; color: #991b1b; }
.priority-badge.urgent { background: #ef4444; color: #fff; }

.note-handled {
    color: var(--text-light);
}

/* ---- Scratch Pad ---- */

.scratch-pad {
    background: #fffde7;
    border: 1px solid #fff176;
    border-radius: 8px;
    padding: 12px;
    margin-bottom: 16px;
}

.scratch-pad textarea {
    width: 100%;
    min-height: 200px;
    border: none;
    background: transparent;
    font-family: inherit;
    font-size: 13px;
    resize: vertical;
    outline: none;
}

.scratch-pad-label {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    color: #f59e0b;
    margin-bottom: 6px;
}

/* Saved indicator: always present in the layout (so showing/hiding it
 * doesn't reflow the textarea below). Visibility-toggled via .is-visible. */
.scratch-pad-status {
    display: inline-block;
    visibility: hidden;
    opacity: 0;
    font-size: 11px;
    color: #888;
    font-style: italic;
    padding: 2px 4px;
    min-height: 1em;
    line-height: 1;
    transition: opacity 0.2s linear;
}
.scratch-pad-status.is-visible {
    visibility: visible;
    opacity: 1;
}

.scratch-pad-list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 8px;
}

.scratch-pad-item {
    background: var(--bg-alt);
    border: 1px solid var(--border-light);
    border-radius: 6px;
    padding: 6px 10px;
    font-size: 12px;
    cursor: pointer;
    min-width: 100px;
    max-width: 200px;
    position: relative;
    display: flex;
    align-items: center;
    gap: 6px;
}
.scratch-pad-item strong { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.scratch-pad-delete {
    background: none;
    border: none;
    color: #999;
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    padding: 0 2px;
    flex-shrink: 0;
}
.scratch-pad-delete:hover { color: #ef4444; }
.scratch-pad-item:hover { border-color: var(--border); }

/* Scratch-pad drawer split: top half = scratch pad UI, bottom half = open
   todos for the current context. Each half scrolls independently when its
   content overflows the 50% allocation. */
.gsp-split {
    display: flex;
    flex-direction: column;
    height: 100%;
    gap: 0;
    margin: -16px;  /* cancel .drawer-body's 16px padding so the split fills */
}
.gsp-split-top,
.gsp-split-bottom {
    overflow-y: auto;
    padding: 12px 16px;
}
.gsp-split-top {
    flex: 1 1 50%;
    min-height: 0;
    border-bottom: 1px solid var(--border);
}
.gsp-split-bottom {
    flex: 1 1 50%;
    min-height: 0;
    background: #fafbfc;
}
.gsp-todos-header {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 8px;
    letter-spacing: 0.04em;
}
.gsp-todo-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 6px;
    border-bottom: 1px solid var(--border-light);
    font-size: 12px;
    line-height: 1.3;
    /* Row renders as an anchor — strip default link styling. */
    color: inherit;
    text-decoration: none;
    cursor: pointer;
}
.gsp-todo-row:hover {
    background: #f3f4f6;
    color: inherit;
    text-decoration: none;
}
.gsp-todo-prio {
    flex: 0 0 auto;
    font-size: 10px;
    padding: 1px 5px;
}
.gsp-todo-status {
    flex: 0 0 auto;
    font-size: 10px;
    padding: 1px 6px;
    border-radius: 3px;
    border: 1px solid #d1d5db;
    background: #f3f4f6;
    color: #4b5563;
    white-space: nowrap;
}
/* Status-key tints. Keys match TodoStatus.key values seeded in 0040. */
.gsp-todo-status-not_started { background: #f3f4f6; color: #4b5563; border-color: #d1d5db; }
.gsp-todo-status-do_next     { background: #fef3c7; color: #92400e; border-color: #fde68a; }
.gsp-todo-status-in_progress { background: #dbeafe; color: #1e40af; border-color: #93c5fd; }
.gsp-todo-status-on_hold     { background: #fce7f3; color: #9d174d; border-color: #fbcfe8; }
.gsp-todo-status-waiting     { background: #ede9fe; color: #5b21b6; border-color: #ddd6fe; }
.gsp-todo-status-complete    { background: #d1fae5; color: #065f46; border-color: #a7f3d0; }
.gsp-todo-proj {
    flex: 0 0 auto;
    font-size: 11px;
    font-weight: 600;
    max-width: 90px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.gsp-todo-text {
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.gsp-todo-due {
    flex: 0 0 auto;
    font-size: 10px;
    color: var(--text-muted);
}
.scratch-pad-item.active {
    border-color: #2563eb;
    background: #eff6ff;
}

.scratch-pad-snippet {
    color: var(--muted);
    font-size: 11px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: block;
}

/* ---- Calendar ---- */

/* Calendar toolbar */
.cal-toolbar {
    margin-bottom: 8px;
}
.cal-toolbar-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: 6px 0;
}
.cal-toolbar-group {
    display: flex;
    align-items: center;
    gap: 6px;
}
.cal-toolbar-sep {
    width: 1px;
    height: 24px;
    background: var(--border-light);
}

/* Mode toggle */
.cal-mode-toggle {
    display: flex;
    border: 1px solid var(--border);
    border-radius: 6px;
    overflow: hidden;
}
.cal-mode-btn {
    padding: 5px 14px;
    font-size: 12px;
    font-weight: 500;
    border: none;
    background: var(--bg);
    color: var(--text-muted);
    cursor: pointer;
    transition: all 0.15s;
}
.cal-mode-btn:not(:last-child) {
    border-right: 1px solid var(--border);
}
.cal-mode-btn.active {
    background: var(--primary);
    color: #fff;
}
.cal-mode-btn:hover:not(.active) {
    background: var(--bg-alt);
    color: var(--text);
}

/* Nav buttons */
.cal-nav {
    display: flex;
    align-items: center;
    gap: 2px;
}
.cal-nav-btn {
    padding: 4px 10px;
    font-size: 12px;
    border: 1px solid var(--border-light);
    background: var(--bg);
    border-radius: 4px;
    cursor: pointer;
    color: var(--text);
}
.cal-nav-btn:hover {
    background: var(--bg-alt);
}
.cal-today-btn {
    font-weight: 600;
}
.cal-period-label {
    font-weight: 600;
    font-size: 13px;
    padding: 0 8px;
    white-space: nowrap;
}

/* Select */
.cal-select {
    padding: 4px 8px;
    font-size: 12px;
    border: 1px solid var(--border-light);
    border-radius: 4px;
    background: var(--bg);
    cursor: pointer;
}

/* Checkbox options */
.cal-options {
    gap: 10px;
}
.cal-check {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    color: var(--text-muted);
    cursor: pointer;
    white-space: nowrap;
}
.cal-check input {
    margin: 0;
}

/* Date type dropdown */
.cal-dropdown {
    position: relative;
}
.cal-dropdown-btn {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 4px 8px;
    font-size: 12px;
    border: 1px solid var(--border-light);
    border-radius: 4px;
    background: var(--bg);
    cursor: pointer;
    white-space: nowrap;
}
.cal-dropdown-btn:hover {
    background: var(--bg-alt);
}
.cal-dropdown-caret {
    font-size: 10px;
    color: var(--text-muted);
}
.cal-dropdown-menu {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 2px;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 4px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.12);
    z-index: 50;
    min-width: 160px;
    max-height: 300px;
    overflow-y: auto;
    padding: 4px 0;
}
.cal-dropdown-menu.open {
    display: block;
}
.cal-dropdown-item {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    font-size: 12px;
    cursor: pointer;
    white-space: nowrap;
}
.cal-dropdown-item:hover {
    background: var(--bg-alt);
}
.cal-dropdown-item input {
    margin: 0;
}

/* Show/hide controls based on active mode */
.cal-std-controls { display: none; }
.cal-ss-controls { display: none; }
.cal-ss-only { display: none; }
[data-active-mode="standard"] .cal-std-controls { display: flex; }
[data-active-mode="spreadsheet"] .cal-ss-controls { display: flex; }
[data-active-mode="spreadsheet"] .cal-ss-only { display: flex; }

.calendar-grid {
    border: 1px solid #999;
    border-radius: 8px;
    overflow-x: auto;
}

.calendar-cell {
    border: 1px solid #999;
    min-height: 90px;
    padding: 4px 6px;
}

.calendar-cell-header {
    font-size: 12px;
    font-weight: 600;
    color: var(--text-muted);
    margin-bottom: 4px;
}
.cal-today-circle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 3px;
    border-radius: 50%;
    background: rgb(234, 88, 12);
    color: #fff;
    font-weight: 700;
    font-size: 11px;
    line-height: 18px;
    margin: -3px 0;
}

.calendar-event {
    /* Two-column layout: name fills available space and truncates with an
       ellipsis; bold date-type label is pinned to the right and never
       compressed. */
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 2px 6px;
    border-radius: 4px;
    font-size: 11px;
    margin-bottom: 2px;
    color: #fff;
    white-space: nowrap;
    overflow: hidden;
}
.calendar-event .cal-ev-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
.calendar-event .cal-ev-type {
    flex: 0 0 auto;
    font-weight: 700;
    margin-left: auto;
}
.calendar-event.cal-ev-quiet { opacity: 0.5; }

.calendar-event.continuous {
    border-radius: 0;
    margin: 0 -7px 2px -7px;
    padding: 0 6px;
    height: 18px;
    line-height: 18px;
}

/* Calendar milestones */
.calendar-milestone {
    padding: 2px 6px;
    font-size: 10px;
    margin-bottom: 2px;
    color: #333;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    background: #f8f8f8;
    border-left: 3px solid #6b7280;
    border-radius: 0 3px 3px 0;
}
.cal-ms-icon {
    font-size: 8px;
    vertical-align: middle;
}
.ss-milestone-marker {
    font-size: 10px;
    position: absolute;
    top: -1px;
    right: 0;
    line-height: 1;
    pointer-events: none;
    text-shadow: 0 0 2px rgba(255,255,255,0.8);
}
.ss-milestone-cell {
    font-weight: 600;
}

/* Spreadsheet calendar */
.spreadsheet-calendar-top-scroll {
    overflow-x: auto;
    overflow-y: hidden;
    height: 12px;
}
.spreadsheet-calendar-top-scroll-inner {
    height: 1px;
}

.spreadsheet-calendar {
    overflow: auto;
    max-height: calc(100vh - 190px);
}

.spreadsheet-calendar table {
    /* `separate` (not `collapse`) so position:sticky works on the
     * <th>/<td class="project-label"> cells. Most browsers don't apply
     * sticky to table cells when borders are collapsed. */
    border-collapse: separate;
    border-spacing: 0;
    width: max-content;
    margin-bottom: 60px;
}

.spreadsheet-calendar th,
.spreadsheet-calendar td {
    border: 1px solid var(--border-light);
    padding: 2px 4px;
    font-size: 11px;
    min-width: 32px;
    text-align: center;
}

.spreadsheet-calendar th {
    background: var(--bg-alt);
    font-weight: 600;
    position: sticky;
    top: 0;
    z-index: 12;
}

.spreadsheet-calendar .ss-month-start {
    border-left: 2px solid #000 !important;
}

.spreadsheet-calendar .ss-weekend {
    background-color: #eff6ff;
}

.spreadsheet-calendar th.ss-weekend {
    background-color: #dbeafe;
}

.spreadsheet-calendar td.ss-today {
    background-color: rgba(249, 115, 22, 0.08);
}

.spreadsheet-calendar th.ss-today {
    background-color: rgba(249, 115, 22, 0.15) !important;
    color: #c2410c;
    font-weight: 700;
}

.ss-dow {
    display: block;
    font-size: 9px;
    font-weight: 400;
    color: var(--text-muted);
    line-height: 1;
}

.spreadsheet-calendar th.project-label {
    z-index: 13;
}

.spreadsheet-calendar .project-label {
    position: sticky;
    left: 0;
    /* Solid opaque background so day cells aren't visible "through" the
     * project label as the user scrolls horizontally. The slightly
     * tinted bg-alt + a strong right border + subtle shadow visually
     * mark this column as its own container, separated from the day
     * grid. */
    background: var(--bg-alt, #f9fafb);
    z-index: 11;
    text-align: left;
    padding: 4px 8px;
    font-weight: 500;
    white-space: nowrap;
    border-right: 2px solid var(--border);
    box-shadow: 2px 0 4px -2px rgba(0, 0, 0, 0.08);
    /* Force a fixed column width so the cell holds its size regardless
     * of content. Without this, table-layout:auto sizes the column to
     * fit its longest unbreakable token (the project number link),
     * which collapses the cell down to ~100px and hides the project
     * name even though sticky is working. Clip overflow so long
     * names / statuses / notes don't bleed onto the day grid.
     *
     * EXPANDED mode (default) needs more room to fit the Status +
     * Notes inputs + scroll-to button alongside the name. COMPACT mode
     * (ss-compact class on the container) hides those fields, so a
     * narrower column is plenty. */
    width: 700px;
    min-width: 700px;
    max-width: 700px;
    overflow: hidden;
}
.spreadsheet-calendar .project-label .ss-label-inner {
    overflow: hidden;
    flex-wrap: nowrap;
    min-width: 0;
}
.spreadsheet-calendar .ss-project-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    /* Natural width on the LEFT (shrink/truncate if long), NOT flex-grow — the
     * gap is held by .ss-label-fields' margin-left:auto so status/notes/locate
     * right-anchor to the same columns on every row. */
    flex: 0 1 auto;
}
/* Row mine/watched tints set their own bg on the project label to keep
 * the row indicator visible in compact mode — make sure that bg also
 * stays opaque when sticky-scrolled. */
.spreadsheet-calendar tr:nth-child(even) > .project-label {
    background: #f3f4f6;
}

.ss-label-inner {
    display: flex;
    align-items: center;
    gap: 6px;
    /* Fill the whole 700px label cell so margin-left:auto on .ss-label-fields
     * has room to push the fields (Status/Notes/⌖) to the right edge. Without
     * this the flex row shrink-wraps to its content and the fields sit right
     * after the name — the "columns all over the place" symptom. */
    width: 100%;
    box-sizing: border-box;
}

.ss-label-fields {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-left: auto;
    padding-left: 12px;
}

.ss-status-input,
.ss-notes-input {
    border: 1px solid var(--border-light);
    background-color: transparent;
    font-size: 10px;
    font-family: inherit;
    outline: none;
    transition: border-color 0.2s, background-color 0.2s;
    padding: 2px 4px;
    border-radius: 3px;
    /* Fixed columns — neither grow nor shrink, so Status/Notes line up across
     * every row (the name shrinks/truncates instead when space is tight). */
    flex: 0 0 auto;
}
.ss-status-input { width: 90px; }
.ss-notes-input { width: 120px; }
span.ss-lazy-field {
    display: inline-block;
    cursor: text;
    height: 18px;
    vertical-align: middle;
    /* Inline labels were overflowing their fixed width when not focused
     * — clip + ellipsis so a long status/note doesn't crash into the
     * adjacent field. The full value still appears once the user
     * clicks in (the field expands into an editable input). */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Compact mode: hides Status + Notes inside the project label cell so
 * the column becomes "name + scroll-to-btn + days". The scroll-to
 * crosshair stays visible (it's the most useful button in either
 * mode). `display: contents` on the wrapper makes its box disappear
 * but lets the surviving children flow into the parent flex layout. */
.spreadsheet-calendar.ss-compact .ss-label-fields {
    display: contents;
}
.spreadsheet-calendar.ss-compact .ss-label-fields .ss-field-label,
.spreadsheet-calendar.ss-compact .ss-label-fields .ss-status-input,
.spreadsheet-calendar.ss-compact .ss-label-fields .ss-notes-input {
    display: none;
}
.spreadsheet-calendar.ss-compact .project-label {
    width: 240px !important;
    min-width: 240px !important;
    max-width: 240px !important;
}
/* Project name in compact mode: stay one line. The .ss-label-inner
 * wrapper handles horizontal overflow scroll, so we don't need to
 * clip — long names just push past the visible viewport and the user
 * scrolls sideways. */
.spreadsheet-calendar .ss-project-name {
    white-space: nowrap;
}
.ss-compact-toggle {
    position: absolute;
    top: 2px;
    right: 4px;
    width: 18px;
    height: 18px;
    line-height: 16px;
    text-align: center;
    border: 1px solid var(--border);
    border-radius: 50%;
    background: #fff;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 11px;
    padding: 0;
    z-index: 5;
}
.ss-compact-toggle:hover {
    background: var(--bg-alt);
    color: var(--text);
}
/* (Removed `th.project-label { position: relative }` — that override
 * was knocking out position:sticky on the header label cell. Sticky
 * is itself a positioning context, so the .ss-compact-toggle absolute
 * button still anchors correctly inside the sticky header. */
.ss-status-input:focus,
.ss-notes-input:focus,
.ss-crew-input:focus {
    border-color: var(--border);
    background: #fff;
}
.ss-save-pending,
.ss-save-pending:focus {
    border-color: #eab308 !important;
    background-color: #fefce8 !important;
}
.ss-save-ok,
.ss-save-ok:focus {
    border-color: #22c55e !important;
    background-color: #dcfce7 !important;
}
.ss-save-err,
.ss-save-err:focus {
    border-color: #ef4444 !important;
    background-color: #fee2e2 !important;
}
.ss-field-label {
    font-size: 9px;
    color: var(--text-muted);
    font-weight: 400;
    white-space: nowrap;
    flex: 0 0 auto;   /* fixed — part of the right-anchored field block */
}

.ss-scroll-to-btn {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 14px;
    color: var(--text-muted);
    padding: 0 2px;
    line-height: 1;
    flex: 0 0 auto;   /* locate icon pinned at the far right, never shrinks */
    margin-left: 4px;
}
.ss-scroll-to-btn:hover {
    color: #2563eb;
}

/* Day cell selection */
.ss-day-cell {
    cursor: cell;
    user-select: none;
    position: relative;
}
.ss-drag-active {
    cursor: cell !important;
    user-select: none !important;
}
.ss-day-cell.ss-selected {
    outline: 2px solid #2563eb !important;
    outline-offset: -2px;
}

/* Date type dropdown */
.ss-dt-dropdown {
    display: flex;
    align-items: center;
    gap: 4px;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 4px 6px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.ss-dt-input {
    font-size: 12px;
    padding: 3px 6px;
    border: 1px solid var(--border-light);
    border-radius: 3px;
    outline: none;
    width: 140px;
}
.ss-dt-input:focus {
    border-color: #2563eb;
}
.ss-dt-clear-btn {
    background: none;
    border: none;
    cursor: pointer;
    font-size: 16px;
    color: #991b1b;
    padding: 0 4px;
    line-height: 1;
}
.ss-dt-clear-btn:hover {
    color: #dc2626;
}

.ss-drag-handle {
    cursor: grab;
    color: var(--text-muted);
    font-size: 11px;
    margin-right: 4px;
    user-select: none;
}
.ss-drag-handle:hover { color: var(--text); }

.ss-dragging {
    opacity: 0.4;
}
.ss-drag-over > td:first-child {
    box-shadow: 0 2px 0 #2563eb inset;
}
.ss-drag-over {
    outline: 2px solid #2563eb;
    outline-offset: -2px;
}
.ss-crew-drag-handle {
    cursor: grab;
    color: var(--text-muted);
    margin-right: 3px;
    font-size: 10px;
    user-select: none;
}
.ss-crew-drag-handle:hover { color: var(--text); }
.ss-crew-dragging {
    opacity: 0.4;
    background: #dbeafe !important;
}

.ss-move-btn {
    background: none;
    border: none;
    font-size: 10px;
    cursor: pointer;
    color: var(--text-muted);
    padding: 0 2px;
    margin-right: 2px;
}
.ss-move-btn:hover { color: var(--text); }
.ss-move-reset { color: #991b1b; }

.ss-project-label-cell {
    position: relative;
    overflow: visible !important;
}
.ss-insert-btn {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: 1px solid var(--border-light);
    background: var(--bg);
    color: var(--text-muted);
    font-size: 12px;
    line-height: 14px;
    text-align: center;
    cursor: pointer;
    padding: 0;
    opacity: 0;
    transition: opacity 0.15s;
}
.ss-insert-btn-inline {
    position: absolute;
    left: 4px;
    top: -8px;
    z-index: 2;
}
/* Calendar spreadsheet: mine/watched row indicators */
.spreadsheet-calendar tr.ss-row-mine > .project-label {
    border-left: 3px solid #3B82F6;
}
.spreadsheet-calendar tr.ss-row-watched > .project-label {
    border-left: 3px solid #f59e0b;
}

.spreadsheet-calendar tr:hover > .project-label {
    z-index: 15;
    background: #fefce8;
}
.spreadsheet-calendar tr:hover > td,
.spreadsheet-calendar tr:hover > th {
    box-shadow: inset 0 1px 0 #94a3b8, inset 0 -1px 0 #94a3b8;
}
.ss-project-label-cell:hover .ss-insert-btn-inline,
tr:hover .ss-insert-btn-inline,
.ss-vrow-addrole:hover .ss-insert-btn {
    opacity: 1;
}
.ss-insert-btn:hover {
    background: #2563eb;
    color: #fff;
    border-color: #2563eb;
}

.ss-insert-form {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 8px;
    background: #eff6ff;
}
.ss-insert-name { width: 200px; font-size: 12px; }
.ss-insert-number { width: 120px; font-size: 12px; }

.ss-project-number {
    color: var(--text-muted);
    font-size: 10px;
    margin-left: 4px;
    text-decoration: none;
}
.ss-project-number:hover {
    text-decoration: underline;
    color: #2563eb;
}
/* "ORDER"/"QUOTE" prefix before the number — small, bold, muted. */
.ss-order-kind {
    font-weight: 700;
    letter-spacing: 0.03em;
    margin-right: 3px;
    opacity: 0.8;
}
.ss-no-order-number {
    color: #dc2626;
    font-size: 10px;
    margin-left: 4px;
    text-decoration: none;
    font-style: italic;
    opacity: 0.75;
}
.ss-no-order-number:hover {
    text-decoration: underline;
    opacity: 1;
}

/* Spreadsheet crew sub-rows */
.ss-caret {
    cursor: pointer;
    display: inline-block;
    width: 14px;
    font-size: 10px;
    user-select: none;
}

.ss-crew-row td {
    background: #f8fafc;
}

.ss-crew-label {
    font-weight: 400 !important;
    padding-left: 12px !important;
    font-size: 10px !important;
    color: #64748b;
    min-width: 280px !important;
    background: #f8fafc !important;
}

.ss-crew-label-inner {
    display: flex;
    align-items: center;
    gap: 4px;
}

.ss-crew-role-name {
    flex-shrink: 0;
    font-weight: 600;
    color: #475569;
    min-width: 80px;
}
input.ss-crew-role-name {
    width: 90px;
    font-size: 11px;
    padding: 0 2px;
    border: 1px solid #000;
    border-radius: 3px;
}
span.ss-crew-role-name {
    cursor: text;
}

.ss-crew-input {
    border: 1px solid #000;
    border-radius: 4px;
    padding: 1px 4px;
    font-size: 10px;
    flex: 1;
    min-width: 80px;
    background: #fff;
}

/* Labor black-box controls on a calendar crew row: status (autocomplete),
   note, and the public toggle. Thin black borders so they read against the
   near-white row background. */
.ss-crew-status,
.ss-crew-note {
    border: 1px solid #000;
    border-radius: 4px;
    padding: 1px 4px;
    font-size: 10px;
    background: #fff;
    cursor: text;
    flex: 0 0 auto;
    min-width: 14px;
    text-align: center;
}
.ss-crew-status { min-width: 54px; text-align: left; }
.ss-crew-public-btn {
    border: 1px solid #000 !important;
    border-radius: 4px;
    padding: 0 4px !important;
    line-height: 1.4;
    background: #fff;
    color: #888;
}
.ss-crew-public-btn.is-public {
    color: #1a7f37;
    border-color: #1a7f37 !important;
    font-weight: 700;
}

/* Read-only crew name for viewers without build_labor; masked private
   assignments show "tentative" in muted italic (role stays visible). */
.ss-crew-private .ss-crew-role-name,
.ss-crew-label-inner > .ss-crew-input:not(.ss-lazy-field) {
    padding: 1px 4px;
    font-size: 10px;
}
.ss-crew-tentative {
    font-style: italic;
    color: var(--text-muted, #888);
    border: 1px dashed var(--border-light);
    border-radius: 4px;
    background: transparent;
}

.ss-crew-search-btn {
    padding: 0 4px !important;
    font-size: 10px !important;
    line-height: 1.4 !important;
    flex-shrink: 0;
    border: 1px solid #000 !important;
    border-radius: 4px;
}

.ss-crew-delete-btn {
    padding: 0 4px !important;
    font-size: 12px !important;
    line-height: 1.2 !important;
    flex-shrink: 0;
    color: var(--text-light);
    border: 1px solid #000 !important;
    border-radius: 4px;
    opacity: 0;
    transition: opacity 0.15s, color 0.15s;
}

.ss-crew-label-inner:hover .ss-crew-delete-btn {
    opacity: 1;
}

.ss-crew-delete-btn:hover {
    color: var(--danger);
}

.ss-crew-cell {
    font-size: 9px !important;
    white-space: nowrap;
    user-select: none;
    -webkit-user-select: none;
}
.ss-crew-toggle:hover {
    opacity: 0.7;
}

/* Crew pending changes */
@keyframes crew-pending-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.4; }
}
.ss-crew-pending {
    animation: crew-pending-pulse 1.2s ease-in-out infinite;
}
@keyframes crew-pending-remove-pulse {
    0%, 100% { box-shadow: inset 0 0 0 2px #dc2626; background: #fee2e2; opacity: 1; }
    50% { box-shadow: inset 0 0 0 2px #dc2626; background: #fee2e2; opacity: 0.4; }
}
.ss-crew-pending-remove {
    animation: crew-pending-remove-pulse 1.2s ease-in-out infinite;
}
/* Staged (not-yet-saved) date-type change on a spreadsheet day cell — pulses
   for attention like the crew cells. Create/retype = blue pulse; delete reuses
   the crew red-remove pulse. */
@keyframes date-pending-pulse {
    0%, 100% { box-shadow: inset 0 0 0 2px #2563eb; opacity: 1; }
    50% { box-shadow: inset 0 0 0 2px #2563eb; opacity: 0.45; }
}
.ss-date-pending {
    animation: date-pending-pulse 1.2s ease-in-out infinite;
}
.ss-date-pending-remove {
    animation: crew-pending-remove-pulse 1.2s ease-in-out infinite;
}
.ss-float-error {
    position: fixed;
    transform: translate(-50%, -100%);
    background: #dc2626;
    color: #fff;
    font-size: 12px;
    padding: 4px 10px;
    border-radius: 4px;
    white-space: nowrap;
    pointer-events: none;
    z-index: 9999;
    box-shadow: 0 2px 6px rgba(0,0,0,.25);
    transition: opacity .6s;
}
.ss-float-error-fade {
    opacity: 0;
}

/* In-flow (above the date grid) so the Save/Cancel bar no longer floats over
   and obscures the dates. Collapses to nothing when there are no changes. */
#ssCrewPendingBarSlot {
    display: flex;
    justify-content: center;
    pointer-events: none;
    margin: 2px 0 4px;
}
#ssCrewPendingBarSlot:empty { display: none; margin: 0; }

/* Pulsing "dates filtered" warning — sits above the dates next to the pending
   bar; click to clear the date-type filter back to all. */
@keyframes ss-filter-warn-pulse {
    0%, 100% { background: #fef3c7; }
    50% { background: #fde68a; }
}
.ss-date-filter-warn {
    text-align: center;
    font-size: 12px;
    font-weight: 600;
    color: #92400e;
    background: #fef3c7;
    border: 1px solid #fcd34d;
    border-radius: 6px;
    padding: 4px 10px;
    margin: 2px auto 4px;
    max-width: max-content;
    cursor: pointer;
    animation: ss-filter-warn-pulse 1.1s ease-in-out infinite;
}
.ss-crew-pending-bar {
    pointer-events: auto;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 16px;
    background: #fef3c7;
    border: 1px solid #f59e0b;
    border-radius: 6px;
    font-size: 13px;
    font-weight: 500;
    color: #92400e;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    white-space: nowrap;
}
.ss-crew-pending-bar .pending-icon {
    font-size: 16px;
}
.ss-crew-pending-bar .pending-text {
    flex: 1;
}
.ss-crew-pending-bar .btn {
    font-size: 12px;
    padding: 4px 12px;
}

/* ==========================================================================
   Virtualized spreadsheet (CSS-grid skeleton, DayRole model)
   #ss-scroll > #ss-head + #ss-spacer > #ss-rows > .ss-vrow
   Explicit widths (set inline by calendar.js) + sticky recipe verified in
   the spike. Only rows are virtualized; the 365 day columns are real.
   ========================================================================== */
:root {
    --ss-row-h: 24px;   /* MUST match SS_ROW_H in calendar.js (read from here) */
    --ss-col-w: 32px;   /* per-day column width */
}

#ss-scroll { position: relative; }

#ss-head {
    display: grid;
    position: sticky;
    top: 0;
    z-index: 12;
}
#ss-head .ss-head-cell,
#ss-head .ss-head-label {
    border: 1px solid var(--border-light);
    border-top: none;
    padding: 2px 4px;
    font-size: 11px;
    line-height: 1.1;
    background: var(--bg-alt);
    font-weight: 600;
    overflow: hidden;
    box-sizing: border-box;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}
#ss-head .ss-head-label {
    position: sticky;
    left: 0;
    z-index: 13;
    /* Same checkerboard exemption as .ss-vrow > .project-label. */
    will-change: transform;
    text-align: left;
    align-items: flex-start;
    background: var(--bg-alt, #f9fafb);
    border-right: 2px solid var(--border);
    box-shadow: 2px 0 4px -2px rgba(0, 0, 0, 0.08);
}

#ss-spacer { position: relative; }
#ss-rows {
    position: absolute;
    top: 0;
    left: 0;
}

/* Ring-buffer recycler (see VL.createFixed in virtual_list.js): each pooled
   row is independently `top: idx*rowH` positioned (set inline by the engine)
   rather than living in normal document flow inside a single translateY'd
   container — a row that stays inside the scroll window keeps its DOM
   position/content untouched across scrolls, so only rows actually entering
   the window get repositioned + refilled. position/left/width are set
   inline by the engine at row-creation time; only the shared per-row look
   (grid template, height, borders) lives here. */
.ss-vrow {
    display: grid;
    height: var(--ss-row-h);
    box-sizing: border-box;
}
/* Every grid child (label + day cells) shares the base cell frame. */
.ss-vrow > div {
    border: 1px solid var(--border-light);
    border-top: none;
    box-sizing: border-box;
    overflow: hidden;
    text-align: center;
    font-size: 9px;
    line-height: calc(var(--ss-row-h) - 5px);
    white-space: nowrap;
}
/* Grid tracks control the label width; neutralise the table-era fixed widths
   so the sticky label fills exactly its column (700px / 240px compact). */
#ss-head .ss-head-label,
.ss-vrow > .project-label {
    width: auto;
    min-width: 0;
    max-width: none;
}
.ss-vrow > .project-label {
    position: sticky;
    left: 0;
    z-index: 11;
    /* Own compositor layer: during fast leftward scrolls the freshly
     * exposed left edge (where these sticky labels sit) can outrun tile
     * rasterization and flash blank tiles OVER the labels. Keeping the
     * labels pre-rasterized on their own layer exempts them from that
     * checkerboarding. ~50 layers x 700x24px — negligible memory. */
    will-change: transform;
    background: var(--bg-alt, #f9fafb);
    text-align: left;
    font-size: 11px;
    line-height: normal;
    padding: 0 8px;
    display: flex;
    align-items: center;
    border-right: 2px solid var(--border);
    box-shadow: 2px 0 4px -2px rgba(0, 0, 0, 0.08);
}
.ss-vrow.ss-vrow-crew > .project-label,
.ss-vrow.ss-vrow-addrole > .project-label {
    background: #f8fafc;
    font-size: 10px;
}
.ss-vrow-crew .ss-crew-label-inner,
.ss-add-role-label { display: flex; align-items: center; gap: 4px; width: 100%; }

/* Row tints on div day cells (table variants used td/th selectors). */
.ss-vrow > .ss-weekend { background-color: #eff6ff; }
.ss-vrow > .ss-today { background-color: rgba(249, 115, 22, 0.08); }
#ss-head .ss-today { background-color: rgba(249, 115, 22, 0.15); color: #c2410c; }
.ss-vrow > .ss-day-cell,
.ss-vrow > .ss-crew-cell { cursor: cell; }
/* mine / watched row indicators */
.ss-vrow.ss-row-mine > .project-label { border-left: 3px solid #3B82F6; }
.ss-vrow.ss-row-watched > .project-label { border-left: 3px solid #f59e0b; }
.ss-vrow:hover > .project-label { background: #fefce8; z-index: 15; }
/* Whole-row hover highlight. The sticky label AND every day cell are grid
   children of one .ss-vrow, so a pure :hover lights the whole row no matter
   which part the cursor is over — no JS, and it survives row recycling (a
   pseudo-class isn't node state the fill cache can wipe). Day cells carry
   their own OPAQUE backgrounds (weekend/today tints, milestone fills), so a
   plain row `background` would only show in the gaps; instead we paint an
   inset box-shadow on each child — a full-bleed translucent yellow fill (huge
   spread so it covers the 700px label too) plus an amber line top+bottom.
   box-shadow paints over the cell's own background, so the tint reads across
   the entire row. Applied via box-shadow only (no filter/transform on an
   ancestor of the sticky label), so the frozen label column keeps sticking. */
.ss-vrow:hover > div {
    box-shadow: inset 0 1px 0 rgba(202, 138, 4, 0.55),
                inset 0 -1px 0 rgba(202, 138, 4, 0.55),
                inset 0 0 0 1000px rgba(250, 204, 21, 0.14);
}

.ss-float-form {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 8px;
    background: #eff6ff;
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}


/* ---- Crew Schedule ---- */

.crew-date-nav {
    display: flex;
    flex-wrap: wrap;
    gap: 1px 0;
    padding: 4px 6px;
    margin-bottom: 4px;
    background: var(--bg-alt);
    border: 1px solid var(--border);
    border-radius: 6px;
}

.crew-date-nav-link {
    font-size: 11px;
    padding: 2px 5px;
    color: var(--primary);
    text-decoration: none;
    border-radius: 3px;
    white-space: nowrap;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    line-height: 1.1;
}

.crew-date-nav-type {
    font-size: 7px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-muted);
    max-width: 32px;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1;
}
/* Non-working RW property date label in the nav (Start/Pick/Stop) — italic and
   fainter so it reads as reference, distinct from working day-type labels. */
.crew-date-nav-type.crew-date-nav-prop {
    font-style: italic;
    text-transform: none;
    opacity: 0.75;
}

.crew-date-nav-link:hover {
    background: var(--primary);
    color: #fff;
}

.crew-date-nav-link.dark {
    color: var(--text-muted);
}

.crew-date-nav-link.today {
    font-weight: 700;
    border-bottom: 2px solid rgb(234, 88, 12);
    border-radius: 0;
}

.crew-date-nav-link.nav-active {
    background: var(--primary);
    color: #fff;
    font-weight: 700;
}

/* Bottom-panel date nav: same look as top, but doesn't navigate — clicks
   toggle the shared `selectedDates` set (handleHeaderClick). The .selected
   class is applied by applySelectionClass() in lockstep with the timeline
   day-headers, so picking days in either place keeps both in sync. */
.crew-date-nav-bottom { margin: 4px 6px; }
.crew-bottom-date-link.selected {
    background: #c7d2fe;
    color: #1e293b;
    font-weight: 700;
}

/* Meal rows in the bottom-panel task lists (Day's Tasks + All Tasks).
   Greyed-out "unavailable time" treatment — matches the spreadsheet
   meal row style. Bold so the row reads as a fixed slot. */
.assigned-task-row.assigned-task-meal {
    background: #e5e7eb;
    border-left: 2px solid #9ca3af;
    color: #6b7280;
    font-weight: 600;
}
.assigned-task-row.assigned-task-meal:hover {
    background: #d1d5db;
}

/* ---------------------------------------------------------------
   Spreadsheet view (production schedule). Lives between the
   timeline and the bottom grid. Collapsible.
   --------------------------------------------------------------- */
.sheet-view-wrap {
    margin: 12px 0;
    border: 1px solid var(--border, #e5e7eb);
    border-radius: 6px;
    background: #fff;
}
.sheet-view-toolbar {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 6px 10px;
    border-bottom: 1px solid var(--border-light, #e5e7eb);
    background: #f9fafb;
    border-radius: 6px 6px 0 0;
}
.sheet-view-collapse {
    background: transparent;
    border: none;
    cursor: pointer;
    font-size: 13px;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.sheet-view-title { font-size: 13px; }
.sheet-view-body { padding: 8px 10px; }
.sheet-day { margin-bottom: 18px; }
.sheet-day-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
    border-bottom: 1px solid var(--border-light, #e5e7eb);
}
.sheet-day-meta {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 12px;
    margin: 6px 0 8px;
}
/* EOD goals textarea: shrink to one row by default — `textarea.form-control`
 * sets min-height:80px globally, which we explicitly override here. The
 * resize handle stays so the user can grow it for longer goal lists. */
textarea.sheet-eod-goals {
    min-height: 0;
}
.sheet-meta-cell label {
    display: block;
    font-size: 10px;
    font-weight: 600;
    color: var(--text-muted, #6b7280);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.sheet-heq-rollup {
    padding: 4px 6px;
    border: 1px solid var(--border-light, #e5e7eb);
    border-radius: 3px;
    font-size: 12px;
    background: #fafafa;
    min-height: 28px;
}
.sheet-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
    /* Fixed layout + explicit per-column widths below so every day's
       table aligns to the same grid. Without this, each day sizes its
       own columns from its content. */
    table-layout: fixed;
}
/* Column widths (kept tight for the right-side columns; the wider
   Description / Name flex with the remaining space). */
.sheet-table col.sheet-col-w-handle { width: 18px; }
.sheet-table col.sheet-col-w-sel { width: 24px; }
.sheet-table col.sheet-col-w-date { width: 60px; }
.sheet-table col.sheet-col-w-time { width: 70px; }
.sheet-table col.sheet-col-w-dur { width: 60px; }
.sheet-table col.sheet-col-w-team { width: 110px; }
.sheet-table col.sheet-col-w-leads { width: 40px; }
.sheet-table col.sheet-col-w-name { width: 160px; }
.sheet-table col.sheet-col-w-desc { width: 220px; }
.sheet-table col.sheet-col-w-loc { width: 100px; }
.sheet-table col.sheet-col-w-vendor { width: 100px; }
.sheet-table col.sheet-col-w-contact { width: 100px; }
.sheet-table col.sheet-col-w-heq { width: 110px; }
.sheet-table col.sheet-col-w-sh { width: 110px; }
.sheet-table col.sheet-col-w-actions { width: 28px; }
.sheet-table th, .sheet-table td {
    border: 1px solid #9ca3af;
    padding: 2px 4px;
    vertical-align: middle;
}
.sheet-table th {
    background: #f3f4f6;
    text-align: left;
    font-weight: 600;
    font-size: 11px;
    white-space: nowrap;
}
.sheet-col-sel { width: 22px; text-align: center; }
.sheet-col-handle { width: 18px; text-align: center; padding: 0 !important; }
.sheet-drag-handle {
    cursor: grab;
    color: #9ca3af;
    font-size: 12px;
    line-height: 1;
    user-select: none;
    padding: 4px 2px;
    display: inline-block;
}
.sheet-drag-handle:hover { color: #4338ca; background: #eef2ff; border-radius: 3px; }
.sheet-drag-handle:active { cursor: grabbing; }
.sheet-row-dragging { opacity: 0.35; }
.sheet-row-loading td {
    border-color: #ca8a04;
}
.sheet-row-error td {
    border-color: #dc2626;
}
.sheet-row-success td {
    animation: sheet-row-success-fade 2500ms forwards;
}
@keyframes sheet-row-success-fade {
    0%, 80% {
        border-color: #16a34a;
    }
    100% {
        border-color: #9ca3af;
    }
}
.sheet-row-drop-target {
    box-shadow: inset 0 2px 0 #6366f1;
}
.sheet-row-drop-ghost {
    background: #eef2ff !important;
    color: #4338ca;
    opacity: 0.85;
    box-shadow: inset 0 0 0 2px #6366f1;
}
.sheet-row-drop-ghost td {
    border-top: 1px dashed #6366f1 !important;
    border-bottom: 1px dashed #6366f1 !important;
}
.sheet-row-drop-ghost input,
.sheet-row-drop-ghost select,
.sheet-row-drop-ghost textarea {
    color: #4338ca;
    background: transparent;
}
.sheet-row-drop-ghost .sheet-drag-handle {
    visibility: hidden;
}
/* Affected by an in-progress cascade preview: bump the time text indigo
   so the user sees what's about to change. The original text is kept in
   data-original so we can restore on dragleave. */
.sheet-row-cascade-preview .sheet-cell-time,
.sheet-row-cascade-preview td.sheet-col-date,
.sheet-row-cascade-preview td:nth-child(5) {
    color: #4338ca;
    font-weight: 700;
}
.sheet-cell-input {
    border: none;
    background: transparent;
    width: 100%;
    font: inherit;
    padding: 2px 4px;
    box-sizing: border-box;
}
.sheet-cell-input:focus {
    outline: 2px solid #c7d2fe;
    outline-offset: -2px;
    background: #fff;
}
.sheet-cell-readonly { color: var(--text-muted, #6b7280); }
/* Trucking rows — direction-tinted background. Pickup leans purple,
 * delivery / both leans green. Bold like meals so the row reads as
 * a fixed slot rather than work. */
.sheet-row-trucking-delivery,
.sheet-row-trucking-delivery td {
    background: #d1fae5 !important;   /* light green */
    font-weight: 600;
}
.sheet-row-trucking-pickup,
.sheet-row-trucking-pickup td {
    background: #ede9fe !important;   /* light purple */
    font-weight: 600;
}
.sheet-row-trucking .sheet-cell-input {
    background: transparent;
    font-weight: 600;
}

/* Meal rows render as "unavailable" time — greyed BG, muted text, and
 * bold so the row reads as a fixed slot rather than a regular work
 * task. Applies in every mode (Color up team-tinting is suppressed
 * for meals on the JS side). */
.sheet-row-meal,
.sheet-row-meal td {
    background: #e5e7eb !important;
    color: #6b7280;
    font-weight: 600;
}
.sheet-row-meal .sheet-cell-input {
    background: transparent;
    color: #6b7280;
    font-weight: 600;
}
.sheet-row-meal .sheet-cell-readonly {
    color: #9ca3af;
}
.sheet-row-selected {
    background: #eef2ff;
    box-shadow: inset 3px 0 0 #6366f1, inset -1px 0 0 #6366f1;
}
.sheet-row-selected td {
    border-top-color: #6366f1;
    border-bottom-color: #6366f1;
}
.sheet-row-note { background: #f0fdf4; }
.sheet-col-date {
    font-variant-numeric: tabular-nums;
    color: var(--text-muted, #6b7280);
    white-space: nowrap;
}
/* End cell turns red when the END time crosses past midnight. Inherits
   the readonly muted color otherwise. */
.sheet-cell-end-overnight .sheet-cell-readonly {
    color: #dc2626;
    font-weight: 700;
}

/* Overnight tasks: same shift_day, but start (or end) lands on the next
   calendar day. Diagonal stripe + "+" suffix on the value (added in JS). */
.sheet-cell-overnight {
    background-image: repeating-linear-gradient(
        45deg,
        rgba(99,102,241,0.08),
        rgba(99,102,241,0.08) 4px,
        rgba(99,102,241,0.18) 4px,
        rgba(99,102,241,0.18) 8px
    );
    color: #4338ca;
    font-weight: 600;
}

/* Extend Timeline mode: each day's grid grows down to fit overnight tasks
   in-place, so we hide the "wraps to next day" / "from previous day" labels
   and grow the track height by the per-day overflow (set as a CSS variable
   on each track by JS from data-overflow-minutes). */
body.crew-extend-timeline .crew-timeline-continues-label,
body.crew-extend-timeline .crew-overflow-gutter,
body.crew-extend-timeline .crew-overflow-gutter-label,
body.crew-extend-timeline .crew-overflow-gutter-stripe {
    display: none !important;
}
/* In extend mode the next day's content shouldn't reserve gutter space —
   the previous day already shows the overnight portion in-place. */
body.crew-extend-timeline .has-overflow-gutter .crew-timeline-generic,
body.crew-extend-timeline .has-overflow-gutter .crew-team-labels,
body.crew-extend-timeline .has-overflow-gutter .crew-timeline-track {
    margin-left: 0 !important;
}
/* The day column itself is sized to (col_units + 1) * 100px to leave room
   for the inbound gutter. In extend mode the gutter is hidden, so drop the
   extra unit — otherwise the team-labels grid (col_units columns of 1fr)
   stretches across the inflated width and labels drift right of their
   timeline lanes. */
body.crew-extend-timeline .crew-day-column.crew-day-has-inbound {
    min-width: max(200px, calc(var(--col-units, 2) * 100px)) !important;
    width: max(200px, calc(var(--col-units, 2) * 100px)) !important;
}
body.crew-extend-timeline .crew-timeline-track {
    height: calc((1440 + var(--day-overflow-min, 0)) * var(--ppm) * 1px);
}
body.crew-extend-timeline .crew-ruler-track {
    /* Match the tallest day so the ruler stays aligned with extended cols. */
    height: calc((1440 + var(--max-overflow-min, 0)) * var(--ppm) * 1px);
}
.sheet-row-note .sheet-cell-note-body { font-style: italic; }
.sheet-cell-note-label {
    font-weight: 600;
    text-align: left;
    white-space: nowrap;
    color: #4338ca;
}
/* Floating insert buttons that appear to the LEFT of each row on hover.
 * `position: relative` belongs on the handle cell, not the <tr>; setting
 * it on the row breaks table border-collapse rendering (top/bottom edges
 * disappear, especially noticeable on meal rows). */
.sheet-row-task .sheet-col-handle,
.sheet-row-note .sheet-col-handle { position: relative; }
.sheet-row-insert-btn {
    position: absolute;
    left: -28px;
    width: 22px;
    height: 18px;
    background: #eef2ff;
    color: #4338ca;
    border: 1px solid #4338ca;
    border-radius: 3px;
    cursor: pointer;
    opacity: 0;
    transition: opacity 120ms ease;
    font-size: 14px;
    font-weight: 700;
    line-height: 1;
    padding: 0;
    z-index: 5;
}
.sheet-row-insert-btn:hover {
    background: #c7d2fe;
}
.sheet-row-insert-above { top: -10px; }
.sheet-row-insert-below { bottom: -10px; display: none; }
/* Only the last task/note row of each day gets a below button so the
 * gap between every pair of rows has exactly one insert point. */
.sheet-row-task:last-of-type .sheet-row-insert-below,
.sheet-row-note:last-of-type .sheet-row-insert-below {
    display: block;
}
.sheet-row-task:hover .sheet-row-insert-btn,
.sheet-row-note:hover .sheet-row-insert-btn,
.sheet-row-insert-btn:hover {
    opacity: 1;
}
.sheet-row-draft td {
    background: #eef2ff;
}
.sheet-team-popover {
    background: #fff;
    border: 1px solid #4338ca;
    border-radius: 4px;
    box-shadow: 0 4px 14px rgba(0,0,0,0.15);
    padding: 4px 0;
    min-width: 180px;
    max-height: 280px;
    overflow-y: auto;
    font-size: 12px;
}
.sheet-team-pop-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    cursor: pointer;
    user-select: none;
}
.sheet-team-pop-row:hover {
    background: #eef2ff;
}
.sheet-team-pop-create {
    color: #4338ca;
    font-weight: 600;
    border-top: 1px dashed #c7d2fe;
}
.sheet-row-draft td:first-child {
    border-left: 2px solid #6366f1;
}
.sheet-row-draft .sheet-col-handle {
    color: #4338ca;
}
.sheet-row-note.sheet-row-goal {
    background: #fefce8;
    border-left: 3px solid #ca8a04;
}
.sheet-bulk-bar {
    position: sticky;
    bottom: 0;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    background: #1e293b;
    color: #fff;
    border-top: 1px solid var(--border, #e5e7eb);
    border-radius: 0 0 6px 6px;
}
.sheet-bulk-bar .form-control { color: #1e293b; }
.sheet-bulk-bar .btn { background: #fff; color: #1e293b; }
.sheet-bulk-bar .btn-danger { background: #dc2626; color: #fff; }

.crew-snap-select {
    margin-left: auto;
    font-size: 11px;
    padding: 2px 4px;
    border: 1px solid var(--border);
    border-radius: 3px;
    background: #fff;
    align-self: center;
    flex-shrink: 0;
}

.crew-grid-with-pool {
    display: flex;
    gap: 0;
    align-items: stretch;
}

.crew-grid-with-pool > .crew-grid {
    flex: 1;
    min-width: 0;
}

.crew-pool-sidebar {
    flex-shrink: 0;
    width: 200px;
    min-width: 200px;
    background: #fff;
    border: 1px solid var(--border);
    border-left: none;
    border-radius: 0 8px 8px 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.crew-tools-sidebar {
    flex-shrink: 0;
    width: 280px;
    min-width: 280px;
    background: #fff;
    border: 1px solid var(--border);
    border-left: none;
    border-radius: 0;
    overflow-y: auto;
    padding: 10px;
    font-size: 12px;
}
.crew-tools-sidebar + .crew-pool-sidebar {
    /* hide pool sidebar when tools panel is open */
}
.crew-tools-sidebar .tool-card {
    border: 1px solid var(--border);
    border-top: none;
    border-radius: 0 0 6px 6px;
    padding: 10px;
    background: var(--bg);
}
.crew-tools-sidebar .tool-day-pill {
    display: inline-block;
    font-size: 10px;
    font-weight: 600;
    padding: 2px 8px;
    border-radius: 10px;
    background: var(--primary);
    color: #fff;
}
.crew-tools-sidebar .tool-option-group {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.crew-tools-sidebar .tool-option-row {
    display: flex;
    align-items: center;
    gap: 6px;
}
.crew-tools-sidebar input[type="number"]::-webkit-inner-spin-button,
.crew-tools-sidebar input[type="number"]::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
.crew-tools-sidebar .tool-option-label {
    font-weight: 600;
    font-size: 10px;
    color: var(--text-muted);
    min-width: 48px;
    flex-shrink: 0;
}
.crew-tools-sidebar .tool-section-label {
    font-weight: 600;
    font-size: 11px;
    color: var(--text-muted);
    margin-bottom: 4px;
}
.crew-tools-sidebar .tool-summary {
    font-size: 11px;
    color: var(--text-muted);
    margin-bottom: 6px;
    max-height: 120px;
    overflow-y: auto;
}

.crew-pool-sidebar .crew-panel-header {
    padding: 8px 10px;
}

.crew-pool-sidebar .crew-panel-header h3 {
    font-size: 12px;
}

.crew-pool-create-form {
    padding: 6px 8px;
    border-bottom: 1px solid var(--border-light);
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.crew-pool-create-form .form-control {
    font-size: 11px;
    padding: 3px 6px;
    margin: 0;
}

.crew-pool-edit-panel {
    padding: 8px;
    border-bottom: 1px solid var(--border);
    background: var(--bg-alt);
}

.crew-pool-edit-panel .form-control {
    font-size: 11px;
    padding: 3px 6px;
    margin: 0;
}
.crew-time-nudge {
    padding: 2px 6px;
    font-size: 13px;
    font-weight: 700;
    line-height: 1;
    min-width: 24px;
}

.crew-task-edit-column {
    width: 200px;
    min-width: 200px;
    padding: 8px;
    border-left: 1px solid var(--border);
    background: var(--bg-alt);
}
.crew-task-edit-column .form-control {
    font-size: 11px;
    padding: 3px 6px;
    margin: 0;
}
.crew-task-edit-column.disabled {
    opacity: 0.5;
    pointer-events: none;
}

.crew-pool-list {
    flex: 1;
    overflow-y: auto;
    padding: 6px 8px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-height: 0;
}

.crew-grid {
    display: flex;
    overflow-x: auto;
    gap: 0;
    border: 1px solid var(--border);
    border-radius: 8px;
}

.crew-grid-with-pool > .crew-grid {
    border-radius: 8px 0 0 8px;
}

.crew-day-column {
    min-width: 200px;
    border-right: 1px solid var(--border);
    flex-shrink: 0;
}

.crew-range-expand {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 12px 2px 4px;
    flex-shrink: 0;
    min-width: 40px;
    width: 40px;
    background: var(--bg-alt);
    border-right: 1px solid var(--border);
}

.crew-range-expand:last-child {
    border-right: none;
    border-left: 1px solid var(--border);
}

/* Day columns are nested one-per-project inside a .crew-date-group. The very
   last real column of the grid drops its right border (as before Chunk 2);
   the last column inside a red-bordered multi group drops it too so it
   doesn't double up against the group's own border. */
.crew-date-group:last-child > .crew-day-column:last-child,
.crew-date-group--multi > .crew-day-column:last-child {
    border-right: none;
}

/* One date's columns, grouped so a date reads as a unit. Groups are flex
   containers; they in turn flex within .crew-grid because #crewGridBody is
   display:contents. Single-column (single-project) groups carry no border and
   look exactly like the pre-Chunk-2 flat column list. */
.crew-date-group {
    display: flex;
    flex-shrink: 0;
}
.crew-date-group--multi {
    border: 2px solid var(--danger, #dc2626);
    border-radius: 6px;
    margin: 0 4px;
    /* No vertical padding so the grouped columns' timeline tracks stay aligned
       with the sticky ruler; the 2px border offset is negligible. */
    padding: 0 1px;
    background: color-mix(in srgb, var(--danger, #dc2626) 4%, transparent);
}

.crew-day-header {
    padding: 8px;
    background: var(--bg-alt);
    border-bottom: 1px solid var(--border);
    font-size: 12px;
    font-weight: 600;
    text-align: center;
}

.crew-day-column.weekend .crew-day-header {
    background: #dbeafe;
}

.crew-day-header-clickable {
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 4px;
    user-select: none;
}

/* Read-only header note for a NON-working RW property date (Start/Pick/Stop) —
   e.g. a dark day reading "(Warehouse Start)". Distinct from the editable
   date-type input so it reads as reference text, not something you edit/save. */
/* Permanent single-line sub-row under the date. ALWAYS present (blank on days
   with no property date) and locked to exactly ONE line via a fixed height +
   nowrap, so every day header is identical height and the timelines stay
   aligned across all columns. */
.day-property-note {
    font-size: 10px;
    font-style: italic;
    color: #6b7280;
    line-height: 1.2;
    height: 1.2em;              /* reserve one line even when empty */
    margin-top: 1px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.crew-dark-day .crew-day-header .day-property-note { color: #334155; }
/* Interim badge for a rare 2nd working type on one calendar day — inline in the
   sub-row so it never adds height. */
.day-extra-working {
    font-weight: 600;
    color: var(--danger);
    font-style: normal;
}

.crew-day-header:has(.crew-day-header-clickable:hover) {
    background: rgba(59, 130, 246, 0.08);
}

.crew-day-header.selected {
    outline: 2px solid var(--primary);
    outline-offset: -2px;
    background: rgba(59, 130, 246, 0.15);
}

.crew-day-column.sunday-col {
    border-left: 2px solid #94a3b8;
}

/* Dark day shading is scoped to the header + timeline area only — the
   space where a roster would live (below the timeline) stays plain white
   so dark-day columns don't visually extend past the timeline grid. */
.crew-dark-day { background: transparent; }
.crew-dark-day .crew-day-header {
    background: #cbd5e1;
    color: #1f2937;
}
.crew-dark-day .crew-day-header .crew-day-desc-input { color: #374151; }
.crew-dark-day .crew-day-header .crew-day-notes-input { color: #4b5563; }
.crew-dark-day .crew-timeline-wrap {
    background: #e5e7eb;
}

.crew-datetype-input {
    border: 1px solid transparent;
    background: transparent;
    font-size: 11px;
    font-weight: 600;
    text-align: center;
    padding: 2px 4px;
    border-radius: 3px;
    width: 100%;
    margin-top: 2px;
}

.crew-datetype-input:hover {
    border-color: var(--border-light);
    background: #fff;
}

.crew-datetype-input:focus {
    outline: none;
    border-color: var(--primary);
    background: #fff;
}

.crew-day-header {
    position: relative;
}

.crew-fill-handle {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: ew-resize;
    opacity: 0;
    transition: opacity 0.1s;
    z-index: 5;
    color: var(--primary);
    font-size: 18px;
    font-weight: 900;
    line-height: 1;
    user-select: none;
    background: transparent;
}

.crew-fill-handle.left { left: -14px; }
.crew-fill-handle.right { right: -14px; }

/* Hide drag handles on timeline edges so expand-range buttons stay accessible */
.crew-day-column.crew-edge-first .crew-fill-handle.left,
.crew-day-column.crew-edge-last .crew-fill-handle.right {
    display: none !important;
}
/* Fallback: also hide via first/last-child inside the grid body */
#crewGridBody > .crew-day-column:first-child .crew-fill-handle.left,
#crewGridBody > .crew-day-column:last-child .crew-fill-handle.right {
    display: none !important;
}

.crew-fill-handle:hover,
.crew-fill-handle.dragging {
    opacity: 1;
}

.crew-datetype-input.crew-fill-ghost {
    background: #fef3c7 !important;
    border-color: #f59e0b !important;
    color: #92400e !important;
    font-style: italic;
}

body.crew-filling,
body.crew-filling * {
    cursor: crosshair !important;
    user-select: none;
}

.crew-bottom-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    margin-top: 16px;
}

.crew-tasks-panel,
.crew-roster-panel {
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 6px;
    overflow: hidden;
}

.crew-panel-header {
    padding: 10px 12px;
    background: var(--bg-alt);
    border-bottom: 1px solid var(--border);
}

.crew-panel-header h3 {
    font-size: 14px;
    font-weight: 700;
    margin: 0;
}

.crew-panel-section + .crew-panel-section {
    border-top: 1px solid var(--border-light);
}

/* New Task + Edit Task shown side-by-side. Stack on narrow screens. */
.crew-task-forms-row {
    display: flex;
    flex-wrap: wrap;
    border-top: 1px solid var(--border-light);
}
.crew-task-form-col {
    flex: 1 1 320px;
    border-top: none !important;
}
.crew-task-form-col + .crew-task-form-col {
    border-left: 1px solid var(--border-light);
}
@media (max-width: 700px) {
    .crew-task-form-col + .crew-task-form-col {
        border-left: none;
        border-top: 1px solid var(--border-light);
    }
}
.crew-task-form-inline {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
}
.crew-task-form-inline .form-control { margin: 0; }

/* Unassigned pool in sidebar: stack vertically. */
/* Unassigned-task pool: pills laid out as wrapping inline flow rather
 * than stacked block cards. Each .crew-task-block inside #taskPool
 * becomes a rounded chip; container wraps to as many rows as needed.
 * Explicitly sets flex-direction: row to override .crew-pool-list's
 * column (the same element carries both classes). */
#taskPool {
    min-height: 32px;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 4px;
    padding: 6px;
    align-content: flex-start;
}
.crew-pool-sidebar #taskPool .crew-task-block {
    flex: 0 0 auto;
    width: auto;
    padding: 3px 8px;
    font-size: 11px;
    border-radius: 12px;
    white-space: nowrap;
}

/* Tabbed tasks panel inside the crew schedule. */
.crew-task-tabs {
    padding: 4px 8px 0;
    border-bottom: 1px solid var(--border-light);
    display: flex;
    gap: 4px;
}
.crew-task-tabs .tab {
    padding: 4px 10px;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    cursor: pointer;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
}
.crew-task-tabs .tab.active {
    color: var(--primary);
    border-bottom-color: var(--primary);
}

/* Day's Tasks list rows. */
.assigned-day-group + .assigned-day-group { margin-top: 10px; }
.assigned-day-header {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    margin-bottom: 4px;
}
.assigned-task-row {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 3px 6px;
    margin: 0 -6px;
    font-size: 12px;
    cursor: pointer;
    border-radius: 3px;
    user-select: none;
}
.assigned-task-row:hover { background: #f1f5f9; }
.assigned-task-row.task-selected {
    background: #bfdbfe;
    outline: 1px solid var(--primary);
}
.assigned-task-time {
    font-weight: 700;
    font-size: 11px;
    min-width: 66px;
    color: var(--primary);
}
.assigned-task-team {
    flex: 0 0 auto;
    font-size: 9px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #475569;
    background: #e2e8f0;
    padding: 1px 5px;
    border-radius: 3px;
}
.assigned-task-team:empty { display: none; }
.assigned-task-desc { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.assigned-task-dur { flex: 0 0 auto; }

/* When no task is selected, the Edit column stays in the flex layout
   (reserving its width) but its content is invisible so the other
   columns don't jump around on select/deselect. */
.crew-task-form-col.edit-inactive .crew-panel-body {
    opacity: 0.4;
    pointer-events: none;
}
.crew-task-form-col.edit-inactive .crew-panel-body .form-control,
.crew-task-form-col.edit-inactive .crew-panel-body .btn {
    cursor: default;
}

.crew-panel-subhead {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    margin: 0;
    padding: 8px 12px 4px;
}

.crew-panel-body {
    padding: 8px 12px 12px;
    min-height: 40px;
}

.crew-drag-source {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.crew-roster-chip {
    padding: 4px 10px;
    background: var(--bg-alt);
    border: 1px solid var(--border);
    border-radius: 12px;
    font-size: 12px;
    cursor: grab;
    user-select: none;
}

.crew-roster-chip:active {
    cursor: grabbing;
}

.crew-roster-chip-new {
    background: #ecfdf5;
    border-color: #10b981;
    color: #065f46;
    cursor: pointer;
}

.crew-roster-chip-new:hover {
    background: #d1fae5;
}

.crew-role-input {
    width: 100%;
    border: 1px solid transparent;
    background: transparent;
    font-size: 11px;
    padding: 1px 4px;
    border-radius: 3px;
    margin-top: 2px;
}

.crew-role-input:hover { border-color: var(--border-light); background: #fff; }
.crew-role-input:focus { outline: none; border-color: var(--primary); background: #fff; }

/* Per-day roster block (replaces old CREW block in day columns). */
.crew-roster-block {
    padding: 4px 8px;
    border-bottom: 1px solid var(--border);
}
.crew-roster-row.crew-roster-no-team {
    background: #fef3c7;
    border-left: 3px solid #f59e0b;
    padding-left: 4px;
    border-radius: 2px;
}
.crew-roster-row {
    cursor: pointer;
    user-select: none;
    display: grid;
    grid-template-columns: 60px 1fr auto 20px;
    gap: 2px;
    align-items: center;
}
.crew-roster-col {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.crew-roster-name-col .crew-roster-crew-input {
    width: 100%;
}
.crew-roster-team-tag {
    font-size: 8px;
    color: var(--text-muted);
    background: var(--bg-alt);
    padding: 0 3px;
    border-radius: 2px;
    white-space: nowrap;
    text-align: right;
}
.crew-roster-team-tag:empty {
    display: none;
}
.crew-roster-remove-col {
    text-align: center;
}
.crew-roster-row.roster-selected {
    background: #dbeafe;
    outline: 1px solid #2563eb;
    outline-offset: -1px;
    border-radius: 2px;
}
.crew-roster-actions {
    display: flex;
    gap: 4px;
    align-items: center;
    margin-top: 4px;
}
.crew-roster-team-assign {
    font-size: 10px;
    padding: 2px 4px;
    border: 1px solid var(--border);
    border-radius: 3px;
    background: #fff;
}
.crew-roster-row {
    padding: 1px 0;
    font-size: 11px;
}
.crew-roster-role {
    font-weight: 700;
    white-space: nowrap;
    min-width: 60px;
    cursor: text;
}
input.crew-roster-role {
    width: 70px;
    font-size: 10px;
    font-weight: 700;
    padding: 0 2px;
    border: 1px solid var(--border);
    border-radius: 3px;
}
.crew-roster-crew-input {
    flex: 1;
    border: 1px solid transparent;
    background: transparent;
    font-size: 11px;
    padding: 1px 4px;
    border-radius: 3px;
    min-width: 60px;
}
.crew-roster-crew-input:hover { border-color: var(--border-light); background: #fff; }
.crew-roster-crew-input:focus { outline: none; border-color: var(--primary); background: #fff; }
.crew-roster-crew-input::placeholder { color: #94a3b8; font-style: italic; }

.crew-roster-remove {
    font-size: 10px;
    padding: 0 3px;
    line-height: 1;
    opacity: 0;
    transition: opacity 0.1s;
    color: #991b1b;
}
.crew-roster-row:hover .crew-roster-remove { opacity: 0.7; }
.crew-roster-remove:hover { opacity: 1 !important; }

.crew-roster-time {
    display: inline-block;
    padding: 0 3px;
    border-radius: 2px;
    font-size: 10px;
}
.crew-roster-time-lobby_call {
    background: #e0e7ff;
    color: #3730a3;
    font-weight: 600;
}
.crew-roster-time-lobby_call::before {
    content: 'LC ';
}

/* Project Roles list in the bottom panel. */
.crew-project-role-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 3px 0;
    font-size: 12px;
    flex-wrap: wrap;
}
.crew-role-status-input,
.crew-role-notes-input {
    flex: 1;
    min-width: 60px;
    font-size: 11px;
    padding: 1px 4px;
    border: 1px solid var(--border-light);
    border-radius: 3px;
    background: var(--bg-alt);
}
.crew-role-status-input:focus,
.crew-role-notes-input:focus {
    border-color: var(--border);
    background: #fff;
    outline: none;
}
.crew-project-role-name {
    font-weight: 700;
    min-width: 80px;
    cursor: text;
}
input.crew-project-role-name {
    width: 90px;
    font-size: 12px;
    font-weight: 700;
    padding: 0 3px;
    border: 1px solid var(--border);
    border-radius: 3px;
}

/* Team popover */

.crew-team-popover {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 8px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.15);
    min-width: 220px;
    max-width: 300px;
}

.crew-team-pop-header {
    padding: 8px 10px;
    border-bottom: 1px solid var(--border-light);
}

.crew-team-pop-name {
    width: 100%;
    border: 1px solid var(--border-light);
    border-radius: 4px;
    padding: 4px 8px;
    font-size: 13px;
    font-weight: 600;
    outline: none;
}

.crew-team-pop-name:focus {
    border-color: var(--primary);
}

.crew-team-pop-roles {
    padding: 6px 0;
    max-height: 250px;
    overflow-y: auto;
}

.crew-team-pop-role {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    cursor: pointer;
    font-size: 12px;
    transition: background 0.1s;
}

.crew-team-pop-role:hover {
    background: var(--bg-hover);
}

.crew-team-label.team-pop-selected {
    background: #dbeafe;
    outline: 2px solid #2563eb;
    outline-offset: -2px;
}
.crew-team-labels {
    position: relative;
}
.crew-team-paste-btn {
    position: absolute;
    right: 2px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 11px;
    line-height: 1;
    padding: 1px 3px;
    background: transparent;
    border: none;
    cursor: pointer;
    opacity: 0.6;
}
.crew-team-paste-btn:hover {
    opacity: 1;
}

.crew-add-team-btn,
.crew-roster-add-btn,
.crew-move-btn {
    display: block;
    width: 100%;
    margin-top: 4px;
    padding: 2px 4px;
    font-size: 10px;
    background: transparent;
    border: 1px dashed var(--border);
    border-radius: 3px;
    color: var(--text-muted);
    cursor: pointer;
}
.crew-add-team-btn:hover,
.crew-roster-add-btn:hover,
.crew-move-btn:hover {
    background: var(--bg-hover);
    color: var(--text);
}
/* Move-day mode: click Move on a day, then click a destination day column. */
body.crew-move-mode .crew-day-header-clickable { cursor: crosshair; }
body.crew-move-mode .crew-day-column:hover .crew-day-header {
    outline: 2px dashed var(--primary);
    outline-offset: -2px;
    background: rgba(37, 99, 235, 0.10);
}
.crew-move-btn.active, body.crew-move-mode .crew-move-btn { border-style: solid; }
.crew-move-hint {
    position: fixed;
    bottom: 16px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 2000;
    background: #2563eb;
    color: #fff;
    padding: 7px 16px;
    border-radius: 6px;
    font-size: 12px;
    cursor: pointer;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.35);
}
.crew-roster-add-picker {
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 4px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    min-width: 200px;
    max-height: 400px;
    overflow-y: auto;
}

/* ---- Searchable project picker ---- */
.searchable-project-picker {
    position: relative;
    display: inline-block;
}
.searchable-project-input {
    width: 320px;
}
.nav-project-input {
    width: 200px;
    font-size: 12px;
    padding: 3px 8px;
    height: 28px;
}
.top-nav .searchable-project-menu {
    z-index: 200;
}
.searchable-project-menu {
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 100%;
    width: max-content;
    max-width: 480px;
    max-height: 320px;
    overflow-y: auto;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 4px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    z-index: 100;
    display: none;
    margin-top: 2px;
}
.searchable-project-picker.open .searchable-project-menu {
    display: block;
}
.searchable-project-menu:focus {
    /* Focus can land here via keyboard Tab (toggling between the input and
       the menu); the active-item highlight below is the visual indicator,
       so suppress the browser's default focus ring on the container. */
    outline: none;
}
.searchable-project-item {
    padding: 6px 14px 6px 10px;
    cursor: pointer;
    font-size: 12px;
    white-space: nowrap;
}
.searchable-project-item:hover,
.searchable-project-item.active {
    background: var(--bg-hover);
}
.searchable-project-item.nav-proj-mine {
    background: #f0f7ff;
}
.searchable-project-item.nav-proj-mine:hover {
    background: #dbeafe;
}
.nav-proj-star {
    color: #f59e0b;
    font-size: 11px;
}
/* Past-only projects (every dated day before today): dimmed but still fully
   selectable — a visual "this one's done" cue, not a filter. */
.searchable-project-item.nav-proj-past {
    opacity: 0.5;
}
.searchable-project-item.nav-proj-past:hover,
.searchable-project-item.nav-proj-past.active {
    opacity: 0.8;
}
/* Same past-only dimming in the calendar project-filter modal + the reports
   multi-select (still selectable). */
.proj-filter-item.proj-filter-past { opacity: 0.5; }
.proj-filter-item.proj-filter-past:hover { opacity: 0.85; }
option.rpt-proj-past { color: #9ca3af; }

/* ---- Blackouts: type-to-search crew picker ---- */
.bo-crew-picker {
    position: relative;
    display: block;
}
.bo-crew-input {
    width: 220px;
}
.bo-crew-menu {
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 100%;
    width: max-content;
    max-width: 320px;
    max-height: 260px;
    overflow-y: auto;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 4px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    z-index: 100;
    display: none;
    margin-top: 2px;
}
.bo-crew-item {
    padding: 5px 12px;
    cursor: pointer;
    font-size: 12px;
    white-space: nowrap;
}
.bo-crew-item:hover,
.bo-crew-item.active {
    background: var(--bg-hover);
}
.bo-crew-empty {
    padding: 6px 12px;
}

/* ---- Crew Hours spreadsheet ---- */
.ch-table-wrap {
    overflow: auto;
    max-height: calc(100vh - 140px);
    border: 1px solid var(--border);
    border-radius: 4px;
}
.ch-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
}
.ch-table th {
    background: var(--bg-alt);
    padding: 6px 8px;
    text-align: left;
    border-bottom: 1px solid var(--border);
    font-weight: 600;
    font-size: 11px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.4px;
    position: sticky;
    top: 0;
    z-index: 2;
}
.ch-table td {
    padding: 4px 6px;
    border-bottom: 1px solid var(--border-light);
    vertical-align: middle;
}
.ch-row:hover {
    background: var(--bg-hover);
}
.ch-row-dark {
    background: repeating-linear-gradient(
        45deg,
        #f5f5f5,
        #f5f5f5 6px,
        #e5e5e5 6px,
        #e5e5e5 10px
    );
    color: #888;
}
.ch-row-dark .ch-time-input,
.ch-row-dark .ch-text-input {
    opacity: 0.4;
    pointer-events: none;
}

.ch-day-cell {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.ch-day-label {
    font-weight: 600;
    white-space: nowrap;
}
.ch-date-type {
    display: inline-block;
    padding: 1px 4px;
    border-radius: 2px;
    font-size: 9px;
    color: #fff;
    text-transform: uppercase;
    width: fit-content;
}
.ch-role-cell {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 140px;
}
.ch-role-name {
    font-weight: 600;
}
.ch-crew-name {
    font-size: 10px;
    color: var(--text-muted);
}
.ch-team-name {
    font-size: 10px;
    color: #4f46e5;
    font-style: italic;
}
body.ch-hide-dark .ch-row-dark { display: none; }

.ch-time-input {
    width: 90px;
    padding: 2px 4px;
    font-size: 11px;
    border: 1px solid var(--border);
    background: #fff;
    border-radius: 2px;
}
.ch-time-input:focus {
    border-color: var(--primary);
    outline: none;
}
.ch-text-input {
    width: 100%;
    padding: 2px 4px;
    font-size: 11px;
    border: 1px solid var(--border);
    background: #fff;
    border-radius: 2px;
    min-width: 100px;
}
.ch-text-input:focus {
    border-color: var(--primary);
    outline: none;
}

.ch-extras-list {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.ch-extra-chip {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    background: #fef3c7;
    border: 1px solid #f59e0b;
    border-radius: 3px;
    padding: 1px 2px;
}
.ch-extra-type {
    width: 70px;
    font-size: 10px;
    border: none;
    background: transparent;
    padding: 1px 2px;
}
.ch-extra-time {
    width: 70px !important;
}
.ch-extra-del {
    background: none;
    border: none;
    color: #dc2626;
    font-size: 12px;
    cursor: pointer;
    padding: 0 2px;
}
.ch-extra-add-btn {
    margin-top: 2px;
    background: transparent;
    border: 1px dashed var(--border);
    border-radius: 2px;
    padding: 0 4px;
    font-size: 10px;
    color: var(--text-muted);
    cursor: pointer;
}

.ch-dark-toggle {
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 2px;
    padding: 2px 6px;
    font-size: 10px;
    cursor: pointer;
    color: var(--text-muted);
}
.ch-row-dark .ch-dark-toggle {
    background: #6b7280;
    color: #fff;
    border-color: #6b7280;
    font-weight: 600;
}

.ch-reset-auto {
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 2px;
    padding: 2px 6px;
    font-size: 11px;
    cursor: pointer;
    color: var(--text-muted);
    margin-left: 2px;
    display: none;
}
.ch-row-manual .ch-reset-auto {
    display: inline-block;
}
.ch-row-manual .ch-time-input {
    font-weight: 600;
    color: #1e40af;
}
.ch-row-auto .ch-time-input {
    color: #6b7280;
    font-style: italic;
}

.ch-mark-btn {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: 1px solid var(--border);
    background: #fff;
    font-weight: 700;
    font-size: 11px;
    cursor: pointer;
    color: var(--text-muted);
}
.ch-mark-btn:hover {
    background: var(--bg-hover);
}
.ch-row-actual .ch-mark-btn {
    background: #16a34a;
    color: #fff;
    border-color: #16a34a;
}
.ch-row-actual .ch-time-input {
    background: #f0fdf4;
}
.ch-row-actual {
    background: #f0fdf4;
}
.ch-row-actual:hover {
    background: #dcfce7;
}

.ch-group-header td {
    background: #1f2937;
    color: #fff;
    font-weight: 700;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 6px 10px;
    position: sticky;
    left: 0;
}
.ch-group-label {
    margin-right: 12px;
}
.ch-group-actions {
    display: inline-flex;
    gap: 6px;
}
.ch-group-mark-btn {
    background: rgba(255,255,255,0.15);
    border: 1px solid rgba(255,255,255,0.3);
    color: #fff;
    font-size: 10px;
    padding: 2px 8px;
    border-radius: 3px;
    cursor: pointer;
    text-transform: none;
    letter-spacing: 0;
}
.ch-group-mark-btn:hover {
    background: rgba(255,255,255,0.25);
}

/* Paid hours column */
.ch-hours {
    text-align: right;
    white-space: nowrap;
    min-width: 60px;
}
.ch-paid-hours {
    font-size: 12px;
    font-weight: 600;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

/* Meal P/NP toggle */
.ch-meal-paid-cell {
    text-align: center;
}
.ch-meal-paid-btn {
    font-size: 10px;
    width: 26px;
    height: 24px;
}
.ch-meal-paid-btn[data-state="paid"] {
    background: #16a34a;
    color: #fff;
    border-color: #16a34a;
}
.ch-meal-paid-btn[data-state="np"] {
    background: #f97316;
    color: #fff;
    border-color: #f97316;
}

.crew-add-team-picker {
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 4px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    min-width: 160px;
    max-height: 300px;
    overflow-y: auto;
}
.crew-add-team-picker-header {
    padding: 6px 10px;
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    border-bottom: 1px solid var(--border-light);
}
.crew-add-team-picker-item {
    padding: 6px 10px;
    font-size: 12px;
    cursor: pointer;
}
.crew-add-team-picker-item:hover {
    background: var(--bg-hover);
}
.crew-add-team-picker-divider {
    border-top: 1px solid var(--border-light);
    margin: 2px 0;
}
.crew-add-team-new-input {
    width: calc(100% - 20px);
    margin: 4px 10px 6px;
    padding: 4px 6px;
    font-size: 12px;
    border: 1px solid var(--border);
    border-radius: 3px;
    outline: none;
}
.crew-add-team-new-input:focus {
    border-color: var(--primary);
}
.crew-team-pop-team-select {
    font-size: 11px;
    padding: 2px 4px;
    border: 1px solid var(--border);
    border-radius: 3px;
    background: #fff;
}

.crew-team-pop-divider {
    border-top: 2px solid var(--border);
    margin: 6px 0 2px;
    position: relative;
}
.crew-team-pop-divider::after {
    content: 'Not on This Day\2019s Roster';
    position: absolute;
    top: -7px;
    left: 8px;
    background: #fff;
    padding: 0 4px;
    font-size: 8px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.3px;
}

.crew-team-pop-role.crew-team-pop-offday {
    opacity: 1;
    color: #c0c0c0;
}
.crew-team-pop-role.crew-team-pop-offday .crew-team-pop-role-name,
.crew-team-pop-role.crew-team-pop-offday .crew-team-pop-crew-name {
    color: #c0c0c0;
}

.crew-team-pop-role.crew-team-pop-conflict {
    opacity: 0.5;
    background: #fef2f2;
}
.crew-team-pop-role.crew-team-pop-conflict .crew-team-pop-crew-name {
    color: #b91c1c;
}
.crew-team-pop-conflict-tag {
    margin-left: auto;
    color: #dc2626;
    font-size: 12px;
}

.crew-team-pop-role-name {
    font-weight: 600;
    white-space: nowrap;
}

.crew-team-pop-crew-name {
    color: var(--text-muted);
    font-size: 11px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Team label clickable */

.crew-team-label-click {
    cursor: pointer;
    transition: background 0.1s;
}

.crew-team-label-click:hover {
    background: var(--bg-hover);
}

/* Teams tab management */

.crew-team-mgmt-row {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 3px 0;
}

.crew-team-name-input {
    flex: 1;
    font-size: 12px !important;
    padding: 3px 6px !important;
}

/* Find Crew modal results. */
.find-crew-tier-header {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    padding: 8px 0 4px;
    border-bottom: 1px solid var(--border-light);
    margin-bottom: 4px;
}
.find-crew-tier-header:first-child { padding-top: 0; }
.find-crew-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
    font-size: 13px;
}
.find-crew-name { flex: 1; }
.find-crew-avail {
    font-size: 11px;
    font-weight: 600;
    padding: 1px 6px;
    border-radius: 3px;
}
.find-crew-avail.tier-1 { background: #dcfce7; color: #166534; }
.find-crew-avail.tier-2 { background: #dbeafe; color: #1e40af; }
.find-crew-avail.tier-3 { background: #fef3c7; color: #92400e; }
.find-crew-avail.tier-4 { background: #fee2e2; color: #991b1b; }
.find-crew-avail.tier-5 { background: #f3e8ff; color: #6b21a8; }

.find-crew-exp {
    font-size: 10px;
    color: var(--text-muted);
    margin-right: 6px;
    white-space: nowrap;
}

/* Two-pane Find Crew modal. */
.find-crew-modal { max-width: 90vw; width: 80vw; }

/* ---- Standalone Crew Searcher ---- */
.crew-searcher-modal { max-width: 720px; width: 92vw; }
.crew-searcher-controls {
    display: flex; align-items: flex-end; gap: 10px; padding: 10px 12px;
    border-bottom: 1px solid var(--border); flex-wrap: wrap;
}
.crew-searcher-controls label { display: flex; flex-direction: column; font-size: 11px;
    color: var(--text-muted); gap: 2px; }
.crew-searcher-controls .form-control { font-size: 13px; }
.crew-searcher-results { max-height: 65vh; overflow-y: auto; padding: 4px 10px 12px; }
.cs-role-section { margin-top: 8px; }
.cs-role-header { font-size: 13px; font-weight: 700; padding: 4px 2px; position: sticky; top: 0;
    background: var(--bg, #fff); border-bottom: 1px solid var(--border-light); }
.cs-top-note { font-size: 11px; font-weight: 700; color: #dc2626; background: #fef08a;
    border-radius: 3px; padding: 0 6px; margin-left: 6px; }
/* The top-N note doubles as a show-all/less button. */
.cs-top-toggle { border: none; cursor: pointer; font-family: inherit; line-height: 1.7; }
.cs-top-toggle:hover { background: #fde047; text-decoration: underline; }
/* Rows past the top 5 stay hidden until the toggle reveals them. Two-class
   selector so it outranks the plain `.cs-crew-row { display: flex }` rule
   (which is declared later in the file) regardless of source order. */
.cs-crew-row.cs-crew-row-extra { display: none; }
.cs-role-section.cs-show-all .cs-crew-row.cs-crew-row-extra { display: flex; }
.cs-crew-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
    padding: 5px 6px; border-radius: 4px; cursor: pointer; }
.cs-crew-row:hover { background: var(--bg-hover, #f1f5f9); }
.cs-crew-name { font-weight: 600; font-size: 13px; min-width: 140px; }
.cs-avail { font-size: 10px; font-weight: 600; padding: 1px 6px; border-radius: 3px; white-space: nowrap; }
.cs-avail-clear { background: #dcfce7; color: #166534; }
.cs-avail-adj { background: #fef9c3; color: #854d0e; }
.cs-avail-busy { background: #fee2e2; color: #991b1b; }
.cs-avail-pto { background: #e0e7ff; color: #3730a3; }
.cs-pto { font-size: 10px; font-weight: 600; color: #3730a3; }
.cs-crew-meta { font-size: 11px; margin-left: auto; }
.cs-person-status { flex-basis: 100%; }
.cs-ps-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 4px 14px;
    font-size: 12px; background: var(--bg-muted, #f8fafc); border-radius: 4px; padding: 6px 10px; margin-top: 4px; }
/* "What are they doing during the range" — per-overlapping-project grid: a date
   header, a "This Show" row, and the other show's working type per day. Clashing
   (in-range) days are red, showing the date type. */
.cs-overlap-wrap { margin-top: 6px; }
.cs-overlap-tbl { border-collapse: collapse; display: block; overflow-x: auto;
    white-space: nowrap; margin-bottom: 6px; }
.cs-ov-rowlabel { font-size: 10px; font-weight: 700; text-align: right; padding: 1px 6px;
    white-space: nowrap; color: #374151; position: sticky; left: 0; background: var(--bg, #fff); }
.cs-ov-dcell { font-size: 10px; font-weight: 600; text-align: center; padding: 1px 5px;
    border: 1px solid var(--border-light); min-width: 34px; }
.cs-ov-cell { font-size: 9px; text-align: center; padding: 1px 5px; border: 1px solid var(--border-light);
    color: var(--text-muted); min-width: 34px; max-width: 80px; overflow: hidden; text-overflow: ellipsis; }
/* "This Show" reference row — plain, no color/symbols. */
.cs-ov-ref { color: #6b7280; font-style: italic; }
.cs-ov-hit { background: #dc2626; }
.cs-ov-dcell.cs-ov-hit { color: #fff; }
.cs-ov-cell.cs-ov-hit { color: #fff; font-weight: 700; }
.cs-ov-x { color: #000; font-weight: 900; }   /* the black ✕ on a red conflict cell */
.cs-overlap-more { font-size: 10px; color: var(--text-muted); margin: 2px 0 4px; }
.find-crew-body {
    display: flex;
    min-height: 400px;
    max-height: 70vh;
}
.find-crew-list-pane {
    flex: 1;
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.find-crew-list-scroll {
    flex: 1;
    overflow-y: auto;
    padding: 0 8px 8px;
}
.find-crew-preview-pane {
    flex: 1;
    overflow-y: auto;
    padding: 12px;
}
.find-crew-row { cursor: pointer; border-radius: 4px; padding: 5px 6px; }
.find-crew-row:hover { background: #f1f5f9; }
.find-crew-row.find-crew-selected {
    background: #dbeafe;
    outline: 1px solid var(--primary);
}

/* Preview pane detail. */
.find-crew-preview-header {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}
.find-crew-preview-name { font-size: 16px; }
.find-crew-preview-detail { font-size: 12px; color: var(--text-muted); margin-bottom: 2px; }
.find-crew-preview-section {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    padding: 10px 0 4px;
    border-bottom: 1px solid var(--border-light);
    margin-bottom: 4px;
}
/* Manage Crew modal rows. */
.manage-crew-row {
    display: flex;
    gap: 6px;
    align-items: center;
    padding: 3px 0;
    border-bottom: 1px solid var(--border-light);
}
.manage-crew-row .form-control {
    margin: 0;
    font-size: 12px;
    padding: 3px 6px;
}
.manage-crew-roles {
    display: flex;
    flex-wrap: wrap;
    gap: 3px;
    align-items: center;
    /* was min-width:50% + flex:3 1 50% — that forced this data column far wider
       than its inline flex:2, so it no longer lined up under the flex:2 "Role
       History" header. min-width:0 lets it shrink/wrap to its flex:2 share. */
    min-width: 0;
}
.manage-crew-role-pill {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    background: #e2e8f0;
    color: #334155;
    font-size: 10px;
    font-weight: 600;
    padding: 1px 6px;
    border-radius: 8px;
    white-space: nowrap;
}
.manage-crew-role-count {
    background: #94a3b8;
    color: #fff;
    font-size: 9px;
    font-weight: 700;
    padding: 0 4px;
    border-radius: 6px;
    min-width: 14px;
    text-align: center;
}

.find-crew-conflict-summary {
    font-size: 12px;
    color: #dc2626;
    padding: 2px 0 6px;
}

.find-crew-conflict-row,
.find-crew-history-row {
    display: flex;
    gap: 8px;
    padding: 2px 0;
    font-size: 12px;
}

/* Shortcut legend in the crew-schedule top toolbar. */
.crew-shortcut-legend {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 1;
    justify-content: center;
    font-size: 11px;
    color: var(--text-muted);
    white-space: nowrap;
}
.crew-shortcut-legend .sep { color: var(--border); }
.crew-shortcut-legend kbd {
    font-family: inherit;
    background: #f1f5f9;
    border: 1px solid var(--border-light);
    border-radius: 3px;
    padding: 0 4px;
    font-weight: 700;
    font-size: 10px;
}

/* ---- Timeline (replaces TASKS block) ---- */
/* --ppm: pixels per minute. Set once at grid level; 0.4 → 576px / 24h.
   Overridden at runtime as an inline style on #crewGrid by the zoom
   controls (crew_schedule.js setZoomPpm) — this rule is just the default
   / first-paint value before that JS runs. */
.crew-grid { --ppm: 0.4; --snap-min: 15; }

.crew-zoom-toolbar {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 8px;
}
.crew-zoom-toolbar .crew-zoom-pct {
    min-width: 38px;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.crew-zoom-toolbar .btn {
    padding: 2px 10px;
    font-weight: 700;
    line-height: 1.2;
}

.crew-timeline-wrap {
    position: relative;
    background: #fff;
    border-bottom: 1px solid var(--border);
}

.crew-timeline-generic {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    padding: 4px 6px;
    border-bottom: 1px dashed var(--border-light);
    min-height: 24px;
}

.crew-timeline-generic-empty {
    text-align: center;
    padding: 6px;
}

.crew-timeline-generic.drop-target-active,
.crew-timeline-track.drop-target-active {
    outline: 2px solid var(--primary);
    outline-offset: -2px;
}

.crew-team-labels {
    display: grid;
    grid-template-columns: repeat(var(--col-units, 2), 1fr);
    gap: 0;
    height: 18px;
    border-bottom: 1px solid var(--border-light);
}

.crew-team-label {
    font-size: 9px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    color: var(--text-muted);
    text-align: center;
    padding: 2px 2px;
    border-right: 1px solid var(--border-light);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.crew-team-label:last-child {
    border-right: none;
}
.crew-team-dur {
    font-weight: 400;
    opacity: 0.7;
}
.crew-team-dur-only {
    font-size: 9px;
    font-weight: 600;
    color: var(--text-muted);
    text-align: center;
    padding: 2px 2px;
    grid-column: 1 / -1;
}
/* Single team on a day: span the full label row width so the name centers */
.crew-team-single {
    grid-column: 1 / -1;
    border-right: none;
}
/* Generic team rendered as the only team on a day: hide name, center duration */
.crew-team-generic {
    text-align: center;
    color: var(--text-muted);
}

.crew-timeline-track {
    position: relative;
    background-color: #fff;
    /* Base 24h height = 1440 * ppm. Overflow tasks are clipped — the
       bleed-through shows on the next day's inbound overflow instead. */
    height: calc(1440 * var(--ppm) * 1px);
    overflow: hidden;
    background-image:
        /* major hourly line — drawn at the START of each cell so a task
           border at start_min N exactly overlaps the gridline at N. */
        repeating-linear-gradient(
            to bottom,
            #d1d5db 0,
            #d1d5db 1px,
            transparent 1px,
            transparent calc(60 * var(--ppm) * 1px)
        ),
        /* snap-interval sub-grid — same start-of-cell convention. */
        repeating-linear-gradient(
            to bottom,
            #f1f5f9 0,
            #f1f5f9 1px,
            transparent 1px,
            transparent calc(var(--snap-min) * var(--ppm) * 1px)
        );
}

/* Time ruler column — rendered before day 0 and every 7 days. Shares
   the .crew-day-column structure so its header + generic-strip spacers
   naturally line up with the adjacent day columns' timeline tracks.
   First ruler stays glued to the left edge during horizontal scroll so
   times are always visible. The repeating rulers further right still
   render but lose their stickiness so they scroll with the grid. */
.crew-ruler-column {
    min-width: 28px !important;
    width: 28px;
    background: var(--bg-alt);
    flex-shrink: 0;
    z-index: 5;
}
.crew-ruler-column:first-of-type {
    position: sticky;
    left: 0;
    /* Slightly stronger right border so the sticky column visually
       separates from the scrolling content behind it. */
    border-right: 1px solid #94a3b8;
    box-shadow: 1px 0 4px rgba(0,0,0,0.06);
}
.crew-ruler-column .crew-day-header,
.crew-ruler-column .crew-timeline-generic,
.crew-ruler-column .crew-ruler-team-spacer {
    visibility: hidden;
}
.crew-ruler-team-spacer {
    height: 30px !important;
}
.crew-ruler-track {
    position: relative;
    height: calc(1440 * var(--ppm) * 1px);
    border-left: 1px solid var(--border);
    border-right: 1px solid var(--border);
    overflow: hidden;
}
.crew-ruler-label {
    position: absolute;
    right: 3px;
    top: calc(var(--display-min, var(--start-min)) * var(--ppm) * 1px);
    transform: translateY(-50%);
    font-size: 9px;
    font-weight: 700;
    color: var(--text-muted);
    line-height: 1;
    white-space: nowrap;
}
.crew-ruler-label:first-of-type { transform: translateY(0); }
.crew-ruler-label:last-of-type { display: block; }
.crew-ruler-label-overnight {
    color: #dc2626;
    font-weight: 700;
}
/* Past-midnight labels are only relevant when extend mode is on (the
   ruler-track grows to fit them). Otherwise they'd render past the
   track bottom into whatever sits below. */
body:not(.crew-extend-timeline) .crew-ruler-label-overnight {
    display: none;
}

/* Hover indicator — thin horizontal line that follows the cursor across
   the entire timeline, with a time badge in the sticky ruler. Driven by
   JS-set CSS variables on .crew-grid. */
.crew-grid {
    position: relative;
}
.crew-grid::after {
    content: '';
    position: absolute;
    left: 0; right: 0;
    top: var(--hover-y, -100px);
    height: 1px;
    background: rgba(99, 102, 241, 0.5);
    pointer-events: none;
    z-index: 4;
    display: var(--hover-display, none);
}
/* Lives inside .crew-ruler-track on the sticky ruler column, so it stays
   pinned to the viewport's left edge as the grid scrolls horizontally.
   Its CSS variables are set on the ruler-track element by the mousemove
   handler. */
.crew-hover-time-badge {
    position: absolute;
    top: var(--hover-y, -100px);
    left: 1px;
    transform: translateY(-50%);
    background: #4338ca;
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    padding: 1px 5px;
    border-radius: 3px;
    pointer-events: none;
    z-index: 6;
    display: var(--hover-display, none);
    white-space: nowrap;
}

/* Generic strip fixed height so ruler column aligns with each day's
   timeline track. Overflow chips scroll horizontally within the strip. */
.crew-timeline-generic {
    height: 28px;
    overflow-x: auto;
    overflow-y: hidden;
    flex-wrap: nowrap !important;
    align-items: center;
}

.crew-timeline-task {
    position: absolute;
    /* Default lane-based positioning: 100px per lane, 2px inset each side.
       Multi-lane spans cover `var(--lane-span)` consecutive lanes. */
    left: calc(var(--lane, 0) * 100px + 2px);
    width: calc(var(--lane-span, 1) * 100px - 4px);
    /* --display-min is JS-computed (start - grid_start). Falls back to
       --start-min for code paths that haven't been updated yet. */
    top: calc(var(--display-min, var(--start-min)) * var(--ppm) * 1px);
    height: calc(var(--duration-min) * var(--ppm) * 1px);
    margin: 0;  /* override .crew-task-block's 2px vertical margin */
    box-sizing: border-box;
    background: #dbeafe;
    border: 1px solid var(--primary);
    border-radius: 3px;
    padding: 2px 4px;
    font-size: 10px;
    overflow: hidden;
    cursor: pointer;
    z-index: 2;
}

/* Single-lane days: task uses the entire column width, not one lane. */
.crew-day-column[data-max-lanes="0"] .crew-timeline-task,
.crew-day-column[data-max-lanes="1"] .crew-timeline-task {
    left: 2px;
    right: 2px;
    width: auto;
}

/* Span-drag handles on the left/right edges of a multi-lane task.
   Only show when hovering the task AND nothing is currently selected
   (selection has priority — user can click the task normally). */
.crew-task-span-handle {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 6px;
    background: var(--primary);
    opacity: 0;
    cursor: ew-resize;
    z-index: 3;
    transition: opacity 0.1s;
}
.crew-task-span-handle.left { left: -3px; border-radius: 3px 0 0 3px; }
.crew-task-span-handle.right { right: -3px; border-radius: 0 3px 3px 0; }

.crew-timeline-task:hover .crew-task-span-handle { opacity: 0.8; }
.crew-task-span-handle:hover,
.crew-task-span-handle.dragging { opacity: 1 !important; }

/* Hide span handles when a selection is active — selecting wins. */
body.task-drop-mode .crew-task-span-handle { display: none; }

/* Time-drag handles — clickable 4px area at the top/bottom edge of the
   task. Visual treatment is a 2px medium-blue line at the edge (via the
   ::before pseudo) so the handle barely occludes any of the task body.
   The remaining 2px of the click target is invisible but still grabbable. */
.crew-task-time-handle {
    position: absolute;
    left: 0;
    right: 0;
    height: 4px;
    background: transparent;
    opacity: 0;
    cursor: ns-resize;
    z-index: 5;
    transition: opacity 0.1s;
}
.crew-task-time-handle::before {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    height: 2px;
    background: #3b82f6;
    border-radius: 1px;
}
.crew-task-time-handle.top { top: 0; }
.crew-task-time-handle.top::before { top: 0; }
.crew-task-time-handle.bottom { bottom: 0; }
.crew-task-time-handle.bottom::before { bottom: 0; }
.crew-timeline-task:hover .crew-task-time-handle { opacity: 1; }
.crew-task-time-handle.dragging { opacity: 1 !important; }
body.task-drop-mode .crew-task-time-handle { display: none; }
body.crew-time-dragging { cursor: ns-resize; }
body.crew-time-dragging .crew-timeline-task,
body.crew-time-dragging .crew-timeline-track { pointer-events: none; }

/* Floating tooltip during time-drag — shows the edge time we'd commit to
   on mouseup, plus the resulting duration. Anchored to the cursor with a
   small offset so it doesn't sit under the pointer. */
.crew-time-drag-tip {
    position: fixed;
    z-index: 10000;
    background: #111827;
    color: #fff;
    padding: 4px 8px;
    border-radius: 4px;
    font-size: 12px;
    line-height: 1.3;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
    pointer-events: none;
    white-space: nowrap;
}
.crew-time-drag-tip-edge { font-weight: 600; }
.crew-time-drag-tip-dur { font-size: 11px; opacity: 0.75; }

/* Highlight today's column in timeline and sheet */
/* Today's column / row — soft amber tint, no inverted text. Same amber hue
   used for both the timeline column and the spreadsheet day-head so the
   "today" cue reads consistently across views. */
.crew-day-column.crew-day-today {
    background: rgba(245, 158, 11, 0.22);
}
.crew-day-column.crew-day-today .crew-day-header {
    background: rgba(245, 158, 11, 0.22);
}
.sheet-day-head.sheet-day-today {
    background: rgba(245, 158, 11, 0.22);
    border-radius: 4px;
    padding-left: 8px;
    padding-right: 8px;
}

/* New day columns sliding/fading in.
   - .crew-day-expanding: used by the 'after' (right) path — animates max-width
     so the timeline visually grows on the right.
   - .crew-day-fading-in: used by the 'before' (left) path — only fades opacity.
     A width animation on this side would interfere with the scroll-restore math
     that keeps the user's viewport stable while content is pushed right. */
.crew-day-column { transition: opacity 0.25s ease, max-width 0.3s ease, min-width 0.3s ease, padding 0.3s ease, margin 0.3s ease; }
.crew-day-column.crew-day-expanding {
    opacity: 0;
    max-width: 0 !important;
    min-width: 0 !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
    overflow: hidden;
}
.crew-day-column.crew-day-fading-in {
    opacity: 0;
}

/* Task name edit popup — appended inside the task block so it tracks the
   task as the timeline scrolls / reflows. */
.crew-task-name-popup {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 100;
    background: #fff;
    border: 1px solid var(--border-light);
    border-radius: 4px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    padding: 4px;
    cursor: default;
}
.crew-task-name-popup input {
    font-size: 13px;
    padding: 4px 8px;
    border: 1px solid var(--border-light);
    border-radius: 3px;
    width: 200px;
    outline: none;
}
.crew-task-name-popup input:focus {
    border-color: var(--primary);
}

/* Subtle divider between lanes once a day is multi-lane. */
.crew-day-column[data-max-lanes="2"] .crew-timeline-track,
.crew-day-column[data-max-lanes="3"] .crew-timeline-track,
.crew-day-column[data-max-lanes="4"] .crew-timeline-track,
.crew-day-column[data-max-lanes="5"] .crew-timeline-track,
.crew-day-column[data-max-lanes="6"] .crew-timeline-track {
    background-image:
        repeating-linear-gradient(
            to right,
            transparent 0,
            transparent 99px,
            rgba(148, 163, 184, 0.4) 99px,
            rgba(148, 163, 184, 0.4) 100px
        ),
        repeating-linear-gradient(
            to bottom,
            transparent 0,
            transparent calc(60 * var(--ppm) * 1px - 1px),
            #d1d5db calc(60 * var(--ppm) * 1px - 1px),
            #d1d5db calc(60 * var(--ppm) * 1px)
        ),
        repeating-linear-gradient(
            to bottom,
            transparent 0,
            transparent calc(var(--snap-min) * var(--ppm) * 1px - 1px),
            #f1f5f9 calc(var(--snap-min) * var(--ppm) * 1px - 1px),
            #f1f5f9 calc(var(--snap-min) * var(--ppm) * 1px)
        );
}

.crew-timeline-task:active { cursor: grabbing; }

/* Selected-task highlight. Applied to any task-block (pool, generic, timeline). */
.crew-task-block.task-selected {
    outline: 2px solid var(--primary);
    outline-offset: 1px;
    background: #bfdbfe;
}
.crew-task-block { cursor: pointer; user-select: none; }
.crew-task-block.pool-dragging { opacity: 0.4; }

/* While any task is selected, valid drop zones glow to guide the user. */
body.task-drop-mode .crew-timeline-track,
body.task-drop-mode .crew-timeline-generic,
body.task-drop-mode #taskPool {
    box-shadow: inset 0 0 0 1px rgba(59, 130, 246, 0.4);
    cursor: crosshair;
}

/* Drop-time hover indicator on timeline tracks. The container's top
   border IS the precision line — it sits at the exact drop time, and
   the ghost blocks hang below showing each task's duration. */
.crew-timeline-drop-indicator {
    position: absolute;
    left: 2px; right: 2px;
    border-top: 2px solid var(--primary);
    pointer-events: none;
    z-index: 4;
}
.crew-timeline-drop-indicator.alt-drop { border-top-color: #f59e0b; }

.crew-drop-ghost {
    position: absolute;
    background: rgba(59, 130, 246, 0.18);
    border: 1px dashed rgba(59, 130, 246, 0.6);
    color: var(--primary);
    font-size: 9px;
    font-weight: 600;
    padding: 1px 4px;
    line-height: 1.1;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    box-sizing: border-box;
}
.crew-timeline-drop-indicator.alt-drop .crew-drop-ghost {
    background: rgba(245, 158, 11, 0.18);
    border-bottom-color: rgba(245, 158, 11, 0.6);
    color: #b45309;
}

.crew-marquee-rect {
    position: absolute;
    border: 1px dashed #3b82f6;
    background: rgba(59, 130, 246, 0.08);
    pointer-events: none;
    z-index: 50;
}

/* Alt-held cursor cue: tasks show a "+" cursor so user knows alt-click
   drops rather than selects. */
body.alt-held.task-drop-mode .crew-task-block { cursor: copy; }

.crew-timeline-task-body {
    font-weight: 600;
    line-height: 1.2;
}

/* Short tasks (30–59 min): at 0.4 px/min a 30-min task is only 12px tall.
   Zero vertical padding on the block + zero margin on the body lets an
   8px label actually fit inside the box. */
.crew-timeline-task-short { padding: 0 3px; line-height: 1; }
.crew-timeline-task-short .crew-timeline-task-body { font-size: 8px; margin: 0; vertical-align: center; }

.crew-timeline-task-tiny { padding: 0 3px; font-size: 8px; line-height: 1; }
.crew-timeline-task-tiny .crew-timeline-task-body { font-size: 8px; font-weight: 600; margin: 0; vertical-align: center; }

/* Red stripes: overflow extension past 4am next day. Positioned at bottom
   of current day's track, extending beyond the base 1440-minute height. */
/* Overflow gutter: extra lane on the left of a day that receives overflow
   from the previous day. Purely visual — not an actual team column. */
.crew-overflow-gutter {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100px;
    height: calc(1440 * var(--ppm) * 1px);
    border-right: 1px dashed var(--border);
    z-index: 1;
    pointer-events: none;
    background-color: #fff;
    background-image:
        repeating-linear-gradient(
            to bottom,
            transparent 0,
            transparent calc(60 * var(--ppm) * 1px - 1px),
            #d1d5db calc(60 * var(--ppm) * 1px - 1px),
            #d1d5db calc(60 * var(--ppm) * 1px)
        );
}
.crew-overflow-gutter-label {
    position: sticky;
    top: 4px;
    padding: 2px 6px;
    font-size: 8px;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    color: var(--text);
    font-weight: 600;
    text-align: center;
    background: rgba(255,255,255,0.5);
    z-index: 2;
}
.crew-overflow-gutter-stripe {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    background-image: repeating-linear-gradient(
        -45deg,
        rgba(59, 130, 246, 0.10) 0, rgba(59, 130, 246, 0.10) 6px,
        rgba(59, 130, 246, 0.22) 6px, rgba(59, 130, 246, 0.22) 12px
    );
}
/* When a day has an overflow gutter, shift the actual timeline content right */
.has-overflow-gutter .crew-timeline-generic,
.has-overflow-gutter .crew-team-labels,
.has-overflow-gutter .crew-timeline-track {
    margin-left: 100px;
}

/* "Continues on next day" label at the bottom of the source day track */
.crew-timeline-continues-label {
    position: absolute;
    bottom: 4px;
    left: calc(var(--lane, 0) * 100px + 4px);
    width: calc(var(--lane-span, 1) * 100px - 8px);
    text-align: center;
    font-size: 9px;
    color: var(--text);
    font-weight: 600;
    background: rgba(255,255,255,0.5);
    padding: 2px 4px;
    border-radius: 2px;
    z-index: 3;
}
/* Single-lane days: label spans the full column, same as tasks. */
.crew-day-column[data-max-lanes="0"] .crew-timeline-continues-label,
.crew-day-column[data-max-lanes="1"] .crew-timeline-continues-label {
    left: 4px;
    right: 4px;
    width: auto;
}

/* The legacy per-day overflow-extend element is now superseded by the
   .crew-timeline-track::after pseudo, which paints the stripe on EVERY
   track (so empty days also stripe in extend mode, not just days with
   their own overflow tasks). Hide the old element to avoid double-paint. */
.crew-timeline-overflow-extend { display: none !important; }

/* Past-midnight stripe on every timeline track. In non-extend mode the
   track is 1440min tall with overflow:hidden, so this pseudo renders past
   the visible area and is clipped. In extend mode the track grows to
   1440 + max_overflow, so this pseudo paints the visible past-midnight
   area uniformly across every column. */
.crew-timeline-track::after {
    content: '';
    position: absolute;
    left: 0; right: 0;
    top: calc((1440 - var(--grid-start-min, 0)) * var(--ppm) * 1px);
    bottom: 0;
    background-image: repeating-linear-gradient(
        -45deg,
        rgba(59, 130, 246, 0.10) 0, rgba(59, 130, 246, 0.10) 6px,
        rgba(59, 130, 246, 0.22) 6px, rgba(59, 130, 246, 0.22) 12px
    );
    z-index: 0;
    pointer-events: none;
}

/* Past-midnight portion of a task gets a stripe overlay using the same
   blue pattern. --past-midnight-from-min is set inline by the server only
   when end_min > 1440; for normal tasks it defaults to a huge value so the
   pseudo-element renders past the bottom and is clipped (invisible). */
.crew-timeline-task::after {
    content: '';
    position: absolute;
    left: 0; right: 0;
    top: calc(var(--past-midnight-from-min, 99999) * var(--ppm) * 1px);
    bottom: 0;
    background-image: repeating-linear-gradient(
        -45deg,
        rgba(59, 130, 246, 0.18) 0, rgba(59, 130, 246, 0.18) 6px,
        rgba(59, 130, 246, 0.36) 6px, rgba(59, 130, 246, 0.36) 12px
    );
    pointer-events: none;
}

/* (crew-timeline-overflow-inbound removed — overflow is now shown
   only in the gutter lane to the left of the track.) */

.crew-day-header .day-date {
    font-size: 14px;
}


.crew-day-type-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
}

.crew-day-desc-input {
    font-size: 11px;
    font-weight: 400;
    color: var(--text);
    background: transparent;
    border: 1px solid transparent;
    border-radius: 3px;
    padding: 1px 4px;
    min-width: 50px;
    max-width: 80px;
    text-align: center;
}
.crew-day-desc-input:focus {
    border-color: var(--accent);
    background: var(--bg);
    outline: none;
}
.crew-day-desc-input::placeholder { color: var(--text-muted); opacity: 0.5; }

.crew-day-notes-input {
    font-size: 10px;
    font-weight: 400;
    color: var(--text-muted);
    background: transparent;
    border: 1px solid transparent;
    border-radius: 3px;
    padding: 1px 4px;
    width: 100%;
    text-align: center;
    line-height: 1.2;
    margin-top: 1px;
    box-sizing: border-box;
}
.crew-day-notes-input:focus {
    border-color: var(--accent);
    background: var(--bg);
    outline: none;
    color: var(--text);
}
.crew-day-notes-input::placeholder { color: var(--text-muted); opacity: 0.5; }

.crew-time-block {
    padding: 4px 8px;
    border-bottom: 1px solid var(--border-light);
    min-height: 32px;
    font-size: 12px;
}

.crew-task-block {
    background: #dbeafe;
    border: 1px solid #93c5fd;
    border-radius: 4px;
    padding: 4px 6px;
    font-size: 11px;
}

/* Timeline tasks override the base padding because their height is
   dictated by duration — vertical padding steals from the label. */
.crew-timeline-task { padding: 0 4px; }

/* Timeline / pool meal blocks: greyed "unavailable time" look so meals
 * read as fixed slots rather than another regular task. Bold label
 * makes the meal stand out at a glance even when greyed. */
.crew-task-meal {
    background: #e5e7eb !important;
    border-color: #9ca3af !important;
    color: #6b7280;
    font-weight: 600;
}
/* Trucking blocks — direction-tinted. Pickup leans purple,
 * delivery / both leans green. Bold like meals because the slot is
 * fixed (truck arrives at the scheduled time). */
.crew-task-trucking-delivery {
    background: #d1fae5 !important;
    border-color: #6ee7b7 !important;
    font-weight: 600;
}
.crew-task-trucking-pickup {
    background: #ede9fe !important;
    border-color: #c4b5fd !important;
    font-weight: 600;
}

/* Pool task that's a meal — small icon prefix already added in template,
   but the meal background should still apply here. */
.crew-pool-meal .crew-pool-meal-icon { font-size: 11px; }
.crew-task-trucking .crew-pool-trucking-icon { font-size: 11px; }

/* Generic (unscheduled-on-day) strip: pill-style flow so many tasks fit
   without ballooning the row. Container scrolls when pills overflow.
   See _crew_day_column.html .crew-timeline-generic. */
.crew-timeline-generic {
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    gap: 3px;
    overflow-y: auto;
    /* ~2 rows of 22px pills + small breathing room. */
    min-height: 50px;
    max-height: 76px;
    padding: 3px;
}
.crew-generic-pill {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 1px 6px;
    border-radius: 10px;
    font-size: 11px;
    line-height: 18px;
    background: #eef2ff;
    border: 1px solid #c7d2fe;
    cursor: pointer;
    max-width: 100%;
    overflow: hidden;
    /* override absolute positioning the timeline blocks normally use */
    position: static !important;
    width: auto !important;
    height: auto !important;
}
.crew-generic-pill .crew-generic-pill-name {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 140px;
}
.crew-generic-pill .crew-generic-pill-dur {
    color: #6b7280;
    font-size: 10px;
    flex-shrink: 0;
}
.crew-generic-pill.crew-task-meal { background: #e5e7eb; border-color: #9ca3af; color: #6b7280; font-weight: 600; }

/* ---- Teams tab (inside .crew-roster-panel) ---- */
.teams-tab-toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 4px 6px;
    border-bottom: 1px solid var(--border-light, #e5e7eb);
    flex-wrap: wrap;
}
.teams-tab-toolbar .cal-mode-toggle { margin-right: 4px; }
.teams-tab-body {
    display: flex;
    gap: 0;
    min-height: 200px;
    max-height: 420px;
}
.teams-tab-left {
    width: 40%;
    min-width: 160px;
    border-right: 1px solid var(--border-light, #e5e7eb);
    overflow-y: auto;
    padding: 4px;
    font-size: 12px;
}
.teams-tab-right {
    flex: 1;
    overflow-y: auto;
    padding: 6px 8px;
    font-size: 12px;
}
.teams-tab-day { margin-bottom: 4px; }
.teams-tab-day-head {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 3px 4px;
    font-weight: 600;
    cursor: pointer;
    border-radius: 3px;
}
.teams-tab-day.is-active > .teams-tab-day-head { background: #eef2ff; }
.teams-tab-add-team {
    margin-left: auto;
    font-size: 10px;
    background: transparent;
    border: 1px solid var(--border-light, #e5e7eb);
    border-radius: 3px;
    padding: 0 4px;
    cursor: pointer;
}
.teams-tab-add-team:hover { background: #eef2ff; }
.teams-tab-day-empty {
    padding-left: 14px;
    font-size: 11px;
    color: var(--text-muted, #6b7280);
}
.teams-tab-team {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 2px 4px 2px 14px;
    cursor: pointer;
    border-radius: 3px;
}
.teams-tab-team:hover { background: #f3f4f6; }
.teams-tab-team.is-active { background: #c7d2fe; }
.teams-tab-team-name { flex: 1; }
.teams-tab-team-count {
    font-size: 10px;
    background: var(--border-light, #e5e7eb);
    color: #374151;
    border-radius: 8px;
    padding: 0 6px;
    min-width: 16px;
    text-align: center;
}
.teams-tab-right-head { margin-bottom: 6px; }
.teams-tab-empty { padding: 8px 0; }
.teams-tab-role-list { display: flex; flex-direction: column; gap: 2px; margin-bottom: 8px; }
.teams-tab-role {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 2px 4px;
    border-radius: 3px;
}
.teams-tab-role:hover { background: #f9fafb; }
/* By Team states: on-this team (default look) → tap removes; available
 * (grey, italic) → tap adds; on-other (grey + red tag) → tap is a no-op
 * unless Allow already-assigned is on. */
.teams-tab-role-on-this {
    background: #eff6ff;
    border-left: 3px solid var(--primary, #2563eb);
}
.teams-tab-role-available {
    color: var(--text-muted, #6b7280);
}
.teams-tab-role-available:hover { background: #ecfdf5; }
.teams-tab-role-on-other {
    color: #9ca3af;
    cursor: not-allowed;
}
.teams-tab-role-on-other:hover { background: transparent; }
.teams-tab-role-other-tag {
    margin-left: auto;
    font-size: 10px;
    padding: 1px 6px;
    background: #fee2e2;
    color: #b91c1c;
    border-radius: 8px;
    white-space: nowrap;
}
.teams-tab-role-x {
    margin-left: auto;
    background: transparent;
    border: none;
    color: #b91c1c;
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
    padding: 0 4px;
}
.teams-tab-role-x:hover { background: #fee2e2; border-radius: 3px; }
.teams-tab-add-row { display: flex; gap: 4px; align-items: center; }
.teams-tab-crew-group { margin-bottom: 10px; }
.teams-tab-crew-head {
    font-weight: 600;
    padding: 2px 0;
    border-bottom: 1px dashed var(--border-light, #e5e7eb);
    margin-bottom: 2px;
}
.teams-tab-role-team { font-size: 11px; padding: 1px 4px; min-width: 110px; }

.crew-task-overlap,
.sheet-cell-overlap {
    background-image: repeating-linear-gradient(
        45deg,
        transparent,
        transparent 6px,
        rgba(220, 38, 38, 0.15) 6px,
        rgba(220, 38, 38, 0.15) 10px
    );
}
/* Gap callout: when a same-lane task has empty time before it, mark the
 * top edge of its start/dur/end cells with a thicker bright-blue border. */
.sheet-cell-gap-before {
    border-top: 3px solid #2563eb !important;
}
/* Day-header shortcut buttons (Remove Gaps / Fill Time) — slightly
 * accented so they read as "fix something" actions next to the neutral
 * + Task / + Note buttons. */
.sheet-day-shortcut {
    background: #eff6ff;
    border-color: #2563eb;
    color: #1d4ed8;
}
.sheet-day-shortcut:hover {
    background: #dbeafe;
}

/* Always-on change log drawer pinned under the top-nav. Toggle bar is
 * always visible; body slides open/closed. Body is intentionally compact
 * (~4 rows visible) so it stays minimally intrusive while still letting
 * the user scroll through every change Remove Gaps / Fill Time / cell
 * edits made during the session. */
.sheet-change-drawer {
    /* Fixed so the toggle bar (and any pending preview) stays pinned to
     * the viewport regardless of scroll position. Sticky was unreliable
     * inside .main-content's overflow-x:auto container — when the user
     * clicked Fill/Remove Gaps from a day card mid-page, the preview
     * would open above the viewport and feel like nothing happened. The
     * pending preview must always be visible. */
    position: fixed;
    top: var(--header-height);
    left: 0;
    right: 0;
    z-index: 90;
    background: transparent;
    font-size: 11px;
}
/* Push the schedule page's title row down so the always-on toggle bar
 * doesn't overlay it at scroll-top. */
body[data-url-name="crew_schedule"] .main-content > :first-child {
    margin-top: 28px;
}
.sheet-change-drawer-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 2px 24px;
    background: #f9fafb;
    cursor: pointer;
    user-select: none;
    border-top: 1px solid var(--border-light);
    border-bottom: 1px solid var(--border-light);
    font-size: 11px;
    line-height: 1.4;
}
.sheet-change-drawer-toggle:hover {
    background: #f3f4f6;
}
.sheet-change-drawer-toggle strong {
    font-weight: 600;
}
.sheet-change-drawer-caret {
    display: inline-block;
    transition: transform 0.15s ease;
    color: var(--text-muted);
    font-size: 10px;
}
.sheet-change-drawer.open .sheet-change-drawer-caret {
    transform: rotate(180deg);
}
.sheet-change-drawer-count {
    color: var(--text-muted);
    font-size: 10px;
}
.sheet-change-drawer-clear {
    margin-left: auto;
    background: transparent;
    border: none;
    color: var(--text-muted);
    font-size: 10px;
    cursor: pointer;
    padding: 0 4px;
    text-decoration: underline;
}
.sheet-change-drawer-clear:hover {
    color: var(--text);
}
.sheet-change-drawer-body {
    /* Absolute so opening the drawer overlays the content below the
     * toggle bar (crewStats, conflict warnings, the sheet) without
     * pushing it down. Anchored to the toggle's bottom edge via top:100%. */
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    max-height: 0;
    overflow: hidden;
    background: #fff;
    border-bottom: 1px solid var(--border);
    box-shadow: 0 4px 8px rgba(0,0,0,0.08);
    transition: max-height 0.22s ease;
    padding: 0 24px;
}
.sheet-change-drawer.open .sheet-change-drawer-body {
    /* ~4 rows of 20px + vertical padding */
    max-height: 96px;
    overflow-y: auto;
    padding: 2px 24px;
}
.sheet-change-row {
    display: flex;
    align-items: baseline;
    gap: 18px;
    padding: 2px 0;
    border-bottom: 1px solid var(--border-light);
    font-size: 11px;
    line-height: 1.5;
}
.sheet-change-row:last-child {
    border-bottom: none;
}
.sheet-change-row .sheet-change-time {
    color: var(--text-muted);
    font-family: ui-monospace, monospace;
    font-size: 10px;
}
.sheet-change-row .sheet-change-name {
    font-weight: 500;
    white-space: nowrap;
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
}
.sheet-change-row .sheet-change-day {
    color: var(--text-muted);
    font-size: 10px;
    white-space: nowrap;
}
.sheet-change-row .sheet-change-diff {
    font-family: ui-monospace, monospace;
    color: #1d4ed8;
    white-space: nowrap;
}
.sheet-change-row.added .sheet-change-diff { color: #047857; }
.sheet-change-row.removed .sheet-change-diff { color: #b91c1c; }
.sheet-change-row .sheet-change-diff .from {
    color: var(--text-muted);
    text-decoration: line-through;
}
.sheet-change-row .sheet-change-diff .arrow {
    margin: 0 4px;
    color: var(--text-muted);
}
.sheet-change-empty {
    color: var(--text-muted);
    font-size: 11px;
    padding: 4px 0;
}

/* Pending preview block — sits above the change log when Remove Gaps /
 * Fill Time has computed proposed changes the user can Apply or Cancel. */
.sheet-change-pending {
    background: #fffbeb;
    border: 1px solid #fde68a;
    border-radius: 4px;
    padding: 4px 8px;
    margin: 2px 0 6px;
}
.sheet-change-pending-head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 2px 0 4px;
    border-bottom: 1px solid #fde68a;
    margin-bottom: 4px;
}
.sheet-change-pending-head .sheet-pending-apply {
    margin-left: auto;
}
.sheet-change-row.pending .sheet-change-time {
    color: #b45309;
}
.sheet-change-row.pending .sheet-change-diff {
    color: #b45309;
}

.crew-task-block.midnight-warning {
    background: repeating-linear-gradient(
        45deg,
        #dbeafe,
        #dbeafe 4px,
        #bfdbfe 4px,
        #bfdbfe 8px
    );
}

.crew-task-block.bleed-warning {
    background: repeating-linear-gradient(
        -45deg,
        #fef3c7,
        #fef3c7 4px,
        #fde68a 4px,
        #fde68a 8px
    );
}

.crew-assignment-block {
    background: #f0fdf4;
    border: 1px solid #86efac;
    border-radius: 4px;
    padding: 4px 6px;
    margin: 2px 0;
    font-size: 11px;
}

.crew-conflict-warning {
    background: #fef2f2;
    border: 1px solid #fca5a5;
    color: var(--danger);
    font-size: 10px;
    padding: 2px 6px;
    border-radius: 3px;
    margin-top: 2px;
}

/* ---- Detail Page ---- */

.detail-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin-bottom: 24px;
    gap: 16px;
}

.detail-section {
    margin-bottom: 20px;
    padding: 14px 16px 16px;
    background: linear-gradient(to bottom right, #f5f5f5 0%, #f5f5f5 35%, #ffffff 65%, #ffffff 100%);
    border: 1px solid var(--border-light);
    border-radius: 6px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
}

.detail-section h2 {
    font-size: 16px;
    font-weight: 600;
    margin: 0 0 12px;
    padding-bottom: 6px;
    border-bottom: 2px solid var(--border-light);
}

.detail-fields {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 12px;
}

.linked-project-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: #e5e7eb;
    border-radius: 12px;
    padding: 2px 8px;
    font-size: 12px;
    line-height: 1.4;
}
.linked-project-tag a {
    color: #1a1a1a;
    text-decoration: none;
    font-weight: 500;
}
.linked-project-tag a:hover { text-decoration: underline; }
.linked-project-remove {
    background: none;
    border: none;
    color: #6b7280;
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
    padding: 0 2px;
}
.linked-project-remove:hover { color: #dc2626; }

/* ---- Report ---- */

.report-section {
    page-break-after: always;
    margin-bottom: 32px;
}

/* Reports drop the boxed/shadowed `.detail-section` styling — sections are
 * separated by a bold rule and ample whitespace, so the section-break
 * never gets confused with the lighter under-rule on each section's header. */
#reportContent .detail-section {
    background: none;
    border: none;
    border-radius: 0;
    box-shadow: none;
    padding: 0 0 32px;
    margin-bottom: 32px;
    border-bottom: 4px double #6b7280;
}
#reportContent .detail-section:last-child {
    border-bottom: none;
}
/* When a section is followed only by hidden sections (toggled off
 * via .rpt-section-hidden), drop its trailing rule — there's nothing
 * visible after it to separate from. Modern browsers support :has(). */
#reportContent .detail-section:not(:has(~ .detail-section:not(.rpt-section-hidden))) {
    border-bottom: none;
    padding-bottom: 0;
    margin-bottom: 0;
}
/* Schedule Spreadsheet section — the last day's .rpt-sched-sheet-day
 * already has a heavy 2px black outline serving as a section-end
 * marker. Stacking the section's own `4px double` rule on top of
 * that produces a visibly doubled/tripled line at the bottom of the
 * report. Drop it here; the next section's own header / spacing
 * handles separation when one follows. */
#reportContent .detail-section[data-section="schedule_sheet"] {
    border-bottom: none;
    padding-bottom: 0;
}
#reportContent .detail-section h2 {
    border-bottom: 1px solid var(--border-light);
}

/* ====================================================================
 * Responsive — site-wide
 *
 * Two breakpoints: half-page (≤1024px, e.g. browser at 50% on a desktop
 * monitor) and phone (≤600px). Most fixes are: let nav wrap, drop the
 * right sidebar below content, stack stacked-flex rows, and on the
 * crew-schedule page move the unassigned-tasks pool ABOVE the timeline
 * as a horizontal pill row so the timeline (which can't be made
 * phone-shaped) is at least visible without scrolling past the pool.
 * The spreadsheet stays wide and scrolls horizontally — per-table.
 * ==================================================================== */

@media (max-width: 1024px) {
    /* Top nav: wrap to multiple rows, tighter spacing. */
    .top-nav {
        flex-wrap: wrap;
        height: auto;
        min-height: var(--header-height);
        padding: 4px 12px;
        gap: 4px 8px;
        row-gap: 4px;
    }
    .top-nav .nav-links {
        flex-wrap: wrap;
        gap: 0 8px;
    }
    .top-nav .nav-right {
        flex-wrap: wrap;
        gap: 4px;
    }
    .top-nav .searchable-project-picker {
        min-width: 140px;
    }

    /* Right-side sidebar: drop below main content instead of squeezing. */
    .page-wrapper {
        flex-direction: column;
    }
    .sidebar {
        width: 100%;
        height: auto;
        position: static;
        border-left: none;
        border-top: 1px solid var(--border);
    }

    /* Main content: tighter side padding so wide tables have room. */
    .main-content {
        padding: 12px 16px;
    }

    /* Crew schedule grid + pool sidebar: stack vertically with the pool
     * ABOVE the timeline so the horizontally-scrolling timeline doesn't
     * push the pool off-screen. */
    .crew-grid-with-pool {
        flex-direction: column;
    }
    .crew-pool-sidebar {
        order: -1;
        width: 100%;
        min-width: 0;
        flex-direction: column;
        max-height: 30vh;
        overflow-y: auto;
        border-radius: 8px 8px 0 0;
        border-left: 1px solid var(--border);
        border-bottom: none;
    }
    /* Pool pill flow rules live in the base #taskPool block — no
     * overrides needed at this breakpoint. */

    /* Tools panel sits inline with pool — also full-width above timeline. */
    .crew-tools-sidebar {
        order: -1;
        width: 100%;
        min-width: 0;
        max-height: 50vh;
    }

    /* Schedule title row + buttons: wrap. */
    body[data-url-name="crew_schedule"] .main-content > :first-child {
        flex-wrap: wrap;
    }

    /* Reports + admin modals: full-width on smaller screens. */
    .manage-req-modal {
        width: 95vw !important;
        max-width: 95vw !important;
    }

    /* Generic flex utility rows: wrap so big buttons don't overflow. */
    .flex.justify-between { flex-wrap: wrap; gap: 6px; }

    /* Tasks/Roster bottom grid: stack vertical on smaller screens
     * (two-column is only useful with enough horizontal room). */
    .crew-bottom-grid {
        grid-template-columns: 1fr;
    }

    /* ---- Dashboard rows: wrap into vertical layout ----
     *  1. Left (project info)
     *  2. Milestones (only if any)
     *  3. Requirements
     *  4. People (Sales/PM/CC) + Next Step on the same row
     *  5. Action buttons
     *  6. Feed (notes/todos/specs) — internally scrolling
     * Each block goes full-width except people+next-step which share
     * 50/50.
     */
    #projectList { overflow-x: visible; }
    .project-group {
        min-width: 0;
    }
    .dash-row {
        flex-wrap: wrap;
        min-width: 0;
    }
    .dash-row > .dash-col {
        flex: 0 0 100%;
        width: auto;
        min-width: 0;
        max-width: 100%;
        border-right: none;
        border-bottom: 1px solid var(--border-light);
    }
    .dash-row > .dash-col:last-child { border-bottom: none; }

    /* The milestone-alert stripe is a 2em ::before pinned left:0 across
     * the whole row. In flat-row layout only the first column got the
     * cleared padding; in the wrapped vertical layout EVERY column sits
     * over the stripe, so push them all clear. */
    .dash-row-ms-overdue   > .dash-col,
    .dash-row-ms-alerting  > .dash-col,
    .dash-row-ms-upcoming  > .dash-col {
        padding-left: calc(2em + 10px);
    }
    .dash-row > .dash-col-left      { order: 1; }
    .dash-row > .dash-col-ms-alerts { order: 2; }
    .dash-row > .dash-col-reqs      { order: 3; }
    .dash-row > .dash-col-people    {
        order: 4;
        flex: 0 0 50%;
        max-width: 50%;
        border-right: 1px solid var(--border-light);
    }
    .dash-row > .dash-col-field     {
        order: 5;
    }
    .dash-row > .dash-col-actions   { order: 6; }
    .dash-row > .dash-col-notes     { order: 7; }

    /* Feed (notes/todos/specs) on smaller screens: each card is 1.5in
     * wide and the strip wraps + scrolls vertically inside a fixed
     * ~96px window. Cards flow left-to-right then wrap to the next row
     * inside the scroll viewport. */
    .dash-col-notes {
        display: block;  /* drop the flex-row default so the strip can size to 100% */
    }
    .dash-col-notes .dash-notes-strip {
        flex-direction: row;
        flex-wrap: wrap;
        max-height: 96px;
        overflow-y: auto;
        gap: 4px;
        width: 100%;
        box-sizing: border-box;
        align-content: flex-start;
    }
    .dash-col-notes .dash-note-card {
        flex: 0 0 1.5in;
        width: 1.5in;
        box-sizing: border-box;
        /* 4 lines tall: 1 header (~22px) + 3 body lines (~18px each) +
         * a bit of padding. Card is display:flex column with the
         * textarea already `flex: 1`, so the body fills the leftover
         * space below the header. */
        height: 88px;
    }
    .dash-col-notes .dash-note-card .dash-feed-input {
        height: 100%;
        line-height: 1.4;
    }
}

@media (max-width: 600px) {
    /* Top nav: bare-minimum compact — text scrunches but stays usable. */
    :root { --header-height: 44px; }
    .top-nav {
        padding: 2px 6px;
        gap: 2px 6px;
        font-size: 12px;
    }
    .top-nav .logo { font-size: 13px; margin-right: 8px; padding-left: 6px; }
    .top-nav .logo .logo-sub { font-size: 7px; }
    .top-nav .nav-links a { padding: 2px 4px; font-size: 11px; }
    .top-nav .nav-right { font-size: 11px; }
    .top-nav .nav-right .btn,
    .top-nav .nav-right .form-control { font-size: 11px; padding: 2px 6px; }
    .top-nav .nav-right .text-muted,
    .top-nav .nav-right label { display: none; }

    /* Main content: minimum side padding. */
    .main-content { padding: 6px 8px; }

    /* Forms: stack vertical. */
    .crew-task-form-inline,
    .form-grid {
        flex-direction: column;
        align-items: stretch;
    }
    .form-grid > * { width: 100% !important; }

    /* Long flex rows that aren't tables → vertical stacks. */
    .flex.gap-2, .flex.gap-4 {
        flex-wrap: wrap;
    }

    /* Page title rows: smaller heading, wrap controls. */
    h1 { font-size: 18px !important; }
    h2 { font-size: 16px; }

    /* Drawer (right-side slide-out modal): full width. */
    .drawer { width: 100% !important; max-width: 100% !important; }

    /* Pool sidebar: smaller pills, lower max-height. */
    .crew-pool-sidebar { max-height: 22vh; }
    .crew-pool-sidebar #taskPool .crew-task-block {
        font-size: 10px;
        padding: 2px 6px;
    }

    /* Change drawer: tighter so 4 rows still fit on a small screen. */
    .sheet-change-drawer-toggle { padding: 2px 8px; font-size: 11px; }
    .sheet-change-row { gap: 8px; }
    .sheet-change-row .sheet-change-name { max-width: 140px; }
    .sheet-change-row .sheet-change-day { display: none; }

    /* Spreadsheet: keep horizontal scroll, but tighten per-cell padding. */
    .sheet-table { font-size: 10px; }
    .sheet-table th,
    .sheet-table td { padding: 2px 4px; }
    .sheet-cell-input { font-size: 10px; padding: 1px 4px; }

    /* Modals: full viewport. */
    .manage-req-modal,
    .find-crew-modal {
        width: 100vw !important;
        max-width: 100vw !important;
        height: 100vh !important;
        max-height: 100vh !important;
        border-radius: 0;
    }
    .manage-req-modal-overlay { padding: 0; }

    /* Sidebar: collapsed-style minimal. */
    .sidebar { padding: 8px; }

    /* Reports: 1-col project picker, stack action buttons. */
    #reportSectionToggles { font-size: 11px; gap: 6px; }

    /* Crew sheet font: tiny by default to fit. */
    .crew-sheet-table { font-size: 9px; }

    /* Dashboard on phone: people + next-step stack full-width too
     * (50/50 was OK at half-page, too cramped at <600px). */
    .dash-row > .dash-col-people,
    .dash-row > .dash-col-field {
        flex: 0 0 100%;
        max-width: 100%;
        border-right: none;
    }
    /* Sales / PM / CC inline 3-up so the people row stays one row tall. */
    .dash-col-people {
        flex-direction: row !important;
        gap: 6px;
    }
    .dash-col-people .dash-people-field { flex: 1 1 0; min-width: 0; }
}

@media print {
    .top-nav, .sidebar, .btn, .no-print,
    .milestone-alert-placeholder, #milestoneAlertBanner,
    #todoAlertBanner,
    .drawer, .drawer-overlay {
        display: none !important;
    }
    .rpt-internal {
        display: none !important;
    }
    .main-content {
        padding: 0;
    }
    .report-section {
        page-break-after: always;
    }
    /* On screen we use generous whitespace + a double rule for clarity.
       On paper that wastes vertical space — tighten it so sections pack
       together and the page-break engine has more leeway. */
    #reportContent .detail-section {
        padding-bottom: 8px;
        margin-bottom: 8px;
    }
    @page {
        size: landscape;
        margin: 0.5in;
    }
}

/* Add-row at the bottom of fixture/trucking spreadsheets. The separator row
   gives a clear visual break between existing data and the entry row. */
.add-row-separator td {
    border: none !important;
    padding: 0 !important;
    height: 8px;
    border-top: 2px solid #d1d5db !important;
    background: transparent;
}
.add-row td {
    background: #f9fafb;
    padding: 4px;
}
.add-row .inline-edit {
    width: 100%;
    box-sizing: border-box;
}

/* Items flagged internal — greyed out in browser, hidden in print. */
.rpt-internal {
    opacity: 0.4;
}

/* Sections toggled off via the top-bar checkboxes — hidden in browser
   and print alike. */
.rpt-section-hidden {
    display: none !important;
}

/* ---- Wave-2: "Clean view" (copy-for-email) ---- */
/* Same effect as the @media print rule above ('.no-print'/'.rpt-internal'
   hidden), but toggleable on-screen so a plain Ctrl+C also yields a clean
   copy without printing first. Scoped to #reportContent so the toolbar's
   own no-print controls (including this checkbox) stay visible. */
#reportContent.report-clean-view .no-print,
#reportContent.report-clean-view .rpt-internal {
    display: none !important;
}

/* ---- Wave-2: per-report-type column-hide popover ---- */
.rpt-col-toggle {
    position: relative;
    display: inline-block;
    font-size: 11px;
    color: #4b5563;
}
.rpt-col-toggle > summary {
    cursor: pointer;
    user-select: none;
}
.rpt-col-toggle-list {
    position: absolute;
    top: 100%;
    left: 0;
    z-index: 20;
    margin-top: 4px;
    padding: 6px 10px;
    background: #fff;
    border: 1px solid var(--border-light, #e5e7eb);
    border-radius: 4px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
    display: flex;
    flex-direction: column;
    gap: 2px;
    white-space: nowrap;
}
.rpt-col-toggle-list label {
    display: flex;
    align-items: center;
    gap: 4px;
    font-weight: 400;
    color: #374151;
}

/* "Separate sections" toggle: each section starts on a new page when
   printing, and gets a thicker rule on screen so the boundaries read like
   independent sheets. */
@media print {
    .rpt-section-page-break {
        page-break-before: always;
    }
    .report-section > .rpt-section-page-break:first-child {
        page-break-before: auto;
    }
}

/* ---- Crew Sheet ---- */
.crew-sheet-table {
    border-collapse: collapse;
    font-size: var(--crew-sheet-font-size, 13px);
}
.crew-sheet-table th,
.crew-sheet-table td {
    border: 1px solid #9ca3af;  /* darker than default — stands out on the section gradient */
}
.crew-sheet-table thead th.crew-sheet-day {
    background: #f3f4f6;
}
.crew-sheet-table .crew-sheet-name {
    white-space: nowrap;
    padding: 4px 8px;
}
.crew-sheet-table .crew-sheet-cell {
    padding: 4px;
    text-align: center;
    font-size: 12px;
}
.crew-sheet-table .crew-sheet-day {
    text-align: center;
    padding: 2px 4px;
    white-space: nowrap;
}
/* Dark days — gap days with no project work. Striped grey background. */
.crew-sheet-table .crew-sheet-dark {
    background: repeating-linear-gradient(45deg, #e5e7eb, #e5e7eb 4px, #d1d5db 4px, #d1d5db 8px);
    color: #6b7280;
}
.crew-sheet-table thead th.crew-sheet-dark {
    background: #d1d5db;
    color: #4b5563;
    font-style: italic;
}
/* Each .crew-sheet-block is one row table holding CHUNKS_PER_ROW × 7 days
   plus a single Name/Phone/Email column on the left. Rows stack vertically;
   the name column repeats with each new row. Spacer cells provide a small
   visual gap between the 7-day groups within a row. */
.crew-sheet-blocks {
    display: flex;
    flex-direction: column;
    gap: 16px;
}
.crew-sheet-table .crew-sheet-spacer {
    border: none !important;
    background: transparent !important;
    width: 12px;
    padding: 0;
}
.crew-sheet-row-header {
    font-size: 12px;
    font-weight: 700;
    color: #4b5563;
    margin: 0 0 4px;
}
/* Title embedded inside the first row's page-break-inside container, so
   it cannot get stranded at the bottom of a page. Mirrors the look of a
   normal section H2. */
.crew-sheet-section-title {
    font-size: 16px;
    font-weight: 600;
    margin: 0 0 12px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--border-light);
}
/* Synthetic "unfilled" row — italicized name, role still shown plain in
   the day cells so it reads like any other crew row. */
.crew-sheet-unfilled .crew-sheet-name em {
    font-style: italic;
    color: #6b7280;
}
.crew-sheet-team-tag {
    font-size: 9px;
    color: #6b7280;
    line-height: 1.1;
}

/* Section header with inline option toggles. Section H2 stays on the
   left at its normal weight; the .rpt-section-opts cluster sits to the
   right with smaller text and faint dividers between checkboxes. */
.rpt-section-head {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}
.rpt-section-head h2 { margin: 0; }
.rpt-section-opts {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    font-size: 12px;
    font-weight: 400;
    color: var(--text-muted);
}
.rpt-section-opts label {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    cursor: pointer;
}

/* Crew Schedule report section — one table per project, banner rows
   separate days. table-layout: fixed + colgroup widths keep every day's
   columns aligned regardless of content. */
.rpt-crew-sched-table {
    width: 100%;
    border-collapse: collapse;
    table-layout: fixed;
    font-size: 12px;
    margin-bottom: 8px;
}
.rpt-crew-sched-table th,
.rpt-crew-sched-table td {
    padding: 3px 6px;
    border: 1px solid #e5e7eb;
    text-align: left;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.rpt-crew-sched-row-headers th {
    background: #f9fafb;
    font-weight: 600;
    font-size: 11px;
}
.rpt-crew-sched-day-banner td {
    background: #f3f4f6;
    border-left: 3px solid #6b7280;
    font-weight: 600;
    font-size: 13px;
    padding: 5px 8px;
}
.rpt-crew-sched-table td.text-center { text-align: center; }
/* Column widths for the fixed-layout grid. Sum is 100%; values chosen so
   crew names get the most room and time/E-A stay narrow. */
.rpt-cs-w-crew { width: 18%; }
.rpt-cs-w-role { width: 11%; }
.rpt-cs-w-team { width: 11%; }
.rpt-cs-w-ea   { width: 5%; }
.rpt-cs-w-time { width: 9%; }
.rpt-cs-w-meal { width: 13%; }
.rpt-cs-w-pnp  { width: 3%; }
.rpt-cs-w-paid { width: 5%; }

/* Print-only truncation: full version on screen, short version (~7 chars)
   when printing. Used in the crew sheet so names + project labels don't push
   the day grid off the page. */
.print-trunc-short { display: none; }
@media print {
    .print-trunc-full { display: none; }
    .print-trunc-short { display: inline; }
}

/* Clickable phone/email cells in the crew sheet — build a bulk-message
   list to paste into Messages or Gmail. */
.crew-bulk-clickable {
    cursor: pointer;
    color: #2563eb;
}
.crew-bulk-clickable:hover {
    text-decoration: underline;
}
.crew-edit-icon {
    cursor: pointer;
    color: #9ca3af;
    font-size: 10px;
    margin-left: 6px;
    opacity: 0;
    transition: opacity 0.1s;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.crew-contact-cell:hover .crew-edit-icon {
    opacity: 1;
}
.crew-edit-icon:hover {
    color: #2563eb;
    text-decoration: underline;
}
.crew-contact-input {
    width: 100%;
    box-sizing: border-box;
    padding: 2px 4px;
    border: 1px solid #2563eb;
    border-radius: 3px;
    font: inherit;
}
.crew-bulk-container {
    align-items: center;
    gap: 6px;
    padding: 4px 8px;
    background: #f3f4f6;
    border: 1px solid #d1d5db;
    border-radius: 4px;
    font-size: 13px;
}
.crew-bulk-label {
    font-weight: 600;
    color: #4b5563;
    /* Excluded from clipboard copy via JS — separate span from the list. */
}
.crew-bulk-list {
    font-family: ui-monospace, SFMono-Regular, monospace;
    font-size: 12px;
    user-select: text;
    max-width: 60vw;
    overflow-x: auto;
    white-space: nowrap;
}
@media print {
    /* ---- Strict mode (default) ----
       Big containers stay together at the cost of trailing whitespace
       at page bottoms. */
    .crew-sheet-block {
        page-break-inside: avoid;
    }
    .rpt-day-block {
        page-break-inside: avoid;
    }
    /* Don't orphan a section header at the bottom of a page. */
    #reportContent .detail-section h2 {
        page-break-after: avoid;
    }
    .crew-sheet-row-header {
        page-break-after: avoid;
    }

    /* ---- Compact mode ----
       Body class toggled by the "Compact print" checkbox. Loosens the big
       containers above so content packs tightly across page boundaries,
       and only protects small atomic units (single day cards, individual
       table rows / list items) from being sliced. */
    body.print-compact .crew-sheet-block,
    body.print-compact #reportContent .detail-section h2,
    body.print-compact .crew-sheet-row-header {
        page-break-after: auto !important;
        page-break-inside: auto !important;
    }
    body.print-compact .rpt-day-block,
    body.print-compact .rpt-req-card,
    body.print-compact .note-item,
    body.print-compact .todo-item,
    body.print-compact .rpt-fixture-table tr,
    body.print-compact .crew-sheet-table tr {
        page-break-inside: avoid;
    }

    /* Schedule Spreadsheet section in compact print:
     *  • Drop the per-day bottom margin so days pack edge-to-edge.
     *  • Let the day's container break across pages (the heavy 2px
     *    border still marks the boundary visually).
     *  • Only protect individual task / note rows from being sliced
     *    so a row of text never gets cut in half.
     */
    body.print-compact .rpt-sched-sheet-day {
        margin-bottom: 0;
        page-break-inside: auto;
    }
    body.print-compact .rpt-sched-sheet-table tbody tr {
        page-break-inside: avoid;
    }

    /* Tighter padding + smaller default font so a row of crew typically
       fits within one landscape page (~7.5" tall). */
    .crew-sheet-table {
        font-size: var(--crew-sheet-print-font-size, 9px);
    }
    .crew-sheet-table th,
    .crew-sheet-table td {
        padding: 1px 3px;
    }
    .crew-sheet-table .crew-sheet-cell {
        padding: 1px 2px;
    }
    .crew-sheet-table .crew-sheet-name {
        padding: 1px 4px;
    }
}

/* Fixture table on the report. */
.rpt-fixture-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
}
.rpt-fixture-table th,
.rpt-fixture-table td {
    text-align: left;
    padding: 4px 8px;
    border-bottom: 1px solid #e5e7eb;
    vertical-align: top;
}
.rpt-fixture-table th {
    font-weight: 600;
    background: #f9fafb;
}

/* ---- Filter Bar ---- */

.filter-bar {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-bottom: 16px;
    flex-wrap: wrap;
}

.filter-bar select,
.filter-bar input {
    padding: 5px 10px;
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 13px;
    font-family: inherit;
}

/* ---- Tabs ---- */

.tab-bar {
    display: flex;
    gap: 0;
    border-bottom: 2px solid var(--border);
    margin-bottom: 16px;
}

.tab-bar .tab {
    padding: 8px 16px;
    font-size: 13px;
    font-weight: 500;
    color: var(--text-muted);
    cursor: pointer;
    border-bottom: 2px solid transparent;
    margin-bottom: -2px;
    transition: color 0.15s, border-color 0.15s;
    background: none;
    border-top: none;
    border-left: none;
    border-right: none;
}

.tab-bar .tab:hover {
    color: var(--text);
}

.tab-bar .tab.active {
    color: var(--primary);
    border-bottom-color: var(--primary);
}

.tab-content {
    display: none;
}

.tab-content.active {
    display: block;
}

/* ---- Empty State ---- */

.empty-state {
    text-align: center;
    padding: 40px;
    color: var(--text-muted);
}

.empty-state p {
    margin-bottom: 12px;
}

/* ---- Login Page ---- */

.login-page {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    background: var(--bg-alt);
}

.login-card {
    background: var(--bg);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 32px;
    width: 360px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}

.login-card h1 {
    font-size: 22px;
    margin-bottom: 24px;
    text-align: center;
}

.login-card .form-group {
    margin-bottom: 16px;
}

.login-card .btn-primary {
    width: 100%;
    padding: 10px;
    font-size: 14px;
}

/* ---- Utilities ---- */

/* ---- Manage Requirements Modal ---- */

.manage-req-modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.4);
    z-index: 300;
    display: flex;
    align-items: center;
    justify-content: center;
}

.manage-req-modal {
    background: var(--bg);
    border-radius: 12px;
    width: 80vw;
    max-width: 90vw;
    max-height: 80vh;
    display: flex;
    flex-direction: column;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
}

.manage-req-modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px;
    border-bottom: 1px solid var(--border);
}

.manage-req-modal-header h3 {
    font-size: 16px;
    font-weight: 600;
}

.manage-req-modal-body {
    padding: 16px 20px;
    overflow-y: auto;
    flex: 1;
}

.manage-req-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 0;
    border-bottom: 1px solid var(--border-light);
}

.manage-req-item:last-child {
    border-bottom: none;
}

.manage-req-tabs {
    display: flex;
    gap: 2px;
    background: var(--border-light);
    border-radius: 6px;
    padding: 2px;
}

.manage-req-tab {
    padding: 4px 14px;
    font-size: 12px;
    font-weight: 500;
    border: none;
    background: transparent;
    border-radius: 4px;
    cursor: pointer;
    color: var(--text-muted);
}

.manage-req-tab.active {
    background: var(--bg);
    color: var(--text);
    box-shadow: 0 1px 2px rgba(0,0,0,0.08);
}

/* ---- DateType Grid (spreadsheet-style modal) ---- */
.dt-grid {
    display: grid;
    grid-template-columns: 60px 1fr 50px 62px 74px 64px 64px 64px 32px;
    gap: 4px;
    align-items: center;
    padding: 4px 0;
}
.dt-grid-header {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 2px;
}
.dt-grid-row {
    border-bottom: 1px solid var(--border-light);
    padding: 3px 0;
}
.dt-grid-row:hover {
    background: var(--bg-alt);
}
.dt-col-sort { text-align: center; }
.dt-col-name { min-width: 0; }
.dt-col-color { text-align: center; justify-self: center; }
.dt-col-check { text-align: center; justify-self: center; }
.dt-col-del { text-align: center; justify-self: center; }
.dt-grid-row .form-control {
    font-size: 12px;
    padding: 3px 6px;
    height: auto;
}
.dt-color-input {
    width: 32px;
    height: 26px;
    padding: 1px;
    border: 1px solid var(--border);
    border-radius: 4px;
    cursor: pointer;
    background: none;
}
.dt-check-label {
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0;
    cursor: pointer;
}
.dt-check {
    width: 16px;
    height: 16px;
    cursor: pointer;
}
.dt-del-btn {
    color: #991b1b !important;
    font-size: 16px;
    line-height: 1;
    padding: 2px 6px;
}
.dt-del-btn:hover {
    background: #fee2e2;
}

/* ---- DateType delete modal (in-use: replace or cascade) ---- */
.dt-del-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    z-index: 10001;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}
.dt-del-modal-box {
    background: var(--bg, #fff);
    color: var(--text, #111);
    border: 1px solid var(--border);
    border-radius: 8px;
    max-width: 520px;
    width: 100%;
    padding: 18px 20px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
    font-size: 13px;
}
.dt-del-modal-head {
    font-size: 15px;
    font-weight: 700;
    margin-bottom: 10px;
}
.dt-del-usage { margin-bottom: 10px; line-height: 1.5; }
.dt-del-projs { margin-top: 4px; color: var(--text-muted); font-size: 12px; }
.dt-del-note {
    background: #fffbeb;
    border: 1px solid #fcd34d;
    color: #92400e;
    border-radius: 6px;
    padding: 7px 10px;
    font-size: 12px;
    margin-bottom: 12px;
}
.dt-del-section {
    border-top: 1px solid var(--border-light);
    padding-top: 12px;
    margin-top: 4px;
}
.dt-del-section-title { font-weight: 600; margin-bottom: 8px; }
.dt-del-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.dt-del-alias-check,
.dt-del-alias-row {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 8px;
    font-size: 12px;
    color: var(--text-muted);
    flex-wrap: wrap;
}
.dt-del-danger .dt-del-section-title { color: #991b1b; }
.dt-del-everything { margin-top: 10px; }
.dt-del-modal-foot { margin-top: 16px; text-align: right; }

/* ---- API Feedback States ---- */

/* Global API toast — fixed pill at top-center. */
.api-toast {
    position: fixed;
    top: 8px;
    left: 50%;
    transform: translateX(-50%) translateY(-40px);
    padding: 6px 14px;
    border-radius: 6px;
    font-size: 12px;
    font-weight: 700;
    z-index: 9999;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.15s, transform 0.15s;
    white-space: pre-line;
    text-align: center;
    max-width: 80vw;
}
.api-toast.visible {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}
.api-toast-pending { background: #fefce8; color: #92400e; border: 1px solid #facc15; }
.api-toast-success { background: #f0fdf4; color: #166534; border: 1px solid #22c55e; }
.api-toast-error   { background: #fef2f2; color: #991b1b; border: 1px solid #ef4444; }

.feedback-pending {
    background-color: #fefce8 !important;
    border-color: #facc15 !important;
    transition: background-color 0.15s, border-color 0.15s;
}

.feedback-success {
    background-color: #f0fdf4 !important;
    border-color: #22c55e !important;
    transition: background-color 0.15s, border-color 0.15s;
}

.feedback-error {
    background-color: #fef2f2 !important;
    border-color: #ef4444 !important;
    transition: background-color 0.15s, border-color 0.15s;
}

/* ---- Utilities ---- */

.text-muted { color: var(--text-muted); }
.text-sm { font-size: 12px; }
.text-xs { font-size: 11px; }
.mt-2 { margin-top: 8px; }
.mt-4 { margin-top: 16px; }
.mb-2 { margin-bottom: 8px; }
.mb-4 { margin-bottom: 16px; }
.flex { display: flex; }
.flex-wrap { flex-wrap: wrap; }
.gap-2 { gap: 8px; }
.gap-4 { gap: 16px; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.hidden { display: none; }

/* Impersonation banner */
.impersonation-banner {
    background: #d32f2f;
    color: #fff;
    padding: 8px 20px;
    font-size: 0.85rem;
    text-align: center;
    font-weight: 500;
}
.impersonation-banner strong {
    font-weight: 700;
}

/* Milestone alert banner */
.milestone-alert-placeholder {
    min-height: 38px;
}
.milestone-alert-placeholder:empty {
    min-height: 38px;
}
.milestone-alert-banner {
    background: #fef3c7;
    border-bottom: 1px solid #f59e0b;
    padding: 8px 20px;
    font-size: 13px;
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}
.milestone-alert-banner.has-overdue {
    background: #fee2e2;
    border-bottom-color: #ef4444;
}
/* Background-refresh banner — subtle blue/neutral variant of the alert banner.
   Shown only when a live change was deferred because the user was mid-edit. */
.bg-refresh-banner {
    background: #eff6ff;
    border-bottom: 1px solid #93c5fd;
    color: #1e3a5f;
}
.bg-refresh-banner .milestone-alert-label {
    font-weight: 600;
}
.bg-refresh-apply {
    color: #2563eb;
    font-weight: 600;
    text-decoration: underline;
    cursor: pointer;
}
.bg-refresh-apply:hover {
    color: #1d4ed8;
}
.bg-refresh-dismiss {
    margin-left: auto;
    background: none;
    border: none;
    color: #64748b;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    padding: 0 4px;
}
.bg-refresh-dismiss:hover {
    color: #1e293b;
}

/* Always-on freshness badge: "Refreshed 4:55pm · 13 changes". Small, fixed in
   the bottom-right, subtle until it flashes on a change. */
.bg-refreshed-badge {
    position: fixed;
    right: 10px;
    bottom: 10px;
    z-index: 900;
    padding: 3px 9px;
    border-radius: 10px;
    background: rgba(30, 41, 59, 0.82);
    color: #e2e8f0;
    font-size: 11px;
    line-height: 1.4;
    white-space: nowrap;
    pointer-events: none;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
    transition: background 0.4s, color 0.4s;
}
.bg-refreshed-badge--flash {
    background: #1a7f37;
    color: #fff;
}

/* Year badge on the detail Dates rows — surfaces the real year hidden behind
   the M/D display. Non-current years turn red so stale dates are obvious. */
.date-year-badge {
    font-size: 11px;
    font-weight: 700;
    color: #6b7280;
    min-width: 52px;
    padding: 1px 6px;
    border-radius: 6px;
    background: #f3f4f6;
    text-align: center;
    flex-shrink: 0;
}
.date-year-badge.year-old {
    background: #fee2e2;
    color: #b91c1c;
}

/* Kanban "+ Add column" — creates a private per-user status column. */
.kb-col-add {
    min-width: 120px;
    background: transparent;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding-top: 8px;
}
.kb-add-col-btn {
    border: 1px dashed #9ca3af;
    background: transparent;
    color: #6b7280;
    border-radius: 6px;
    padding: 6px 10px;
    font-size: 12px;
    cursor: pointer;
    white-space: nowrap;
}
.kb-add-col-btn:hover {
    border-color: #4b5563;
    color: #374151;
    background: #f9fafb;
}

/* Project-search boxes (dashboard + calendar Find-Project) turn highlighter
   yellow while focused, so it's obvious you're in search mode (Ctrl/Cmd-F). */
#dashSearchBar:focus,
#calSearchInput:focus {
    background: #fff275;
}

/* Red border on the element the user is focused in when an update is waiting on
   it (applied via the "apply updates" banner, or on blur). outline = no reflow. */
.bg-focus-pending {
    outline: 2px solid #e11d48 !important;
    outline-offset: -1px;
    border-radius: 3px;
}
.milestone-alert-item {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 4px;
    background: rgba(0,0,0,0.06);
    cursor: pointer;
    text-decoration: none;
    color: inherit;
}
.milestone-alert-item:hover {
    background: rgba(0,0,0,0.1);
}
.milestone-alert-item.overdue {
    color: #dc2626;
    font-weight: 600;
}
.milestone-alert-item.alerting {
    color: #d97706;
    font-weight: 600;
}
.milestone-alert-label {
    font-weight: 700;
    margin-right: 4px;
    white-space: nowrap;
}

/* Watch button on dashboard */
.dash-watch-btn {
    cursor: pointer;
    font-size: 14px;
    color: #d1d5db;
    flex-shrink: 0;
    user-select: none;
    transition: color 0.15s;
    line-height: 1;
}
.dash-watch-btn:hover {
    color: #f59e0b;
}
.dash-watch-btn.watched {
    color: #f59e0b;
}

/* Snooze / don't-care (level-of-attention) row controls */
.dash-snooze-btn,
.dash-dontcare-btn {
    cursor: pointer;
    font-size: 12px;
    flex-shrink: 0;
    user-select: none;
    line-height: 1;
    opacity: 0.4;
    filter: grayscale(1);
    transition: opacity 0.15s, filter 0.15s;
}
.dash-snooze-btn:hover,
.dash-dontcare-btn:hover,
.dash-dontcare-btn.active {
    opacity: 1;
    filter: none;
}
.dash-attention-badge {
    font-size: 11px;
    font-style: italic;
    color: var(--text-muted);
    flex-shrink: 0;
}
.dash-attention-badge:empty {
    display: none;
}
/* Revealed-but-muted rows (snoozed / don't-care) render greyed when
   "Show snoozed/ignored" is on; hidden entirely otherwise (JS filter). */
.dash-row-muted {
    opacity: 0.5;
}
.dash-row-muted:hover {
    opacity: 0.85;
}
/* Project-detail header "Don't care" toggle (active = marked) */
.dontcare-toggle.active {
    background: #fee2e2;
    border-color: #ef4444;
    color: #b91c1c;
}

/* ---- Import page ---- */
.import-section h2 {
    font-size: 16px;
    font-weight: 600;
    margin-bottom: 8px;
}
.import-initials-table {
    border-collapse: collapse;
    font-size: 13px;
}
.import-initials-table th {
    text-align: left;
    padding: 4px 12px 4px 0;
    font-weight: 600;
    font-size: 11px;
    text-transform: uppercase;
    color: var(--text-muted);
}
.import-initials-table td {
    padding: 4px 12px 4px 0;
}
.import-summary {
    background: var(--bg-alt);
    padding: 8px 12px;
    border-radius: 6px;
    font-size: 13px;
    display: flex;
    align-items: center;
    gap: 4px;
}
.import-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border-bottom: 1px solid #f0f0f0;
    font-size: 13px;
    transition: opacity 0.15s;
}
.import-row:hover {
    background: #fafafa;
}
.import-row-unchecked {
    opacity: 0.45;
}
.import-row-header {
    background: #f3f4f6;
    font-weight: 600;
    font-size: 12px;
    text-transform: uppercase;
    color: var(--text-muted);
}
.import-check-label {
    display: flex;
    align-items: center;
    cursor: pointer;
    margin: 0;
    flex-shrink: 0;
}
.import-name {
    flex: 3;
    min-width: 200px;
    font-weight: 500;
}
.import-sales {
    flex: 1.5;
    min-width: 100px;
    color: var(--text-muted);
    font-size: 12px;
}
.import-status {
    width: 60px;
    font-size: 11px;
    color: var(--text-muted);
}
.import-job {
    width: 100px;
    font-size: 11px;
    font-family: monospace;
    color: var(--text-muted);
}
.import-dates-count,
.import-crew-count {
    width: 55px;
    font-size: 11px;
    color: var(--text-muted);
    text-align: right;
}
.import-match {
    width: 130px;
    text-align: right;
}
.import-badge {
    display: inline-block;
    padding: 1px 6px;
    border-radius: 4px;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.3px;
}
.import-badge-new {
    background: #dcfce7;
    color: #15803d;
}
.import-badge-update {
    background: #fef3c7;
    color: #92400e;
}
.import-badge-header {
    background: #e5e7eb;
    color: #6b7280;
}
.import-badge-fuzzy {
    background: #dbeafe;
    color: #1d4ed8;
    margin-left: 4px;
}
.import-flags {
    width: 100%;
    padding-left: 28px;
}
.import-flag {
    display: inline-block;
    font-size: 11px;
    color: #d97706;
    background: #fffbeb;
    padding: 1px 6px;
    border-radius: 3px;
    margin-right: 4px;
}
.import-match-info {
    width: 100%;
    padding-left: 28px;
}
.import-results-box {
    background: #f9fafb;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    padding: 16px;
}
.import-errors {
    color: #dc2626;
    margin-top: 8px;
    font-size: 13px;
}
.import-details-list {
    max-height: 300px;
    overflow-y: auto;
    margin-top: 4px;
    padding: 4px 0;
}

/* ---- Kanban Board ---- */

.kanban-board {
    display: flex;
    gap: 10px;
    overflow-x: auto;
    padding-bottom: 12px;
    align-items: flex-start;
}

.kb-col {
    flex: 0 0 220px;
    min-width: 220px;
    background: var(--bg-alt);
    border: 1px solid var(--border-light);
    border-radius: 8px;
    display: flex;
    flex-direction: column;
    overflow: visible;
}

.kb-col-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 10px;
    border-bottom: 1px solid var(--border-light);
    font-weight: 600;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    color: var(--text-muted);
}

.kb-col-title {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.kb-col-count {
    background: var(--border);
    color: var(--text-muted);
    font-size: 11px;
    font-weight: 700;
    padding: 1px 7px;
    border-radius: 10px;
    min-width: 20px;
    text-align: center;
    flex-shrink: 0;
}

.kb-quick-add {
    padding: 6px 8px;
    border-bottom: 1px solid var(--border-light);
}

.kb-quick-input {
    width: 100%;
    border: 1px solid var(--border-light);
    border-radius: 4px;
    padding: 5px 8px;
    font-size: 12px;
    background: var(--bg);
    color: var(--text);
    outline: none;
    transition: border-color 0.15s;
}

.kb-quick-input:focus {
    border-color: var(--primary);
    box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.15);
}

.kb-quick-input::placeholder {
    color: var(--text-light);
}

.kb-cards {
    flex: 1;
    overflow-y: visible;
    padding: 6px 8px;
    min-height: 40px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    transition: background 0.15s;
}

.kb-cards:empty::after {
    content: '';
    display: block;
    min-height: 30px;
}

.kb-card {
    background: var(--bg);
    border: 1px solid var(--border-light);
    border-radius: 6px;
    padding: 8px 10px;
    cursor: grab;
    transition: box-shadow 0.15s, opacity 0.15s, border-color 0.15s;
    user-select: none;
    position: relative;
    overflow: visible;
}

.kb-card:hover {
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
    border-color: var(--border);
}

.kb-card:active {
    cursor: grabbing;
}

/* The dragging card stays in the DOM as a "placeholder" — it's moved live
 * to the cursor's insertion point so siblings reflow around it. Style it as
 * an outline/ghost so the drop target is visually obvious. */
.kb-card-dragging {
    opacity: 0.45;
    border-style: dashed !important;
    border-color: var(--primary, #3b82f6) !important;
    background: rgba(59, 130, 246, 0.06) !important;
    box-shadow: none !important;
}
.kb-card-dragging * { pointer-events: none; }

.kb-drop-over {
    background: rgba(59, 130, 246, 0.06);
    border-radius: 0 0 8px 8px;
}

.kb-card-selected {
    border-color: var(--primary);
    background: #eff6ff;
    box-shadow: 0 0 0 1px var(--primary);
}

.kb-card-top {
    display: flex;
    align-items: flex-start;
    gap: 5px;
}

.kb-drag-handle {
    cursor: grab;
    color: var(--text-light);
    font-size: 14px;
    line-height: 1;
    padding: 1px 0;
    flex-shrink: 0;
    user-select: none;
    transition: color 0.15s;
}

.kb-drag-handle:hover {
    color: var(--text-muted);
}

.kb-drag-handle:active {
    cursor: grabbing;
}

.kb-card-cb {
    margin-top: 2px;
    flex-shrink: 0;
    cursor: pointer;
}

.kb-card-text {
    font-size: 13px;
    line-height: 1.4;
    word-break: break-word;
    flex: 1;
    cursor: pointer;
}

.kb-card-link {
    color: var(--primary);
    text-decoration: none;
    font-weight: 600;
}

.kb-card-link:hover {
    text-decoration: underline;
}

.kb-card-assign {
    font-size: 11px;
    color: var(--text-muted);
    margin-top: 4px;
    padding: 2px 4px;
    border-radius: 3px;
    cursor: pointer;
    position: relative;
    transition: background 0.15s;
    user-select: none;
}

.kb-card-assign:hover {
    background: var(--bg-hover);
}

.kb-assign-icon {
    font-size: 11px;
}

.kb-assign-input {
    border: 1px solid var(--primary);
    border-radius: 4px;
    padding: 3px 8px;
    font-size: 12px;
    outline: none;
    box-shadow: 0 2px 8px rgba(0,0,0,0.12);
    background: var(--bg);
    color: var(--text);
}

.kb-card-text.completed {
    text-decoration: line-through;
    color: var(--text-muted);
}

.kb-card-text-edit {
    font-size: 13px;
    line-height: 1.4;
    word-break: break-word;
    white-space: pre-wrap;
    flex: 1;
    border: 1px solid transparent;
    padding: 2px 4px;
    border-radius: 3px;
    background: transparent;
    font-family: inherit;
    width: 100%;
    min-height: 22px;
    /* Default: collapse to 5 lines. Focused/hovered-to-edit = expand fully. */
    max-height: calc(1.4em * 5 + 4px);
    overflow: hidden;
    resize: none;
    transition: max-height 0.15s ease;
}
.kb-card-text-edit:hover { border-color: var(--border-light); background: var(--bg-alt); }
.kb-card-text-edit:focus {
    outline: none;
    border-color: var(--primary);
    background: var(--bg);
    box-shadow: 0 0 0 2px rgba(59,130,246,.15);
    max-height: none;
    overflow: auto;
    resize: vertical;
}
.kb-card-text-edit.completed { text-decoration: line-through; color: var(--text-muted); }

.kb-card-meta {
    font-size: 11px;
    color: var(--text-muted);
    margin-top: 5px;
    line-height: 1.3;
}

/* Kanban card urgency backgrounds */
.kb-card-week {
    background: #fefce8;
    border-color: #fde68a;
}
.kb-card-soon {
    background: #fff7ed;
    border-color: #fdba74;
}
.kb-card-today {
    background: #fef2f2;
    border-color: #fca5a5;
}
.kb-card-overdue {
    background: #fef2f2;
    border: 3px solid #f87171;
}

/* ---- Todo Status Badges ---- */

.todo-status-badge {
    display: inline-block;
    font-size: 11px;
    padding: 1px 7px;
    border-radius: 3px;
    font-weight: 600;
    letter-spacing: 0.2px;
}

.todo-status-not_started {
    background: #f3f4f6;
    color: #6b7280;
}
.todo-status-in_progress {
    background: #dbeafe;
    color: #1d4ed8;
}
.todo-status-on_hold {
    background: #fef3c7;
    color: #92400e;
}
.todo-status-waiting {
    background: #f3e8ff;
    color: #7c3aed;
}
.todo-status-complete {
    background: #dcfce7;
    color: #15803d;
}

/* One-shot highlight for a newly created project row pinned to top. */
.dash-row-pin-flash {
    animation: dashPinFlash 2s ease-out;
}
@keyframes dashPinFlash {
    0%   { background-color: #fff7d6; }
    100% { background-color: transparent; }
}

/* Hidden schedule day — visually muted + strikethrough so the user can see
 * at a glance which days are excluded from calendar/schedule rendering.
 * Inputs stay clickable; they're how the user un-hides the row. */
.sched-day-hidden { opacity: 0.55; }
.sched-day-hidden .inline-edit,
.sched-day-hidden > span.text-sm { text-decoration: line-through; }

/* Watch toggle on project detail header. */
.btn.watch-toggle { display:inline-flex; align-items:center; gap:4px; }
.btn.watch-toggle .watch-star { font-size: 14px; line-height: 1; color: #9ca3af; }
.btn.watch-toggle.is-watched { background:#fff7d6; border-color:#f59e0b; }
.btn.watch-toggle.is-watched .watch-star { color: #f59e0b; }

/* Kanban status pills — consistent colored label on every card. */
.kb-status-pill {
    display: inline-block;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.4;
    letter-spacing: 0.2px;
    border: 1px solid transparent;
}
.kb-status-pill.status-not_started { background: #f3f4f6; color: #4b5563; border-color: #e5e7eb; }
.kb-status-pill.status-in_progress { background: #dbeafe; color: #1d4ed8; border-color: #bfdbfe; }
.kb-status-pill.status-on_hold     { background: #fef3c7; color: #92400e; border-color: #fde68a; }
.kb-status-pill.status-waiting     { background: #ede9fe; color: #5b21b6; border-color: #ddd6fe; }
.kb-status-pill.status-complete    { background: #dcfce7; color: #15803d; border-color: #bbf7d0; }

/* Reports: column-major requirements — columns of flex cards, stacked 8 tall
 * then overflow to the next column. Each card auto-widths around its content
 * (name + inline flag chips). Column width is fixed so the layout stays
 * readable in print. */
.rpt-req-cols {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: flex-start;
}
.rpt-req-col {
    flex: 0 0 auto;
    width: 320px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.rpt-req-card {
    border: 1px solid var(--border-light, #e5e7eb);
    border-radius: 4px;
    padding: 4px 8px;
    background: #fff;
    font-size: 12px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.rpt-req-card-title { line-height: 1.3; }
.rpt-req-card-flags { display: flex; flex-wrap: wrap; gap: 6px 10px; }
.rpt-req-flag {
    font-size: 11px;
    color: #4b5563;
    white-space: nowrap;
}

/* Do Next status pill */
.kb-status-pill.status-do_next { background: #fee2e2; color: #991b1b; border-color: #fecaca; }

/* Status pill is clickable — opens kb-status-menu (see below). */
.kb-status-pill-clickable { user-select: none; }
.kb-status-pill-clickable:hover { filter: brightness(0.95); }

.kb-status-menu {
    background: #fff;
    border: 1px solid var(--border, #d1d5db);
    border-radius: 6px;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    padding: 4px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 120px;
}
.kb-status-menu-item {
    padding: 4px 10px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    border: 1px solid transparent;
    cursor: pointer;
    text-align: center;
    line-height: 1.4;
}
.kb-status-menu-item:hover { filter: brightness(0.95); }
.kb-status-menu-item.kb-status-menu-active { box-shadow: 0 0 0 2px rgba(0,0,0,0.15) inset; }

/* Import: daily-update per-row category checkboxes + owner tag. */
.import-owner-tag {
    display: inline-block;
    font-size: 10px;
    padding: 1px 6px;
    border-radius: 10px;
    background: #fef3c7;
    color: #92400e;
    border: 1px solid #fde68a;
    margin-left: 6px;
}
.import-daily-cats {
    margin-top: 4px;
    padding: 4px 8px;
    background: rgba(59, 130, 246, 0.05);
    border-left: 2px solid #3b82f6;
    border-radius: 0 3px 3px 0;
    font-size: 12px;
}

/* Admin: Todo Statuses tab */
.todostatus-table th, .todostatus-table td {
    padding: 4px 6px;
    border-bottom: 1px solid var(--border-light, #e5e7eb);
    vertical-align: middle;
    text-align: left;
}
.todostatus-table th { font-size: 11px; color: #6b7280; font-weight: 600; }
.todostatus-row.ts-dragging { opacity: 0.4; }

/* Todos: Personal toggle chip (click on Generic/Personal label). */
.kb-personal-toggle {
    display: inline-block;
    padding: 1px 8px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    border: 1px solid #d1d5db;
    background: #f3f4f6;
    color: #4b5563;
    user-select: none;
    transition: all 0.12s;
}
.kb-personal-toggle:hover { background: #e5e7eb; }
.kb-personal-toggle.is-on {
    background: #ecfeff;
    color: #0e7490;
    border-color: #a5f3fc;
}

/* Public/private toggle for PROJECT todos (🌐 public / 🔒 private). */
.todo-pub-toggle {
    cursor: pointer;
    font-size: 12px;
    line-height: 1;
    padding: 0 2px;
    user-select: none;
    opacity: 0.85;
}
.todo-pub-toggle:hover { opacity: 1; }
.todo-pub-toggle.is-private { opacity: 0.7; }

/* Private (non-public) project todos read muted across every surface. */
.todos-list-dense .todo-row-private .todo-row-text {
    color: #6b7280;
    font-style: italic;
}
.todo-item.todo-row-private > div .inline-edit { font-style: italic; color: #6b7280; }
.kb-card-private { border-left: 2px dashed #9ca3af; }
.dash-feed-private { font-size: 10px; margin-left: 3px; opacity: 0.65; vertical-align: middle; }

/* Snoozed cards */
.kb-card-snoozed { opacity: 0.2; }
.kb-card-snoozed:hover { opacity: 0.8; }
.kb-snooze-btn {
    font-size: 11px; cursor: pointer; padding: 1px 6px;
    border: 1px solid var(--border-light); border-radius: 3px;
    background: #f9fafb; color: var(--text-muted);
    font-style: italic;
}
.kb-snooze-btn:hover { background: #eef2ff; border-color: #6366f1; color: #6366f1; }
.kb-snoozed-label { font-style: italic; }
.kb-snooze-menu {
    background: #fff; border: 1px solid var(--border-light);
    border-radius: 6px; box-shadow: 0 4px 12px rgba(0,0,0,0.12);
    min-width: 100px; padding: 4px 0;
}
.kb-snooze-option {
    padding: 6px 12px; font-size: 13px; cursor: pointer;
}
.kb-snooze-option:hover { background: #f0f4ff; }

/* Denser list view — single grid row per todo. Columns:
   select | done | project | pub-toggle | text (flex) | priority | status | due | snooze-btn | snoozed-label | assigned | created | delete */
.todos-list-dense .todo-row-dense {
    display: grid;
    grid-template-columns:
        18px         /* select checkbox */
        18px         /* done checkbox */
        140px        /* project */
        20px         /* public/private toggle (project todos only) */
        minmax(120px, 1fr)  /* text */
        60px         /* priority badge */
        110px        /* status */
        110px        /* due date */
        40px         /* zzz */
        60px         /* snoozed label */
        120px        /* assigned */
        50px         /* created date */
        28px;        /* delete */
    column-gap: 6px;
    align-items: center;
    padding: 3px 8px;
    border-bottom: 1px solid var(--border-light, #e5e7eb);
    font-size: 12px;
    line-height: 1.3;
}
.todos-list-dense .todo-row-dense:hover { background: #f9fafb; }
.todos-list-dense .todo-row-project {
    font-weight: 600;
    font-size: 11px;
    text-decoration: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.todos-list-dense .todo-row-text {
    border: 1px solid transparent;
    background: transparent;
    padding: 2px 4px;
    width: 100%;
    font-size: 13px;
}
.todos-list-dense .todo-row-text:hover,
.todos-list-dense .todo-row-text:focus {
    border-color: var(--border-light);
    background: #fff;
    outline: none;
}
.todos-list-dense .todo-row-text.completed {
    text-decoration: line-through;
    color: #9ca3af;
}
.todos-list-dense .todo-row-status,
.todos-list-dense .todo-row-due,
.todos-list-dense .todo-row-assigned {
    font-size: 11px;
    padding: 1px 4px;
    width: 100%;
}
.todos-list-dense .todo-row-delete {
    padding: 0 6px;
    font-size: 14px;
    line-height: 1;
}
/* Snoozed → dim and sort-to-bottom is handled in JS; CSS does the dim. */
.todos-list-dense .todo-row-snoozed { opacity: 0.5; }
.todos-list-dense .todo-row-snoozed:hover { opacity: 0.85; }

/* Reports: schedule summary + flex grid of day blocks. */
.rpt-sched-summary {
    margin-bottom: 16px;
    padding-bottom: 12px;
    border-bottom: 1px dashed #e5e7eb;
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.rpt-sched-summary-row { font-size: 13px; line-height: 1.4; }
.rpt-sched-dot {
    display: inline-block;
    width: 10px; height: 10px;
    border-radius: 50%;
    margin-right: 4px;
    vertical-align: middle;
}
.rpt-sched-range { color: #1f2937; font-variant-numeric: tabular-nums; }

/* Day blocks — flex wrap with a large row-gap so wrapped rows are clearly
 * separated; horizontal gap is modest so blocks pack tightly across. */
.rpt-sched-grid {
    display: flex;
    flex-wrap: wrap;
    column-gap: 8px;
    row-gap: 36px;
    align-items: stretch;
}

/* Schedule Spreadsheet section — one fixed-layout table per day with
 * identical column widths, so the columns line up day-to-day for
 * readability and printing. Day boundary is shown with a 2px black
 * border around the whole day's table — easier on the eyes (and
 * printer ink) than a dark header bar. */
.rpt-sched-sheet-day {
    margin-bottom: 18px;
    page-break-inside: avoid;
    border: 2px solid #000;
}
.rpt-sched-sheet-day-head {
    font-weight: 600;
    font-size: 13px;
    margin-bottom: 4px;
}
.rpt-sched-sheet-table {
    border-collapse: collapse;
    table-layout: fixed;
    width: 100%;
    font-size: 11px;
}
.rpt-sched-sheet-table col.rpt-ss-w-date    { width: 5%; }
.rpt-sched-sheet-table col.rpt-ss-w-start   { width: 6%; }
.rpt-sched-sheet-table col.rpt-ss-w-dur     { width: 6%; }
.rpt-sched-sheet-table col.rpt-ss-w-end     { width: 6%; }
.rpt-sched-sheet-table col.rpt-ss-w-name    { width: 11%; }
.rpt-sched-sheet-table col.rpt-ss-w-desc    { width: 13%; }
.rpt-sched-sheet-table col.rpt-ss-w-team    { width: 12%; }
.rpt-sched-sheet-table col.rpt-ss-w-loc     { width: 7%; }
.rpt-sched-sheet-table col.rpt-ss-w-loc-min { width: 5%; }
.rpt-sched-sheet-table col.rpt-ss-w-vendor  { width: 6%; }
.rpt-sched-sheet-table col.rpt-ss-w-contact { width: 6%; }
.rpt-sched-sheet-table col.rpt-ss-w-heq     { width: 5%; }
.rpt-sched-sheet-table col.rpt-ss-w-leads   { width: 5%; }
.rpt-sched-sheet-table td.rpt-ss-cell-leads { text-align: center; }
.rpt-sched-sheet-table col.rpt-ss-w-sh      { width: 6%; }
.rpt-sched-sheet-table th,
.rpt-sched-sheet-table td {
    /* Tight padding — vertical compressed to 1px so each row barely
     * spends any wasted space, horizontal kept to 4px so text isn't
     * jammed against the cell edge. line-height 1.3 keeps multi-line
     * cells legible without ballooning the row. */
    padding: 1px 4px;
    line-height: 1.3;
    border: 1px solid #d1d5db;
    text-align: left;
    vertical-align: top;
    /* Wrap long content instead of pushing the column wider. With
     * table-layout: fixed columns can't grow, so word-wrap is the
     * only way to handle a 30-char description. */
    overflow-wrap: break-word;
    word-break: break-word;
}
.rpt-sched-sheet-table thead th {
    background: #f3f4f6;
    font-weight: 600;
}
/* Excel-style stacked rows at the top of each day:
 *  1. banner — merged date + date_type + description
 *  2. goals — merged EOD goals
 *  3. column headers (inline as a <tr> in tbody)
 */
.rpt-sched-sheet-table .rpt-ss-row-banner td {
    /* Plain banner — no dark fill. The 2px black outline on the
     * .rpt-sched-sheet-day wrapper marks the day boundary instead, so
     * print output isn't dominated by ink-heavy headers. */
    background: transparent;
    color: #000;
    font-weight: 700;
    font-size: 12px;
    padding: 2px 6px;
    border-bottom: 1px solid #000;
}
.rpt-sched-sheet-table .rpt-ss-row-goals td {
    background: #fef3c7;
    font-size: 11px;
    padding: 1px 6px;
}
.rpt-sched-sheet-table .rpt-ss-goals-label {
    font-weight: 600;
    text-transform: uppercase;
    font-size: 10px;
    letter-spacing: 0.04em;
    color: #92400e;
    margin-right: 6px;
}
.rpt-sched-sheet-table .rpt-ss-row-summary td {
    background: #dbeafe;
    font-weight: 600;
    font-size: 10px;
    padding: 1px 6px;
    color: #1e40af;
}
.rpt-sched-sheet-table .rpt-ss-row-headers th {
    background: #f3f4f6;
    font-weight: 600;
}
.rpt-sched-sheet-table .rpt-ss-row-meal,
.rpt-sched-sheet-table .rpt-ss-row-meal td {
    background: #e5e7eb;
    color: #6b7280;
    font-weight: 600;
}
/* Overnight marker for report tables — red + bold. Applied to the date
   cell (after a "+" suffix is appended) when a row's start is past
   midnight, and to the end cell when the row's end runs past midnight. */
.rpt-cell-overnight {
    color: #c81e1e;
    font-weight: 700;
}

/* Trucking rows tint a soft green — slight enough to catch the eye
   without overpowering the row text. */
.rpt-sched-sheet-table .rpt-ss-row-trucking,
.rpt-sched-sheet-table .rpt-ss-row-trucking td {
    background: #ecfdf5;
    font-weight: 600;
}
/* Trucking line items in the simple Schedule day-block list. */
.rpt-day-tasks li.rpt-day-task-trucking {
    background: #ecfdf5;
    font-weight: 600;
    padding: 1px 4px;
    border-radius: 2px;
}
.rpt-sched-sheet-table .rpt-ss-row-note,
.rpt-sched-sheet-table .rpt-ss-row-note td {
    background: #fffbeb;
}
.rpt-sched-sheet-table .rpt-ss-note-label {
    font-style: italic;
    color: #6b7280;
}
.rpt-day-block {
    flex: 0 0 160px;
    width: 160px;
    border: 1px solid #e5e7eb;
    border-left: 4px solid #6b7280;
    border-radius: 4px;
    padding: 6px 8px;
    background: #fff;
    font-size: 12px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.rpt-day-head { line-height: 1.3; }
.rpt-day-date { font-weight: 700; font-size: 14px; font-variant-numeric: tabular-nums; }
.rpt-day-dow { font-size: 11px; margin-left: 2px; }
.rpt-day-type { font-weight: 600; font-size: 12px; color: #374151; margin-top: 1px; }
.rpt-day-desc { margin-top: 1px; line-height: 1.2; }
.rpt-day-times {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-variant-numeric: tabular-nums;
    font-size: 11px;
    border-top: 1px solid #f3f4f6;
    border-bottom: 1px solid #e5e7eb;
    padding-top: 3px;
    padding-bottom: 4px;
    margin-bottom: 4px;
}
.rpt-day-tasks {
    margin: 0;
    padding-left: 0;
    list-style: none;
    font-size: 11px;
    line-height: 1.35;
}
.rpt-day-tasks li { padding: 1px 0; }

/* Import: sticky action bar at the top of step 2. */
.import-action-bar {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    margin: 0 -12px 12px;
    background: #f9fafb;
    border: 1px solid #e5e7eb;
    border-radius: 6px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
}
.import-action-bar.is-busy {
    background: #fef3c7;
    border-color: #fcd34d;
}
.import-action-bar.is-busy #executeBtn {
    cursor: wait;
}

/* Import: Finesse modal — per-day decisions + diff highlights. */
.finesse-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
}
.finesse-table th, .finesse-table td {
    padding: 6px 8px;
    border-bottom: 1px solid #e5e7eb;
    vertical-align: top;
    text-align: left;
}
.finesse-table th {
    font-size: 11px;
    color: #6b7280;
    font-weight: 600;
    position: sticky;
    top: 0;
    background: #fff;
    z-index: 1;
    border-bottom: 1px solid #d1d5db;
}
.finesse-date { white-space: nowrap; min-width: 80px; font-variant-numeric: tabular-nums; }
.finesse-type { white-space: nowrap; }
.finesse-crew { min-width: 180px; }
.finesse-crew-item { line-height: 1.35; }

.finesse-radios { display: flex; flex-direction: column; gap: 2px; }
.finesse-radio { font-size: 11px; white-space: nowrap; }

/* Row tint per change type — muted so the table stays readable. */
.finesse-row.finesse-both    { background: rgba(168,  85, 247, 0.08); }  /* purple */
.finesse-row.finesse-day     { background: rgba(234, 179,   8, 0.10); }  /* amber */
.finesse-row.finesse-crew    { background: rgba( 59, 130, 246, 0.08); }  /* blue */
.finesse-row.finesse-added   { background: rgba( 34, 197,  94, 0.10); }  /* green */
.finesse-row.finesse-removed { background: rgba(239,  68,  68, 0.10); }  /* red */

/* Tiny swatches in the legend. Named .finesse-sw-* so they don't collide
 * with the cell-width classes like .finesse-crew (min-width:180px) that
 * live elsewhere — the legend chips were getting stretched to 180px. */
.finesse-sw {
    display: inline-block !important;
    width: 10px !important;
    height: 10px !important;
    min-width: 0 !important;
    border-radius: 2px;
    margin-right: 2px;
    vertical-align: middle;
}
.finesse-sw.finesse-sw-both    { background: rgba(168,  85, 247, 0.5); }
.finesse-sw.finesse-sw-day     { background: rgba(234, 179,   8, 0.6); }
.finesse-sw.finesse-sw-crew    { background: rgba( 59, 130, 246, 0.5); }
.finesse-sw.finesse-sw-added   { background: rgba( 34, 197,  94, 0.6); }
.finesse-sw.finesse-sw-removed { background: rgba(239,  68,  68, 0.6); }

/* Incoming type edit input inside the finesse modal. */
.finesse-incoming-edit {
    font: inherit;
    width: 14ch;
    padding: 2px 4px;
    border: 1px solid #d1d5db;
    border-radius: 3px;
    background: #fff;
}
.finesse-incoming-edit:focus {
    outline: none;
    border-color: #3b82f6;
    box-shadow: 0 0 0 2px rgba(59,130,246,.15);
}

/* Import: change-summary tags on the preview row. */
.import-change-tag {
    display: inline-block;
    font-size: 10px;
    padding: 1px 6px;
    border-radius: 10px;
    border: 1px solid transparent;
    margin-left: 6px;
    letter-spacing: 0.3px;
    font-weight: 600;
    white-space: nowrap;
}
.import-change-tag.import-change-none {
    background: #e0f2fe; color: #075985; border-color: #bae6fd;
}
.import-change-tag.import-change-some {
    background: #fef3c7; color: #92400e; border-color: #fde68a;
}
/* Hash-matched against the previous import (ImportedDay) — distinct from
 * NO CHANGE, which compares against the schedule. Surfaced separately
 * because the schedule may legitimately differ from the import (manual
 * edits) while the import itself hasn't moved. */
.import-change-tag.import-change-imported {
    background: #ede9fe; color: #5b21b6; border-color: #ddd6fe;
}
.import-change-tag.import-change-mixed {
    background: #f1f5f9; color: #334155; border-color: #cbd5e1;
}

/* Daily-update row whose Finesse decisions have been saved — the per-row
 * Schedule / Crew Names / Crew Assignments checkboxes are server-bypassed,
 * so we mute them here to match. The "(N days customised)" badge spells
 * out what's happening for the user. */
.import-row-finesse-locked input.import-cat {
    opacity: 0.5;
    cursor: not-allowed;
}
.import-row-finesse-locked label.cal-check {
    text-decoration: line-through;
    opacity: 0.7;
}

/* Finesse modal: inline "NO CHANGE" pill on unchanged day rows. */
.finesse-nochange-tag {
    display: inline-block;
    font-size: 9px;
    padding: 0 5px;
    border-radius: 8px;
    background: #e5e7eb;
    color: #6b7280;
    letter-spacing: 0.3px;
    font-weight: 600;
    vertical-align: middle;
    margin-left: 4px;
}

/* Hitlist */
.hitlist-table {
    width: auto;
    border-collapse: collapse;
    font-size: 13px;
    margin-top: 8px;
}
.hitlist-table th,
.hitlist-table td {
    border: 1px solid var(--border-light, #e5e7eb);
    padding: 4px 10px;
    text-align: left;
    vertical-align: middle;
    white-space: nowrap;
}
.hitlist-table th {
    background: #f9fafb;
    font-weight: 600;
}
.hitlist-table tr.hitlist-row-done td { color: #9ca3af; }
.hitlist-table tr.hitlist-row-done td:nth-child(2) { text-decoration: line-through; }

.hitlist-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px; border-radius: 11px; cursor: pointer;
    font-size: 13px; border: 2px solid #d1d5db; color: #9ca3af;
    transition: all .15s;
}
.hitlist-toggle:hover { border-color: #6366f1; color: #6366f1; }
.hitlist-toggle.hitlist-complete {
    background: #6366f1; border-color: #6366f1; color: #fff;
}

/* Fixture row highlight on focus */
/* Focused fixture row — distinct background plus a left accent bar and a
   subtle outline so it stays obvious even when scanning a long sheet. */
.fixture-row:focus-within {
    background: #dbeafe;
    box-shadow: inset 4px 0 0 #2563eb, 0 0 0 1px #93c5fd;
}
.fixture-row:focus-within td { border-color: #93c5fd; }

/* Quick-wins batch: date countdown, RW deal number, status "last changed" */
.dash-date-label-group {
    display: flex;
    align-items: center;
    gap: 3px;
    min-width: 0;
    flex-shrink: 0;
}

.dash-date-countdown {
    font-size: 10px;
    color: var(--text-muted, #9ca3af);
    white-space: nowrap;
    flex-shrink: 0;
}

/* Countdown urgency color-coding (reuses the req-dot red/orange/green palette):
   past = today or already passed, soon = within the next 7 days, later = beyond. */
.dash-date-countdown.dash-countdown--past { color: var(--danger); font-weight: 600; }
.dash-date-countdown.dash-countdown--soon { color: var(--orange); font-weight: 600; }
.dash-date-countdown.dash-countdown--later { color: var(--success); }

.dash-rw-deal {
    font-size: 11px;
    margin-left: 6px;
    white-space: nowrap;
}

a.dash-rw-deal {
    text-decoration: none;
}

a.dash-rw-deal:hover {
    text-decoration: underline;
}

/* Order/quote kind chip — soft green for orders, soft yellow for quotes. */
.rw-kind-chip {
    display: inline-flex;
    align-items: center;
    padding: 1px 7px;
    border-radius: 10px;
    font-weight: 600;
    text-decoration: none;
}

.rw-kind-chip:hover {
    text-decoration: underline;
}

.rw-kind-order {
    background: #d1fae5;
    color: #065f46;
}

.rw-kind-quote {
    background: #fef3c7;
    color: #92400e;
}

.status-ago {
    font-size: 10px;
    font-weight: 400;
    color: var(--text-muted, #9ca3af);
    margin-left: 4px;
}

.detail-field-header {
    display: flex;
    align-items: baseline;
    gap: 6px;
}

/* Project detail subnav split: internal TOC anchors (left) vs external
   page jumps (right, arrow-marked). Wave-2 menu bar cleanup. */
.detail-subnav-toc {
    display: flex;
    gap: 4px;
    align-items: center;
    flex: 0 1 auto;
    min-width: 0;
    overflow-x: auto;
    white-space: nowrap;
}

.detail-subnav-external {
    display: flex;
    gap: 4px;
    align-items: center;
    flex-shrink: 0;
    margin-left: 12px;
    padding-left: 12px;
    border-left: 1px solid var(--border);
    white-space: nowrap;
}

.detail-subnav-ext-link {
    padding: 4px 8px;
    color: var(--text-muted);
    text-decoration: none;
    border-radius: 3px;
}

.detail-subnav-ext-link:hover {
    background: var(--bg-hover);
    color: var(--text);
}

.detail-subnav-ext-arrow {
    margin-left: 3px;
    opacity: 0.6;
    font-size: 11px;
}

/* ==========================================================================
   Project detail: subnav as a FIXED LEFT COLUMN (scroll-spy TOC).
   Wide screens only — below 1025px it falls back to the default horizontal
   sticky bar defined above (mobile/narrow fallback). Everything is scoped to
   body[data-url-name="project_detail"] so no other page's .main-content or
   .detail-subnav is affected.
   ========================================================================== */
@media (min-width: 1025px) {
    body[data-url-name="project_detail"] {
        --detail-toc-width: 190px;
    }

    /* The nav bar leaves normal flow and pins down the left edge, below the
       sticky top-nav. Fixed (not sticky) so it stays put while the page
       scrolls and can scroll internally if the list exceeds the viewport. */
    body[data-url-name="project_detail"] .detail-subnav {
        position: fixed;
        top: var(--header-height);
        left: 0;
        width: var(--detail-toc-width);
        height: calc(100vh - var(--header-height));
        flex-direction: column;
        align-items: stretch;
        gap: 1px;
        padding: 10px 8px;
        overflow-y: auto;
        overflow-x: hidden;
        border-right: 1px solid var(--border-light);
        border-bottom: none;
        z-index: 90;
    }

    /* External page jumps move to the TOP of the column (order:-1), separated
       from the internal section links by a rule. */
    body[data-url-name="project_detail"] .detail-subnav-external {
        order: -1;
        flex-direction: column;
        align-items: stretch;
        gap: 1px;
        margin: 0 0 6px;
        padding: 0 0 6px;
        border-left: none;
        border-bottom: 1px solid var(--border);
        white-space: normal;
    }

    body[data-url-name="project_detail"] .detail-subnav-toc {
        order: 0;
        flex-direction: column;
        align-items: stretch;
        gap: 1px;
        overflow: visible;
        white-space: normal;
    }

    body[data-url-name="project_detail"] .detail-subnav a,
    body[data-url-name="project_detail"] .detail-subnav-ext-link {
        display: block;
        padding: 4px 8px;
        border-radius: 4px;
        line-height: 1.3;
    }

    /* Scroll-spy active section: bold + subtle highlight (not the solid blue
       pill the horizontal bar uses). */
    body[data-url-name="project_detail"] .detail-subnav-toc a.active {
        background: var(--bg-hover);
        color: var(--text);
        font-weight: 700;
    }

    /* Shift the detail page's content right to clear the fixed column. */
    body[data-url-name="project_detail"] .main-content {
        padding-left: calc(var(--detail-toc-width) + 20px);
    }

    /* No horizontal subnav sits above the content now, so section anchors
       only need to clear the top nav (not the old header+subnav stack). */
    body[data-url-name="project_detail"] .detail-section[id^="section-"] {
        scroll-margin-top: calc(var(--header-height) + 10px);
    }
}

/* ---- Crew Schedule: Hands (manual-vs-rollup) summary — Wave 2 ---- */
.sheet-hands-summary {
    display: flex;
    align-items: center;
    gap: 6px;
    min-height: 0;
}
.sheet-hands-total {
    font-weight: 700;
    min-width: 14px;
}
.sheet-hands-manual-input {
    width: 52px;
    font-size: 11px;
    padding: 2px 4px;
    border: 1px solid var(--border-light, #e5e7eb);
    border-radius: 3px;
}
.sheet-hands-breakdown {
    padding: 2px 0 0;
}
.sheet-hands-mismatch {
    padding: 1px 0 0;
    font-style: italic;
}

/* ---- Crew Schedule: find-crew modal previous/next gig — Wave 2 ---- */
.find-crew-gig-row {
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 2px 0;
}
.find-crew-gig-dates {
    font-size: 11px;
    color: var(--text-muted);
}
.find-crew-gigs-empty {
    font-size: 12px;
    color: var(--text-muted);
    padding: 2px 0 6px;
}

/* ---- Dashboard: Milestones expand panel — Wave 2 ---- */
.dash-ms-row-overdue > td {
    background: #fee2e2;
}
.dash-ms-row-alerting > td {
    background: #fff7ed;
}
.dash-ms-row-complete > td {
    opacity: 0.6;
}

/* ---- RW status chip (read-only, next to name/order-type) ---- */
.rw-status-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 1px 8px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 600;
    background: var(--bg-alt);
    color: var(--text-muted);
    border: 1px solid var(--border-light);
    white-space: nowrap;
}

/* ---- Dashboard: requirements block header ---- */
.dash-req-header {
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    color: var(--text-muted);
    margin-bottom: 2px;
}

/* ---- Project detail: requirements quick-add (ported from dashboard) ---- */
.detail-req-quickadd {
    display: flex;
    gap: 4px;
    align-items: center;
    margin-left: auto;
}
select.detail-quickadd-select {
    font-size: 12px;
    padding: 2px 6px;
    max-width: 160px;
}

/* ==========================================================================
   Daily-journal Notes page
   ========================================================================== */

.journal-page {
    /* Fill the width .main-content actually has left over between the
       journal's own date margin (left) and the post-it sidebar (right) —
       there's no reason to cap it mid-page like a prose column. */
    max-width: 100%;
}

.journal-head {
    display: flex;
    align-items: baseline;
    gap: 12px;
    margin-bottom: 8px;
}
.journal-head h1 {
    font-size: 20px;
    font-weight: 700;
    margin: 0;
}
.journal-status {
    font-size: 12px;
    color: var(--text-light);
    opacity: 0;
    transition: opacity 0.25s;
}
.journal-status.show { opacity: 1; }
.journal-status.is-error { color: #dc2626; }

.journal-loading,
.journal-end {
    text-align: center;
    color: var(--text-light);
    font-size: 12px;
    padding: 20px 0;
}

/* One day = ruled page block. Grid: [margin date] [body].
   Auto-flow lays the date + journal on row 1, then each project note as a
   check(col1)+note(col2) row beneath. A faint vertical rule = notepad margin. */
.journal-day {
    display: grid;
    grid-template-columns: 66px 1fr;
    column-gap: 16px;
    align-items: start;
    padding: 16px 0 20px;
    border-top: 1px solid var(--border);
    background:
        linear-gradient(to right,
            transparent 0, transparent 74px,
            rgba(220, 38, 38, 0.18) 74px, rgba(220, 38, 38, 0.18) 75px,
            transparent 75px);
}
.journal-day:first-child { border-top: none; }

.jd-date {
    text-align: right;
    padding-right: 10px;
    position: sticky;
    top: calc(var(--header-height) + 8px);
    line-height: 1.05;
    user-select: none;
}
.jd-date-dow {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-light);
}
.jd-date-day {
    font-size: 26px;
    font-weight: 700;
    color: var(--text);
}
.jd-date-mon {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--text-muted);
}

/* Free journal area — borderless, ruled, endless-notepad feel. */
.jd-journal { min-width: 0; }
.jd-journal-note,
.jd-note-text {
    display: block;
    width: 100%;
    border: none;
    background: transparent;
    resize: none;
    overflow: hidden;
    font-family: inherit;
    font-size: 14px;
    line-height: 26px;
    color: var(--text);
    padding: 0 4px;
    outline: none;
    white-space: pre-wrap;
    background-image: linear-gradient(to bottom,
        transparent 0, transparent 25px,
        var(--border-light) 25px, var(--border-light) 26px);
    background-size: 100% 26px;
    min-height: 26px;
}
.jd-journal-note:focus,
.jd-note-text:focus {
    background-color: rgba(59, 130, 246, 0.04);
}
.jd-new::placeholder { color: var(--text-light); font-style: italic; }

/* Project / other notes attached to a day. */
.jd-note {
    min-width: 0;
    padding: 2px 0 4px;
}
.jd-note-tag {
    display: block;
    font-size: 11px;
    font-weight: 600;
    text-decoration: none;
    margin-bottom: 1px;
}
.jd-note-tag:hover { text-decoration: underline; }
.jd-note-time {
    display: block;
    font-size: 10px;
    color: var(--text-light);
    padding-left: 4px;
}
.jd-note.note-handled .jd-note-text { color: var(--text-light); text-decoration: line-through; }

/* Stylized handled check in the margin (circled tick — not a native box). */
.jd-check {
    justify-self: end;
    width: 20px;
    height: 20px;
    margin-top: 4px;
    border: 2px solid var(--border);
    border-radius: 50%;
    cursor: pointer;
    box-sizing: border-box;
    transition: background 0.15s, border-color 0.15s;
    position: relative;
}
.jd-check:hover { border-color: var(--primary); }
.jd-check.checked {
    background: #16a34a;
    border-color: #16a34a;
}
.jd-check.checked::after {
    content: '';
    position: absolute;
    left: 5px;
    top: 1px;
    width: 5px;
    height: 10px;
    border: solid #fff;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
}

/* Right sidebar: yellow post-its. */
.journal-sidebar h3 { margin-top: 0; }
.postit {
    background: #fffde7;
    border: 1px solid #fff176;
    border-radius: 8px;
    padding: 10px;
    margin-bottom: 12px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}
.postit-label {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: #b7791f;
    margin-bottom: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.postit-text {
    width: 100%;
    border: none;
    background: transparent;
    resize: none;
    overflow: hidden;
    font-family: inherit;
    font-size: 13px;
    line-height: 1.4;
    color: #4b3f1a;
    outline: none;
    min-height: 40px;
    white-space: pre-wrap;
}

/* Used by several admin-tab toolbars (e.g. "flex gap-2 mb-4 items-end")
   that reference this utility class without it having been defined. */
.items-end { align-items: flex-end; }

/* ── Holidays (calendar tint + step-on warnings) ──────────────────────────
   Appended by the Holiday feature. Spreadsheet holiday columns get a green
   tint (header + day cells) via the ss-holiday class baked into each day's
   class list — green so it can't blur into the orange "today" column; a
   scheduled day landing on a holiday gets a corner marker via
   ss-holiday-hit. Standard month grid gets a small holiday label. Dashboard
   date groups get a ⚠ badge; the date-range editor toasts on save. */
.spreadsheet-calendar .ss-holiday {
    background-color: #e3f5e9;
}
.spreadsheet-calendar .ss-head-cell.ss-holiday,
.spreadsheet-calendar div.ss-holiday.ss-head-cell {
    color: #15803d;
}
.ss-holiday-hit {
    position: relative;
}
.ss-holiday-hit::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 0 0 7px 7px;
    border-color: transparent transparent #15803d transparent;
    pointer-events: none;
}

.calendar-cell-holiday {
    background-color: #e3f5e9 !important;
}
.cal-holiday-label {
    font-size: 10px;
    font-weight: 600;
    color: #15803d;
    background: #c9ecd4;
    border-radius: 3px;
    padding: 0 4px;
    margin-bottom: 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dash-holiday-badge {
    color: #b45309;
    font-size: 11px;
    margin-left: 2px;
    cursor: help;
}

.dash-holiday-toast {
    position: fixed;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%) translateY(12px);
    background: #7c2d12;
    color: #fff;
    padding: 10px 16px;
    border-radius: 6px;
    font-size: 13px;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
    z-index: 10000;
    opacity: 0;
    transition: opacity 0.3s ease, transform 0.3s ease;
    cursor: pointer;
    max-width: 90vw;
}
.dash-holiday-toast.show {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

/* ---- Crew Blackout (PTO) — phase 2: availability search + warnings ---- */

/* Crew schedule grid: roster row whose crew member is on PTO that day. */
.crew-roster-row.crew-roster-blackout {
    background: #fee2e2;
    border-left: 3px solid #dc2626;
    padding-left: 4px;
    border-radius: 2px;
}

/* Find-crew modal: "PTO 6/15-6/20" badge in the results list + a dedicated
   sort/dim tier (6) below the existing busy tiers (1-5). */
.find-crew-pto-badge {
    font-size: 10px;
    font-weight: 700;
    color: #991b1b;
    background: #fee2e2;
    border: 1px solid #fecaca;
    padding: 1px 6px;
    border-radius: 3px;
    white-space: nowrap;
}
.find-crew-avail.tier-6 { background: #fecdd3; color: #9f1239; }

/* Admin Blackouts tab: "booked project" collision warnings shown under a
   newly added/edited blackout row (crew_blackouts.js). */
.blackout-warning-list {
    margin: 2px 0 6px;
}
.blackout-warning-row {
    font-size: 11px;
    color: #b45309;
    padding: 1px 0;
}

/* Optimistic timeline task creation (crew_schedule.js _insertPendingTimelineTask).
   A task the user just added/is naming but hasn't been confirmed by the
   server yet — feedback-pending (loaded earlier) supplies the yellow
   tint; this just marks it as not-yet-interactive (no drag handles are
   ever rendered on it, so there's nothing to grab either way) and keeps
   the name-edit popup, which IS allowed while pending, readable on top. */
.crew-pending-task {
    cursor: default;
}
.crew-pending-task .crew-task-name-popup {
    cursor: text;
}

/* ============================================================
   Linked-projects combined view (crew schedule).
   The toggle bar merges a linked project's schedule into the
   page for READ-ONLY context; foreign day blocks are color-coded
   by the linked project's own Project.color and kept structurally
   separate from the main project's editable data.
   ============================================================ */
.crew-linked-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    margin-bottom: 10px;
    background: var(--bg-alt);
    border: 1px solid var(--border-light);
    border-radius: 6px;
}
.crew-linked-bar-label {
    font-size: 12px;
    font-weight: 700;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}
.crew-linked-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 12px;
    padding: 2px 8px 2px 4px;
    border: 1px solid var(--border-light);
    border-radius: 999px;
    cursor: pointer;
    user-select: none;
    background: #fff;
}
.crew-linked-chip:hover { background: var(--bg-hover); }
.crew-linked-swatch {
    width: 12px;
    height: 12px;
    border-radius: 3px;
    flex: 0 0 auto;
    box-shadow: inset 0 0 0 1px rgba(0,0,0,0.15);
}
.crew-linked-chip-name {
    max-width: 220px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.crew-linked-all-chip { font-weight: 600; }
.crew-linked-hint { margin-left: auto; }

/* Per-column project identifier (multi-project view only). Subtle/small,
   accented with the owning project's color. Disabled this chunk — Chunk 3
   may wire it for reorder. Hidden entirely in single-project view (the
   template omits it when only one project is in the view). */
.crew-col-project {
    display: block;
    width: 100%;
    box-sizing: border-box;
    margin: 0 0 2px;
    padding: 1px 4px;
    font-size: 10px;
    font-weight: 700;
    line-height: 1.3;
    color: var(--col-project-color, #4b5563);
    background: color-mix(in srgb, var(--col-project-color, #4b5563) 8%, transparent);
    border: 1px solid color-mix(in srgb, var(--col-project-color, #4b5563) 40%, transparent);
    border-left: 3px solid var(--col-project-color, #4b5563);
    border-radius: 3px;
    text-overflow: ellipsis;
    /* Disabled selects otherwise render greyed-out; keep it legible. */
    opacity: 1;
    cursor: default;
    -webkit-appearance: none;
    appearance: none;
}
