/* App-level base styles. Reads M3 design tokens from md3-theme.css.
 * Per-feature CSS belongs next to the Stimulus controller it pairs with.
 */
*, *::before, *::after { box-sizing: border-box; }

body {
    margin: 0;
    /* Pure white base — surface-container-lowest is M3's "white" token,
     * lighter than --md-sys-color-surface which carries M3's pale-lilac tint. */
    background: var(--md-sys-color-surface-container-lowest);
    color: var(--md-sys-color-on-surface);
    font-family: var(--md-sys-typescale-body-large-font);
    font-size: var(--md-sys-typescale-body-large-size);
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

a {
    color: var(--md-sys-color-primary);
}

.page {
    max-width: 960px;
    margin: 0 auto;
    padding: 48px 24px;
}

.hero h1 {
    margin: 0 0 8px;
    font-size: var(--md-sys-typescale-headline-medium-size);
    font-weight: var(--md-sys-typescale-headline-medium-weight);
    color: var(--md-sys-color-on-surface);
}

.hero .lede {
    margin: 0 0 24px;
    color: var(--md-sys-color-on-surface-variant);
}

.actions {
    display: flex;
    gap: 12px;
    align-items: center;
    margin-top: 16px;
    flex-wrap: wrap;
}

.status {
    display: inline-block;
    padding: 8px 16px;
    border-radius: var(--md-sys-shape-corner-full);
    background: var(--md-sys-color-secondary-container);
    color: var(--md-sys-color-on-secondary-container);
    font-size: var(--md-sys-typescale-label-large-size);
    font-weight: var(--md-sys-typescale-label-large-weight);
    transition: background var(--md-sys-motion-duration-short2) var(--md-sys-motion-easing-standard);
}

.status[data-state="ok"] {
    background: var(--md-sys-color-primary-container);
    color: var(--md-sys-color-on-primary-container);
}

.status[data-state="error"] {
    background: var(--md-sys-color-error-container);
    color: var(--md-sys-color-on-error-container);
}

.grid {
    display: grid;
    gap: 16px;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    margin-top: 32px;
}

/* Light-surface elements (anything reading a `--md-sys-color-surface-*` token
 * for its background — `surface-container-lowest` for cards, `-highest` for
 * the profile chip) reset the body-text tokens back to M3 dark defaults.
 * The operator's `text_color` is meant for text on `--app-landing-bg` — the
 * PAGE background — not for icons/text inside light-surface widgets, which
 * keep a stable light surface regardless of theme. Without this scope, a
 * dark-page operator (text=white) ends up with white-on-light card titles
 * or invisible profile icons. The selector list covers every light-surface
 * wrapper in the codebase; brand-colored surfaces (.module-hero,
 * .module-promo, .module-detail-header) are *not* in the list — they need
 * to stay on-primary text. */
.card,
.module-card,
.module-detail-body,
.modules-list-item,
.landing-profile {
    --md-sys-color-on-surface: #1D1B20;
    --md-sys-color-on-surface-variant: #49454F;
}

.card {
    padding: 24px;
    /* White cards on a white page bg — the existing shadow + a faint border
     * give them a discrete edge so they read as separate surfaces. */
    background: var(--md-sys-color-surface-container-lowest);
    color: var(--md-sys-color-on-surface);
    border-radius: var(--md-sys-shape-corner-large);
    border: 1px solid var(--md-sys-color-outline-variant);
    box-shadow: var(--md-sys-elevation-level1);
}

/* Stack-spacing between sibling cards. Adjacency selector keeps the last
 * card flush so we don't accumulate stray margin at the end of a page. */
.card + .card {
    margin-top: 16px;
}

.card h2 {
    margin: 0 0 12px;
    font-size: var(--md-sys-typescale-title-medium-size);
    font-weight: var(--md-sys-typescale-title-medium-weight);
}

.card ul {
    margin: 0;
    padding-left: 20px;
    color: var(--md-sys-color-on-surface-variant);
}

/* ---- Auth pages ---- */

.auth-page {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 24px;
}

.auth-card {
    width: 100%;
    max-width: 440px;
    padding: 32px;
    background: var(--md-sys-color-surface-container-lowest);
    border-radius: var(--md-sys-shape-corner-large);
    border: 1px solid var(--md-sys-color-outline-variant);
    box-shadow: var(--md-sys-elevation-level2);
}

.auth-header h1 {
    margin: 0 0 8px;
    font-size: var(--md-sys-typescale-headline-medium-size);
    font-weight: var(--md-sys-typescale-headline-medium-weight);
}

.auth-header .lede {
    margin: 0 0 24px;
    color: var(--md-sys-color-on-surface-variant);
}

.auth-form {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* Wrappers for the reveal Stimulus controller (conditional form sections).
   display: contents keeps the children participating directly in the
   form's flex gap; the controller toggles inline display:none. */
.reveal-group,
.reveal-section {
    display: contents;
}

.auth-form md-outlined-text-field {
    width: 100%;
}

/* Mobile field row — dialing-code md-outlined-select on the left, local
 * number md-outlined-text-field on the right. Both components carry their
 * own M3 outline, so we just need the side-by-side layout (and a sane
 * stack at phone widths). */
.mobile-row {
    display: inline-flex;
    gap: 1rem;
    align-items: flex-start;
    width: 100%;
}

.mobile-row .mobile-country-code {
    flex: 0 0 auto;
    min-width: 140px;
}

.mobile-row .mobile-local {
    flex: 1 1 auto;
    min-width: 0;
}

@media (max-width: 480px) {
    .mobile-row {
        flex-direction: column;
    }
    .mobile-row .mobile-country-code,
    .mobile-row .mobile-local {
        width: 100%;
        min-width: 0;
        flex-basis: auto;
    }
}


/* Secondary form on the verify-phone screen — wraps the standalone
 * "resend code" button so it lays out below the main form. */
.auth-secondary-form {
    display: flex;
    justify-content: center;
    margin-top: 8px;
}

.auth-links {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    margin-top: 8px;
    font-size: var(--md-sys-typescale-label-large-size);
}

/* Native checkbox/radio + M3 token tint. We use native inputs (not
 * <md-checkbox>) because the M3 docs explicitly accept this when paired
 * with a labelled row, and it avoids Shadow DOM headaches when toggling
 * state from inline JS (e.g. the inherit-color picker on /operator/modules).
 * Sizing is fixed at 18×18 (M3 baseline) so the box doesn't drift across
 * browsers, and align-items: center + flex-shrink: 0 keep the box vertically
 * lined up with multi-line label text. */
.checkbox-row {
    display: flex;
    align-items: center;
    gap: 10px;
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-label-large-size);
    line-height: 1.4;
    cursor: pointer;
}

.checkbox-row input[type="checkbox"],
.checkbox-row input[type="radio"] {
    width: 18px;
    height: 18px;
    margin: 0;
    accent-color: var(--md-sys-color-primary);
    flex-shrink: 0;
    cursor: pointer;
}

.checkbox-field.has-error .checkbox-row {
    color: var(--md-sys-color-error);
}

.field-error {
    margin: 4px 16px 0;
    color: var(--md-sys-color-error);
    font-size: var(--md-sys-typescale-label-small-size, 0.6875rem);
}

.muted {
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-label-large-size);
}

/* ---- Flash messages ---- */

.flash {
    padding: 12px 16px;
    border-radius: var(--md-sys-shape-corner-medium);
    font-size: var(--md-sys-typescale-label-large-size);
    margin-bottom: 16px;
}

.flash-success {
    background: var(--md-sys-color-primary-container);
    color: var(--md-sys-color-on-primary-container);
}

.flash-error {
    background: var(--md-sys-color-error-container);
    color: var(--md-sys-color-on-error-container);
}

.flash-warning {
    background: var(--md-sys-color-tertiary-container);
    color: var(--md-sys-color-on-tertiary-container);
}

.flash-info {
    background: var(--md-sys-color-secondary-container);
    color: var(--md-sys-color-on-secondary-container);
}

/* ---- Dashboard (KPI tiles + chart cards) ------------------------------- */

.kpi-grid {
    display: grid;
    gap: 16px;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    margin-bottom: 24px;
}

.kpi-card {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 20px 24px;
}

.kpi-label {
    font-size: var(--md-sys-typescale-label-large-size);
    color: var(--md-sys-color-on-surface-variant);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.kpi-value {
    font-size: 32px;
    font-weight: 600;
    color: var(--md-sys-color-on-surface);
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}

.chart-card {
    display: flex;
    flex-direction: column;
    gap: 16px;
    min-height: 320px;
}

.chart-canvas-wrap {
    position: relative;
    flex: 1;
    height: 240px;
}

.chart-canvas-wrap > canvas {
    width: 100% !important;
    height: 100% !important;
}

/* ---- Filter form ---- */

.dashboard-filter {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    align-items: end;
    margin-bottom: 24px;
    padding: 20px 24px;
}

.dashboard-filter md-outlined-select {
    /* Fill the flex field and keep the selected text on one line — white-space
       is inherited, so it crosses the M3 shadow boundary (overflow/ellipsis
       would not). Stops a long option wrapping and growing the field height. */
    width: 100%;
    white-space: nowrap;
}

/* Filter-field date inputs are styled to match @material/web's
 * md-outlined-text-field shape (56px tall, label as a "notch" over the
 * outline) so they sit on the same baseline as md-outlined-select in the
 * filter row. We can't actually use md-outlined-text-field here because
 * Flatpickr attaches to the raw <input>; this is the closest visual
 * match without sacrificing the date-picker library. */
.filter-field {
    position: relative;
    /* Grow to share the row equally; the actions block stays content-width and
       flush right, so the row justifies edge-to-edge (right margin = left inset). */
    flex: 1 1 200px;
    min-width: 0;
}

.filter-field label {
    position: absolute;
    top: -8px;
    left: 12px;
    padding: 0 4px;
    background: var(--md-sys-color-surface-container-lowest);
    font-size: var(--md-sys-typescale-body-small-size);
    color: var(--md-sys-color-on-surface-variant);
    font-weight: 400;
    pointer-events: none;
    z-index: 1;
}

.filter-field input {
    width: 100%;
    height: 56px;
    /* The label is a floating notch on the outline (positioned outside the
       input), so the text is centered vertically via line-height to line up
       with the md-outlined-select fields in the same row. */
    padding: 0 12px;
    line-height: 54px;
    border: 1px solid var(--md-sys-color-outline);
    border-radius: var(--md-sys-shape-corner-extra-small);
    background: var(--md-sys-color-surface-container-lowest);
    color: var(--md-sys-color-on-surface);
    font: inherit;
    font-size: var(--md-sys-typescale-body-large-size);
    box-sizing: border-box;
}

.filter-field input:hover {
    border-color: var(--md-sys-color-on-surface);
}

.filter-field input:focus {
    outline: none;
    border-color: var(--md-sys-color-primary);
    border-width: 2px;
    /* Compensate the extra 1px of border (top/bottom via line-height, sides via
       padding) so the text doesn't jump on focus. */
    padding: 0 11px;
    line-height: 52px;
}

.filter-field input:focus + .filter-field-floating,
.filter-field input:focus ~ label {
    color: var(--md-sys-color-primary);
}

.filter-actions {
    display: flex;
    gap: 8px;
    align-items: center;
    /* Content-width, flush to the right end of the flex row. */
    flex: 0 0 auto;
    /* Match the field height so the buttons sit vertically centered in the
     * same band as the input outlines. */
    min-height: 56px;
}

/* Flatpickr calendar — bring its surface in line with M3 tokens. */
.flatpickr-calendar {
    background: var(--md-sys-color-surface-container) !important;
    color: var(--md-sys-color-on-surface) !important;
    border-radius: var(--md-sys-shape-corner-medium) !important;
    box-shadow: var(--md-sys-elevation-level2) !important;
    border: 1px solid var(--md-sys-color-outline-variant) !important;
}
.flatpickr-day.selected,
.flatpickr-day.selected:hover {
    background: var(--md-sys-color-primary) !important;
    color: var(--md-sys-color-on-primary) !important;
    border-color: transparent !important;
}
.flatpickr-day.today {
    border-color: var(--md-sys-color-primary) !important;
}
.flatpickr-day:hover {
    background: var(--md-sys-color-surface-container-high, rgba(0,0,0,0.04)) !important;
}
.flatpickr-months .flatpickr-month,
.flatpickr-current-month,
.flatpickr-weekdays {
    color: var(--md-sys-color-on-surface) !important;
    fill: var(--md-sys-color-on-surface) !important;
}

/* ---- Events table + pagination ---- */

.events-card {
    margin-top: 24px;
}

/* ---- Image upload + crop + gallery ------------------------------------ */

.image-uploader {
    margin-bottom: 32px;
    padding: 24px;
}

.cropper-editor {
    margin-top: 16px;
}

.cropper-stage {
    /* Cropper.js needs a defined size on the wrapping element; max-height
     * keeps tall portraits from pushing the apply button off-screen. */
    max-width: 100%;
    max-height: 60vh;
    overflow: hidden;
    margin-bottom: 16px;
    background: var(--md-sys-color-surface-container-high);
    border-radius: var(--md-sys-shape-corner-medium);
}

/* Re-skin Cropper.js's chrome with M3 tokens — the lib uses fixed colors and
 * 1px borders, both of which clash with the M3 surface scheme. */
.cropper-view-box,
.cropper-face {
    outline-color: var(--md-sys-color-primary) !important;
}
.cropper-line,
.cropper-point {
    background-color: var(--md-sys-color-primary) !important;
}
.cropper-modal {
    background: rgba(0, 0, 0, 0.55);
}

/* ---- Welcome photo: live-selfie capture ------------------------------ */

/* Stack the primary "Take selfie" button above the secondary "Choose file"
 * — selfie is the priority entry point per the registration spec. The
 * default .actions row would put them side-by-side; this variant stacks. */
.actions.actions-stacked {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
}

.selfie-stage {
    /* Same sizing posture as .cropper-stage so the layout doesn't jump
     * when the user switches from viewfinder → cropper. */
    max-width: 100%;
    max-height: 60vh;
    overflow: hidden;
    margin-bottom: 16px;
    background: var(--md-sys-color-surface-container-high);
    border-radius: var(--md-sys-shape-corner-medium);
    position: relative;
    aspect-ratio: 1 / 1;
}

.selfie-stage video {
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* Mirror the live preview so the visitor sees themselves the way
     * they expect from any phone camera/mirror app. The captured canvas
     * is NOT mirrored — selfie.jpg is stored in its "real" orientation. */
    transform: scaleX(-1);
}

.image-gallery {
    display: grid;
    gap: 16px;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    margin-top: 16px;
}

.image-card {
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    position: relative;
}

.image-card-delete {
    position: absolute;
    top: 16px;
    right: 16px;
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.55);
    color: #fff;
    cursor: pointer;
    opacity: 0;
    transition: opacity var(--md-sys-motion-duration-short2) var(--md-sys-motion-easing-standard);
    z-index: 1;
}

.image-card-delete .material-symbols-outlined {
    font-size: 18px;
    line-height: 1;
    /* Material Symbols' em-box has a small typographic baseline offset that
     * shifts the glyph 1–2px off true visual center. block + line-height 1
     * removes the inline-baseline gap; the explicit size makes it predictable. */
    display: block;
}

.image-card:hover .image-card-delete,
.image-card-delete:focus-visible {
    opacity: 1;
}

.image-card-delete:hover {
    background: var(--md-sys-color-error);
}

.image-thumb {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: var(--md-sys-shape-corner-medium);
    background: var(--md-sys-color-surface-container-high);
}

.image-meta {
    margin: 0;
    font-size: var(--md-sys-typescale-label-small-size, 0.6875rem);
}

.events-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

.events-header-meta {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
}

.events-table-wrap {
    overflow-x: auto;
    border-radius: var(--md-sys-shape-corner-small);
    border: 1px solid var(--md-sys-color-outline-variant);
}

.events-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--md-sys-typescale-body-large-size);
}

.events-table thead th {
    text-align: left;
    padding: 12px 16px;
    background: var(--md-sys-color-surface-container-high);
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-label-large-size);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    border-bottom: 1px solid var(--md-sys-color-outline-variant);
}

.events-table tbody td {
    padding: 10px 16px;
    border-bottom: 1px solid var(--md-sys-color-outline-variant);
    vertical-align: top;
}

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

.events-table tbody tr:hover {
    background: var(--md-sys-color-surface-container-high, rgba(0,0,0,0.02));
}

.events-table code {
    font-size: 0.875em;
    color: var(--md-sys-color-on-surface);
}

.payload-cell {
    max-width: 360px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pagination {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 16px;
    padding-top: 16px;
}

.pagination-status {
    font-size: var(--md-sys-typescale-label-large-size);
    color: var(--md-sys-color-on-surface-variant);
    font-variant-numeric: tabular-nums;
}

/* ---- App shell (sidebar + topbar) -------------------------------------- */

.material-symbols-outlined {
    font-family: 'Material Symbols Outlined', sans-serif;
    font-weight: normal;
    font-style: normal;
    font-size: 24px;
    /* Material Symbols variable-font axes: FILL=1 (solid/filled glyphs vs.
     * the default 0 hollow-outline), wght=400 (regular stroke), GRAD=0
     * (neutral grade), opsz=24 (24-pixel optical size). The URL in
     * base.html.twig requests the same axis values so the font shipping
     * over the wire already prefers the filled glyph; this CSS pins it
     * defensively in case some component overrides the axis at runtime. */
    font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    display: inline-block;
    white-space: nowrap;
    -webkit-font-feature-settings: 'liga';
    font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased;
}

/* When the symbol is slotted into an M3 button, size to the spec'd 18px and
 * align so it sits on the text baseline. The default 24px makes the button
 * grow vertically, which then shifts the text label off-center. */
md-filled-button .material-symbols-outlined,
md-text-button .material-symbols-outlined,
md-outlined-button .material-symbols-outlined,
md-elevated-button .material-symbols-outlined,
md-filled-tonal-button .material-symbols-outlined {
    font-size: 18px;
    line-height: 1;
    vertical-align: middle;
}

.app-shell {
    --app-sidenav-width: 264px;
    --app-topbar-height: 64px;
    min-height: 100vh;
    display: grid;
    grid-template-columns: var(--app-sidenav-width) 1fr;
    /* White content area; sidebar stays surface-container for visual separation. */
    background: var(--md-sys-color-surface-container-lowest);
}

.sidenav {
    position: sticky;
    top: 0;
    height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--md-sys-color-surface-container-lowest);
    border-right: 1px solid var(--md-sys-color-outline-variant);
    z-index: 10;
}

.sidenav-brand {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0 20px;
    height: var(--app-topbar-height);
    border-bottom: 1px solid var(--md-sys-color-outline-variant);
}

.sidenav-logo {
    width: 36px;
    height: 36px;
    display: grid;
    place-items: center;
    border-radius: var(--md-sys-shape-corner-medium);
    background: var(--md-sys-color-primary-container);
    color: var(--md-sys-color-on-primary-container);
}

.sidenav-brand-text {
    font-size: var(--md-sys-typescale-title-medium-size);
    font-weight: var(--md-sys-typescale-title-medium-weight);
    color: var(--md-sys-color-on-surface);
}

.sidenav-nav {
    flex: 1;
    overflow-y: auto;
    padding: 12px 8px;
}

.nav-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.nav-section-label {
    margin: 16px 12px 4px;
    font-size: var(--md-sys-typescale-label-small-size, 0.6875rem);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--md-sys-color-on-surface-variant);
}

.nav-item {
    position: relative;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 16px;
    margin: 0 4px;
    border-radius: var(--md-sys-shape-corner-full);
    color: var(--md-sys-color-on-surface-variant);
    text-decoration: none;
    font-size: var(--md-sys-typescale-label-large-size);
    font-weight: var(--md-sys-typescale-label-large-weight);
    transition:
        background var(--md-sys-motion-duration-short2) var(--md-sys-motion-easing-standard),
        color var(--md-sys-motion-duration-short2) var(--md-sys-motion-easing-standard);
}

.nav-item:hover {
    background: var(--md-sys-color-surface-container-high, rgba(0, 0, 0, 0.04));
    color: var(--md-sys-color-on-surface);
}

.nav-item.is-active {
    background: var(--md-sys-color-secondary-container);
    color: var(--md-sys-color-on-secondary-container);
}

.nav-item .material-symbols-outlined {
    font-size: 22px;
}

.sidenav-foot {
    padding: 12px 16px 16px;
    border-top: 1px solid var(--md-sys-color-outline-variant);
}

.sidenav-user {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 4px;
}

.sidenav-user-avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: var(--md-sys-color-tertiary-container);
    color: var(--md-sys-color-on-tertiary-container);
    font-weight: 500;
    flex-shrink: 0;
}

.sidenav-user-meta {
    min-width: 0;
    flex: 1;
}

.sidenav-user-name {
    display: block;
    font-size: var(--md-sys-typescale-label-large-size);
    color: var(--md-sys-color-on-surface);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidenav-user-sub {
    display: block;
    font-size: var(--md-sys-typescale-label-small-size, 0.6875rem);
    color: var(--md-sys-color-on-surface-variant);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidenav-signout {
    margin-top: 8px;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 10px 16px;
    border-radius: var(--md-sys-shape-corner-full);
    background: transparent;
    color: var(--md-sys-color-on-surface-variant);
    text-decoration: none;
    font-size: var(--md-sys-typescale-label-large-size);
    border: 1px solid var(--md-sys-color-outline-variant);
}

.sidenav-signout:hover {
    background: var(--md-sys-color-error-container);
    color: var(--md-sys-color-on-error-container);
    border-color: transparent;
}

.sidenav-scrim {
    display: none;
}

.app-main {
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.topbar {
    position: sticky;
    top: 0;
    z-index: 5;
    height: var(--app-topbar-height);
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 0 24px;
    background: var(--md-sys-color-surface-container-lowest);
    border-bottom: 1px solid var(--md-sys-color-outline-variant);
}

.topbar-hamburger {
    display: none;
    background: transparent;
    border: 0;
    padding: 8px;
    border-radius: 50%;
    cursor: pointer;
    color: var(--md-sys-color-on-surface-variant);
}

.topbar-hamburger:hover {
    background: var(--md-sys-color-surface-container-high, rgba(0, 0, 0, 0.04));
}

.topbar-title {
    margin: 0;
    flex: 1;
    font-size: var(--md-sys-typescale-title-large-size, 1.375rem);
    font-weight: var(--md-sys-typescale-title-large-weight, 500);
    color: var(--md-sys-color-on-surface);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.topbar-actions {
    display: flex;
    align-items: center;
    gap: 8px;
}

.app-content {
    flex: 1;
    padding: 32px;
    max-width: 1200px;
    width: 100%;
}

.app-content > .hero:first-child {
    margin-bottom: 24px;
}

@media (max-width: 900px) {
    .app-shell {
        grid-template-columns: 1fr;
    }

    .sidenav {
        position: fixed;
        top: 0;
        left: 0;
        height: 100vh;
        width: var(--app-sidenav-width);
        transform: translateX(-100%);
        transition: transform var(--md-sys-motion-duration-medium2, 300ms) var(--md-sys-motion-easing-emphasized, cubic-bezier(0.2, 0, 0, 1));
        box-shadow: var(--md-sys-elevation-level2);
    }

    .app-shell.is-open .sidenav {
        transform: translateX(0);
    }

    .sidenav-scrim {
        display: block;
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.4);
        opacity: 0;
        pointer-events: none;
        transition: opacity var(--md-sys-motion-duration-short4, 200ms) var(--md-sys-motion-easing-standard);
        z-index: 9;
    }

    .app-shell.is-open .sidenav-scrim {
        opacity: 1;
        pointer-events: auto;
    }

    .topbar-hamburger {
        display: grid;
        place-items: center;
    }

    .app-content {
        padding: 24px 16px;
    }
}

/* Color picker row used by the operator appearance form. */
.color-field {
    display: grid;
    grid-template-columns: 160px 56px 1fr;
    align-items: center;
    column-gap: 16px;
    row-gap: 4px;
}

.color-field label {
    font-size: var(--md-sys-typescale-body-medium-size);
    color: var(--md-sys-color-on-surface);
}

.color-field input[type="color"] {
    width: 56px;
    height: 36px;
    border: 1px solid var(--md-sys-color-outline-variant);
    border-radius: var(--md-sys-shape-corner-small);
    padding: 2px;
    background: transparent;
    cursor: pointer;
}

.color-field small {
    grid-column: 1 / -1;
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-label-small-size);
    margin-top: -2px;
}

/* Optional "inherit" toggle under a color picker (feature-grid text defaults).
 * Span the full grid width so its label stays on one line instead of wrapping
 * inside the narrow 160px label column. */
.color-field .checkbox-row {
    grid-column: 1 / -1;
}

/* Horizontal divider between major sections of the operator settings form
 * (e.g. between the operator account fields and the daily-meal voucher
 * section). Uses the M3 outline-variant token so it sits quietly on light
 * surfaces. Generous vertical margin makes the section break feel
 * deliberate without needing a second card. */
.settings-section-divider {
    border: 0;
    border-top: 1px solid var(--md-sys-color-outline-variant);
    margin: 32px 0 24px;
}

/* Compact heading block immediately after a .settings-section-divider —
 * smaller scale than the top-of-page .hero so the eye treats it as a
 * sub-section, not a peer page heading. */
.settings-section-header {
    margin: 0 0 16px;
}

.settings-section-header h2 {
    margin: 0 0 4px;
    font-size: var(--md-sys-typescale-title-medium-size, 1.125rem);
    font-weight: 600;
    color: var(--md-sys-color-on-surface);
}

.settings-section-header .lede {
    margin: 0;
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-body-medium-size, 0.875rem);
}

/* Two-column row used to pair settings fields visually (e.g. the watermark
 * color picker + opacity numeric input on /operator/settings#voucher).
 * `minmax(0, 1fr)` lets children with their own inner grids (.color-field)
 * shrink within the half-column without overflowing. Stacks on narrow
 * viewports. */
.settings-inline-pair {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
    gap: 16px;
}

.settings-inline-pair > * {
    min-width: 0;
}

@media (max-width: 640px) {
    .settings-inline-pair {
        grid-template-columns: 1fr;
    }
}


/* ---- Operator: modules list ---- */
.modules-list-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

.modules-preview-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: var(--md-sys-color-primary);
    text-decoration: none;
    font-size: var(--md-sys-typescale-label-large-size);
    /* Button resets — the same class is now used on a <button> for the
     * Copy-link affordance in the pages list, so wipe the browser defaults
     * to keep the icon-only chip visually identical to the <a> variant. */
    background: transparent;
    border: 0;
    padding: 0;
    cursor: pointer;
    font-family: inherit;
}

.modules-preview-link:hover {
    text-decoration: underline;
}

/* Subtle confirmation flash when the clipboard controller swaps the icon
 * to "check" — green tint draws the eye for ~1.5s without being noisy. */
.modules-preview-link[data-controller="clipboard"] .material-symbols-outlined {
    transition: color var(--md-sys-motion-duration-short2, 150ms);
}

.modules-empty {
    color: var(--md-sys-color-on-surface-variant);
    text-align: center;
    padding: 32px 16px;
}

.modules-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.modules-list-item {
    display: grid;
    grid-template-columns: 56px 56px 1fr auto auto;
    align-items: center;
    gap: 12px;
    padding: 12px;
    border: 1px solid var(--md-sys-color-outline-variant);
    border-radius: var(--md-sys-shape-corner-medium);
    background: var(--md-sys-color-surface-container-lowest);
}

/* Handle-less variant — pickers and other read-only lists that show
 * icon + text + (optional badge) + action buttons, with no drag-to-reorder
 * column. Without this the default 5-column template above forces the text
 * into the 56px icon slot and buttons collide with the title (visible in
 * the page element-type picker and the custom-pages index).
 *
 * 4 columns covers both shapes: the pages index renders an optional
 * "Draft" badge between text and buttons; lists without a badge just
 * leave col 3 empty and the button block lands flush right via col 4. */
.modules-list--simple .modules-list-item {
    grid-template-columns: 56px 1fr auto auto;
}

.modules-list-position {
    font-variant-numeric: tabular-nums;
    color: var(--md-sys-color-on-surface-variant);
    font-weight: 500;
    text-align: center;
}

.modules-list-handle {
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    color: var(--md-sys-color-on-surface-variant);
    cursor: grab;
    user-select: none;
    border-radius: 50%;
    transition: background var(--md-sys-motion-duration-short2, 100ms);
}

.modules-list-handle:hover {
    background: var(--md-sys-color-surface-variant);
    color: var(--md-sys-color-on-surface);
}

.modules-list-handle:active {
    cursor: grabbing;
}

.modules-reorder-hint {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 12px;
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-label-medium-size);
}

.modules-reorder-hint .material-symbols-outlined {
    font-size: 18px;
}

.modules-reorder-status {
    margin-left: auto;
    font-variant-numeric: tabular-nums;
}

.modules-reorder-status[data-state="saving"] { color: var(--md-sys-color-on-surface-variant); }
.modules-reorder-status[data-state="saved"]  { color: var(--md-sys-color-primary); }
.modules-reorder-status[data-state="error"]  { color: var(--md-sys-color-error); }

/* Sortable.js drag states */
.sortable-ghost {
    opacity: 0.4;
    background: var(--md-sys-color-primary-container);
}

.sortable-chosen {
    cursor: grabbing;
}

.sortable-drag {
    box-shadow: var(--md-sys-elevation-level3);
    cursor: grabbing;
}

.modules-list-icon {
    width: 40px;
    height: 40px;
    border-radius: var(--md-sys-shape-corner-small);
    background: var(--md-sys-color-primary);
    color: var(--md-sys-color-on-primary, #fff);
    display: grid;
    place-items: center;
}

/* Operator-uploaded module icon (alternative to a Material Symbol). Sits
 * inside any of the icon containers — .module-hero-illustration,
 * .module-promo-icon, .module-card-icon, .module-detail-icon,
 * .modules-list-icon, .bottomnav-item, .bottomnav-fab. Contain-fit ensures
 * arbitrary aspect ratios (square SVG, wide PNG, etc.) don't crop or
 * distort. Filling the parent works because every container above sets
 * explicit width/height; bottomnav overrides live in landing.css since the
 * bar's icon sits in a flex column without its own sized wrapper. */
.module-icon-img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

.modules-list-text {
    min-width: 0;
}

.modules-list-text strong {
    display: block;
    color: var(--md-sys-color-on-surface);
}

.modules-list-type {
    display: inline-block;
    font-size: var(--md-sys-typescale-label-small-size);
    color: var(--md-sys-color-on-surface-variant);
    background: var(--md-sys-color-surface-variant);
    border-radius: 6px;
    padding: 2px 6px;
    margin-top: 2px;
}

.modules-list-subtitle {
    margin: 4px 0 0;
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-body-small-size);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.modules-list-inactive {
    background: var(--md-sys-color-surface-variant);
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-label-small-size);
    padding: 2px 8px;
    border-radius: 999px;
}

.modules-list-buttons {
    display: flex;
    align-items: center;
    gap: 4px;
}

.modules-list-delete-form {
    margin: 0;
    display: inline;
}

/* ---- Operator: QR generator result ---- */
.qr-result {
    display: flex;
    gap: 24px;
    align-items: center;
    flex-wrap: wrap;
    margin-top: 16px;
}

.qr-result-image {
    background: #fff;
    padding: 12px;
    border-radius: var(--md-sys-shape-corner-medium);
    border: 1px solid var(--md-sys-color-outline-variant);
    flex-shrink: 0;
}

.qr-result-image img {
    display: block;
    max-width: 100%;
    height: auto;
}

.qr-result-meta {
    flex: 1;
    min-width: 280px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.qr-result-payload {
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.qr-result-payload code {
    font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
    font-size: var(--md-sys-typescale-body-small-size);
    background: var(--md-sys-color-surface-variant);
    color: var(--md-sys-color-on-surface);
    padding: 8px 10px;
    border-radius: var(--md-sys-shape-corner-small);
    word-break: break-all;
}

.qr-result-label {
    font-size: var(--md-sys-typescale-label-medium-size);
    color: var(--md-sys-color-on-surface-variant);
    text-transform: uppercase;
    letter-spacing: 0.4px;
}

/* ---- Operator: QR code list ---- */
.qr-section-heading {
    margin: 0 0 16px;
    font-size: var(--md-sys-typescale-title-medium-size, 16px);
    color: var(--md-sys-color-on-surface);
}

.qr-filter-form {
    display: flex;
    /* The text field has no supporting-text underneath (no maxlength,
     * no help text), so it's a clean 56px row and center-aligning with
     * the 40px buttons puts both midpoints on the same line. */
    align-items: center;
    gap: 12px;
    margin-bottom: 16px;
    flex-wrap: wrap;
}

.qr-filter-form md-outlined-text-field {
    flex: 1 1 240px;
    min-width: 200px;
}

/* Read-only field on the operator settings form. Mirrors the visual
 * weight of an md-outlined-text-field row but with no input affordance —
 * the slug is shown as a static value with a "contact admin to change"
 * hint, since changing it 404s every printed QR code. */
.settings-readonly-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 12px 16px;
    border: 1px solid var(--md-sys-color-outline-variant);
    border-radius: var(--md-sys-shape-corner-extra-small);
    background: var(--md-sys-color-surface-container);
}

.settings-readonly-label {
    font-size: var(--md-sys-typescale-body-small-size);
    color: var(--md-sys-color-on-surface-variant);
}

.settings-readonly-value {
    font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
    font-size: var(--md-sys-typescale-body-large-size);
    color: var(--md-sys-color-on-surface);
}

.settings-readonly-field small {
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-body-small-size);
}

/* Sub-section divider + heading inside the operator settings form. M3
 * zeroes the UA-default <hr> styling so we re-paint it explicitly; without
 * this class the rule is invisible. The heading reuses the M3 title-medium
 * type scale to sit a clear notch above body copy. */
.settings-section-divider {
    border: 0;
    border-top: 1px solid var(--md-sys-color-outline-variant);
    margin: 24px 0 8px;
}

.settings-section-heading {
    margin: 0 0 4px;
    font-size: var(--md-sys-typescale-title-medium-size, 1rem);
    font-weight: var(--md-sys-typescale-title-medium-weight, 500);
    color: var(--md-sys-color-on-surface);
}

.settings-section-lede {
    margin: 0 0 8px;
    font-size: var(--md-sys-typescale-body-small-size);
    color: var(--md-sys-color-on-surface-variant);
}

/* ---- Voucher status panel + history badge ----
 * Big visual on /account/voucher/status/{id} showing where the user is
 * in the verification workflow. Each state gets its own background tint
 * (state-layer derived from the relevant token) so the moment a visitor
 * lands on the page they know whether they're waiting, approved, or
 * rejected. The smaller .voucher-state-badge variant is used in the
 * /account/vouchers history table. */
.voucher-code {
    font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
    font-size: var(--md-sys-typescale-headline-medium-size);
    letter-spacing: 0.08em;
    color: var(--md-sys-color-on-surface);
    margin: 0 0 8px;
}

.voucher-meta {
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-body-medium-size);
    margin: 4px 0;
}

.voucher-rejection-reason {
    margin-top: 12px;
    padding: 12px;
    border-radius: var(--md-sys-shape-corner-small);
    background: var(--md-sys-color-error-container);
    color: var(--md-sys-color-on-error-container);
}

.voucher-state {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 16px;
    border-radius: var(--md-sys-shape-corner-medium);
    margin: 16px 0;
}

.voucher-state h3 {
    margin: 0 0 4px;
    font-size: var(--md-sys-typescale-title-large-size);
    font-weight: var(--md-sys-typescale-title-large-weight);
}

.voucher-state p {
    margin: 0;
    color: inherit;
    opacity: 0.9;
}

.voucher-state .material-symbols-outlined {
    font-size: 32px;
    flex-shrink: 0;
    margin-top: 4px;
}

.voucher-state-pending,
.voucher-state-in_review {
    background: var(--md-sys-color-secondary-container);
    color: var(--md-sys-color-on-secondary-container);
}

.voucher-state-verified {
    background: var(--md-sys-color-primary-container);
    color: var(--md-sys-color-on-primary-container);
}

.voucher-state-rejected {
    background: var(--md-sys-color-error-container);
    color: var(--md-sys-color-on-error-container);
}

/* Pill variant for the history table. Same color tokens, smaller form. */
.voucher-state-badge {
    display: inline-block;
    padding: 4px 12px;
    border-radius: var(--md-sys-shape-corner-full);
    font-size: var(--md-sys-typescale-label-medium-size);
    font-weight: var(--md-sys-typescale-label-medium-weight);
    letter-spacing: 0.02em;
}

.voucher-state-badge.voucher-state-pending,
.voucher-state-badge.voucher-state-in_review {
    background: var(--md-sys-color-secondary-container);
    color: var(--md-sys-color-on-secondary-container);
}

.voucher-state-badge.voucher-state-verified {
    background: var(--md-sys-color-primary-container);
    color: var(--md-sys-color-on-primary-container);
}

.voucher-state-badge.voucher-state-rejected {
    background: var(--md-sys-color-error-container);
    color: var(--md-sys-color-on-error-container);
}

/* Generated-QR list. Uses .events-table for the table chrome (header,
 * borders, hover row); the .qr-table-* rules below cover only the
 * column-specific tweaks: thumbnail size, param chips, payload
 * truncation, action-button row. */
.qr-table-th-thumb {
    width: 80px;
}

.qr-table-thumbnail-cell {
    width: 80px;
}

.qr-table-thumbnail {
    width: 64px;
    height: 64px;
    border-radius: var(--md-sys-shape-corner-small);
    background: #fff;
    padding: 4px;
    display: block;
}

.qr-table-label-cell strong {
    font-size: var(--md-sys-typescale-body-large-size);
    color: var(--md-sys-color-on-surface);
}

.qr-table-payload-cell {
    max-width: 320px;
}

.qr-table-payload-cell code {
    display: block;
    font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
    font-size: var(--md-sys-typescale-label-small-size);
    color: var(--md-sys-color-on-surface-variant);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.qr-table-scans-cell {
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--md-sys-color-on-surface-variant);
}

.qr-table-actions-cell {
    white-space: nowrap;
}

.qr-table-delete-form {
    margin: 0;
    display: inline;
}

.qr-table-legacy-code {
    display: block;
    margin-top: 2px;
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-label-small-size);
    font-family: 'SFMono-Regular', Menlo, Consolas, monospace;
}

.qr-import-file-label {
    display: block;
    margin-bottom: 8px;
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-label-medium-size);
}

.qr-import-status-ok {
    color: var(--md-sys-color-primary);
    font-weight: 600;
}

.qr-import-status-skip {
    color: var(--md-sys-color-error);
    font-size: var(--md-sys-typescale-label-small-size);
}

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ---- Operator: QR-param schema editor (multicolumnwizard) ---- */
.qr-params-form {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.qr-params-header,
.qr-params-row {
    display: grid;
    grid-template-columns: 1fr 1fr 130px 80px 1fr 1.4fr 40px;
    gap: 8px;
    align-items: start;
}

.qr-params-header {
    font-size: var(--md-sys-typescale-label-medium-size);
    font-weight: 600;
    color: var(--md-sys-color-on-surface-variant);
    padding-bottom: 4px;
    border-bottom: 1px solid var(--md-sys-color-outline-variant);
}

.qr-params-header-required {
    text-align: center;
}

.qr-params-rows {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.qr-params-row {
    align-items: center;
}

.qr-params-cell {
    width: 100%;
    box-sizing: border-box;
    padding: 8px 10px;
    border: 1px solid var(--md-sys-color-outline-variant);
    border-radius: var(--md-sys-shape-corner-extra-small);
    background: var(--md-sys-color-surface-container-lowest);
    font: inherit;
    color: var(--md-sys-color-on-surface);
}

.qr-params-cell:focus {
    outline: 2px solid var(--md-sys-color-primary);
    outline-offset: -1px;
}

.qr-params-textarea {
    resize: vertical;
    min-height: 60px;
    font-size: var(--md-sys-typescale-label-medium-size);
}

.qr-params-required {
    justify-self: center;
    width: 18px;
    height: 18px;
    margin-top: 12px;
}

.qr-params-toolbar {
    margin-top: 4px;
}

.qr-params-add {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    background: transparent;
    color: var(--md-sys-color-primary);
    border: 1px dashed var(--md-sys-color-primary);
    border-radius: var(--md-sys-shape-corner-small);
    cursor: pointer;
    font: inherit;
}

.qr-params-add:hover {
    background: var(--md-sys-color-primary-container);
    color: var(--md-sys-color-on-primary-container);
    border-color: var(--md-sys-color-on-primary-container);
}

.qr-params-remove {
    background: transparent;
    border: none;
    color: var(--md-sys-color-error);
    cursor: pointer;
    padding: 0;
    width: 32px;
    height: 32px;
    display: grid;
    place-items: center;
    margin-top: 4px;
}

.qr-params-remove:hover {
    color: var(--md-sys-color-on-error);
    background: var(--md-sys-color-error);
    border-radius: 50%;
}

/* ---- Operator: logo upload field ---- */
.logo-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.logo-field-label {
    font-size: var(--md-sys-typescale-body-medium-size);
    color: var(--md-sys-color-on-surface);
}

.logo-field-row {
    display: grid;
    grid-template-columns: 96px 1fr;
    gap: 16px;
    align-items: center;
}

.logo-field-preview {
    width: 96px;
    height: 96px;
    border-radius: var(--md-sys-shape-corner-small);
    background: var(--md-sys-color-surface-container-lowest);
    border: 1px dashed var(--md-sys-color-outline-variant);
    display: grid;
    place-items: center;
    overflow: hidden;
}

.logo-field-preview img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}

.logo-field-preview .material-symbols-outlined {
    color: var(--md-sys-color-outline);
    font-size: 40px;
}

.logo-field-input {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.logo-field-input input[type="file"] {
    font: inherit;
    color: var(--md-sys-color-on-surface);
}

.logo-field small {
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-label-small-size);
}

/* ---- Error pages (404, etc.) ---- */
.error-page {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 24px;
}

.error-page-card {
    width: 100%;
    max-width: 480px;
    text-align: center;
    padding: 48px 24px;
}

.error-page-icon {
    font-size: 72px !important;
    color: var(--md-sys-color-on-surface-variant);
}

.error-page-status {
    margin: 8px 0;
    font-size: var(--md-sys-typescale-display-small-size, 36px);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    color: var(--md-sys-color-on-surface-variant);
}

.error-page-card h1 {
    margin: 0 0 12px;
    font-size: var(--md-sys-typescale-headline-medium-size);
    font-weight: var(--md-sys-typescale-headline-medium-weight);
    color: var(--md-sys-color-on-surface);
}

.error-page-card .lede {
    margin: 0 0 24px;
    color: var(--md-sys-color-on-surface);
}

.error-page-hint {
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-label-large-size);
}

/* ---- Operator users list ----
 * Plain wide table; wrap allows horizontal scroll on narrow viewports so
 * the email column doesn't break the layout when an address is long. */
.users-table-wrap {
    overflow-x: auto;
}

.users-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--md-sys-typescale-body-medium-size);
}

.users-table thead th {
    text-align: left;
    padding: 8px 12px;
    font-weight: 500;
    color: var(--md-sys-color-on-surface-variant);
    border-bottom: 1px solid var(--md-sys-color-outline-variant);
}

.users-table tbody td {
    padding: 12px;
    border-bottom: 1px solid var(--md-sys-color-outline-variant);
    color: var(--md-sys-color-on-surface);
    vertical-align: middle;
}

.users-table tbody tr:hover {
    background: var(--md-sys-color-surface-container-low);
}

.users-table-email {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: var(--md-sys-typescale-body-small-size);
}

.users-badge {
    display: inline-block;
    padding: 2px 8px;
    border-radius: var(--md-sys-shape-corner-full);
    font-size: var(--md-sys-typescale-label-small-size);
    line-height: 1.6;
    white-space: nowrap;
}

.users-badge-ok {
    background: var(--md-sys-color-primary-container);
    color: var(--md-sys-color-on-primary-container);
}

.users-badge-warn {
    background: var(--md-sys-color-error-container);
    color: var(--md-sys-color-on-error-container);
}

.users-badge-muted {
    background: var(--md-sys-color-surface-container-high);
    color: var(--md-sys-color-on-surface-variant);
}

/* Subscription cell: plan/amount + renewal note stacked under the badge. */
.users-table-subscription {
    white-space: nowrap;
}

.users-sub-meta {
    margin-top: 4px;
    font-size: var(--md-sys-typescale-body-small-size);
    color: var(--md-sys-color-on-surface);
}

.users-sub-note {
    display: block;
    margin-top: 2px;
    font-size: var(--md-sys-typescale-label-small-size);
    color: var(--md-sys-color-on-surface-variant);
}

.users-sub-note-warn {
    color: var(--md-sys-color-error);
}

/* Active-member badge cell. */
.users-table-account {
    white-space: nowrap;
    text-align: right;
}

/* Activate/deactivate action — rightmost column, button centered. */
.users-col-action {
    white-space: nowrap;
    text-align: center;
}

.users-action-form md-text-button {
    --md-text-button-container-height: 32px;
    font-size: var(--md-sys-typescale-label-small-size);
}

/* ---- Account billing page ---- */
.billing-section-title {
    margin: 0 0 16px;
    font-size: var(--md-sys-typescale-title-medium-size);
    font-weight: 500;
}

.billing-current-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 16px;
    margin: 0 0 16px;
}

.billing-current-grid > div {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.billing-current-grid dt {
    margin: 0;
    font-size: var(--md-sys-typescale-label-medium-size);
    color: var(--md-sys-color-on-surface-variant);
}

.billing-current-grid dd {
    margin: 0;
    color: var(--md-sys-color-on-surface);
}

.billing-current + .billing-invoices,
.billing-invoices + .billing-current {
    margin-top: 16px;
}

/* ---- Impersonation banner ---- */
.impersonation-banner {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 16px;
    background: var(--md-sys-color-error-container);
    color: var(--md-sys-color-on-error-container);
    font-size: var(--md-sys-typescale-body-medium-size);
}

.impersonation-banner-exit {
    margin-left: auto;
    color: inherit;
    text-decoration: underline;
    font-weight: 500;
}

/* ---- Platform-admin stat grid ---- */
.platform-stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 16px;
}

.platform-stats-grid > div {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.platform-stats-grid dt {
    margin: 0;
    font-size: var(--md-sys-typescale-label-medium-size);
    color: var(--md-sys-color-on-surface-variant);
}

.platform-stats-grid dd {
    margin: 0;
    font-size: var(--md-sys-typescale-headline-small-size);
    font-weight: 500;
    color: var(--md-sys-color-on-surface);
}

.audit-log-payload code {
    font-size: var(--md-sys-typescale-body-small-size);
    word-break: break-all;
}

/* ---- Operator vouchers + verifications ---- */
.vouchers-codes-block {
    margin: 12px 0 0;
    padding: 12px;
    background: var(--md-sys-color-surface-container-high);
    color: var(--md-sys-color-on-surface);
    border-radius: var(--md-sys-shape-corner-small);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: var(--md-sys-typescale-body-medium-size);
    white-space: pre-wrap;
    word-break: break-all;
    overflow-x: auto;
}

.vouchers-filter {
    display: flex;
    gap: 8px;
    align-items: center;
    margin-left: auto;
}

.verifications-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0 0 16px;
}

.verifications-tab {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 12px;
    border-radius: var(--md-sys-shape-corner-full);
    background: var(--md-sys-color-surface-container-low);
    color: var(--md-sys-color-on-surface);
    text-decoration: none;
    font-size: var(--md-sys-typescale-label-large-size);
}

.verifications-tab.is-active {
    background: var(--md-sys-color-secondary-container);
    color: var(--md-sys-color-on-secondary-container);
}

.verifications-actions {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.verifications-reject-form {
    display: flex;
    align-items: center;
    gap: 6px;
}

.pagination {
    display: flex;
    gap: 12px;
    margin-top: 16px;
    align-items: center;
    font-size: var(--md-sys-typescale-body-medium-size);
}

/* ---- Welcome: subscribe interval picker (monthly / yearly) ---- */
.welcome-subscribe-form {
    flex-direction: column;
    gap: 16px;
    align-items: stretch;
}

.welcome-subscribe-slots {
    margin: 0;
    padding: 8px 12px;
    border-radius: var(--md-sys-shape-corner-small, 8px);
    background: color-mix(in srgb, var(--md-sys-color-tertiary) 14%, transparent);
    color: var(--md-sys-color-on-surface);
    font-size: var(--md-sys-typescale-label-large-size);
    text-align: center;
}

.welcome-subscribe-plans {
    display: flex;
    flex-direction: column;
    gap: 12px;
    border: 0;
    padding: 0;
    margin: 0;
}

.welcome-subscribe-plan {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    border: 1px solid var(--md-sys-color-outline-variant);
    border-radius: var(--md-sys-shape-corner-medium, 12px);
    cursor: pointer;
    transition: border-color var(--md-sys-motion-duration-short, 150ms) ease,
                background var(--md-sys-motion-duration-short, 150ms) ease;
}

.welcome-subscribe-plan:has(input:checked) {
    border-color: var(--md-sys-color-primary);
    background: color-mix(in srgb, var(--md-sys-color-primary) 8%, transparent);
}

.welcome-subscribe-plan input {
    accent-color: var(--md-sys-color-primary);
    width: 20px;
    height: 20px;
}

.welcome-subscribe-plan-body {
    display: flex;
    flex: 1 1 0%;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
}

.welcome-subscribe-plan-name {
    font-size: var(--md-sys-typescale-title-medium-size);
    color: var(--md-sys-color-on-surface);
}

.welcome-subscribe-plan-price strong {
    font-size: var(--md-sys-typescale-title-large-size);
    color: var(--md-sys-color-on-surface);
}

.welcome-subscribe-plan-price small {
    color: var(--md-sys-color-on-surface-variant);
}

.welcome-subscribe-plan-was {
    margin-right: 6px;
    color: var(--md-sys-color-on-surface-variant);
}

/* ---- Operator: pricing opening-discount enable toggle ---- */
.pricing-toggle {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    cursor: pointer;
}

.pricing-toggle input {
    margin-top: 4px;
    width: 18px;
    height: 18px;
    accent-color: var(--md-sys-color-primary);
}

.pricing-toggle span {
    display: flex;
    flex-direction: column;
}

.pricing-toggle small {
    color: var(--md-sys-color-on-surface-variant);
}

/* ---- Media library (/operator/assets) + asset-picker dialog ---- */
.assets-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 16px;
}

.asset-card {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--md-sys-color-outline-variant);
    border-radius: var(--md-sys-shape-corner-medium);
    overflow: hidden;
    background: var(--md-sys-color-surface);
}

.asset-thumb {
    aspect-ratio: 4 / 3;
    display: grid;
    place-items: center;
    background: var(--md-sys-color-surface-container-high);
    overflow: hidden;
}

.asset-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.asset-thumb .material-symbols-outlined {
    font-size: 44px;
    color: var(--md-sys-color-on-surface-variant);
}

.asset-meta {
    padding: 10px 12px 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.asset-meta strong {
    font-size: var(--md-sys-typescale-label-large-size);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.asset-meta span {
    color: var(--md-sys-color-on-surface-variant);
    font-size: var(--md-sys-typescale-label-small-size);
}

.asset-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 6px 8px 8px;
}

/* ---- compact upload bar (label · file input · button on one row) ---- */
.assets-upload {
    margin-bottom: 16px;
}

.assets-upload-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px 16px;
}

/* Left column: label + file input on one line, help text under it. The row's
   align-items:center then centres the Upload button against the whole column. */
.assets-upload-main {
    flex: 1 1 240px;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.assets-upload-field {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px 16px;
}

.assets-upload-label {
    font-size: var(--md-sys-typescale-label-large-size);
    font-weight: 600;
}

.assets-upload-label small {
    font-weight: 400;
    color: var(--md-sys-color-on-surface-variant);
}

.assets-upload-input {
    flex: 1 1 200px;
    min-width: 0;
}

.assets-upload-row md-filled-button {
    flex: 0 0 auto;
}

.assets-upload-help {
    display: block;
    font-size: var(--md-sys-typescale-label-small-size);
    color: var(--md-sys-color-on-surface-variant);
}

/* ---- library toolbar: breadcrumb + folder/view actions ---- */
.assets-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 16px;
}

.assets-breadcrumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    font-size: var(--md-sys-typescale-label-large-size);
    min-width: 0;
}

.assets-breadcrumb a {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--md-sys-color-primary);
    text-decoration: none;
    border-radius: var(--md-sys-shape-corner-small);
    padding: 2px 6px;
}

.assets-breadcrumb a:hover {
    background: var(--md-sys-color-surface-container-high);
}

.assets-breadcrumb a .material-symbols-outlined {
    font-size: 18px;
}

.assets-breadcrumb .is-current {
    color: var(--md-sys-color-on-surface);
    font-weight: 600;
    padding: 2px 6px;
}

.assets-crumb-sep {
    color: var(--md-sys-color-on-surface-variant);
}

.assets-toolbar-actions {
    display: flex;
    align-items: center;
    gap: 8px;
}

.assets-view-toggle {
    display: inline-flex;
    border: 1px solid var(--md-sys-color-outline-variant);
    border-radius: var(--md-sys-shape-corner-full);
    overflow: hidden;
}

.assets-view-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    background: transparent;
    color: var(--md-sys-color-on-surface-variant);
    cursor: pointer;
    padding: 6px 12px;
}

.assets-view-btn.is-active {
    background: var(--md-sys-color-secondary-container);
    color: var(--md-sys-color-on-secondary-container);
}

/* ---- folder cards ---- */
.asset-card--folder .asset-thumb {
    cursor: pointer;
    text-decoration: none;
}

.asset-card--folder .asset-thumb .material-symbols-outlined {
    color: var(--md-sys-color-primary);
    font-size: 52px;
}

.asset-card--folder .asset-thumb:hover {
    background: var(--md-sys-color-surface-container-highest);
}

/* ---- list (details) view: same cards, row layout ---- */
.assets-grid--list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.assets-grid--list .asset-card {
    flex-direction: row;
    align-items: center;
    gap: 12px;
    padding-right: 8px;
}

.assets-grid--list .asset-thumb {
    flex: 0 0 auto;
    width: 52px;
    height: 52px;
    aspect-ratio: auto;
    border-radius: var(--md-sys-shape-corner-small);
}

.assets-grid--list .asset-thumb .material-symbols-outlined,
.assets-grid--list .asset-card--folder .asset-thumb .material-symbols-outlined {
    font-size: 28px;
}

.assets-grid--list .asset-meta {
    flex: 1 1 auto;
    flex-direction: row;
    align-items: baseline;
    gap: 12px;
    padding: 0;
}

.assets-grid--list .asset-meta strong {
    flex: 1 1 auto;
}

.assets-grid--list .asset-meta span {
    flex: 0 0 auto;
    white-space: nowrap;
}

.assets-grid--list .asset-actions {
    flex: 0 0 auto;
    padding: 0;
}

/* ---- new-folder / rename / move dialogs ---- */
.asset-dialog {
    border: none;
    border-radius: var(--md-sys-shape-corner-large);
    background: var(--md-sys-color-surface-container);
    color: var(--md-sys-color-on-surface);
    padding: 20px;
    width: min(440px, calc(100vw - 32px));
}

.asset-dialog::backdrop {
    background: rgba(0, 0, 0, 0.4);
}

.asset-dialog-form {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.asset-dialog-form h2 {
    margin: 0;
    font-size: var(--md-sys-typescale-title-medium-size);
}

.asset-dialog-form md-outlined-text-field,
.asset-dialog-form md-outlined-select {
    width: 100%;
}

.asset-dialog-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}

.asset-picker-dialog {
    border: none;
    border-radius: var(--md-sys-shape-corner-large);
    background: var(--md-sys-color-surface-container);
    color: var(--md-sys-color-on-surface);
    padding: 16px;
    width: min(640px, calc(100vw - 32px));
    max-height: min(70vh, 560px);
}

.asset-picker-dialog::backdrop {
    background: rgba(0, 0, 0, 0.4);
}

.asset-picker-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 12px;
}

.asset-picker-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: 10px;
    overflow-y: auto;
    max-height: calc(70vh - 120px);
}

.asset-picker-item {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 6px;
    border: 1px solid var(--md-sys-color-outline-variant);
    border-radius: var(--md-sys-shape-corner-medium);
    background: var(--md-sys-color-surface);
    color: var(--md-sys-color-on-surface);
    cursor: pointer;
    font: inherit;
    text-align: left;
}

.asset-picker-item:hover {
    border-color: var(--md-sys-color-primary);
}

.asset-picker-item-thumb {
    aspect-ratio: 4 / 3;
    display: grid;
    place-items: center;
    border-radius: var(--md-sys-shape-corner-small);
    overflow: hidden;
    background: var(--md-sys-color-surface-container-high);
}

.asset-picker-item-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.asset-picker-item-thumb .material-symbols-outlined {
    font-size: 36px;
    color: var(--md-sys-color-on-surface-variant);
}

.asset-picker-item-name {
    font-size: var(--md-sys-typescale-label-small-size);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.asset-picker-chosen {
    color: var(--md-sys-color-primary);
    font-size: var(--md-sys-typescale-label-small-size);
    word-break: break-all;
}

.asset-picker-empty {
    color: var(--md-sys-color-on-surface-variant);
    margin: 8px 0 0;
}
