/* Public Timetable — horizontal EPG-style schedule (mw-pt-*) */

.mw-pt-container {
    --mw-pt-block-color: #6366f1;
    --mw-pt-accent-color: #818cf8;
    --mw-pt-bg-color: #0f172a;
    --mw-pt-text-color: #ffffff;
    --mw-pt-border-radius: 8px;
    --mw-pt-label-width: 150px;
    --mw-pt-row-height: 64px;

    /* NOTE: On phones the label column never eats more than ~28% of the viewport,
       regardless of the configured desktop width */
    --mw-pt-label-width-clamped: min(var(--mw-pt-label-width), 28vw);

    background: var(--mw-pt-bg-color);
    color: var(--mw-pt-text-color);
    border-radius: 12px;
    overflow: auto;
    overscroll-behavior: contain;
    position: relative;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    /* NOTE: Scrolling/tapping around an EPG grid selects everything otherwise — but act and
       stage names are opted back in below (people copy act names). Both spellings, always:
       Chrome only honors the unprefixed property, older Safari only the -webkit one — writing
       just one of them is exactly the bug where selection behaves differently per browser. */
    user-select: none;
    -webkit-user-select: none;
}

/* Copyable text — the opt-in matching the container's opt-out above */
.mw-pt-block-name,
.mw-pt-block-time,
.mw-pt-block-genre,
.mw-pt-stage-label {
    user-select: text;
    -webkit-user-select: text;
}

/* Fullscreen share-link page (/timetable-view) — the timetable IS the page: no chrome, no
   heading; the container owns the whole viewport, scrolls INTERNALLY (both axes) so the
   sticky time axis and stage labels stay pinned while browsing, and drops the outer rounding. */
.mw-pt-fullscreen {
    height: 100dvh;
}

.mw-pt-fullscreen .mw-pt-container {
    height: 100dvh;
    max-height: 100dvh;
    border-radius: 0;
}

/* Dead-link state on /timetable-view (expired ?nd= handoff or direct navigation) */
.mw-pt-fullscreen-invalid {
    height: 100dvh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 24px;
    text-align: center;
}

.mw-pt-fullscreen-invalid-title {
    font-size: 17px;
    font-weight: 700;
}

.mw-pt-fullscreen-invalid-text {
    font-size: 14px;
    opacity: 0.65;
    max-width: 420px;
}

/* Floating "get the offline app" call-to-action on /timetable-view — funnels guests into the
   installable guest PWA (/app). The live Blazor view stays the canonical share-link target. */
.mw-pt-app-cta {
    position: fixed;
    right: 14px;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 14px);
    z-index: 10;
    display: flex;
    align-items: center;
    gap: 6px;
}

.mw-pt-app-cta-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    border-radius: 999px;
    background: #6366f1;
    color: #ffffff;
    font-weight: 700;
    font-size: 13px;
    text-decoration: none;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.35);
}

.mw-pt-app-cta-close {
    appearance: none;
    border: none;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: rgba(15, 23, 42, 0.8);
    color: #ffffff;
    cursor: pointer;
    font-size: 12px;
    line-height: 1;
}

/* Artist timetable page (/timetable) — same internal both-axis scrolling, capped to the
   viewport under the app bar so the time axis and stage labels stay pinned */
.mw-pt-page {
    padding: 12px;
}

.mw-pt-page .mw-pt-container {
    max-height: calc(100dvh - 140px);
}

@media (max-width: 640px) {
    .mw-pt-page {
        padding: 4px;
    }

    .mw-pt-page .mw-pt-container {
        max-height: calc(100dvh - 90px);
    }
}

/* Header (time axis) — sticky top */
.mw-pt-header {
    display: flex;
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--mw-pt-bg-color);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    min-width: fit-content;
}

.mw-pt-corner {
    width: var(--mw-pt-label-width-clamped);
    min-width: var(--mw-pt-label-width-clamped);
    /* NOTE: max-width + hidden overflow — without them the menu content can grow the corner
       past the stage-label column and the header stops lining up with the rows */
    max-width: var(--mw-pt-label-width-clamped);
    overflow: hidden;
    flex-shrink: 0;
    position: sticky;
    left: 0;
    z-index: 5;
    background: var(--mw-pt-bg-color);
    display: flex;
    align-items: flex-end;
    justify-content: flex-start;
    padding: 0 0 2px 8px;
    border-right: 1px solid rgba(255, 255, 255, 0.06);
}

/* Weekday at the current horizontal scroll position (updated by __mwPtDayTracker) */
.mw-pt-corner-day {
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    opacity: 0.9;
    line-height: 1;
}

/* Tappable corner — opens the day-jump menu (mirrors the shift planner's mobile corner) */
.mw-pt-corner-day-activator {
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 4px 4px 4px 8px;
    border-radius: 6px;
    cursor: pointer;
}

/* Day-jump menu — fully custom panel, styled like the timetable (colors inlined from config
   because the popover portal is outside the container's CSS-var scope) */
.mw-pt-day-menu {
    min-width: 150px;
    padding: 6px;
    border-radius: 10px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    user-select: none;
    -webkit-user-select: none;
}

.mw-pt-day-menu-item {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 20px;
    padding: 8px 10px;
    border-radius: 6px;
    cursor: pointer;
}

.mw-pt-day-menu-item:hover {
    background: rgba(255, 255, 255, 0.08);
}

/* Weekday left — same treatment as the corner activator's weekday */
.mw-pt-day-menu-weekday {
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    opacity: 0.9;
    line-height: 1;
}

/* Date right-aligned, dimmed */
.mw-pt-day-menu-date {
    font-size: 12px;
    opacity: 0.55;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.mw-pt-timeline {
    position: relative;
    height: 36px;
    flex-shrink: 0;
}

.mw-pt-time-mark {
    position: absolute;
    top: 0;
    height: 100%;
    display: flex;
    align-items: flex-end;
    padding: 0 0 6px 8px;
    font-size: var(--mw-pt-time-font-size, 11px);
    font-weight: 500;
    letter-spacing: 0.03em;
    opacity: 0.5;
    border-left: 1px solid rgba(255, 255, 255, 0.08);
    pointer-events: none;
}

.mw-pt-time-mark-midnight {
    opacity: 0.8;
    font-weight: 700;
}

/* Stage rows */
.mw-pt-row {
    display: flex;
    min-height: var(--mw-pt-row-height);
    border-bottom: 1px solid rgba(255, 255, 255, 0.04);
    min-width: fit-content;
}

.mw-pt-row:last-child {
    border-bottom: none;
}

/* Stage label — sticky left */
.mw-pt-stage-label {
    width: var(--mw-pt-label-width-clamped);
    min-width: var(--mw-pt-label-width-clamped);
    max-width: var(--mw-pt-label-width-clamped);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 16px;
    position: sticky;
    left: 0;
    z-index: 2;
    background: var(--mw-pt-bg-color);
    border-right: 1px solid rgba(255, 255, 255, 0.06);
    font-weight: 600;
    font-size: var(--mw-pt-label-font-size, 13px);
    text-transform: var(--mw-pt-label-text-transform, none);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    box-shadow: 4px 0 8px -2px rgba(0, 0, 0, 0.3);
}

.mw-pt-stage-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
    box-shadow: 0 0 6px currentColor;
}

/* Rahmenprogramm sub-row (artist view) */
.mw-pt-row-rahmenprogramm {
    background: rgba(255, 255, 255, 0.025);
}

.mw-pt-stage-label-lines {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
    min-width: 0;
}

.mw-pt-stage-label-lines > span {
    overflow: hidden;
    text-overflow: ellipsis;
}

.mw-pt-stage-sublabel {
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    opacity: 0.55;
}

/* ─── Phone layout (Fusion-inspired): every pixel goes to the programme ───
   Configured sizes arrive as CSS vars, so min() clamps them without fighting inline styles */
@media (max-width: 640px) {
    .mw-pt-container {
        --mw-pt-label-width-clamped: min(var(--mw-pt-label-width), 24vw);
    }

    /* Compact rows */
    .mw-pt-row {
        min-height: min(var(--mw-pt-row-height), 52px);
    }

    /* Stage labels: two-line wrap instead of ellipsis, tighter, smaller */
    .mw-pt-stage-label {
        padding: 0 8px;
        gap: 6px;
        white-space: normal;
        font-size: min(var(--mw-pt-label-font-size), 11px);
        line-height: 1.2;
        overflow-wrap: anywhere;
    }

    .mw-pt-stage-dot {
        width: 8px;
        height: 8px;
    }

    /* Blocks: name only (no time range or genre), centered like a chip */
    .mw-pt-block {
        gap: 0;
    }

    .mw-pt-block-name {
        font-size: min(var(--mw-pt-name-font-size), 12px);
        text-align: center;
    }

    .mw-pt-block-time,
    .mw-pt-block-genre {
        display: none;
    }
}

/* Track (block container) */
.mw-pt-track {
    position: relative;
    flex-shrink: 0;
    padding: 8px 0;
}

/* Hour gridlines */
.mw-pt-gridline {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 1px;
    background: rgba(255, 255, 255, 0.04);
    pointer-events: none;
}

/* NOTE: Colored time-area bands (stage-planner highlights curated per timetable) — rendered
   first inside each track so gridlines, blocks, and the now-line paint on top; translucency
   comes from color-mix in the inline background. */
.mw-pt-time-highlight {
    position: absolute;
    top: 0;
    bottom: 0;
    pointer-events: none;
}

/* Time-area label in the time-axis header, anchored at the area's start.
   Color / size / weight / opacity come from the variant config via inline style. */
.mw-pt-time-highlight-label {
    position: absolute;
    bottom: 2px;
    padding-left: 6px;
    white-space: nowrap;
    letter-spacing: 0.04em;
    pointer-events: none;
}

/* Act blocks */
.mw-pt-block {
    position: absolute;
    top: var(--mw-pt-block-margin-vertical, 8px);
    bottom: var(--mw-pt-block-margin-vertical, 8px);
    background: var(--mw-pt-block-color);
    border-radius: var(--mw-pt-border-radius);
    padding: 6px 12px;
    cursor: pointer;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
    min-width: 0;
}

.mw-pt-block:hover {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
    z-index: 1;
}

.mw-pt-block-name {
    font-weight: 700;
    font-size: var(--mw-pt-name-font-size, 13px);
    text-transform: var(--mw-pt-name-text-transform, none);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.2;
}

.mw-pt-block-time {
    font-size: var(--mw-pt-time-font-size, 10px);
    opacity: 0.65;
    white-space: nowrap;
    line-height: 1.2;
}

/* Genre line under the act name (per-timetable switch: ShowGenreOnBlocks) */
.mw-pt-block-genre {
    font-size: var(--mw-pt-time-font-size, 10px);
    font-style: italic;
    opacity: 0.75;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.2;
}

/* Highlighted block (viewing act in fog-of-war mode) */
.mw-pt-block-highlight {
    outline: 2px solid var(--mw-pt-text-color);
    outline-offset: 1px;
    box-shadow: 0 0 16px rgba(255, 255, 255, 0.25), 0 2px 8px rgba(0, 0, 0, 0.3);
    z-index: 1;
}

.mw-pt-block-highlight .mw-pt-block-name {
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 2px;
}

/* Soundcheck blocks (artist view) — dashed, non-interactive */
.mw-pt-block-soundcheck {
    background: transparent;
    border: 1.5px dashed var(--mw-pt-soundcheck-color);
    box-shadow: none;
    cursor: default;
    opacity: 0.85;
}

.mw-pt-block-soundcheck .mw-pt-block-name {
    color: var(--mw-pt-soundcheck-color);
}

.mw-pt-block-soundcheck:hover {
    transform: none;
    box-shadow: none;
    z-index: 0;
}

/* Soundcheck SLOTS (act-less note slots flagged IsSoundcheck) — filled with the soundcheck
   color (applied inline); the italic label distinguishes them from act blocks of a similar hue */
.mw-pt-block-soundcheck-slot .mw-pt-block-name {
    font-style: italic;
}

/* Fog-of-war hidden blocks */
.mw-pt-block-hidden {
    background: rgba(255, 255, 255, 0.04) !important;
    box-shadow: none;
    cursor: default;
    border: 1px dashed rgba(255, 255, 255, 0.1);
}

.mw-pt-block-hidden:hover {
    transform: none;
    box-shadow: none;
}

.mw-pt-block-hidden .mw-pt-block-name {
    opacity: 0.25;
    font-style: italic;
    font-weight: 400;
}

/* Current-time indicator */
.mw-pt-now-line {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 2px;
    background: #ef4444;
    z-index: 1;
    pointer-events: none;
}

.mw-pt-now-dot {
    position: absolute;
    top: 0;
    width: 2px;
    height: 100%;
    background: #ef4444;
    z-index: 5;
    pointer-events: none;
}

.mw-pt-now-dot::before {
    content: "";
    position: absolute;
    top: -4px;
    left: -4px;
    width: 10px;
    height: 10px;
    background: #ef4444;
    border-radius: 50%;
}

/* Heading above the timetable (share-link landing page) */
.mw-pt-title {
    font-size: 22px;
    font-weight: 800;
    letter-spacing: 0.01em;
    margin: 0 0 12px;
}

/* Empty state */
.mw-pt-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 48px 24px;
    opacity: 0.4;
    font-size: 14px;
}

/* ─── Preview mode (editor page) — consumer view with a way back ─── */
/* NOTE: Plain BLOCK flow (deliberately NOT display:flex) so .mw-pt-container is a normal block
   child — identical to the two proven-working surfaces, .mw-pt-page and .mw-pt-fullscreen.
   A flex-column parent makes the container a flex item whose default min-height:auto resolves to
   the content height and OUTRANKS max-height, so the box grows past the fold and only scrolls
   horizontally (the exact preview bug). Block flow sidesteps that trap: min-height:auto on a block
   is 0, so the viewport-relative max-height below caps the height directly and overflow-y engages. */
.mw-pt-preview {
    padding: 12px 16px;
    box-sizing: border-box;
}

/* Bar owns the gap to the timetable (the flex-column gap is gone with block flow); the optional
   .mw-pt-title carries its own bottom margin, so spacing stays 12px with or without a title. */
.mw-pt-preview-bar {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
}

/* Container scrolls INTERNALLY (both axes) so its sticky time-axis and stage labels stay pinned.
   Cap is viewport-relative, so it never depends on any ancestor's height being constrained —
   same pattern as .mw-pt-page / .mw-pt-fullscreen above. */
.mw-pt-preview .mw-pt-container {
    max-height: calc(100dvh - 200px);
}

/* ─── Editor layout (test page) ─── */
.mw-pt-editor {
    display: flex;
    gap: 0;
    height: calc(100dvh - var(--mud-appbar-height, 64px) - 2 * 16px);
    overflow: hidden;
}

.mw-pt-editor-panel {
    width: 340px;
    min-width: 340px;
    overflow-y: auto;
    border-right: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px 0 0 8px;
    padding: 0;
    scrollbar-width: thin;
}

/* Save toolbar above the editor accordion */
.mw-pt-editor-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 8px 12px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* Share links list (editor page) */
.mw-pt-share-link {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 8px;
    margin-top: 8px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
}

.mw-pt-share-link--revoked {
    opacity: 0.45;
}

.mw-pt-share-link-main {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.mw-pt-share-link-label {
    font-size: 13px;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mw-pt-share-link-mode {
    font-size: 11px;
    opacity: 0.6;
}

/* ─── Dialog host (DtPublicTimetable) ─── */
.mw-pt-dialog-title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    width: 100%;
}

/* Artist-office popup: fill the viewport with a 40px inset on all four sides (no width/height
   restriction on the timetable itself); the timetable renders its own surface, so the dialog
   paper is transparent and chrome-less. */
.mw-pt-dialog-paper {
    position: fixed !important;
    inset: 40px !important;
    width: auto !important;
    height: auto !important;
    max-width: none !important;
    max-height: none !important;
    margin: 0 !important;
    background: transparent !important;
    box-shadow: none !important;
    display: flex;
    flex-direction: column;
}

/* Content + shell + timetable all fill the paper so the timetable scrolls INTERNALLY (both axes)
   and the floating search / close controls stay pinned to the visible box. */
.mw-pt-dialog-content {
    flex: 1;
    min-height: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.mw-pt-dialog-shell {
    position: relative;
    flex: 1;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.mw-pt-dialog-shell > .mw-pt-shell-search {
    flex: 1;
    min-height: 0;
}

.mw-pt-dialog-content .mw-pt-container {
    flex: 1;
    min-height: 0;
    max-height: none;
}

/* Floating close FAB (top-right) and the public-view switch (top-left) over the timetable. */
.mw-pt-dialog-close {
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 10;
}

.mw-pt-dialog-switch {
    position: absolute;
    top: 12px;
    left: 12px;
    z-index: 10;
    display: flex;
    align-items: center;
    padding: 2px 14px 2px 10px;
    border-radius: 999px;
    background: rgba(15, 23, 42, 0.72);
    backdrop-filter: blur(6px);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
}

.mw-pt-dialog-switch .mud-switch-label {
    color: #fff;
    font-size: 13px;
}

/* One area in the editor's "Time areas" curation section: include row + slot-styling rows */
.mw-pt-editor-time-area {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-bottom: 8px;
}

/* One row within an area: include-checkbox + color override, or slot caption + slot color */
.mw-pt-editor-time-area-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.mw-pt-editor-preview {
    flex: 1;
    overflow: auto;
    padding: 16px;
    display: flex;
    align-items: flex-start;
    justify-content: center;
}

/* NOTE: .mw-pt-container must be the both-axis scroller on EVERY surface — its sticky time-axis
   header and stage labels pin relative to its own scrollport, and its overscroll-behavior:contain
   assumes the vertical scroll lives here. Without a cap the container grows to full content height,
   so the pane (.mw-pt-editor-preview) becomes the scroller instead: the sticky header never pins,
   and overscroll-contain swallows wheel-scroll over the timetable (the pane only moves via its
   scrollbar). Capping the container — same viewport-relative pattern as .mw-pt-page — restores
   internal scrolling; the value fits the pane's inner height (editor 100dvh−appbar−32, minus the
   pane's 32px padding), and the pane keeps its own overflow:auto only for the act detail panel. */
.mw-pt-editor-preview .mw-pt-container {
    max-height: calc(100dvh - 140px);
}

/* Detail panel (used on test page) */
.mw-pt-detail-links {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 12px;
}

.mw-pt-detail-embed {
    margin-top: 16px;
    border-radius: 8px;
    overflow: hidden;
}

.mw-pt-detail-embed iframe {
    display: block;
    border: none;
}

/* ─── Timetable editor: variant list + acts list ─── */

.mw-pt-variant-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px;
    border-radius: 6px;
    cursor: pointer;
}

.mw-pt-variant-row:hover {
    background: rgba(128, 128, 128, 0.12);
}

.mw-pt-variant-row--selected {
    background: rgba(128, 128, 128, 0.18);
}

.mw-pt-variant-row-mode {
    margin-left: auto;
    font-size: 11px;
    opacity: 0.55;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.mw-pt-variant-hint {
    display: block;
    opacity: 0.55;
    margin: 0 8px 6px 34px;
}

.mw-pt-variant-edit {
    margin-top: 12px;
    padding: 12px 8px 4px;
    border-top: 1px solid rgba(128, 128, 128, 0.25);
}

/* Extra rows a stage contributes in the current tier (Rahmenprogramm, soundchecks) —
   mirrors the preview so tier switches stay transparent */
.mw-pt-stage-extra {
    display: flex;
    gap: 12px;
    margin: -2px 0 2px 34px;
    font-size: 11px;
    opacity: 0.55;
}

/* Acts list — virtualized, capped scroll area */
.mw-pt-acts-scroll {
    max-height: 600px;
    overflow-y: auto;
    margin-top: 8px;
}

.mw-pt-act-row {
    display: flex;
    align-items: center;
    gap: 6px;
    height: 42px;
    padding: 0 8px 0 2px;
    border-radius: 6px;
    cursor: pointer;
}

.mw-pt-act-row:hover {
    background: rgba(128, 128, 128, 0.12);
}

/* Row of the act currently highlighted in the preview (editor-only state) */
.mw-pt-act-row--highlighted {
    background: rgba(99, 102, 241, 0.18);
    box-shadow: inset 2px 0 0 #6366f1;
}

.mw-pt-act-row-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Colorful usage annotations */
.mw-pt-act-badge {
    flex-shrink: 0;
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
    padding: 4px 7px;
    border-radius: 10px;
}

.mw-pt-act-badge--slots {
    color: #818cf8;
    background: rgba(99, 102, 241, 0.15);
}

.mw-pt-act-badge--hours {
    color: #f59e0b;
    background: rgba(245, 158, 11, 0.14);
}

.mw-pt-act-badge--unscheduled {
    color: rgba(128, 128, 128, 0.9);
    background: rgba(128, 128, 128, 0.12);
    font-weight: 500;
    font-style: italic;
}

/* ─── Bottom-centre act search (mw-pt-search-*) — opt-in via ShowSearch ─── */

/* The component root wraps the scroller. By default it is layout-invisible (display:contents) so
   every existing consumer context renders exactly as before; only the search variant becomes a
   real positioned box that hosts the floating overlay. */
.mw-pt-shell {
    display: contents;
}

.mw-pt-shell-search {
    display: flex;
    flex-direction: column;
    position: relative;
    min-height: 0;
}

/* Floating overlay pinned to the bottom-centre of the visible timetable box. pointer-events:none
   on the wrapper (auto on its children) so the empty space around the pill never blocks the
   timetable underneath. Colors come from the timetable's own CSS vars, so it matches the theme. */
.mw-pt-search {
    position: absolute;
    left: 50%;
    bottom: 16px;
    transform: translateX(-50%);
    z-index: 6;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    pointer-events: none;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

.mw-pt-search > * {
    pointer-events: auto;
}

/* Collapsed pill and expanded bar share this shell; padding animates between the two states. */
.mw-pt-search-bar {
    display: flex;
    align-items: center;
    gap: 6px;
    background: var(--mw-pt-bg-color);
    color: var(--mw-pt-text-color);
    border: 1px solid color-mix(in srgb, var(--mw-pt-text-color) 16%, transparent);
    border-radius: 999px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
    padding: 5px;
    transition: padding 0.2s ease;
}

.mw-pt-search-open .mw-pt-search-bar {
    padding: 4px 6px 4px 12px;
}

.mw-pt-search-pill {
    appearance: none;
    border: none;
    background: transparent;
    color: var(--mw-pt-text-color);
    width: 34px;
    height: 34px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    opacity: 0.85;
    transition: opacity 0.15s ease, background 0.15s ease;
}

.mw-pt-search-pill:hover {
    opacity: 1;
    background: color-mix(in srgb, var(--mw-pt-text-color) 12%, transparent);
}

.mw-pt-search-bar-icon {
    font-size: 18px !important;
    opacity: 0.65;
}

/* The field grows from the pill on open. */
.mw-pt-search-input {
    appearance: none;
    border: none;
    outline: none;
    background: transparent;
    color: var(--mw-pt-text-color);
    font-size: 14px;
    line-height: 1.2;
    width: 220px;
    max-width: 60vw;
    padding: 6px 0;
    animation: mw-pt-search-grow 0.2s ease;
}

.mw-pt-search-input::placeholder {
    color: var(--mw-pt-text-color);
    opacity: 0.45;
}

@keyframes mw-pt-search-grow {
    from {
        width: 0;
        opacity: 0;
    }

    to {
        width: 220px;
        opacity: 1;
    }
}

.mw-pt-search-close {
    appearance: none;
    border: none;
    background: transparent;
    color: var(--mw-pt-text-color);
    width: 30px;
    height: 30px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    opacity: 0.6;
    transition: opacity 0.15s ease, background 0.15s ease;
}

.mw-pt-search-close:hover {
    opacity: 1;
    background: color-mix(in srgb, var(--mw-pt-text-color) 12%, transparent);
}

/* Result list — grows UPWARD from just above the bar (column-reverse puts the best match at the
   bottom, nearest the input), only as tall as its matches, capped at half the timetable height
   (the --mw-pt-search-max-height var is set inline per instance; 50% is the fallback). */
.mw-pt-search-list {
    display: flex;
    flex-direction: column-reverse;
    gap: 2px;
    width: max-content;
    min-width: 240px;
    max-width: min(440px, calc(100vw - 48px));
    max-height: var(--mw-pt-search-max-height, 50%);
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 6px;
    background: var(--mw-pt-bg-color);
    color: var(--mw-pt-text-color);
    border: 1px solid color-mix(in srgb, var(--mw-pt-text-color) 16%, transparent);
    border-radius: 14px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
    animation: mw-pt-search-list-in 0.18s ease;
}

@keyframes mw-pt-search-list-in {
    from {
        opacity: 0;
        transform: translateY(8px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.mw-pt-search-item {
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 7px 10px;
    border-radius: 9px;
    cursor: pointer;
    transition: background 0.12s ease;
}

.mw-pt-search-item:hover {
    background: color-mix(in srgb, var(--mw-pt-text-color) 8%, transparent);
}

.mw-pt-search-item.is-selected {
    background: color-mix(in srgb, var(--mw-pt-accent-color) 30%, transparent);
}

.mw-pt-search-item-name {
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.mw-pt-search-item-genre {
    font-size: 11px;
    opacity: 0.6;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.mw-pt-search-empty {
    padding: 10px 12px;
    font-size: 12px;
    opacity: 0.6;
}

/* ─── Staff overlays: stage-care lanes + additional-shift section (artist office only) ─── */

/* Shared width of the rotated team strip that precedes the position label in the shift section. */
.mw-pt-container {
    --mw-pt-shift-team-strip: 26px;
}

/* Stage-care crew lane — thinner than a stage row, subtly inset. */
.mw-pt-row-care {
    min-height: 34px;
    background: rgba(255, 255, 255, 0.02);
}

.mw-pt-care-label {
    gap: 8px;
}

.mw-pt-care-label-text {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    opacity: 0.65;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Care / shift lane track — tighter vertical padding than the act track so thin lanes read. */
.mw-pt-lane-track {
    padding: 3px 0;
}

/* One crew block on a care or shift lane. Fill color is inline (stage / position color); the
   vertical position + height come inline from the packed sub-lane. */
.mw-pt-shift-block {
    position: absolute;
    border-radius: 6px;
    padding: 0 8px;
    display: flex;
    align-items: center;
    gap: 6px;
    overflow: hidden;
    min-width: 0;
    color: var(--mw-pt-text-color);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
    transition: filter 0.15s ease;
}

.mw-pt-shift-block:hover {
    filter: brightness(1.12);
    z-index: 1;
}

/* Search-highlighted crew block (mirrors the act-block highlight treatment). */
.mw-pt-shift-block-highlight {
    outline: 2px solid var(--mw-pt-text-color);
    outline-offset: 1px;
    box-shadow: 0 0 16px rgba(255, 255, 255, 0.3), 0 1px 4px rgba(0, 0, 0, 0.3);
    z-index: 2;
}

.mw-pt-shift-block-highlight .mw-pt-shift-block-name {
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 2px;
}

.mw-pt-shift-block-name {
    font-weight: 600;
    font-size: 11px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.2;
    user-select: text;
    -webkit-user-select: text;
}

.mw-pt-shift-block-time {
    font-size: 10px;
    opacity: 0.75;
    white-space: nowrap;
    line-height: 1.2;
    flex-shrink: 0;
}

/* Additional-shift section — below all stages. */
.mw-pt-shift-section {
    min-width: fit-content;
    border-top: 2px solid rgba(255, 255, 255, 0.1);
}

/* One team: a rotated vertical header (sticky left) spanning its leaf-position rows. */
.mw-pt-shift-team {
    display: flex;
    min-width: fit-content;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
}

/* NOTE: The rotated label is absolutely centered so its (potentially long) text never dictates
   the team's height — the position rows alone do. Otherwise a short team whose name is longer
   than its rows are tall would stretch the row and leave an empty gap below it. */
.mw-pt-shift-team-label {
    position: sticky;
    left: 0;
    z-index: 2;
    width: var(--mw-pt-shift-team-strip);
    min-width: var(--mw-pt-shift-team-strip);
    flex-shrink: 0;
    overflow: hidden;
    background: color-mix(in srgb, var(--mw-pt-accent-color) 22%, var(--mw-pt-bg-color));
    border-right: 1px solid rgba(255, 255, 255, 0.08);
}

.mw-pt-shift-team-label > span {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%) rotate(180deg);
    writing-mode: vertical-rl;
    max-height: 100%;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.mw-pt-shift-team-body {
    display: flex;
    flex-direction: column;
    min-width: fit-content;
    flex: 1;
}

.mw-pt-shift-row {
    min-height: 40px;
}

/* Leaf-position label — narrower than a stage label by the team strip, pinned just right of it. */
.mw-pt-shift-pos-label {
    width: calc(var(--mw-pt-label-width-clamped) - var(--mw-pt-shift-team-strip));
    min-width: calc(var(--mw-pt-label-width-clamped) - var(--mw-pt-shift-team-strip));
    max-width: calc(var(--mw-pt-label-width-clamped) - var(--mw-pt-shift-team-strip));
    left: var(--mw-pt-shift-team-strip);
    z-index: 2;
    font-weight: 500;
    font-size: 12px;
    text-transform: none;
}
