/* Booking has its own page module. The calendar grid deliberately stays
   custom: it encodes half-hour occupancy, drag-and-drop, overlapping booking
   heights and the club's overnight hours. PrimeVue supplies the surrounding
   navigation and tabs rather than replacing that working interaction. */
.bookings-page {
    min-width: 0;
}

.bookings-page .page-intro {
    margin-bottom: var(--space-5);
}

.bookings-page .page-title {
    letter-spacing: var(--tracking-tight);
}

.bookings-page .bookings-header {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: var(--space-3);
    margin-bottom: var(--space-4);
}

.bookings-page .bookings-control-bar {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
}

.bookings-page .bookings-date-nav {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.bookings-page .bookings-date-nav .p-button {
    width: 2rem;
    height: 2rem;
    padding: 0;
    border-radius: var(--radius-md);
    border-color: transparent;
    background: transparent;
    color: var(--color-text-secondary);
}

.bookings-page .bookings-date-nav .p-button:hover {
    background: var(--color-bg-hover);
    color: var(--color-text);
}

/* Return to today. The arrows beside it step a day at a time; this jumps,
   so it is deliberately not shaped like them — a brand-blue chip, set apart
   by a small gap from the stepper it does not belong to. Outlined on a white
   ground rather than tinted: this toolbar sits on --color-bg now, and
   --color-primary-subtle is too near that grey to register. Hover fills it
   in. It is only ever visible when the calendar is somewhere other than
   today, so its presence is already half the message — but it keeps its
   place in the row even then (.bookings-today-hidden), so the stepper
   arrows never move. */
.bookings-page .bookings-date-nav .p-button.bookings-today-button {
    width: auto;
    height: 1.75rem;
    margin-left: var(--space-1);
    padding: 0 var(--space-3);
    border: 1px solid var(--color-primary);
    border-radius: var(--radius-full);
    background: var(--color-surface);
    color: var(--color-primary);
    font-size: var(--text-md);
    font-weight: 600;
    transition: background-color 0.14s ease, color 0.14s ease;
}

/* Hover commits to the full brand blue, so the target is unmistakable
   under a cursor that is about to move the whole calendar. */
.bookings-page .bookings-date-nav .p-button.bookings-today-button.bookings-today-hidden {
    visibility: hidden;
    pointer-events: none;
}

.bookings-page .bookings-date-nav .p-button.bookings-today-button:hover {
    background: var(--color-primary);
    color: var(--color-on-primary);
}

.bookings-page .bookings-date-nav .p-button.bookings-today-button:focus-visible {
    outline: 2px solid var(--color-primary);
    outline-offset: 2px;
}

.bookings-page .bookings-date-nav .bookings-date-picker {
    width: 150px;
}

.bookings-page .bookings-date-nav .bookings-date-picker .p-inputtext {
    width: 100%;
    cursor: pointer;
    font-variant-numeric: tabular-nums;
    min-height: 2rem;
    padding: 6px var(--space-2);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-text);
    font-size: var(--text-base);
    font-weight: 500;
}

.bookings-page .bookings-stats {
    display: flex;
    gap: 0;
    margin-left: 0;
    color: var(--color-text-secondary);
    font-size: var(--text-base);
    font-variant-numeric: tabular-nums;
}

.bookings-page .bookings-stat {
    padding: 0 var(--space-3);
    color: var(--color-text-secondary);
    font-size: var(--text-sm);
    line-height: 1.2;
}

.bookings-page .bookings-stat + .bookings-stat {
    border-left: 1px solid var(--color-border-subtle);
}

.bookings-page .bookings-stat .stat-value {
    margin-right: var(--space-1);
    color: var(--color-text);
    font-size: var(--text-base);
    font-weight: 600;
}

.bookings-page .bookings-recurring-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-bottom: var(--space-4);
}

.bookings-page .calendar-wrapper,
.bookings-page .bookings-recurring-table-wrap {
    overflow-x: auto;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    box-shadow: none;
}

/* The editor follows the migrated PrimeVue dialogs: a fixed quiet frame,
   one scrolling content column, and a footer that never leaves the save
   action behind. The booking-specific rows and calendar data stay native. */
.booking-editor-dialog.p-dialog {
    display: flex;
    flex-direction: column;
    width: min(780px, 94vw);
    max-width: 94vw;
    height: min(860px, 90vh);
    max-height: 90vh;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-2);
}

.booking-editor-dialog .p-dialog-header {
    flex: 0 0 auto;
    min-height: 64px;
    padding: var(--space-4) var(--space-5);
    border-bottom: 1px solid var(--color-border);
}

.booking-editor-dialog .p-dialog-title {
    font-size: var(--text-xl);
    font-weight: 600;
    letter-spacing: var(--tracking-tight);
}

.booking-editor-dialog .p-dialog-content {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
    padding: 0;
    overflow: hidden;
}

.booking-editor-dialog .booking-editor-main {
    flex: 1 1 auto;
    min-height: 0;
    padding: 0 var(--space-5);
    overflow-y: auto;
}

.booking-editor-dialog .booking-editor-section {
    padding: var(--space-5) 0;
}

.booking-editor-dialog .booking-editor-section + .booking-editor-section {
    border-top: 1px solid var(--color-border-subtle);
}

.booking-editor-dialog .booking-editor-section-head {
    margin-bottom: var(--space-4);
}

.booking-editor-dialog .booking-editor-match-rules .booking-match-flags {
    margin-top: var(--space-4);
}

.booking-editor-dialog .booking-editor-section-head h4 {
    margin: 0;
    color: var(--color-text);
    font-size: var(--text-base);
    font-weight: 600;
    letter-spacing: var(--tracking-tight);
}

.booking-editor-dialog .booking-editor-field-grid {
    display: grid;
    min-width: 0;
}

.booking-editor-dialog .booking-editor-match-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.booking-editor-dialog .booking-editor-event-pricing-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.booking-editor-dialog .booking-editor-details-grid {
    grid-template-columns: minmax(0, 1fr) minmax(128px, 0.75fr) minmax(0, 1.25fr);
}

.booking-editor-dialog .booking-editor-setup > .form-group + .booking-editor-field-grid {
    margin-top: var(--space-5);
}

.booking-editor-dialog .booking-editor-field-grid > * {
    min-width: 0;
}

.booking-editor-dialog .booking-editor-field-grid > * + * {
    margin-left: var(--space-5);
    padding-left: var(--space-5);
    border-left: 1px solid var(--color-border-subtle);
}

.booking-editor-dialog .booking-editor-field {
    display: grid;
    align-content: start;
    gap: var(--space-2);
}

.booking-editor-dialog .booking-editor-field-label {
    color: var(--color-text-secondary);
    font-size: var(--text-sm);
    font-weight: 500;
}

.booking-editor-dialog .booking-court-value {
    display: flex;
    align-items: center;
    min-height: 32px;
    color: var(--color-text);
    font-size: var(--text-base);
    font-weight: 500;
}

.booking-editor-dialog .booking-date-time-input,
.booking-editor-dialog .recurring-date-time-input {
    width: 100%;
    min-height: 32px;
    padding: 0 var(--space-2);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    color: var(--color-text);
    font: inherit;
    font-size: var(--text-sm);
}

.recurring-editor-dialog .recurring-editor-days {
    margin-top: var(--space-5);
}

.recurring-editor-dialog .recurring-editor-schedule-grid {
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.25fr) minmax(128px, 0.75fr);
    margin-top: var(--space-5);
}

.recurring-editor-dialog .recurring-editor-date-range-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin-top: var(--space-4);
}

.recurring-editor-dialog .recurring-editor-field-control.p-select {
    width: 100%;
}

.recurring-editor-dialog .recurring-day-options {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.recurring-editor-dialog .p-button.recurring-day-button {
    min-width: 34px;
    border-color: var(--color-border);
    background: var(--color-surface);
    color: var(--color-text-secondary);
    box-shadow: none;
}

.recurring-editor-dialog .p-button.recurring-day-button:hover {
    border-color: var(--color-border-strong);
    background: var(--color-surface-hover);
    color: var(--color-text);
}

.recurring-editor-dialog .p-button.recurring-day-button.recurring-day-button-active,
.recurring-editor-dialog .p-button.recurring-day-button.recurring-day-button-active:hover {
    border-color: var(--color-text);
    background: var(--color-text);
    color: var(--color-on-primary);
}

.booking-editor-dialog .booking-editor-event-options {
    display: grid;
    gap: var(--space-4);
}

/* The event section stacks label-topped fields with no rhythm of its own:
   each one sat on the box above it, so "Nivel" touched the max-players
   input and "Tipo de evento" touched the level selects. One rule for every
   field after the first — the header keeps its own margin-bottom, so it is
   excluded rather than double-spaced. */
.booking-editor-dialog .booking-editor-event > *:not(.booking-editor-section-head) + * {
    margin-top: var(--space-5);
}

.booking-editor-dialog .booking-editor-extra-courts {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-2);
}

.recurring-editor-dialog .recurring-editor-error,
.recurring-editor-dialog .recurring-editor-note {
    margin: 0;
    padding: 0 0 var(--space-5);
    font-size: var(--text-sm);
    line-height: var(--leading-body);
}

.recurring-editor-dialog .recurring-editor-error {
    color: var(--color-danger);
}

.recurring-editor-dialog .recurring-editor-note {
    color: var(--color-text-secondary);
}

.booking-editor-dialog .form-group {
    gap: var(--space-2);
}

.booking-editor-dialog .form-group > label {
    color: var(--color-text-secondary);
    font-size: var(--text-sm);
    font-weight: 500;
}

.booking-editor-dialog .p-selectbutton {
    flex-wrap: wrap;
}

.booking-editor-dialog .booking-gender-options {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
}

.booking-editor-dialog .p-button.booking-gender-button {
    border-color: var(--color-border);
    background: var(--color-surface);
    color: var(--color-text-secondary);
    box-shadow: none;
}

.booking-editor-dialog .p-button.booking-gender-button:hover {
    border-color: var(--color-border-strong);
    background: var(--color-surface-hover);
    color: var(--color-text);
}

.booking-editor-dialog .p-button.booking-gender-button.booking-gender-button-active,
.booking-editor-dialog .p-button.booking-gender-button.booking-gender-button-active:hover {
    border-color: var(--color-text);
    background: var(--color-text);
    color: var(--color-on-primary);
}


/* Section borders already separate these final rows from the section that
   follows. Leaving their row borders in place creates a visually doubled
   divider with an empty gap between it and the section divider. */

.booking-editor-dialog .booking-level-controls {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    color: var(--color-text-secondary);
    font-size: var(--text-sm);
}

.booking-editor-dialog .booking-match-flags {
    display: grid;
    gap: var(--space-2);
    margin-top: var(--space-4);
}

.booking-editor-dialog .booking-checkbox-option {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    padding: var(--space-3);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-sm);
    color: var(--color-text);
    cursor: pointer;
    font-size: var(--text-base);
    line-height: var(--leading-body);
}

.booking-editor-dialog .booking-checkbox-option:hover {
    border-color: var(--color-border-strong);
    background: var(--color-surface-hover);
}

.booking-editor-dialog .booking-checkbox-option input {
    flex: 0 0 auto;
    width: 16px;
    height: 16px;
    margin: 2px 0 0;
    accent-color: var(--color-primary);
}

.booking-editor-dialog .p-inputtext {
    width: 100%;
}

.booking-editor-dialog .bm-player .p-inputtext {
    font-size: var(--text-xs);
}

/* A settled player is a small status cluster, not a run-on string. Keeping
   the state, method and amount on their own visual levels makes dense roster
   cards easy to scan without changing how payments are recorded or reversed. */
.booking-editor-dialog .bm-pay {
    display: flex;
    align-items: center;
    flex-direction: column;
    width: 100%;
    gap: var(--space-1);
    margin-top: var(--space-1);
    font-size: var(--text-xs);
}

.booking-editor-dialog .booking-player-payment-summary {
    display: grid;
    justify-items: center;
    gap: 3px;
    min-width: 0;
}

.booking-editor-dialog .booking-player-payment-tag.p-tag {
    padding: 2px 6px;
    font-size: var(--text-xs);
    font-weight: 600;
    line-height: 1.25;
}

.booking-editor-dialog .booking-player-payment-tag .p-tag-icon {
    font-size: 10px;
}

.booking-editor-dialog .booking-player-payment-meta {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 2px var(--space-1);
    min-width: 0;
    color: var(--color-text-secondary);
    font-size: var(--text-xs);
    line-height: 1.25;
}

.booking-editor-dialog .booking-player-payment-amount {
    color: var(--color-text);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.booking-editor-dialog .booking-player-payment-method::before {
    content: '·';
    margin-right: var(--space-1);
    color: var(--color-text-tertiary);
}

.booking-editor-dialog .booking-player-payment-action.p-button.p-button-text {
    min-height: 24px;
    padding: 2px 4px;
    color: var(--color-text-secondary);
    font-size: var(--text-xs);
}

.booking-editor-dialog .booking-player-payment-action.p-button.p-button-text:not(:disabled):hover {
    color: var(--color-text);
}

.booking-editor-dialog .booking-player-payment-action.p-button.p-button-text.p-button-danger,
.booking-editor-dialog .booking-player-payment-action.p-button.p-button-text.p-button-danger:not(:disabled):hover {
    color: var(--color-danger);
}

/* The surrounding section provides the one divider between Players and the
   next group. The legacy grid border would draw a second rule in Blocking
   and Training. */
.booking-editor-dialog .bm-players {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-2);
    padding: var(--space-3) 0;
    border-bottom: 0;
}

.booking-editor-dialog .bm-player {
    position: relative;
    display: flex;
    align-items: center;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
    text-align: center;
}

.booking-editor-dialog .bm-empty-slot {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: var(--color-surface-hover);
    color: var(--color-text-secondary);
    font-size: var(--text-base);
    transition: border-color 0.14s ease, background-color 0.14s ease, color 0.14s ease;
}

.booking-editor-dialog .bm-player:focus-within .bm-empty-slot {
    border-color: var(--color-primary);
    background: var(--color-surface);
    color: var(--color-primary);
}

.booking-duration-select.p-select {
    display: inline-flex;
    width: 116px;
    margin-left: var(--space-2);
    vertical-align: middle;
}

.booking-editor-dialog .booking-duration-field-control.p-select {
    width: 100%;
    margin-left: 0;
}

.booking-level-select.p-select {
    width: 84px;
}

.booking-editor-dialog .booking-editor-coach-select.p-select {
    width: 240px;
    max-width: 100%;
}

.booking-number-input.p-inputnumber {
    width: 90px;
}

.booking-price-input.p-inputnumber {
    width: 110px;
}

.booking-editor-dialog .booking-event-field-control.p-inputnumber {
    width: 100%;
    max-width: 180px;
}

.booking-editor-dialog .p-dialog-footer {
    flex: 0 0 auto;
    margin: 0;
    padding: 0;
    border-top: 1px solid var(--color-border);
}

.booking-editor-dialog .booking-editor-actions {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-5);
}

.booking-editor-action-spacer {
    flex: 1 1 auto;
}

.booking-editor-dialog .booking-editor-error {
    margin: 0;
    padding: 0 0 var(--space-5);
    color: var(--color-danger);
    font-size: var(--text-base);
}

/* ============================================================
   The calendar surface. Moved here from index.html with its raw
   hexes swapped for tokens: the grid lines, the empty-slot hover
   and the drop target now follow the same palette as every other
   page instead of a private set of grays and greens.
   ============================================================ */
.bookings-page .calendar-grid {
    display: grid;
    min-width: 600px;
}

.bookings-page .cal-header {
    display: contents;
}

.bookings-page .cal-header-cell {
    position: sticky;
    top: 0;
    z-index: 2;
    padding: 10px var(--space-2);
    border-bottom: 2px solid var(--color-border);
    background: var(--color-bg);
    font-size: var(--text-md);
    font-weight: 600;
    text-align: center;
}

.bookings-page .cal-time-cell {
    display: flex;
    align-items: flex-start;
    justify-content: flex-end;
    min-height: 30px;
    padding: 0 var(--space-2);
    border-right: 1px solid var(--color-border);
    border-bottom: 1px solid var(--color-border-subtle);
    color: var(--color-text-secondary);
    font-size: var(--text-sm);
    /* Hour hugs the slot's start line (top of the cell), not floating
       mid-slot. */
    line-height: 1;
}

.bookings-page .cal-cell {
    position: relative;
    min-height: 30px;
    border-right: 1px solid var(--color-border-subtle);
    border-bottom: 1px solid var(--color-border-subtle);
}

.bookings-page .cal-cell-empty {
    cursor: pointer;
}

.bookings-page .cal-cell-empty:hover {
    background: var(--color-primary-subtle);
}

/* Drop target: success-tinted, because the only thing being said is
   "this move is allowed here". */
.bookings-page .cal-cell.drag-over {
    outline: 2px dashed var(--color-success);
    outline-offset: -2px;
    background: var(--color-success-subtle);
}

/* ---- The booking block itself ---- */
.bookings-page .cal-booking {
    position: absolute;
    z-index: 1;
    top: 1px;
    right: 2px;
    left: 2px;
    overflow: hidden;
    padding: var(--space-1) 6px;
    border-radius: var(--radius-sm);
    /* Fallback ink; the block's inline style picks black or white from its
       own colour (bookingInk). */
    color: var(--color-on-primary);
    cursor: pointer;
    font-size: var(--text-xs);
    line-height: 1.3;
    box-shadow: var(--shadow-1);
}

.bookings-page .cal-booking:hover {
    opacity: 0.9;
    box-shadow: var(--shadow-2);
}

.bookings-page .cal-booking.dragging {
    opacity: 0.4;
}

.bookings-page .cal-booking-title {
    overflow: hidden;
    margin-bottom: 2px;
    font-size: var(--text-xs);
    font-weight: 600;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.bookings-page .cal-booking-player {
    display: flex;
    align-items: center;
    overflow: hidden;
    gap: 3px;
    font-size: 10px;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.bookings-page .cal-booking-headcount {
    font-size: var(--text-xs);
}

.bookings-page .cal-booking-comments {
    margin-top: 1px;
    font-size: 10px;
    font-style: italic;
    opacity: 0.85;
    /* As many lines as the comment needs — the block clips at its own height
       anyway, so a long note fills the slot instead of dying with an ellipsis
       on line one. */
    overflow-wrap: anywhere;
}

/* A match cell can carry both notes at once. The private comment stands
   upright so it cannot be mistaken for the italic public message players
   actually see on their card. */
.bookings-page .cal-booking-comments-private {
    font-style: normal;
}

/* Free seats in a match, one dot each. */
.bookings-page .cal-booking-empty-slots {
    display: flex;
    /* One dot per line, like the apps' calendars: each empty seat is a row
       of the roster, not a counter. */
    flex-direction: column;
    gap: 3px;
    margin-top: 1px;
}

.bookings-page .cal-booking-empty-slots .empty-dot {
    width: 7px;
    height: 7px;
    border-radius: var(--radius-full);
    background: var(--color-danger);
}

.bookings-page .cal-player-pending {
    opacity: 0.55;
    font-style: italic;
}

/* Payment state after the name, drawn like the iOS calendar's SF symbols:
   a filled circle, white glyph — success ✓ paid, warning ! due. */
.bookings-page .pay-badge {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: 11px;
    height: 11px;
    border-radius: var(--radius-full);
    color: var(--color-on-primary);
    font-size: 8px;
    font-weight: 700;
    line-height: 1;
}

.bookings-page .pay-badge-paid { background: var(--color-success); }
.bookings-page .pay-badge-due  { background: var(--color-warning); }
/* An employed coach's lesson with no price frozen: nothing to collect, and
   not because anyone paid. Grey, not green. */
.bookings-page .pay-badge-unpriced { background: var(--color-text-secondary); font-size: 9px; letter-spacing: -0.5px; }

/* Level band, top-right of a match/event block: "17–14", strongest first.
   A light pill so it reads on every block colour. FLOATED, not absolutely
   positioned, so the first lines of text — a long event title especially —
   wrap around it instead of disappearing underneath it. */
.bookings-page .cal-booking-level {
    float: right;
    margin: 0 0 0 4px;
    padding: 0 4px;
    border-radius: var(--radius-full);
    background: var(--color-surface);
    color: var(--color-text);
    font-size: 9px;
    font-weight: 700;
    /* Exactly one roster row tall (13px). A taller margin box overlapped the
       SECOND row too, and those rows clip silently — the first players' pay
       badge simply vanished once a column dropped below ~115px. */
    line-height: 13px;
    opacity: 0.9;
}

/* Text that may shrink and ellipsize inside a block row, so the badge beside
   it (flex: 0 0 auto) never does. A long name or a narrow column costs the
   tail of the label, never the payment state the desk acts on. */
.bookings-page .cal-shrink {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Playtomic sync, bottom-right of the block. Was six inline style
   properties per booking; the ring keeps it readable on any block colour. */
.bookings-page .cal-sync-dot {
    position: absolute;
    right: 3px;
    bottom: 3px;
    width: 5px;
    height: 5px;
    border-radius: var(--radius-full);
    box-shadow: 0 0 0 1px var(--color-surface);
}

.bookings-page .cal-sync-dot-on  { background: var(--color-success); }
.bookings-page .cal-sync-dot-off { background: var(--color-warning); }

/* ============================================================
   Page states. The bookings page used to borrow index.html's global
   .coming-soon for "loading", "empty" and "here is your result" alike;
   these say the same things in the page's own voice.
   ============================================================ */
.bookings-page .bookings-state {
    margin: 0;
    padding: var(--space-6) var(--space-4);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    color: var(--color-text-secondary);
    font-size: var(--text-base);
    text-align: center;
}

.bookings-page .bookings-recurring-report {
    margin: 0 0 var(--space-4);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--color-border-subtle);
    border-left: 3px solid var(--color-success);
    border-radius: var(--radius-md);
    background: var(--color-surface);
    color: var(--color-text);
    font-size: var(--text-base);
}

.bookings-page .bookings-weekday {
    color: var(--color-text-secondary);
    font-size: var(--text-base);
    white-space: nowrap;
    /* All seven names share one grid cell: the cell measures the widest,
       so the Next arrow beside it stays put as the day changes. */
    display: inline-grid;
}

.bookings-page .bookings-weekday > span {
    grid-area: 1 / 1;
}

.bookings-page .bookings-weekday-ghost {
    visibility: hidden;
}

.bookings-page .bookings-tabs {
    margin-bottom: var(--space-4);
}

.bookings-page .bookings-recurring-result {
    color: var(--color-success);
    font-size: var(--text-sm);
}

/* ---- Recurring series table ---- */
.bookings-page .bookings-recurring-table.price-table {
    min-width: 760px;
    border-radius: 0;
    box-shadow: none;
}

.bookings-page .bookings-recurring-table.price-table th {
    padding: 10px var(--space-3);
    border-bottom: 1px solid var(--color-border-subtle);
    color: var(--color-text-tertiary);
}

.bookings-page .bookings-recurring-table.price-table td {
    padding: var(--space-3);
    border-bottom-color: var(--color-border-subtle);
}

.bookings-page .bookings-recurring-row-actions {
    white-space: nowrap;
}

.bookings-page .bookings-recurring-row-actions .p-button {
    padding: var(--space-1) var(--space-2);
}

/* ============================================================
   Read-only booking card. Same dialog frame as the editor, with a
   description list instead of a form: label left, value right.
   ============================================================ */
.booking-detail-dialog.p-dialog {
    width: min(480px, 94vw);
}

.booking-detail-dialog .booking-detail-rows {
    margin: 0;
}

/* A person in the detail list (the training's coach): photo beside the name. */
.booking-detail-dialog .booking-detail-person {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
}

.booking-detail-dialog .booking-detail-avatar {
    width: 24px;
    height: 24px;
    font-size: 10px;
}

.booking-detail-dialog .booking-detail-row {
    display: flex;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-2) 0;
    border-bottom: 1px solid var(--color-border-subtle);
    font-size: var(--text-base);
}

.booking-detail-dialog .booking-detail-row dt {
    color: var(--color-text-secondary);
    font-weight: 500;
}

.booking-detail-dialog .booking-detail-row dd {
    margin: 0;
    font-weight: 500;
    text-align: right;
}

.booking-detail-dialog .booking-detail-players {
    margin-top: var(--space-4);
}

.booking-detail-dialog .booking-detail-players-title {
    margin: 0 0 var(--space-2);
    color: var(--color-text-secondary);
    font-size: var(--text-md);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.booking-detail-dialog .booking-detail-player {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-2) 0;
    border-bottom: 1px solid var(--color-border-subtle);
    font-size: var(--text-base);
}

/* ============================================================
   Roster: the four-across player grid in both editors.
   ============================================================ */
.booking-editor-dialog .bm-avatar-wrap {
    position: relative;
}

.booking-editor-dialog .bm-player .player-avatar {
    width: 56px;
    height: 56px;
    background-position: center;
    background-size: cover;
    font-size: var(--text-xl);
}

/* The avatar owns its X, like the app: a small danger-rimmed circle on the
   avatar's own corner (the column is wider than the photo, so anchoring to
   the column floated it into the gutter). Global button styles are reset —
   they stretched it into an oval. */
.booking-editor-dialog .bm-remove {
    position: absolute;
    z-index: 1;
    top: -3px;
    right: -3px;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    min-width: 0;
    height: 18px;
    margin: 0;
    padding: 0;
    border: 1.5px solid var(--color-danger);
    border-radius: var(--radius-full);
    background: var(--color-surface);
    color: var(--color-danger);
    cursor: pointer;
    font-size: var(--text-sm);
    font-weight: 700;
    line-height: 1;
}

.booking-editor-dialog .bm-player-name {
    overflow-wrap: anywhere;
    font-size: var(--text-sm);
    font-weight: 600;
    line-height: var(--leading-tight);
}

.booking-editor-dialog .bm-player-level {
    color: var(--color-player-level);
    font-size: var(--text-xs);
}

/* The three ways reception settles a player, side by side under the name. */
.booking-editor-dialog .booking-pay-methods {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 3px;
}

.booking-editor-dialog .booking-pay-method.p-button {
    padding: 2px var(--space-2);
    font-size: 10px;
}

/* ============================================================
   Player search. These carried the notifications page's class names
   long after that page moved to its own vocabulary; renamed to what
   they actually are.
   ============================================================ */
.booking-editor-dialog .booking-roster-search {
    margin-top: var(--space-2);
}

.booking-editor-dialog .booking-player-results,
.recurring-editor-dialog .booking-player-results {
    overflow-y: auto;
    max-height: 200px;
    margin-top: var(--space-1);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    background: var(--color-surface);
    text-align: left;
}

.booking-editor-dialog .booking-player-result,
.recurring-editor-dialog .booking-player-result {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    cursor: pointer;
    font-size: var(--text-base);
}

.booking-editor-dialog .booking-player-result:hover,
.recurring-editor-dialog .booking-player-result:hover {
    background: var(--color-surface-hover);
}

.booking-editor-dialog .booking-player-result-meta,
.recurring-editor-dialog .booking-player-result-meta {
    color: var(--color-text-tertiary);
    font-size: var(--text-sm);
}

/* A search that comes up empty offers to create the player instead of
   just sitting there — shown where the results list would otherwise be. */
.booking-player-empty {
    margin-top: var(--space-1);
}

.booking-new-player-btn {
    width: 100%;
}

/* ============================================================
   Event roster: who has signed up, who is waiting, and who is paired
   with whom. Was ~15 inline styles carrying five hard-coded colours.
   ============================================================ */
.booking-editor-dialog .booking-roster-chip {
    display: flex;
    align-items: center;
    /* The payment row wraps onto a second line of its own (flex-basis 100%),
       leaving the name line exactly as it was. */
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-bottom: var(--space-1);
    padding: 6px var(--space-3);
    border: 1px solid transparent;
    border-radius: var(--radius-full);
    background: var(--color-primary);
    color: var(--color-on-primary);
    font-size: var(--text-md);
    font-weight: 500;
}

/* Over capacity: the chip loses its fill so the cut-off line is visible at a
   glance without re-reading the count. */
.booking-editor-dialog .booking-roster-chip-waiting {
    border-color: var(--color-warning);
    background: var(--color-warning-subtle);
    color: var(--color-text);
}

.booking-editor-dialog .booking-roster-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.booking-editor-dialog .booking-roster-meta {
    margin-left: auto;
    opacity: 0.75;
    font-size: var(--text-sm);
}

.booking-editor-dialog .booking-roster-paid {
    font-size: var(--text-sm);
    font-weight: 600;
}

/* Event roster as the match editor's card grid (owner 2026-09-07). The grid
   itself is bm-players; this only spaces it inside the form group. */
.booking-editor-dialog .booking-event-players-grid {
    padding-top: var(--space-2);
}

/* A reserve keeps its place in the grid and is tinted instead of moved — the
   same signal the old waiting chip carried. */
.booking-editor-dialog .bm-player-waiting {
    border-radius: var(--radius-md);
    background: var(--color-warning-subtle);
    padding: var(--space-2) 0;
}

/* How reception settles an event's players, on the chip's own second line
   (owner 2026-09-07). A two-line pill reads as a lozenge, so the radius
   softens once the row is there. */
.booking-editor-dialog .booking-roster-chip-with-actions {
    border-radius: var(--radius-md);
}

.booking-editor-dialog .booking-roster-actions {
    flex-basis: 100%;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 3px;
    padding-top: 4px;
}

/* PrimeVue's secondary outline is tuned for a white surface; on the filled
   chip the buttons take the chip's own ink instead. */
.booking-editor-dialog .booking-roster-chip .booking-pay-method.p-button,
.booking-editor-dialog .booking-roster-chip .booking-player-payment-action.p-button {
    border-color: var(--color-on-primary);
    color: var(--color-on-primary);
}

.booking-editor-dialog .booking-roster-chip-waiting .booking-roster-meta {
    color: var(--color-text-secondary);
    opacity: 1;
}

.booking-editor-dialog .booking-roster-remove {
    width: 18px;
    min-width: 0;
    height: 18px;
    flex: 0 0 auto;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: var(--radius-full);
    background: transparent;
    color: inherit;
    cursor: pointer;
    font-size: var(--text-lg);
    line-height: 1;
    opacity: 0.8;
}

.booking-editor-dialog .booking-roster-remove:hover {
    opacity: 1;
}

.booking-editor-dialog .booking-roster-divider {
    margin: var(--space-2) 0 var(--space-1);
    padding-top: var(--space-2);
    border-top: 1px solid var(--color-border-subtle);
    color: var(--color-warning);
    font-size: var(--text-sm);
    font-weight: 600;
}

/* A team is a box around its one or two chips: pairing is the thing being
   edited here, so the grouping has to be the visible unit. */
.booking-editor-dialog .booking-team-card {
    margin-bottom: 6px;
    padding: 6px var(--space-2);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-md);
}

.booking-editor-dialog .booking-team-card .booking-roster-chip:last-child {
    margin-bottom: 0;
}

.booking-editor-dialog .booking-team-pairing {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin-top: var(--space-2);
}

.booking-editor-dialog .booking-team-pairing-select.p-select {
    flex: 1 1 auto;
    min-width: 0;
}

.booking-editor-dialog .booking-team-actions {
    display: flex;
    justify-content: flex-end;
    margin-top: var(--space-1);
}

@media (max-width: 640px) {
    .bookings-page .bookings-header {
        align-items: flex-start;
        flex-direction: column;
    }

    .bookings-page .bookings-stats {
        flex-wrap: wrap;
        margin-left: 0;
    }

    /* The date toolbar is an inline pill on desktop; on a phone it is wider
       than the screen, so it becomes a full-width block whose controls wrap
       rather than pushing the page sideways. */
    .bookings-page .bookings-control-bar {
        display: flex;
        width: 100%;
    }

    .bookings-page .bookings-date-nav {
        flex-wrap: wrap;
        row-gap: var(--space-2);
    }

    /* Regroup the wrapped row: the arrows stay with the date they move, and
       the weekday sits with Today on the second line. */
    .bookings-page .bookings-date-nav .bookings-nav-prev { order: 1; }
    .bookings-page .bookings-date-nav .bookings-date-picker { order: 2; flex: 1 1 120px; min-width: 0; width: auto; }
    .bookings-page .bookings-date-nav .bookings-nav-next { order: 3; }
    .bookings-page .bookings-date-nav .bookings-weekday { order: 4; }
    /* Last in the wrapped row, kept beside the date it resets rather than
       pushed to the far edge — the chip belongs to the stepper group, and a
       lone control floating right reads as unrelated to it. */
    .bookings-page .bookings-date-nav .p-button.bookings-today-button { order: 5; }

    .bookings-page .bookings-stat {
        padding: var(--space-1) var(--space-2);
    }

    .booking-editor-dialog.p-dialog {
        width: 96vw;
        max-width: 96vw;
        height: 92vh;
        max-height: 92vh;
    }

    .booking-editor-dialog .p-dialog-header,
    .booking-editor-dialog .booking-editor-actions {
        padding-right: var(--space-4);
        padding-left: var(--space-4);
    }

    .booking-editor-dialog .booking-editor-main {
        padding-right: var(--space-4);
        padding-left: var(--space-4);
    }

    .booking-editor-dialog .booking-editor-section {
        padding-top: var(--space-4);
        padding-bottom: var(--space-4);
    }


    .booking-editor-dialog .booking-level-controls {
        width: 100%;
    }

    .booking-editor-dialog .booking-editor-match-grid,
    .booking-editor-dialog .booking-editor-details-grid,
    .booking-editor-dialog .booking-editor-event-pricing-grid,
    .recurring-editor-dialog .recurring-editor-schedule-grid,
    .recurring-editor-dialog .recurring-editor-date-range-grid {
        grid-template-columns: 1fr;
        gap: var(--space-4);
    }

    .booking-editor-dialog .booking-editor-field-grid > * + * {
        margin-left: 0;
        padding-top: var(--space-4);
        padding-left: 0;
        border-top: 1px solid var(--color-border-subtle);
        border-left: 0;
    }

    .booking-editor-dialog .booking-editor-extra-courts {
        grid-template-columns: 1fr;
    }

    .booking-editor-dialog .booking-roster-meta {
        margin-left: 0;
    }

    .booking-editor-dialog .booking-team-pairing {
        align-items: stretch;
        flex-direction: column;
    }
}

/* A child blocking (part of an event) is delete-only; this note replaces the
   editor body in the booking modal. */
.booking-editor-child-note {
    padding: var(--space-4);
    border-radius: var(--radius-md);
    background: var(--color-bg);
    color: var(--color-text-secondary);
    font-size: var(--text-base);
    line-height: var(--leading-body);
}

/* A seat's face and name open the player's profile dialog — make them read
   as tappable without competing with the slot's own remove button. */
.booking-editor-dialog .bm-player-open {
    cursor: pointer;
}

.booking-editor-dialog .bm-player-name.bm-player-open:hover {
    text-decoration: underline;
}

/* Pending join requests — the envelope on the calendar card, and the
   answerable banner in the editor. Amber family: iOS's own banner is a soft
   yellow, and the desk already reads orange as "needs an answer". */
.cal-booking-joinreq {
    display: inline-block;
    margin-top: 2px;
    padding: 0 6px;
    border-radius: 8px;
    background: var(--color-attention);
    color: var(--color-on-attention);
    font-size: var(--text-xs);
    font-weight: 700;
    line-height: 1.6;
}

.booking-editor-dialog .bm-joinreq {
    margin-bottom: var(--space-4);
    padding: var(--space-3);
    border: 1px solid var(--color-attention-border);
    border-radius: var(--radius-md);
    background: var(--color-attention-subtle);
}

.booking-editor-dialog .bm-joinreq-title {
    margin-bottom: var(--space-2);
    color: var(--color-attention-fg);
    font-size: var(--text-sm);
    font-weight: 700;
}

/* Result of a finished match under the roster: the sets set by set, team A's
   games left and team B's right with the set winner in bold, who won, and the
   desk's reset centered beneath — the app's result card. */
.booking-editor-dialog .bm-result {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-2);
    margin-top: var(--space-4);
    padding-top: var(--space-4);
    border-top: 1px solid var(--color-border-subtle);
}

.booking-editor-dialog .bm-result-sets {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
}

.booking-editor-dialog .bm-result-set {
    display: flex;
    gap: var(--space-3);
}

.booking-editor-dialog .bm-result-games {
    width: 2.25rem;
    text-align: center;
    font-size: var(--text-xl);
    font-variant-numeric: tabular-nums;
    color: var(--color-text-secondary);
}

.booking-editor-dialog .bm-result-games.won {
    font-weight: 700;
    color: var(--color-text);
}

.booking-editor-dialog .bm-result-winner {
    color: var(--color-text-secondary);
    font-size: var(--text-sm);
}

/* Points won or lost in this match, under the level on the player card. */
.booking-editor-dialog .bm-player-delta {
    font-size: var(--text-sm);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.booking-editor-dialog .bm-player-delta.up {
    color: var(--color-success);
}

.booking-editor-dialog .bm-player-delta.down {
    color: var(--color-danger);
}

.booking-editor-dialog .bm-joinreq-row {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-1) 0;
}

.booking-editor-dialog .bm-joinreq-avatar {
    width: 32px;
    height: 32px;
    font-size: var(--text-xs);
}

.booking-editor-dialog .bm-joinreq-name {
    flex: 1;
    font-size: var(--text-sm);
    font-weight: 600;
}

.booking-editor-dialog .bm-joinreq-level {
    margin-left: var(--space-2);
    color: var(--color-player-level);
    font-size: var(--text-xs);
    font-weight: 600;
}

.booking-editor-dialog .bm-joinreq-saving {
    color: var(--color-text-secondary);
    font-size: var(--text-sm);
}

/* A seated-but-unconfirmed invitee: the app's gray "?" treatment, plus the
   on-behalf answer where their pay controls would be. */
.booking-editor-dialog .bm-player-invited {
    opacity: 0.55;
}

.booking-editor-dialog .bm-invite-answer {
    opacity: 1;
}

.booking-editor-dialog .bm-invite-pending-label {
    margin-bottom: var(--space-1);
    color: var(--color-attention-fg);
    font-size: var(--text-xs);
    font-weight: 700;
}

/* The match owner's key, riding the avatar's top-left like the app's. */
.booking-editor-dialog .bm-owner-key {
    position: absolute;
    top: -4px;
    left: -6px;
    z-index: 1;
    font-size: 13px;
    line-height: 1;
    filter: drop-shadow(var(--shadow-glyph));
}
