/* Crew Portal — minimal standalone theme stylesheet (not part of the main site's Tailwind build) */

:root {
    --cp-bg: #0f1115;
    --cp-surface: #181b21;
    --cp-surface-2: #21252d;
    --cp-border: #2a2e37;
    --cp-text: #eef0f4;
    --cp-text-muted: #98a0af;
    --cp-primary: #f5a623;
    --cp-primary-hover: #ffb949;
    --cp-primary-contrast: #16130a;
    --cp-primary-soft: rgba(245, 166, 35, 0.14);
    --cp-success: #3ecf6e;
    --cp-success-soft: rgba(62, 207, 110, 0.14);
    --cp-danger: #f0555a;
    --cp-danger-soft: rgba(240, 85, 90, 0.14);
    --cp-info: #4d9fff;
    --cp-info-soft: rgba(77, 159, 255, 0.14);

    --cp-radius-sm: 8px;
    --cp-radius: 12px;
    --cp-radius-lg: 18px;

    --cp-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.28);
    --cp-shadow: 0 10px 28px rgba(0, 0, 0, 0.32), 0 1px 3px rgba(0, 0, 0, 0.28);
    --cp-shadow-lg: 0 24px 56px rgba(0, 0, 0, 0.45);

    --cp-ease: 160ms ease;
}

/* Light mode — applied via explicit data-theme="light" (set by the inline
   no-flash script in the layout <head> based on saved preference or
   prefers-color-scheme), with a prefers-color-scheme fallback for the rare
   case JS is disabled. */
@media (prefers-color-scheme: light) {
    :root:not([data-theme]) {
        --cp-bg: #f2f3f6;
        --cp-surface: #ffffff;
        --cp-surface-2: #f6f7f9;
        --cp-border: #e2e5eb;
        --cp-text: #191c22;
        --cp-text-muted: #656d7c;
        --cp-primary: #d9880f;
        --cp-primary-hover: #c17b0d;
        --cp-primary-contrast: #ffffff;
        --cp-primary-soft: rgba(217, 136, 15, 0.1);
        --cp-success: #1f9d4b;
        --cp-success-soft: rgba(31, 157, 75, 0.1);
        --cp-danger: #cf3a3a;
        --cp-danger-soft: rgba(207, 58, 58, 0.1);
        --cp-info: #2563eb;
        --cp-info-soft: rgba(37, 99, 235, 0.1);
        --cp-shadow-sm: 0 1px 2px rgba(20, 24, 33, 0.06);
        --cp-shadow: 0 10px 24px rgba(20, 24, 33, 0.08), 0 1px 3px rgba(20, 24, 33, 0.05);
        --cp-shadow-lg: 0 28px 56px rgba(20, 24, 33, 0.16);
    }
}

:root[data-theme="light"] {
    --cp-bg: #f2f3f6;
    --cp-surface: #ffffff;
    --cp-surface-2: #f6f7f9;
    --cp-border: #e2e5eb;
    --cp-text: #191c22;
    --cp-text-muted: #656d7c;
    --cp-primary: #d9880f;
    --cp-primary-hover: #c17b0d;
    --cp-primary-contrast: #ffffff;
    --cp-primary-soft: rgba(217, 136, 15, 0.1);
    --cp-success: #1f9d4b;
    --cp-success-soft: rgba(31, 157, 75, 0.1);
    --cp-danger: #cf3a3a;
    --cp-danger-soft: rgba(207, 58, 58, 0.1);
    --cp-info: #2563eb;
    --cp-info-soft: rgba(37, 99, 235, 0.1);
    --cp-shadow-sm: 0 1px 2px rgba(20, 24, 33, 0.06);
    --cp-shadow: 0 10px 24px rgba(20, 24, 33, 0.08), 0 1px 3px rgba(20, 24, 33, 0.05);
    --cp-shadow-lg: 0 28px 56px rgba(20, 24, 33, 0.16);
}

:root[data-theme="dark"] {
    --cp-bg: #0f1115;
    --cp-surface: #181b21;
    --cp-surface-2: #21252d;
    --cp-border: #2a2e37;
    --cp-text: #eef0f4;
    --cp-text-muted: #98a0af;
    --cp-primary: #f5a623;
    --cp-primary-hover: #ffb949;
    --cp-primary-contrast: #16130a;
    --cp-primary-soft: rgba(245, 166, 35, 0.14);
    --cp-success: #3ecf6e;
    --cp-success-soft: rgba(62, 207, 110, 0.14);
    --cp-danger: #f0555a;
    --cp-danger-soft: rgba(240, 85, 90, 0.14);
    --cp-info: #4d9fff;
    --cp-info-soft: rgba(77, 159, 255, 0.14);
    --cp-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.28);
    --cp-shadow: 0 10px 28px rgba(0, 0, 0, 0.32), 0 1px 3px rgba(0, 0, 0, 0.28);
    --cp-shadow-lg: 0 24px 56px rgba(0, 0, 0, 0.45);
}

* {
    box-sizing: border-box;
}

body {
    margin: 0;
    background: var(--cp-bg);
    color: var(--cp-text);
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Inter, Roboto, Helvetica, Arial, sans-serif;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
}

a {
    transition: color var(--cp-ease);
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid var(--cp-primary);
    outline-offset: 2px;
}

.container {
    max-width: 960px;
    margin: 0 auto;
    padding: 2.5rem 1.5rem;
}

/* Wider variant for every page grouped under the nav's "Overzichten"
   dropdown (/rooster, /alle-teams, /maaltijden, /aanmeldstatus) — see
   layouts/default.htm's isWideContainerPage. */
.container--wide {
    max-width: 1600px;
}

.page-title {
    font-size: 1.85rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    margin: 0 0 1.5rem;
}

/* Form fields — shared base, individual containers opt into width:100% */

input,
select,
textarea {
    padding: 0.6rem 0.85rem;
    border-radius: var(--cp-radius-sm);
    border: 1px solid var(--cp-border);
    background: var(--cp-bg);
    color: var(--cp-text);
    font-size: 0.9rem;
    font-family: inherit;
    transition: border-color var(--cp-ease), box-shadow var(--cp-ease);
}

input[type="checkbox"],
input[type="radio"] {
    width: auto;
    padding: 0;
    accent-color: var(--cp-primary);
}

input:focus,
select:focus,
textarea:focus {
    border-color: var(--cp-primary);
    box-shadow: 0 0 0 3px var(--cp-primary-soft);
    outline: none;
}

/* Any `<div class="form-group"><label>...</label><input/select/textarea></div>`
   block gets a consistent stacked, full-width layout automatically —
   applies theme-wide (login, contact details, and every custom form in
   manage.htm) instead of being opted into per form container. Excludes
   checkbox/radio explicitly rather than via a bare `input` selector, so
   specificity can't tie against the `input[type="checkbox"]` override
   above regardless of source order. */

.form-group {
    margin-bottom: 1rem;
}

.form-group label {
    display: block;
    font-size: 0.85rem;
    color: var(--cp-text-muted);
    margin-bottom: 0.35rem;
}

.form-group input[type="text"],
.form-group input[type="email"],
.form-group input[type="password"],
.form-group input[type="tel"],
.form-group input[type="number"],
.form-group select,
.form-group textarea {
    width: 100%;
}

.form-group input:disabled,
.form-group select:disabled,
.form-group textarea:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

/* A `date` + `time` input pair standing in for one logical datetime value —
   native `datetime-local` renders as a single fiddly combined widget in
   several browsers, so every datetime field in this theme uses this pair
   instead (see pages/enrollment.htm and pages/teams/manage.htm), recombined
   server-side into one string before saving. */

.datetime-pair {
    display: flex;
    gap: 0.5rem;
}

.datetime-pair input {
    width: 100%;
    min-width: 0;
}

/* A bordered, labeled sub-group of .form-group fields inside a larger form —
   used to visually set apart a set of fields that plays a distinct *role*
   from the rest of the form (e.g. internal planning times vs. the public
   schedule times, or a scheduled publication window vs. the main content),
   rather than letting every field blur together in one long list. The
   ".form-fieldset__badge" modifier classes below give each role its own
   color so two different fieldsets on the same form don't look
   interchangeable. */

.form-fieldset {
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-radius);
    background: var(--cp-surface-2);
    padding: 1rem 1.1rem 0.25rem;
    margin-bottom: 1.25rem;
}

.form-fieldset__title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    font-weight: 600;
    font-size: 0.95rem;
    margin-bottom: 0.35rem;
}

.form-fieldset__badge {
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
}

.form-fieldset__badge--internal {
    background: var(--cp-border);
    color: var(--cp-text-muted);
}

.form-fieldset__badge--publication {
    background: var(--cp-info-soft);
    color: var(--cp-info);
}

.form-fieldset__hint {
    color: var(--cp-text-muted);
    font-size: 0.85rem;
    margin: 0 0 0.75rem;
}

/* flatpickr popup theming (see assets/js/datetimepicker.js) — the vendored
   flatpickr.min.css only supplies structural/layout rules here, every
   color comes from this theme's own --cp-* tokens so the picker follows
   dark/light mode automatically, same as everything else in this theme. */

.flatpickr-calendar {
    background: var(--cp-surface);
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-radius);
    box-shadow: var(--cp-shadow);
    font-family: inherit;
}

.flatpickr-calendar.arrowTop::before,
.flatpickr-calendar.arrowTop::after {
    border-bottom-color: var(--cp-surface);
}

.flatpickr-months .flatpickr-month,
.flatpickr-current-month,
.flatpickr-weekdays {
    background: var(--cp-surface);
    color: var(--cp-text);
    fill: var(--cp-text);
}

.flatpickr-current-month input.cur-year,
.flatpickr-monthDropdown-months {
    color: var(--cp-text);
    font-family: inherit;
}

.flatpickr-prev-month:hover svg,
.flatpickr-next-month:hover svg {
    fill: var(--cp-primary);
}

span.flatpickr-weekday {
    color: var(--cp-text-muted);
    font-weight: 700;
}

.flatpickr-day {
    color: var(--cp-text);
    border-radius: var(--cp-radius-sm);
}

.flatpickr-day.flatpickr-disabled,
.flatpickr-day.flatpickr-disabled:hover {
    color: var(--cp-text-muted);
    opacity: 0.4;
}

.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay {
    color: var(--cp-text-muted);
}

.flatpickr-day:hover,
.flatpickr-day:focus {
    background: var(--cp-primary-soft);
    border-color: var(--cp-primary-soft);
}

.flatpickr-day.today {
    border-color: var(--cp-primary);
}

.flatpickr-day.selected,
.flatpickr-day.selected:hover,
.flatpickr-day.selected:focus {
    background: var(--cp-primary);
    border-color: var(--cp-primary);
    color: var(--cp-primary-contrast);
}

.flatpickr-time {
    background: var(--cp-surface);
    border-top: 1px solid var(--cp-border);
}

.flatpickr-time input,
.flatpickr-time .flatpickr-am-pm {
    color: var(--cp-text);
    font-family: inherit;
}

.flatpickr-time input:hover,
.flatpickr-time input:focus,
.flatpickr-time .flatpickr-am-pm:hover,
.flatpickr-time .flatpickr-am-pm:focus {
    background: var(--cp-primary-soft);
}

.numInputWrapper:hover {
    background: var(--cp-primary-soft);
}

/* Minimal rich text editor (see assets/js/richeditor.js) — currently only
   /maaltijden's eating-time description. */

.rich-editor {
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-radius-sm);
    overflow: hidden;
}

.rich-editor__toolbar {
    display: flex;
    gap: 0.15rem;
    padding: 0.35rem;
    background: var(--cp-surface-2);
    border-bottom: 1px solid var(--cp-border);
}

.rich-editor__toolbar button {
    width: 2rem;
    height: 2rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: var(--cp-radius-sm);
    background: transparent;
    color: var(--cp-text);
    font-size: 0.85rem;
    cursor: pointer;
    transition: background var(--cp-ease);
}

.rich-editor__toolbar button:hover {
    background: var(--cp-border);
}

.rich-editor__content {
    min-height: 6rem;
    padding: 0.6rem 0.85rem;
    background: var(--cp-bg);
    color: var(--cp-text);
    font-size: 0.9rem;
    line-height: 1.5;
}

.rich-editor__content:focus {
    outline: none;
    box-shadow: inset 0 0 0 2px var(--cp-primary-soft);
}

.rich-editor__content ul,
.rich-editor__content ol {
    margin: 0.5rem 0;
    padding-left: 1.5rem;
}

/* Nav */

.nav {
    position: sticky;
    top: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    padding: 0.85rem 1.75rem;
    background: var(--cp-surface);
    box-shadow: 0 1px 0 var(--cp-border), var(--cp-shadow-sm);
    flex-wrap: wrap;
}

.nav__brand {
    color: var(--cp-text);
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: -0.01em;
    text-decoration: none;
}

/* Visually hidden rather than display:none — a display:none checkbox drops
   out of the tab order entirely, which would make the mobile menu
   unreachable by keyboard. Kept focusable; :focus-visible is forwarded to
   the visible label below via the adjacent-sibling rule further down. */
.nav__toggle-input {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.nav__toggle {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0.5rem;
    border-radius: var(--cp-radius-sm);
    cursor: pointer;
}

.nav__toggle-input:focus-visible + .nav__toggle {
    outline: 2px solid var(--cp-primary);
    outline-offset: 2px;
}

.nav__toggle:hover {
    background: var(--cp-surface-2);
}

.nav__toggle-bar {
    display: block;
    height: 2px;
    border-radius: 1px;
    background: var(--cp-text);
}

.nav__menu {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    flex: 1;
    flex-wrap: wrap;
}

.nav__links {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    flex-wrap: wrap;
}

.nav__link {
    padding: 0.45rem 0.9rem;
    border-radius: 999px;
    color: var(--cp-text-muted);
    text-decoration: none;
    font-size: 0.88rem;
    font-weight: 500;
    transition: background var(--cp-ease), color var(--cp-ease);
}

.nav__link:hover {
    color: var(--cp-text);
    background: var(--cp-surface-2);
}

.nav__link--active {
    color: var(--cp-primary-contrast);
    background: var(--cp-primary);
    font-weight: 600;
}

/* Pending-count badge next to a nav item (currently only "Mijn teams",
   for pending service requests on teams the viewer can approve/deny for) —
   plain solid danger pill, unscoped/reusable if a future nav item ever
   needs the same "something needs your attention" signal. */
.nav__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.15rem;
    height: 1.15rem;
    padding: 0 0.3rem;
    margin-left: 0.4rem;
    border-radius: 999px;
    background: var(--cp-danger);
    color: #fff;
    font-size: 0.7rem;
    font-weight: 700;
    line-height: 1;
}

.nav__logout {
    padding: 0.45rem 0.9rem;
    border-radius: 999px;
    color: var(--cp-text-muted);
    text-decoration: none;
    font-size: 0.88rem;
    font-weight: 500;
    cursor: pointer;
    transition: background var(--cp-ease), color var(--cp-ease);
}

.nav__logout:hover {
    color: var(--cp-danger);
    background: var(--cp-danger-soft);
}

/* Overview-pages dropdown ("Overzichten") in the top nav — a native
   <details>/<summary> pair, same no-JS disclosure pattern already used for
   .breakglass, so it needs no extra script for open/close. */
.nav__dropdown {
    position: relative;
}

.nav__dropdown-summary {
    cursor: pointer;
    list-style: none;
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
}

.nav__dropdown-summary::-webkit-details-marker {
    display: none;
}

.nav__dropdown-summary::after {
    content: '▾';
    font-size: 0.65rem;
    transition: transform var(--cp-ease);
}

.nav__dropdown[open] > .nav__dropdown-summary::after {
    transform: rotate(180deg);
}

.nav__dropdown-menu {
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 0.35rem;
    display: flex;
    flex-direction: column;
    min-width: 190px;
    background: var(--cp-surface);
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-radius-sm);
    box-shadow: var(--cp-shadow);
    padding: 0.35rem;
    z-index: 10;
}

/* Access denied */

.access-denied {
    max-width: 480px;
    margin: 4rem auto;
    padding: 2.25rem;
    text-align: center;
    background: var(--cp-surface);
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-radius-lg);
    box-shadow: var(--cp-shadow);
}

.access-denied__meta {
    color: var(--cp-text-muted);
    font-size: 0.9rem;
}

/* Buttons */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    padding: 0.6rem 1.25rem;
    border-radius: var(--cp-radius-sm);
    border: 1px solid var(--cp-border);
    background: var(--cp-surface-2);
    color: var(--cp-text);
    text-decoration: none;
    cursor: pointer;
    font-size: 0.9rem;
    font-weight: 500;
    line-height: 1.2;
    transition: background var(--cp-ease), border-color var(--cp-ease), box-shadow var(--cp-ease), transform var(--cp-ease);
}

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

.btn:active {
    transform: translateY(1px);
}

.btn--primary {
    background: var(--cp-primary);
    border-color: var(--cp-primary);
    color: var(--cp-primary-contrast);
    font-weight: 600;
    box-shadow: var(--cp-shadow-sm);
}

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

.btn--sm {
    padding: 0.35rem 0.8rem;
    font-size: 0.8rem;
}

/* Login */

.guest-body {
    display: flex;
    min-height: 100vh;
    align-items: center;
    justify-content: center;
    background:
        radial-gradient(circle at 15% 10%, var(--cp-primary-soft), transparent 45%),
        var(--cp-bg);
}

.guest-main {
    width: 100%;
}

.login-panel {
    max-width: 380px;
    margin: 0 auto;
    padding: 2.25rem;
    background: var(--cp-surface);
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-radius-lg);
    box-shadow: var(--cp-shadow-lg);
}

.login-panel__intro {
    color: var(--cp-text-muted);
    font-size: 0.9rem;
    margin-top: -0.75rem;
}

.login-form .btn {
    width: 100%;
    text-align: center;
    margin-top: 0.5rem;
}

/* My Shifts */

.myshifts__roles {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-bottom: 1.5rem;
}

.myshifts__role-badge {
    padding: 0.3rem 0.85rem;
    border-radius: 999px;
    background: var(--cp-surface-2);
    border: 1px solid var(--cp-border);
    font-size: 0.8rem;
    font-weight: 500;
}

.myshifts__list,
.schedule__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.myshifts__shift,
.schedule__shift {
    padding: 0.9rem 1.1rem;
    background: var(--cp-surface);
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-radius);
    box-shadow: var(--cp-shadow-sm);
    transition: box-shadow var(--cp-ease), border-color var(--cp-ease);
}

.myshifts__shift:hover,
.schedule__shift:hover {
    box-shadow: var(--cp-shadow);
}

.schedule__shift--full {
    border-color: var(--cp-success);
}

/* Soft-deleted service request — stays visible everywhere (never hidden),
   just grayed out and clearly marked, per the explicit "must stay visible"
   requirement. Reusable on any .myshifts__shift-shaped card. */
.myshifts__shift--deleted {
    opacity: 0.55;
    background: var(--cp-surface-2);
}

.myshifts__shift-title,
.schedule__shift-title {
    font-weight: 700;
    margin-right: 0.75rem;
}

.myshifts__shift-role,
.schedule__shift-role {
    display: inline-block;
    padding: 0.15rem 0.65rem;
    border-radius: 999px;
    background: var(--cp-surface-2);
    border: 1px solid var(--cp-border);
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--cp-text-muted);
}

.myshifts__shift-time,
.schedule__shift-time,
.myshifts__shift-location,
.schedule__shift-location,
.schedule__shift-capacity {
    display: block;
    color: var(--cp-text-muted);
    font-size: 0.85rem;
    margin-top: 0.35rem;
}

.myshifts__shift-description,
.schedule__shift-description {
    margin: 0.5rem 0 0;
    font-size: 0.9rem;
}

.myshifts__no-shifts,
.myshifts__not-crew,
.myshifts__login-required,
.schedule__empty {
    color: var(--cp-text-muted);
}

/* My Shifts — list/calendar view toggle + calendar grid */

.myshifts__view-tabs {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin-bottom: 1.25rem;
}

.myshifts__view-tabs-ics {
    margin-left: auto;
}

.myshifts__shift-ics {
    margin: 0.6rem 0 0;
}

.myshifts-calendar__nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    margin-bottom: 1rem;
}

.myshifts-calendar__month {
    font-weight: 700;
    min-width: 9rem;
    text-align: center;
}

/* Same reasoning as .roster-grid-wrap/.team-table-wrap — scroll
   horizontally on a phone rather than squeezing 7 columns illegibly. */
.myshifts-calendar-wrap {
    overflow-x: auto;
}

.myshifts-calendar__grid {
    width: 100%;
    min-width: 560px;
    border-collapse: collapse;
    table-layout: fixed;
}

.myshifts-calendar__grid th {
    padding: 0.5rem;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--cp-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border: 1px solid var(--cp-border);
    background: var(--cp-surface-2);
}

.myshifts-calendar__day {
    vertical-align: top;
    height: 5.5rem;
    padding: 0.4rem;
    border: 1px solid var(--cp-border);
}

.myshifts-calendar__day-number {
    display: block;
    font-size: 0.8rem;
    color: var(--cp-text-muted);
    margin-bottom: 0.25rem;
}

.myshifts-calendar__day--outside {
    background: var(--cp-surface-2);
}

.myshifts-calendar__day--outside .myshifts-calendar__day-number {
    opacity: 0.5;
}

/* Days outside the edition's own buildup-to-teardown window (see
   Classes\EditionWindow) — visually inert, never carry a shift, so this
   is purely a "not relevant" cue rather than anything interactive. */
.myshifts-calendar__day--disabled {
    background: repeating-linear-gradient(
        135deg,
        var(--cp-surface-2),
        var(--cp-surface-2) 6px,
        var(--cp-surface) 6px,
        var(--cp-surface) 12px
    );
}

.myshifts-calendar__day--disabled .myshifts-calendar__day-number {
    opacity: 0.4;
}

.myshifts-calendar__day--today {
    border-color: var(--cp-primary);
    box-shadow: inset 0 0 0 1px var(--cp-primary);
}

.myshifts-calendar__day--today .myshifts-calendar__day-number {
    color: var(--cp-primary);
    font-weight: 700;
}

.myshifts-calendar__shift {
    display: block;
    padding: 0.15rem 0.4rem;
    margin-top: 0.2rem;
    border-radius: var(--cp-radius-sm);
    background: var(--cp-primary-soft);
    color: var(--cp-primary);
    font-size: 0.72rem;
    font-weight: 500;
    text-decoration: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.myshifts-calendar__shift:hover {
    text-decoration: underline;
}

/* A multi-day shift's continuation day(s) in the calendar — same pill,
   muted/dashed so it reads as "still going" rather than a separate shift
   starting fresh that day (mirrors .roster-card--continuation on /rooster). */
.myshifts-calendar__shift--continuation {
    background: transparent;
    border: 1px dashed var(--cp-border);
    color: var(--cp-text-muted);
    font-style: italic;
}

.schedule__shift-signup {
    margin: 0.6rem 0 0;
}

.schedule__shift-signup--info {
    color: var(--cp-text-muted);
    font-size: 0.85rem;
    font-style: italic;
}

/* Full rooster — kanban grid, one row per team that has a shift and one
   column per day of the edition's buildup-to-teardown window (see
   Classes\CrewRosterBoard). Horizontally scrollable so a multi-day event
   still fits without wrapping; the team-name column stays pinned via
   `position: sticky` while the day columns scroll underneath it. */

.roster-grid__nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    margin-bottom: 1rem;
}

.roster-grid__range {
    font-weight: 700;
    min-width: 12rem;
    text-align: center;
}

.roster-grid-wrap {
    overflow-x: auto;
    padding-bottom: 0.5rem;
}

.roster-grid {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
}

.roster-grid__team-header,
.roster-grid__day-header {
    padding: 0.6rem 0.9rem;
    background: var(--cp-surface-2);
    border: 1px solid var(--cp-border);
}

.roster-grid__team-header {
    min-width: 140px;
}

.roster-grid__day-header {
    min-width: 240px;
    font-size: 0.85rem;
    font-weight: 700;
    text-align: left;
    text-transform: capitalize;
    white-space: nowrap;
}

.roster-grid__team-name {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--cp-surface-2);
    padding: 0.6rem 0.9rem;
    border: 1px solid var(--cp-border);
    font-size: 0.9rem;
    font-weight: 700;
    text-align: left;
    white-space: nowrap;
    vertical-align: top;
}

.roster-grid__cell {
    padding: 0.6rem;
    border: 1px solid var(--cp-border);
    vertical-align: top;
    min-width: 240px;
}

.roster-grid__cell-stack {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.roster-outside {
    margin-top: 2rem;
}

.roster-outside__title {
    margin: 0 0 0.75rem;
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--cp-danger);
}

.roster-outside__list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    max-width: 420px;
}

.roster-card {
    padding: 0.9rem 1rem;
    background: var(--cp-surface);
    border: 1px solid var(--cp-border);
    border-left: 4px solid var(--roster-card-team-color, var(--cp-border));
    border-radius: var(--cp-radius-sm);
    box-shadow: var(--cp-shadow-sm);
    transition: box-shadow var(--cp-ease), background var(--cp-ease);
}

.roster-card:hover {
    box-shadow: var(--cp-shadow);
}

/* Status is shown via background tint (border-left is reserved for the
   team color, see roster-card.htm's inline --roster-card-team-color). */
.roster-card--full {
    background: var(--cp-success-soft);
}

.roster-card--understaffed {
    background: var(--cp-danger-soft);
}

/* A multi-day shift's own continuation day(s) — same card, but a lighter,
   dashed treatment and no capacity/description/signup content, so it reads
   as "this shift is still going" rather than a second, separate shift. */
.roster-card--continuation {
    border-style: dashed;
    opacity: 0.75;
}

.roster-card__continuation-badge {
    display: block;
    margin-top: 0.3rem;
    color: var(--cp-text-muted);
    font-size: 0.72rem;
    font-style: italic;
}

.roster-card__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.5rem;
}

.roster-card__title {
    display: block;
    font-weight: 700;
    font-size: 0.9rem;
}

.roster-card__title--link {
    color: var(--cp-text);
    text-decoration: none;
    cursor: pointer;
}

.roster-card__title--link:hover {
    text-decoration: underline;
}

.roster-card__team {
    flex-shrink: 0;
    padding: 0.15rem 0.6rem;
    border-radius: 999px;
    background: var(--cp-surface-2);
    border: 1px solid var(--cp-border);
    font-size: 0.72rem;
    font-weight: 500;
    color: var(--cp-text-muted);
}

.roster-card__time,
.roster-card__location,
.roster-card__capacity {
    display: block;
    color: var(--cp-text-muted);
    font-size: 0.8rem;
    margin-top: 0.3rem;
}

.roster-card__description {
    margin: 0.5rem 0 0;
    font-size: 0.85rem;
}

.roster-card__signup {
    margin: 0.6rem 0 0;
}

.roster-card__signup--info {
    color: var(--cp-text-muted);
    font-size: 0.8rem;
    font-style: italic;
}

/* Open opportunities (home page) */

.opportunities__section {
    margin-bottom: 2rem;
}

.opportunities__section:last-child {
    margin-bottom: 0;
}

.opportunities__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.opportunity-card {
    padding: 0.9rem 1.1rem;
    background: var(--cp-surface);
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-radius);
    box-shadow: var(--cp-shadow-sm);
    transition: box-shadow var(--cp-ease);
}

.opportunity-card:hover {
    box-shadow: var(--cp-shadow);
}

.opportunity-card__title {
    font-weight: 700;
    margin-right: 0.75rem;
}

.opportunity-card__meta {
    display: block;
    color: var(--cp-text-muted);
    font-size: 0.85rem;
    margin-top: 0.35rem;
}

.opportunity-card__description {
    margin: 0.5rem 0 0;
    font-size: 0.9rem;
}

.opportunity-card__action {
    margin: 0.6rem 0 0;
}

/* Notice banner (e.g. encouraged-2FA nudge) */

.notice {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
    padding: 0.9rem 1.25rem;
    margin-bottom: 1.5rem;
    background: var(--cp-primary-soft);
    border: 1px solid var(--cp-border);
    border-left: 4px solid var(--cp-primary);
    border-radius: var(--cp-radius);
    font-size: 0.9rem;
}

.notice a {
    color: var(--cp-primary);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}

.notice a:hover {
    text-decoration: underline;
}

.notice--success {
    background: var(--cp-success-soft);
    border-left-color: var(--cp-success);
}

.notice--success a {
    color: var(--cp-success);
}

.notice--danger {
    background: var(--cp-danger-soft);
    border-left-color: var(--cp-danger);
}

.notice--danger a {
    color: var(--cp-danger);
}

.notice--info {
    background: var(--cp-info-soft);
    border-left-color: var(--cp-info);
}

.notice--info a {
    color: var(--cp-info);
}

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

.btn--danger:hover {
    background: var(--cp-danger-soft);
    border-color: var(--cp-danger);
}

/* Enrollment wizard */

.enrollment-steps {
    display: flex;
    gap: 0.5rem;
    list-style: none;
    margin: 0 0 1.5rem;
    padding: 0;
    flex-wrap: wrap;
}

.enrollment-steps__item {
    border-radius: 999px;
}

.enrollment-steps__item a,
.enrollment-steps__item span {
    display: inline-block;
    padding: 0.4rem 1rem;
    border-radius: 999px;
    font-size: 0.85rem;
    font-weight: 600;
    background: var(--cp-surface-2);
    color: var(--cp-text-muted);
    text-decoration: none;
}

.enrollment-steps__item a:hover {
    background: var(--cp-border);
}

.enrollment-steps__item.is-done a,
.enrollment-steps__item.is-done span {
    background: var(--cp-success-soft);
    color: var(--cp-success);
}

/* Matches the step's own current hard-fail/soft-fail condition (see
   Classes\CrewEnrollment::failReasons()) — declared after .is-done but
   before .is-active, so a still-failing step you're not currently on
   shows its fail color, while the step you *are* on keeps its bold
   "selected" look regardless (that page's own content already explains
   what's wrong, no need for the pill itself to also carry the warning).
   Soft-fail reuses --cp-primary, this theme's actual "orange" semantic
   (see the notice banner's own unmodified base state). */
.enrollment-steps__item.is-hard-fail a,
.enrollment-steps__item.is-hard-fail span {
    background: var(--cp-danger-soft);
    color: var(--cp-danger);
}

.enrollment-steps__item.is-soft-fail a,
.enrollment-steps__item.is-soft-fail span {
    background: var(--cp-primary-soft);
    color: var(--cp-primary);
}

.enrollment-steps__item.is-active a,
.enrollment-steps__item.is-active span {
    background: var(--cp-primary);
    color: var(--cp-primary-contrast);
}

.enrollment-steps__item.is-locked span {
    opacity: 0.5;
}

.enrollment-step__hint {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    color: var(--cp-text-muted);
    font-size: 0.9rem;
}

.enrollment-step__form {
    display: flex;
    align-items: flex-end;
    gap: 1rem;
    flex-wrap: wrap;
}

/* A submit button sitting next to labeled fields in a flex-end row (e.g.
   Noodcontact's add-contact form) has no label of its own, so bottom-
   aligning it against `.form-group`'s label+input stack leaves its top
   edge sitting lower than the inputs' — visually "not lined up" even
   though the bottoms match. An invisible label above the button gives it
   the same label-height spacer the other fields already have, so the
   whole row reads as level. */
.enrollment-step__form__button-group label {
    visibility: hidden;
}

/* Some enrollment-step forms (e.g. the mobile-procedure toggle + notes)
   read better stacked top-to-bottom than side-by-side in a row — opt out
   of the base row layout entirely rather than fighting it with wrapping. */
.enrollment-step__form--stacked {
    flex-direction: column;
    align-items: stretch;
}

.enrollment-timeslots {
    list-style: none;
    margin: 0 0 1.25rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.enrollment-timeslots li {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.6rem 1rem;
    background: var(--cp-surface-2);
    border-radius: var(--cp-radius-sm);
    font-size: 0.9rem;
}

.enrollment-timeslots__empty {
    color: var(--cp-text-muted);
    font-size: 0.9rem;
}

.enrollment-meals-form {
    display: block;
}

.enrollment-meals {
    list-style: none;
    margin: 0 0 1.25rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.enrollment-meals__item {
    padding: 0.75rem 1rem;
    background: var(--cp-surface-2);
    border-radius: var(--cp-radius-sm);
}

.enrollment-meals__header {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.6rem;
}

.enrollment-meals__name {
    font-weight: 600;
}

.enrollment-meals__time {
    color: var(--cp-text-muted);
    font-size: 0.85rem;
}

.enrollment-meals__description {
    margin: 0.5rem 0 0;
    font-size: 0.85rem;
    color: var(--cp-text-muted);
}

.enrollment-meals__choice {
    display: flex;
    gap: 1.25rem;
    margin-top: 0.6rem;
}

.enrollment-meals__choice label {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    cursor: pointer;
    font-size: 0.9rem;
}

/* Profile page */

.profile-section {
    padding: 1.25rem;
    margin-bottom: 1.1rem;
    background: var(--cp-surface);
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-radius);
    box-shadow: var(--cp-shadow-sm);
}

/* Used on My Reality (/mijn-reality) to flag a section whose data doesn't
   count towards anything while the viewer is hard-fail — same red tokens
   as .notice--danger, just applied to a card instead of a banner. */
.profile-section--danger {
    background: var(--cp-danger-soft);
    border-color: var(--cp-danger);
}

/* Flags a section whose own condition is currently soft-failing (e.g. an
   expiring certification) — this theme's "orange" semantic is actually
   --cp-primary (see the notice banner's own unmodified base state), not a
   separate warning token. */
.profile-section--warning {
    background: var(--cp-primary-soft);
    border-color: var(--cp-primary);
}

.profile-section__title {
    margin: 0 0 0.35rem;
    font-size: 1.1rem;
    font-weight: 700;
}

.profile-section__header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
}

.profile-section__header .profile-section__title {
    margin-bottom: 0;
}

.profile-section__intro {
    margin: 0 0 0.85rem;
    color: var(--cp-text-muted);
    font-size: 0.9rem;
    white-space: pre-line;
}

.profile-status {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.25rem 0.8rem;
    border-radius: 999px;
    font-size: 0.8rem;
    font-weight: 600;
    margin-bottom: 1rem;
}

.profile-status--on {
    color: var(--cp-success);
    background: var(--cp-success-soft);
}

.profile-status--off {
    color: var(--cp-text-muted);
    background: var(--cp-surface-2);
}

.profile-theme-form {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
}

/* .profile-theme-form's flex row leaves .form-group at its shrink-wrapped
   intrinsic width, so its input's own `width: 100%` just means 100% of
   that small box — fine for the short values most .profile-theme-form
   consumers hold, but a UUID/invite-code value needs real room. Scoped to
   this one form rather than widening .form-group generally, since most
   other .profile-theme-form usages are deliberately compact. */
.upgrade-search-form .form-group {
    flex: 1 1 auto;
    min-width: 240px;
    margin-bottom: 0;
}

.contact-details-form {
    max-width: 420px;
}

/* Reusable live-search dropdown (assets/js/livesearch.js) — the wrap is the
   positioning context, the dropdown floats beneath the input. Used by
   "Gebruiker upgraden" and the team roster add-member picker. */
.livesearch-wrap {
    position: relative;
}

.livesearch-dropdown {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 20;
    margin-top: 4px;
    background: var(--cp-surface);
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-radius-sm);
    box-shadow: var(--cp-shadow);
    max-height: 260px;
    overflow-y: auto;
}

.livesearch-result {
    display: block;
    padding: 0.5rem 0.75rem;
    color: inherit;
    text-decoration: none;
    border-bottom: 1px solid var(--cp-border);
}

.livesearch-result:last-child {
    border-bottom: none;
}

.livesearch-result:hover,
.livesearch-result:focus {
    background: var(--cp-surface-2);
}

.livesearch-result__meta {
    display: block;
    font-size: 0.8em;
    opacity: 0.7;
}

.checkbox-label {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    font-size: 0.9rem;
    color: var(--cp-text);
    cursor: pointer;
}

.checkbox-label input[type="checkbox"] {
    margin-top: 0.2rem;
}

/* Loterijen (/loterijen, and the backend Lotteries controller's own
   equivalent markup) — a compact multi-checkbox row (ticket/seat types)
   instead of the one-per-line stack .checkbox-label alone produces when
   several sit inside their own .form-group, and a single flex row pairing
   a form's action button(s) with its own live stat text, so the two never
   end up stacked on separate lines the way plain block-level children
   would. */
.lottery-checkbox-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1.25rem;
}

.lottery-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
    margin-top: 0.75rem;
}

.lottery-stats {
    color: var(--cp-text-muted);
    font-size: 0.85rem;
}

.user-detail-list {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.4rem 1rem;
    margin: 0;
}

.user-detail-list dt {
    color: var(--cp-text-muted);
    font-size: 0.85rem;
}

.user-detail-list dd {
    margin: 0;
    font-weight: 600;
}

/* Emergency contact block + break-the-glass panel inside the user detail
   popup/page (partials/user-detail-content.htm). The <details>/<summary>
   pair needs no JS for its own open/close toggle — only the "Bevestigen"
   submit inside it goes through data-request, same as every other form. */
.user-detail-emergency {
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid var(--cp-border);
}

.user-detail-emergency__title {
    font-size: 0.9rem;
    margin: 0 0 0.5rem;
}

.user-detail-emergency__subtitle {
    display: block;
    font-size: 0.8rem;
    font-weight: 700;
    margin: 0.75rem 0 0.2rem;
}

/* The whole break-the-glass section (collapsed and expanded alike) gets its
   own danger-tinted box so it visually stands apart from the rest of the
   popup, not just the panel that appears after opening it. */
.breakglass {
    margin-top: 1rem;
    padding: 0.75rem 1rem;
    background: var(--cp-danger-soft);
    border: 1px solid var(--cp-danger);
    border-radius: var(--cp-radius);
}

.breakglass__summary {
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.6rem;
}

.breakglass__summary::-webkit-details-marker {
    display: none;
}

.breakglass__note {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--cp-danger);
}

.breakglass__panel {
    margin-top: 0.75rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--cp-danger);
}

.breakglass__warning {
    font-size: 0.85rem;
    margin: 0 0 0.75rem;
}

/* Team directory */

.team-directory {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.team-directory__team {
    background: var(--cp-surface);
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-radius);
    box-shadow: var(--cp-shadow-sm);
    padding: 0.9rem 1.1rem;
    transition: box-shadow var(--cp-ease);
}

.team-directory__team:hover {
    box-shadow: var(--cp-shadow);
}

.team-directory__name {
    margin: 0 0 0.75rem;
    font-size: 1rem;
    font-weight: 700;
}

.team-directory__group {
    margin-bottom: 0.6rem;
}

.team-directory__group:last-child {
    margin-bottom: 0;
}

.team-directory__group-label {
    display: block;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    font-weight: 600;
    color: var(--cp-text-muted);
    margin-bottom: 0.35rem;
}

.team-directory__members {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 0.6rem;
}

/* Reusable pill-button for a crew member's name (e.g. opens the user-detail modal).
   Unscoped on purpose — used inside .team-directory__members, plain table cells,
   and shift-assignment lists alike, not just wherever it was first introduced. */
.user-chip {
    display: inline-block;
    padding: 0.2rem 0.7rem;
    border-radius: 999px;
    background: var(--cp-surface-2);
    color: var(--cp-primary);
    text-decoration: none;
    font-size: 0.85rem;
    font-weight: 500;
    cursor: pointer;
    transition: background var(--cp-ease), color var(--cp-ease);
}

.user-chip:hover {
    background: var(--cp-primary-soft);
}

/* Marks a team's primary lead (see CrewTeamMember.is_primary_lead) —
   solid instead of soft background so it reads as visually distinct
   from a regular/non-primary lead's chip at a glance. */
.user-chip--primary {
    background: var(--cp-primary);
    color: var(--cp-primary-contrast);
    font-weight: 700;
}

.user-chip--primary:hover {
    background: var(--cp-primary-hover);
}

.team-directory__empty {
    color: var(--cp-text-muted);
    font-size: 0.85rem;
}

/* Compact "(Voornaam Achternaam)" shown next to a username on frontend
   overviews gated by a portal-role capability — those pages already
   require special permission to view at all, so the full name is shown
   unconditionally there, unlike the opt-in-gated reveal used on ungated
   overviews (Alle teams, Gebruiker opzoeken). Reusable/unscoped since it's
   used across several different overview pages. */
.name-hint {
    color: var(--cp-text-muted);
    font-size: 0.85em;
    margin-left: 0.35rem;
}

/* Popup modal */

.modal {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 1000;
}

.modal.is-open {
    display: block;
}

.modal__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(8, 10, 14, 0.6);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
}

/* 720px is the theme-wide default popup width — widened from the original
   420px after the schedule-item popup's wider layout (more room for a
   form with several fields/fieldsets) turned out to read better than the
   old cramped default across the board. Every popup in the crew portal
   shares this one class, so this single change already widens all of
   them — no per-page modifier needed. */
.modal__panel {
    position: relative;
    width: calc(100% - 2rem);
    max-width: 720px;
    max-height: 85vh;
    margin: 5vh auto 0;
    background: var(--cp-surface);
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-radius-lg);
    box-shadow: var(--cp-shadow-lg);
    padding: 1.75rem;
    overflow-y: auto;
    animation: cp-modal-in 160ms ease;
}

@keyframes cp-modal-in {
    from {
        opacity: 0;
        transform: translateY(8px) scale(0.98);
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

.modal__close {
    position: absolute;
    top: 0.6rem;
    right: 0.85rem;
    width: 2rem;
    height: 2rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    border-radius: 999px;
    font-size: 1.4rem;
    line-height: 1;
    color: var(--cp-text-muted);
    cursor: pointer;
    transition: background var(--cp-ease), color var(--cp-ease);
}

.modal__close:hover {
    background: var(--cp-surface-2);
    color: var(--cp-text);
}

.modal__title {
    margin: 0 0 1rem;
    font-size: 1.1rem;
    font-weight: 700;
    padding-right: 1.5rem;
}

/* Team management */

.team-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.team-list__item {
    background: var(--cp-surface);
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-radius);
    box-shadow: var(--cp-shadow-sm);
    transition: box-shadow var(--cp-ease), border-color var(--cp-ease), transform var(--cp-ease);
}

.team-list__item:hover {
    border-color: var(--cp-primary);
    box-shadow: var(--cp-shadow);
    transform: translateY(-1px);
}

/* "Mijn teams" — marks a team the viewer is actually on the roster of
   (not just able to manage, e.g. via a portal role cascaded down from an
   ancestor team's scope without ever having joined it themselves). */
.team-list__item--mine {
    border-color: var(--cp-primary);
    background: var(--cp-primary-soft);
}

/* Compact, flat tree-style listing of just team names (indented per
   nest_depth) — deliberately not styled as cards like .team-list, this is
   meant to be scannable at a glance while picking a parent team, not
   browsable. Reusable/unscoped from the start, per this theme's own
   established convention. */
.team-tree {
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: 0.85rem;
    line-height: 1.7;
}

.team-tree__item {
    color: var(--cp-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.team-tree__empty {
    color: var(--cp-text-muted);
    font-size: 0.9rem;
    margin: 0;
}

/* Rendered block-level HTML content — originally only /wijzigingen's
   Markdown-rendered CHANGELOG.md output, now also the "Tekstblok" Boxes
   block's richeditor `content` field (see partials/boxes/text-block.htm) —
   this theme has no global list/heading reset to fight (unlike the main
   site's Tailwind preflight), so this is spacing/rhythm polish only, not a
   correction. Reusable/unscoped, works for any h1/h2/p/ul/ol content
   regardless of whether it originated as Markdown or richeditor HTML. */
.markdown-content h1,
.markdown-content h2 {
    margin: 1.5rem 0 0.5rem;
    font-size: 1.1rem;
}

.markdown-content h1:first-child,
.markdown-content h2:first-child {
    margin-top: 0;
}

.markdown-content p {
    margin: 0 0 0.75rem;
    color: var(--cp-text-muted);
}

.markdown-content ul,
.markdown-content ol {
    margin: 0 0 1.25rem;
    padding-left: 1.25rem;
    color: var(--cp-text);
}

.markdown-content li {
    margin-bottom: 0.35rem;
}

/* "Tekstblok" Boxes block (partials/boxes/text-block.htm) — a plain
   .profile-section card (same look as every other section in this theme)
   with an optional muted eyebrow-style subtitle and a text-alignment
   modifier for the whole card's content. */
.text-block__subtitle {
    margin: 0 0 0.35rem;
    color: var(--cp-text-muted);
    font-size: 0.85rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.text-block--center {
    text-align: center;
}

.text-block--right {
    text-align: right;
}

.team-list__mine-badge {
    display: inline-block;
    margin-left: 0.5rem;
    padding: 0.1rem 0.6rem;
    border-radius: 999px;
    background: var(--cp-primary);
    color: var(--cp-primary-contrast);
    font-size: 0.7rem;
    font-weight: 700;
    vertical-align: middle;
}

.team-list__link {
    display: block;
    padding: 0.9rem 1.1rem;
    color: var(--cp-text);
    text-decoration: none;
}

.team-list__name {
    font-weight: 700;
    display: block;
}

.team-list__description {
    display: block;
    color: var(--cp-text-muted);
    font-size: 0.85rem;
    margin-top: 0.25rem;
}

/* Wrapper scrolls horizontally on narrow screens instead of squeezing every
   column (and the action buttons inside them) illegibly — the table itself
   needs a min-width so it actually overflows the wrapper on a phone rather
   than just shrinking to fit, same reasoning as .roster-grid-wrap. */
.team-table-wrap {
    overflow-x: auto;
}

.team-table {
    width: 100%;
    min-width: 480px;
    border-collapse: collapse;
    margin-bottom: 1rem;
    font-size: 0.9rem;
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-radius);
    overflow: hidden;
}

.team-table th,
.team-table td {
    text-align: left;
    padding: 0.7rem 0.9rem;
    border-bottom: 1px solid var(--cp-border);
}

.team-table th {
    color: var(--cp-text-muted);
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    background: var(--cp-surface-2);
}

.team-table tbody tr {
    transition: background var(--cp-ease);
}

.team-table tbody tr:hover {
    background: var(--cp-surface-2);
}

.team-table tbody tr:last-child td {
    border-bottom: none;
}

/* /aanmeldstatus row background for hard-fail crew — the same danger-soft
   tint used everywhere else a hard-fail state is flagged in this theme
   (.notice--danger, .profile-section--danger, .meal-stat--hardfail), just
   applied to a whole table row instead of a card/banner. Kept as its own
   rule (not folded into :hover) so the tint stays visible independent of
   mouse position — the row-hover rule above still layers on top on hover. */
.team-table tbody tr.status-row--danger {
    background: var(--cp-danger-soft);
}

.team-table tbody tr.status-row--danger:hover {
    background: var(--cp-danger-soft);
    filter: brightness(0.95);
}

/* Aangemeld / niet aangemeld / pending breakdown on /maaltijden — reuses the
   existing --cp-success/--cp-danger soft-tint pair already used for the
   roster's full/understaffed cards; "pending" (eligible, no answer yet) is
   deliberately left neutral rather than adding a third semantic color, same
   as the plain badge look already used by .myshifts__role-badge. */
.meal-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.meal-stat {
    padding: 0.3rem 0.7rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 600;
    white-space: nowrap;
}

.meal-stat--attending {
    color: var(--cp-success);
    background: var(--cp-success-soft);
}

.meal-stat--absent {
    color: var(--cp-danger);
    background: var(--cp-danger-soft);
}

.meal-stat--pending {
    color: var(--cp-text-muted);
    background: var(--cp-surface-2);
    border: 1px solid var(--cp-border);
}

/* Same danger tokens as .meal-stat--absent, but bordered — "niet
   aangemeld" (a normal answer) and "hard-fail" (an exclusion warning)
   are different situations and shouldn't look identical. */
.meal-stat--hardfail {
    color: var(--cp-danger);
    background: var(--cp-danger-soft);
    border: 1px solid var(--cp-danger);
}

/* Scoreboard-style summary on /aanmeldstatus — three counts (hard-fail /
   soft-fail / complete), same soft-tint pill language as .meal-stat*.
   No dedicated "warning" token exists in this theme, so soft-fail reuses
   the primary/amber tokens — the same color .notice already falls back to
   for its own default (non-success, non-danger) state. */
.status-summary {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-bottom: 1.5rem;
}

.status-summary__item {
    flex: 1 1 160px;
    padding: 1rem 1.25rem;
    border-radius: var(--cp-radius);
    text-align: center;
}

.status-summary__count {
    display: block;
    font-size: 1.75rem;
    font-weight: 700;
}

.status-summary__label {
    font-size: 0.8rem;
    color: var(--cp-text-muted);
}

.status-summary__item--danger {
    background: var(--cp-danger-soft);
}

.status-summary__item--danger .status-summary__count {
    color: var(--cp-danger);
}

.status-summary__item--warning {
    background: var(--cp-primary-soft);
}

.status-summary__item--warning .status-summary__count {
    color: var(--cp-primary);
}

.status-summary__item--success {
    background: var(--cp-success-soft);
}

.status-summary__item--success .status-summary__count {
    color: var(--cp-success);
}

/* Plain bulleted list for prose content (e.g. /handleiding) — deliberately
   not reusing .enrollment-timeslots/.myshifts__list, which are card-row
   layouts built for timeslot/shift entries with an action button on the
   right, not documentation text. */
.help-list {
    margin: 0 0 1rem;
    padding-left: 1.25rem;
    color: var(--cp-text);
}

.help-list li {
    margin-bottom: 0.5rem;
    line-height: 1.5;
}

/* Media library picker (added 2026-08-18) — a small, hand-built browsing UI
   for the "Programma beheren" schedule-item image field, since `mediafinder`
   (the backend equivalent) has no frontend counterpart. See
   assets/js/mediapicker.js and pages/scheduleitems.htm's onBrowseMedia(). */
.media-picker__toolbar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.media-picker__path {
    font-size: 0.85rem;
    color: var(--cp-text-muted);
    word-break: break-all;
}

.media-picker__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
    gap: 0.75rem;
}

.media-picker__item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    padding: 0.6rem;
    border: 1px solid var(--cp-border);
    border-radius: var(--cp-radius-sm);
    background: var(--cp-surface-2);
    color: var(--cp-text);
    text-align: center;
    text-decoration: none;
    transition: border-color var(--cp-ease), transform var(--cp-ease);
}

.media-picker__item:hover {
    border-color: var(--cp-primary);
    transform: translateY(-1px);
}

.media-picker__item--folder {
    font-weight: 600;
    background: var(--cp-primary-soft);
    border-color: var(--cp-primary-soft);
}

.media-picker__thumb {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: var(--cp-radius-sm);
    background: var(--cp-surface);
}

.media-picker__name {
    font-size: 0.8rem;
    word-break: break-all;
}

/* Small fixed-size variant for the "Afbeelding" column on the schedule-item
   list — .media-picker__thumb itself is sized by its grid cell (aspect-
   ratio 1/1, width 100%), which only makes sense inside .media-picker__grid. */
.media-picker__thumb--table {
    width: 48px;
    height: 48px;
    aspect-ratio: 1 / 1;
}

.media-picker-preview {
    margin: 0.5rem 0;
}

.media-picker-preview__img {
    max-width: 160px;
    max-height: 160px;
    object-fit: contain;
    border-radius: var(--cp-radius-sm);
    border: 1px solid var(--cp-border);
    background: var(--cp-surface-2);
}

/* Mobile (added 2026-07-27, see CLAUDE.md's "Mobile-friendliness" note and
   TODO.md for the punch list this addresses) */

@media (max-width: 720px) {
    .nav {
        flex-wrap: nowrap;
    }

    .nav__toggle {
        display: flex;
        order: 2;
    }

    .nav__menu {
        display: none;
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        flex-direction: column;
        align-items: stretch;
        gap: 0.15rem;
        background: var(--cp-surface);
        border-bottom: 1px solid var(--cp-border);
        box-shadow: var(--cp-shadow);
        padding: 0.5rem;
    }

    .nav__toggle-input:checked ~ .nav__menu {
        display: flex;
    }

    .nav__links {
        flex-direction: column;
        align-items: stretch;
        gap: 0.15rem;
    }

    .nav__link,
    .nav__logout {
        padding: 0.75rem 1rem;
        border-radius: var(--cp-radius-sm);
        text-align: left;
    }

    /* The dropdown already lives inside the checkbox-driven mobile menu, so
       it just needs to render inline (indented) instead of floating as a
       popover on top of the page. */
    .nav__dropdown-menu {
        position: static;
        margin-top: 0.15rem;
        border: none;
        box-shadow: none;
        padding-left: 0.75rem;
    }

    /* Compact per-row actions (toggle-lead/remove/approve/reject) are the
       ones most likely to be mis-tapped on a phone — bump them to a
       comfortable touch-target size without changing their density on
       desktop, where several sit side-by-side in a table cell. */
    .btn--sm {
        min-height: 2.75rem;
        padding: 0.6rem 1rem;
    }

    /* .datetime-pair's side-by-side date+time split (each input's own
       min-width: 0 lets flex shrink them without limit) gets genuinely
       cramped once the containing form is also phone-width — a native date
       input needs room for "dd-mm-jjjj" and a time input for "uu:mm", and
       squeezing both into half of an already-narrow column leaves neither
       legible. Stack them instead: full-width date above full-width time,
       same pattern already used for every other form field on this
       breakpoint (a plain .form-group is already a full-width column). */
    .datetime-pair {
        flex-direction: column;
    }

    /* The roster grid (team rows × day columns, /rooster) already scrolls
       horizontally via .roster-grid-wrap, but at desktop min-widths a phone
       viewport fits barely more than the sticky team-name column plus a
       sliver of the first day column — reduce both min-widths so at least
       one full day column is comfortably visible next to the team name
       before scrolling is needed. .roster-card itself has no fixed width,
       so it reflows fine at the smaller cell size. */
    .roster-grid__team-header,
    .roster-grid__team-name {
        min-width: 96px;
    }

    .roster-grid__day-header,
    .roster-grid__cell {
        min-width: 168px;
    }
}
