.cal-day { position: relative; height: 160px; overflow: hidden; padding: 0; }
.cal-day {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}
.cal-day-num {
    position: absolute; top: 4px; left: 8px; right: 6px; z-index: 2; margin: 0;
    display: flex; align-items: center; flex-wrap: wrap; gap: 4px;
}
.cal-day-body {
    position: absolute; top: 26px; left: 4px; right: 4px; bottom: 4px;
    overflow-y: auto;
    display: flex; flex-direction: column; gap: 2px;
}
.cal-tblock {
    box-sizing: border-box; width: 100%;
    border-left: 3px solid var(--secondary);
    border-radius: 0 3px 3px 0; padding: 1px 4px;
    font-size: 0.7rem; line-height: 1.25;
    cursor: pointer;
    position: relative;
}
.cal-tblock::before {
    content: ''; position: absolute;
    top: 100%; left: -3px;
    width: 3px; height: 2px;
    background: var(--secondary);
}
.cal-tblock:last-child::before { display: none; }
.cal-tblock.cal-book-pending { background: #fff9e8; border-left-color: #f0b429; }
.cal-tblock.cal-book-pending::before { background: #f0b429; }
.cal-tblock.cal-book-confirmed { background: transparent; border-left-color: #2e9e5b; }
.cal-tblock.cal-book-confirmed::before { background: #2e9e5b; }
.cal-tblock.cal-book-cancelled { background: transparent; border-left-color: #d64545; }
.cal-tblock.cal-book-cancelled::before { background: #d64545; }
.cal-tblock.cal-book-completed { background: #f0f1fe; border-left-color: #4f46e5; }
.cal-tblock.cal-book-completed::before { background: #4f46e5; }
.cal-tblock.cal-book-short { background: #e0eef2; border-left-color: #0e7490; }
.cal-tblock.cal-book-short::before { background: #0e7490; }
.cal-tblock-text {
    display: block;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    line-height: 1.2;
}
.cal-tblock-text.cal-has-balance {
    padding-right: 44px;
    box-sizing: border-box;
}
.cal-tblock .cal-balance-tag {
    position: absolute;
    top: 50%;
    right: 2px;
    transform: translateY(-50%);
    margin-left: 0;
    padding: 0 4px;
    font-size: 0.62rem;
}
.cal-day-off-chip {
    display: inline-block; background: #fbe1e1; color: #d64545;
    border-radius: 6px; padding: 1px 5px; font-size: 0.6rem; font-weight: 700;
}

/* ===== Day view ===== */
.day-view { margin-top: 20px; }
.day-nav { display: flex; gap: 12px; justify-content: center; align-items: center; margin-bottom: 16px; }
.day-nav h3 { margin: 0; }
.day-banner { text-align: center; padding: 40px; background: var(--card-bg); border-radius: var(--radius); box-shadow: var(--shadow); color: var(--muted); font-weight: 700; }
.day-off-line { margin-top: 8px; }
.day-sched-wrap { border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; }
.day-grid { display: flex; background: var(--card-bg); border-radius: 0; box-shadow: none; overflow: auto; max-height: calc(100vh - 280px); padding-top: 12px; }
.day-view.day-view-fill .day-grid { height: calc(100vh - 280px); min-height: 320px; }
.day-time-axis { width: 64px; position: relative; border-right: 1px solid #f1e9e1; }
.day-hour-label {
    position: absolute; right: 8px; transform: translateY(-50%);
    font-size: 0.68rem; font-weight: 700; color: var(--muted);
    white-space: nowrap;
}
.day-lanes { position: relative; flex: 1; min-width: 0; }
.day-lane { position: absolute; top: 0; height: 100%; }
.day-lane + .day-lane { border-left: 1px dashed #f1e9e1; }
.day-head-row { display: flex; background: var(--card-bg); border-bottom: 2px solid #efe5db; height: 28px; }
.day-head-spacer { width: 64px; flex: none; }
.day-head-lanes { position: relative; flex: 1; min-width: 0; }
.day-head-cell {
    position: absolute; top: 0; bottom: 0; box-sizing: border-box;
    padding: 0 8px; font-size: 0.72rem; font-weight: 700; text-align: center;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    line-height: 26px;
}
.day-head-cell + .day-head-cell { border-left: 1px dashed #f1e9e1; }
.day-gridlines {
    position: absolute; top: 0; left: 0; right: 0; bottom: 0;
    background: repeating-linear-gradient(to bottom, transparent 0 calc(48px - 1px), #f1e9e1 calc(48px - 1px) 48px);
}
.day-block {
    position: absolute; box-sizing: border-box; border-left: 3px solid var(--secondary);
    border-radius: 4px; padding: 2px 6px; font-size: 0.72rem; line-height: 1.3;
    overflow: hidden; cursor: pointer;
    z-index: 2;
}
.day-block.cal-book-pending { background: #fff9e8; border-left-color: #f0b429; }
.day-block.cal-book-confirmed { background: #eefaf2; border-left-color: #2e9e5b; }
.day-block.cal-book-cancelled { background: transparent; border-left-color: #d64545; }
.day-block.cal-book-completed { background: #f0f1fe; border-left-color: #4f46e5; }

/* ===== Context menu day-off picker ===== */
.ctx-menu-note {
    display: block;
    padding: 6px 14px;
    margin-bottom: 4px;
    border-radius: 8px;
    background: #fdf3e7;
    color: var(--primary-dark);
    font-size: 0.78rem;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.ctx-menu-back { color: var(--muted); font-size: 0.78rem; }
.ctx-menu-picker-list { max-height: 260px; overflow-y: auto; }
.ctx-menu-empty { padding: 8px 14px; }
.ctx-menu-check {
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
}
.ctx-menu-check input[type="checkbox"] {
    margin: 0;
    flex: none;
    width: 16px;
    height: 16px;
    accent-color: #d64545;
}
.ctx-menu-check-text { font-weight: 700; font-size: 0.88rem; }
.ctx-menu-item.ctx-menu-day-off-on { color: #d64545; }
.ctx-menu-apply {
    margin-top: 4px;
    border-top: 1px solid #efe5db;
    border-radius: 8px;
    color: var(--primary-dark);
}

/* ===== Calendar multi-day selection ===== */
.cal-day-selected {
    box-shadow: inset 0 0 0 3px var(--primary);
    background: #fdf3e7;
}

.gallery-control-check {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 7px 2px;
    font-size: 0.9rem;
    font-weight: 700;
    color: var(--text);
    cursor: pointer;
}

.gallery-control-check input[type="checkbox"] {
    width: 16px;
    height: 16px;
    accent-color: var(--primary);
    cursor: pointer;
}

/* ===== Calendar side panel layout ===== */
/* The controls live in a bar pinned to the bottom of the viewport at every
   width, so the month grid gets the full page and the actions stay reachable
   while it scrolls. */
.calendar-layout {
    display: block;
}

/* The month grid is the first thing on the calendar page, so the section's
   usual top padding reads as dead space under the nav. Drop it here only. */
.section--calendar {
    padding-top: 16px;
}

/* The dashboard is a working screen, so it skips the marketing-sized 64px top
   padding the base .section carries. Matches the calendar's own tightening. */
.section--dashboard {
    padding-top: 16px;
}

.calendar-main {
    min-width: 0;
}

/* The three view hosts share one grid cell, so switching views swaps the grid
   in place instead of the incoming one landing below the outgoing one and the
   page jumping by its height. A single-item grid row is identical to the block
   layout it replaces, so the no-JS page (one view un-hidden) is unchanged.

   The switch itself is instant -- see setMode in admin_calendar.js. Nothing
   here transitions or animates. */
.calendar-views {
    display: grid;
}

.calendar-views > .calendar-view-host {
    grid-area: 1 / 1;
    min-width: 0;
}

.calendar-side {
    /* Pinned to the bottom of the viewport at every width. */
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 90;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    padding: 6px 16px;
    background: var(--card-bg);
    box-shadow: 0 -2px 12px rgba(51, 40, 43, 0.12);
}

/* Keep the bar short: tighten the controls' vertical padding here only, so the
   shared .btn-small / .seg-btn sizing is unaffected elsewhere. */
.calendar-side .btn,
.calendar-side select,
.calendar-side .seg-btn {
    padding-top: 4px;
    padding-bottom: 4px;
}

.calendar-side-title {
    margin: 0;
    color: var(--primary-dark);
    font-size: 1.05rem;
    line-height: 1.2;
}

/* Switching between Month, Week and Day.

   Switching Month/Week/Day has no transition and no animation: setMode reveals
   the arriving grid and hides the others on the same tick. Two animated designs
   were tried and both were worse than none -- a cross-fade of two overlapping
   grids washed the area out, and a fade-to-page-colour hand-off left the
   calendar looking emptied while the next view's data loaded. Keep it a plain
   show/hide. */


/* Loading state for AJAX-refreshed calendar views. The starting view wears
   this until its own data has rendered (see revealFirstView in
   admin_calendar.js): the grid area is deliberately empty rather than showing
   whatever the server rendered, so the overlay never paints the month grid on
   the way into Week or Day. */
.calendar-grid.is-loading,
.week-view.is-loading,
.day-view.is-loading {
    opacity: 0.55;
    transition: opacity var(--dur-1) ease;
    pointer-events: none;
}

.calendar-side .calendar-nav-group {
    width: auto;
}

.calendar-side .calendar-nav-group .btn,
.calendar-side .view-switch .btn {
    flex: 0 0 auto;
    justify-content: center;
    text-align: center;
}

.calendar-side .btn-primary {
    text-align: center;
}

/* The groomer filter is a single select (+ optional Clear) in the bar. */
.calendar-side .calendar-groomer-filter {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 10px;
}

.calendar-side .calendar-groomer-filter select {
    padding: 8px 12px;
    border: 1px solid #e7d8cc;
    border-radius: 8px;
    font: inherit;
    background: #fff;
}

/* Reserve the bar's height so it never covers the last booking row or the
   footer. --calendar-bar-h is the bar's measured height from JS; the fallback
   covers the pre-JS first paint. */
body.page-calendar {
    padding-bottom: calc(var(--calendar-bar-h, 96px) + 12px);
}

@media (max-width: 1100px) {
    /* Narrow-ish (tablet): let each control group stretch to fill the bar
       rather than sizing to content. Phones get an explicit two-row layout in
       the max-width: 700px block below. */
    .calendar-side .calendar-side-view,
    .calendar-side .calendar-groomer-filter {
        flex: 1 1 auto;
        width: auto;
    }
}

@media (max-width: 700px) {
    /* Thin displays: a single wrap row turns the bar into a jumbled stack, so
       lay it out as two deliberate rows instead.
         Row 1: month title + Prev/Today/Next (title grows, nav stays put).
         Row 2: view switcher + New appointment, with the groomer filter and
                help button wrapping beneath them as needed.
       The bar height is measured in JS, so the reserved padding follows. */
    .calendar-side {
        align-content: center;
        gap: 6px 8px;
        padding: 6px 12px;
    }
    .calendar-side-title {
        flex: 0 1 auto;
        font-size: 1rem;
    }
    .calendar-side .calendar-side-nav {
        flex: 0 0 auto;
        margin-left: auto;
    }
    /* Second row: the view switcher and New appointment button sit at their
       natural size; the groomer filter takes the remaining space. */
    .calendar-side .calendar-side-view,
    .calendar-side .calendar-nav-group {
        flex: 0 0 auto;
    }
    .calendar-side .btn,
    .calendar-side .seg-btn {
        font-size: 0.8rem;
    }
    .calendar-side .calendar-nav-group .btn,
    .calendar-side .view-switch .btn {
        padding-left: 10px;
        padding-right: 10px;
    }
    .calendar-side .calendar-groomer-filter {
        flex: 1 1 130px;
        min-width: 0;
    }
    .calendar-side .calendar-groomer-filter select {
        width: 100%;
        min-width: 0;
        padding: 6px 10px;
    }
}

@media (max-width: 380px) {
    /* Very thin phones: shave the nav padding and let the month title shrink
       instead of forcing the nav buttons onto a third row. */
    .calendar-side {
        padding: 5px 10px;
    }
    .calendar-side-title {
        font-size: 0.9rem;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        min-width: 0;
    }
    .calendar-side .calendar-nav-group {
        gap: 4px;
    }
    .calendar-side .calendar-nav-group .btn {
        padding-left: 6px;
        padding-right: 6px;
    }
}

/* ===== Inline date picker (New appointment modal) ===== */
/* Mon-Fri only, matching the bookable week. Scoped under .ap-cal so it never
   touches the public booking calendar's .bk-cal-* rules. */
.ap-cal {
    border: 2px solid #efe5db;
    border-radius: 6px;
    background: #fff;
    padding: 8px;
    max-width: 320px;
}

.ap-cal-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 6px;
}

.ap-cal-title {
    font-weight: 700;
    font-size: 0.9rem;
    color: var(--primary-dark);
}

.ap-cal-nav {
    border: none;
    background: transparent;
    padding: 2px 8px;
    border-radius: 6px;
    cursor: pointer;
    font: inherit;
    font-size: 1rem;
    line-height: 1;
    color: var(--text);
}

.ap-cal-nav:hover {
    background: #f7ece6;
}

/* New appointment date picker: a Mon-Fri month grid with the chosen day's
   open times in a panel to its right. */
.bk-dt-wrap {
    flex: 1 1 100%;
}

.bk-dt {
    display: grid;
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    gap: 12px;
    align-items: start;
}

@media (max-width: 560px) {
    .bk-dt {
        grid-template-columns: minmax(0, 1fr);
    }
}

.ap-cal-weekdays,
.ap-cal-grid {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 2px;
}

.ap-cal-weekdays {
    margin-bottom: 2px;
}

.ap-cal-weekdays span {
    text-align: center;
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted);
}

.ap-cal-day,
.ap-cal-pad {
    min-height: 30px;
    border-radius: 6px;
    font-size: 0.8rem;
}

.ap-cal-day {
    border: none;
    background: transparent;
    font: inherit;
    font-size: 0.8rem;
    cursor: pointer;
    color: var(--text);
}

.ap-cal-day.is-past {
    color: #c9bfc2;
    cursor: default;
}

.ap-cal-day.is-available:hover,
.ap-cal-day.is-available:focus-visible {
    background: #f7ece6;
    outline: none;
}

.ap-cal-day.is-selected {
    background: var(--primary);
    color: #fff;
    font-weight: 700;
}

.bk-times {
    min-height: 120px;
    padding: 8px;
    border: 1px solid #efe5db;
    border-radius: 8px;
    background: #fffdfb;
}

.bk-times-head {
    margin: 0 0 6px;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--text);
}

.bk-times-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-height: 260px;
    overflow-y: auto;
}

.bk-times-group {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.bk-times-groomer {
    margin: 0;
    font-size: 0.74rem;
    font-weight: 700;
    color: var(--primary-dark);
}

.bk-times-slots {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}

.bk-times-none {
    margin: 0;
    font-size: 0.75rem;
    color: var(--muted);
}

.ap-week-time {
    border: 1px solid #efe5db;
    background: #fff;
    border-radius: 5px;
    padding: 2px 6px;
    font: inherit;
    font-size: 0.72rem;
    line-height: 1.2;
    color: var(--text);
    cursor: pointer;
    white-space: nowrap;
}

.ap-week-time:hover,
.ap-week-time:focus-visible {
    background: #f7ece6;
    border-color: var(--primary);
    outline: none;
}

.ap-week-time.is-selected {
    background: var(--primary);
    border-color: var(--primary);
    color: #fff;
    font-weight: 700;
}

.ap-cal-empty {
    margin: 6px 0 0;
    font-size: 0.75rem;
    color: var(--muted);
}

/* The New-appointment modal is tall enough that its scroll containers would
   otherwise show three scrollbars (the modal body, the open-times panel and
   the calendar). Hide the bars but keep the areas scrollable, so the modal
   reads as one clean sheet of content. Scoped to this modal only. */
#createBookingModal .modal-body,
#createBookingModal .bk-times-list,
#createBookingModal .ap-cal {
    scrollbar-width: none;          /* Firefox */
    -ms-overflow-style: none;       /* legacy Edge/IE */
}

#createBookingModal .modal-body::-webkit-scrollbar,
#createBookingModal .bk-times-list::-webkit-scrollbar,
#createBookingModal .ap-cal::-webkit-scrollbar {
    width: 0;
    height: 0;
    display: none;                  /* Chrome/Safari */
}

.bk-picked {
    margin: 4px 0 0;
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--primary-dark);
}

/* Compact tile grids inside the New appointment modal. */
.bk-tile-grid {
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 8px;
    max-height: 220px;
    overflow-y: auto;
    padding: 2px;
}

.bk-tile-grid .bk-select-card {
    padding: 10px 12px;
    gap: 2px;
}

.bk-tile-grid .bk-card-name {
    font-size: 0.9rem;
}

.bk-tile-grid .bk-card-sub {
    font-size: 0.78rem;
}

.bk-tile-grid .bk-card-price {
    margin-top: 2px;
    font-size: 0.85rem;
}

/* Step 2: the customer's saved dogs as tiles on the left, the "Add a new dog"
   action on the right, split down the middle. The button is centred in its
   half so it lines up with the middle of the tile grid rather than its top.
   With no saved dogs there is nothing to split, so it falls back to a single
   column with the button centred across the full width. */
.bk-dog-picker {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    align-items: center;
}

.bk-dog-picker.is-empty {
    grid-template-columns: 1fr;
}

.bk-dog-picker.is-empty .book-toggle-col {
    justify-content: center;
}

.bk-dog-picker .book-toggle-col {
    align-items: center;
}

.bk-dog-picker .book-toggle-col .btn {
    width: auto;
    max-width: 100%;
}

@media (max-width: 560px) {
    .bk-dog-picker {
        grid-template-columns: 1fr;
    }
}

/* A saved dog's editable record, shown instead of the tiles once one is
   picked. Sits in the same slot as the picker so the step does not jump. */
.bk-dog-details {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.bk-dog-details-name {
    margin: 0;
    font-weight: 700;
    color: var(--primary-dark);
    font-size: 1rem;
}

.bk-dog-details .bk-choice-back {
    align-self: flex-start;
}

.bk-required {
    color: #d64545;
}

.bk-field-note {
    margin: 4px 0 0;
    font-size: 0.8rem;
}

.bk-addon-card {
    position: relative;
}

/* The checkbox has to stay labelable/focusable, so hide it visually rather
   than with the `hidden` attribute (display:none controls don't receive
   clicks forwarded from their <label>). */
.bk-addon-input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    padding: 0;
    border: 0;
    opacity: 0;
    pointer-events: none;
}

.bk-addon-card:focus-within {
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(196, 129, 143, 0.25);
}

.bk-addon-card.is-selected::after {
    content: "\2713";
    position: absolute;
    top: 6px;
    right: 8px;
    font-size: 0.8rem;
    font-weight: 800;
    color: var(--primary);
}

.bk-tile-hint {
    margin: 6px 0 0;
    font-size: 0.78rem;
}

/* ===== New-appointment wizard ===== */
/* The create modal is a stepped wizard: one short panel at a time instead of
   one long scroll, with a numbered stepper above and Back/Next below. */
.bk-steps {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    margin: 0 0 16px;
    padding: 0;
    list-style: none;
}

.bk-step {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 0.82rem;
    color: var(--muted);
    white-space: nowrap;
}

.bk-step-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: #efe5db;
    color: var(--muted);
    font-size: 0.75rem;
    font-weight: 700;
}

.bk-step.is-active {
    color: var(--text);
}

.bk-step.is-active .bk-step-num {
    background: var(--primary);
    color: #fff;
}

/* A completed step keeps a filled badge so staff can see how far they got. */
.bk-step.is-done .bk-step-num {
    background: var(--primary-dark);
    color: #fff;
}

.bk-step-panel {
    min-height: 120px;
}

.bk-wizard-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.bk-wizard-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-left: auto;
}

/* ----- Step 1: pick a customer (existing vs new) ----- */
/* Two big tiles stand in for the old dropdown-plus-toggle. Choosing one fades
   the tiles out and fades the matching panel in, so the step never shows an
   irrelevant control. */
.bk-hidden-select {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    white-space: nowrap;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
}

.bk-choice {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    transition: opacity var(--dur-1) ease, transform var(--dur-1) ease;
}

.bk-choice.is-leaving {
    opacity: 0;
    transform: translateY(-4px);
    pointer-events: none;
}

.bk-choice-card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    padding: 16px 18px;
    text-align: left;
    background: #fff;
    border: 1px solid #e6d9cd;
    border-radius: 10px;
    cursor: pointer;
    font: inherit;
    color: var(--text);
    transition: border-color var(--dur-1) ease, box-shadow var(--dur-1) ease, transform var(--dur-1) ease;
}

.bk-choice-card:hover,
.bk-choice-card:focus-visible {
    border-color: var(--primary);
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.07);
    transform: translateY(-1px);
}

.bk-choice-icon {
    font-size: 1.25rem;
    line-height: 1;
    margin-bottom: 4px;
}

.bk-choice-title {
    font-weight: 700;
}

.bk-choice-sub {
    font-size: 0.78rem;
    color: var(--muted);
}

.bk-choice-panel {
    opacity: 0;
    transform: translateY(6px);
    transition: opacity var(--dur-2) ease, transform var(--dur-2) ease;
}

.bk-choice-panel.is-entering {
    opacity: 1;
    transform: translateY(0);
}

.bk-choice-back {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-bottom: 10px;
    padding: 0;
    background: none;
    border: none;
    color: var(--primary-dark);
    font: inherit;
    font-size: 0.8rem;
    font-weight: 700;
    cursor: pointer;
}

.bk-choice-back:hover {
    text-decoration: underline;
}

/* ----- Rich customer search ----- */
.bk-clients-search {
    position: relative;
    display: flex;
    align-items: center;
}

.bk-clients-search .bk-search-input {
    width: 100%;
    padding-right: 30px;
}

.bk-clients-clear {
    position: absolute;
    right: 8px;
    width: 20px;
    height: 20px;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: #e6d9cd;
    color: var(--text);
    font-size: 0.9rem;
    line-height: 1;
    cursor: pointer;
}

.bk-clients-results {
    list-style: none;
    margin: 8px 0 0;
    padding: 0;
    max-height: 230px;
    overflow-y: auto;
}

.bk-clients-result {
    display: block;
    width: 100%;
    padding: 9px 12px;
    text-align: left;
    background: #fff;
    border: 1px solid #ece0d5;
    border-radius: 8px;
    margin-bottom: 6px;
    cursor: pointer;
    font: inherit;
    color: var(--text);
}

.bk-clients-result:hover,
.bk-clients-result:focus-visible {
    border-color: var(--primary);
    background: #fffaf6;
}

.bk-clients-result.is-selected {
    border-color: var(--primary);
    background: #fff3ea;
    box-shadow: inset 3px 0 0 var(--primary);
}

.bk-clients-name {
    font-weight: 700;
}

/* Dog count, read at a glance next to the name while staff type a search. */
.bk-clients-count {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 7px;
    border-radius: 999px;
    background: #f1e4d8;
    color: var(--text);
    font-size: 0.72rem;
    font-weight: 700;
    white-space: nowrap;
    vertical-align: 1px;
}

.bk-clients-dogs {
    /* Own line, so the count badge stays glued to the name above it. */
    display: block;
    font-size: 0.78rem;
    color: var(--muted);
}

.bk-clients-mark {
    background: #ffe0b2;
    border-radius: 2px;
}

.bk-clients-empty {
    margin: 8px 0 0;
    font-size: 0.85rem;
    color: var(--muted);
}

.bk-clients-picked {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 10px 0 0;
    padding: 8px 12px;
    background: #fff3ea;
    border: 1px solid var(--primary);
    border-radius: 8px;
    font-size: 0.85rem;
}

.bk-clients-picked[hidden] {
    display: none;
}

@media (max-width: 560px) {
    .bk-choice {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 560px) {
    .ap-week-time {
        font-size: 0.68rem;
        padding: 2px 4px;
    }
}

/* ===== Segmented control (admin gallery) ===== */
.seg {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 4px;
    padding: 3px;
    background: #f3e6de;
    border-radius: 6px;
}

.seg-btn {
    border: none;
    background: transparent;
    padding: 6px 10px;
    border-radius: 6px;
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--muted);
    cursor: pointer;
    transition: background var(--dur-1) ease, color var(--dur-1) ease;
}

.seg-btn:hover { color: var(--text); }
.seg-btn.is-active { background: #fff; color: var(--primary-dark); box-shadow: 0 1px 3px rgba(51, 40, 43, 0.15); }

.seg-upload { width: 100%; }
.seg-upload .seg-btn { flex: 1; text-align: center; }

/* ===== Featured toggle (admin gallery) ===== */
.featured-toggle {
    padding: 4px 8px;
    border: 1px solid #efe5db;
    border-radius: 8px;
    background: #fff;
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--muted);
    cursor: pointer;
    align-self: flex-start;
    transition: background var(--dur-1) ease, color var(--dur-1) ease, border-color var(--dur-1) ease;
}

.featured-toggle:hover { border-color: var(--accent); }
.featured-toggle.is-active {
    background: var(--accent);
    border-color: var(--accent);
    color: #4d3a00;
}

/* ===== Toasts ===== */
.toast-stack {
    position: fixed;
    top: 20px;
    right: 20px;
    z-index: 1000;
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-width: 340px;
}

.toast {
    padding: 12px 16px;
    border-radius: 6px;
    background: #33282b;
    color: #fff;
    font-size: 0.9rem;
    font-weight: 700;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
    animation: toast-in var(--dur-2) ease;
}

.toast-error { background: #d64545; }
.toast-success { background: #2e9e5b; }
.toast-alert { background: #b45309; cursor: default; }
.toast-alert .toast-alert-link {
    color: #fff;
    text-decoration: underline;
    font-weight: 700;
    margin-left: 8px;
    white-space: nowrap;
}
.toast.is-leaving { opacity: 0; transform: translateY(-6px); }

/* Error toasts carry a Copy button and a dismiss. The toast is a flex row so
   the message takes the space and the controls stay on one line. */
.toast {
    display: flex;
    align-items: flex-start;
    gap: 8px;
}
.toast-text { flex: 1; min-width: 0; }
.toast-copy,
.toast-close {
    flex: none;
    background: rgba(255, 255, 255, 0.18);
    color: #fff;
    border: 0;
    border-radius: 4px;
    font: inherit;
    font-size: 0.78rem;
    font-weight: 700;
    line-height: 1;
    padding: 4px 7px;
    cursor: pointer;
}
.toast-copy:hover,
.toast-close:hover { background: rgba(255, 255, 255, 0.32); }
.toast-close { font-size: 1rem; padding: 2px 7px 4px; }
/* The clipboard is unavailable outside a secure context; when it is, the bundle
   is offered in a selectable box instead so the detail is never lost. */
.toast-fallback {
    width: 100%;
    height: 90px;
    margin-top: 6px;
    border-radius: 4px;
    border: 0;
    padding: 6px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.68rem;
    line-height: 1.35;
    resize: vertical;
}

/* The toast slides in. Honour a reduced-motion preference: the animation is
   the only motion in this component and some people find it unpleasant. */
@media (prefers-reduced-motion: reduce) {
    .toast { animation: none; }
    .toast.is-leaving { transition: none; }
}

@keyframes toast-in {
    from { opacity: 0; transform: translateY(-8px); }
    to { opacity: 1; transform: translateY(0); }
}

/* ===== Network status banner ===== */
.net-status {
    position: fixed;
    bottom: 24px;
    right: 24px;
    z-index: 2000;
    max-width: 320px;
    padding: 12px 16px;
    border-radius: 6px;
    background: #33282b;
    color: #fff;
    font-size: 0.9rem;
    font-weight: 700;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
    transform: translateX(120%);
    transition: transform var(--dur-4) ease, opacity var(--dur-4) ease;
}

.net-status:not([hidden]) { transform: translateX(0); }
.net-status.is-offline { background: #d64545; }
.net-status.is-online { background: #2e9e5b; }
.net-status.is-leaving { opacity: 0; transform: translateX(120%); }

/* ===== Pair block (admin gallery) ===== */
.pair-block {
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 100%;
}

.pair-link-btn { align-self: flex-start; }

/* ===== Calendar drag & now-line ===== */
.day-lane-drop {
    background: #f7ece6;
}

.day-now-line {
    position: absolute;
    left: 0;
    right: 0;
    height: 2px;
    background: #e0245e;
    z-index: 1;
    pointer-events: none;
}

.day-now-line::after {
    content: '';
    position: absolute;
    left: -4px;
    top: -4px;
    width: 9px;
    height: 9px;
    background: #e0245e;
    border-radius: 50%;
}

/* ===== Upload wizard ===== */
.wizard-question {
    font-weight: 700;
    font-size: 1.05rem;
    margin: 0 0 14px;
}

.wizard-choices {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.wizard-choice {
    min-width: 110px;
}

.wizard-steps {
    display: flex;
    gap: 12px;
    justify-content: center;
    margin: 0;
}

.wizard-step-ind {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
}

.wizard-dot {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: #efe5db;
    border: 2px solid transparent;
    transition: background var(--dur-2) ease, border-color var(--dur-2) ease, box-shadow var(--dur-2) ease, transform var(--dur-2) ease;
}

.wizard-dot-label {
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: capitalize;
    color: #c9beb6;
    transition: color var(--dur-2) ease;
}

.wizard-dot.is-active {
    background: var(--primary);
}

.wizard-step-ind.is-passed .wizard-dot {
    background: var(--primary-dark);
}

.wizard-step-ind.is-passed .wizard-dot-label {
    color: var(--primary-dark);
}

.wizard-step-ind.is-active .wizard-dot {
    background: var(--primary);
    border-color: var(--primary);
    animation: dot-pulse 2.2s ease-in-out infinite;
}

.wizard-step-ind.is-active .wizard-dot-label {
    color: var(--primary-dark);
}

@keyframes dot-pulse {
    0%, 100% { box-shadow: 0 0 0 3px rgba(196, 129, 143, 0.18); }
    50% { box-shadow: 0 0 0 7px rgba(196, 129, 143, 0.06); }
}

.wizard-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 10px;
    margin-top: 18px;
}

.wizard-error {
    margin-top: 10px;
    color: #d64545;
    font-weight: 700;
}

.wizard-link-picker {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 6px;
}

#wizardLinkPicker {
    display: block;
}

.dog-photo-thumb { width: 40px; height: 40px; border-radius: 8px; object-fit: cover; flex-shrink: 0; }

/* Upload wizard fade + modal animations */
.upload-fade {
    position: fixed;
    inset: 0;
    background: #fff;
    z-index: 199;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-4) ease;
}

.upload-fade.is-visible {
    opacity: 1;
}

@keyframes wizard-in {
    from { opacity: 0; transform: translateY(28px) scale(0.96); }
    to { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes wizard-out {
    from { opacity: 1; transform: translateY(0) scale(1); }
    to { opacity: 0; transform: translateY(28px) scale(0.96); }
}

#upload_wizard_modal.modal-overlay {
    background: transparent;
    backdrop-filter: none;
}

#upload_wizard_modal .modal {
    animation: wizard-in var(--dur-4) cubic-bezier(0.22, 1, 0.36, 1) both;
    will-change: transform, opacity;
}

#upload_wizard_modal.is-closing {
    pointer-events: none;
}

#upload_wizard_modal.is-closing .modal {
    animation: wizard-out var(--dur-3) ease both;
}

/* Wizard step transitions */
.wizard-step {
    transition: opacity var(--dur-3) ease, transform var(--dur-3) ease;
}

.wizard-step.is-fading-out {
    opacity: 0;
    transform: translateY(-10px);
}

@keyframes step-in {
    from { opacity: 0; transform: translateY(14px); }
    to { opacity: 1; transform: translateY(0); }
}

.wizard-step.is-fading-in {
    animation: step-in var(--dur-3) cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* ===== Booking wizard (customer) ===== */
#booking_wizard_modal.modal-overlay {
    background: transparent;
    backdrop-filter: none;
}

#booking_wizard_modal .modal {
    animation: wizard-in var(--dur-4) cubic-bezier(0.22, 1, 0.36, 1) both;
    will-change: transform, opacity;
}

#booking_wizard_modal.is-closing {
    pointer-events: none;
}

/* ===== Save-for-later confirmation modal ===== */
#saveDraftModal .modal {
    animation: wizard-in var(--dur-4) cubic-bezier(0.22, 1, 0.36, 1) both;
    will-change: transform, opacity;
}

#saveDraftModal.is-closing {
    pointer-events: none;
}

#saveDraftModal.is-closing .modal {
    animation: wizard-out var(--dur-3) ease both;
}

#booking_wizard_modal.is-closing .modal {
    animation: wizard-out var(--dur-3) ease both;
}

/* ===== Before/After viewer modal ===== */
#baModal.modal-overlay {
    background: transparent;
    backdrop-filter: none;
}

#baModal .modal {
    animation: wizard-in var(--dur-4) cubic-bezier(0.22, 1, 0.36, 1) both;
    will-change: transform, opacity;
}

#baModal.is-closing {
    pointer-events: none;
}

#baModal.is-closing .modal {
    animation: wizard-out var(--dur-3) ease both;
}

/* ===== Generic white-fade modal (site-wide) ===== */
.modal-overlay.fade-modal {
    background: transparent;
    backdrop-filter: none;
}
/* Confirm bodies may carry newline-separated lists (e.g. appointments stranded
   by a day off); preserve them instead of collapsing to one line. */
#adminConfirmMsg {
    white-space: pre-line;
}
.fade-modal .modal {
    animation: wizard-in var(--dur-4) cubic-bezier(0.22, 1, 0.36, 1) both;
    will-change: transform, opacity;
}
.fade-modal.is-closing {
    pointer-events: none;
}
.fade-modal.is-closing .modal {
    animation: wizard-out var(--dur-3) ease both;
}

#booking_wizard_modal .form {
    background: transparent;
    box-shadow: none;
    padding: 0;
    max-width: none;
}

#booking_wizard_modal .wizard-footer {
    justify-content: space-between;
}

#booking_wizard_modal .book-summary {
    position: static;
    top: auto;
}

#booking_wizard_modal .wizard-footer-group {
    display: flex;
    align-items: center;
    gap: 10px;
}

.book-trigger-card {
    background: var(--card-bg);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 40px;
    max-width: 620px;
    margin: 0 auto;
    text-align: center;
    position: relative;
    overflow: hidden;
}

.book-trigger-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 6px;
    background: linear-gradient(90deg, var(--primary), var(--accent), var(--secondary));
    border-radius: var(--radius) var(--radius) 0 0;
}

.book-trigger-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 60px;
    height: 60px;
    border-radius: 50%;
    background: linear-gradient(135deg, #f7ece6, #fdf3ea);
    color: var(--primary-dark);
    margin-bottom: 16px;
}

.book-trigger-icon svg {
    width: 30px;
    height: 30px;
}

.book-trigger-card h2 {
    color: var(--primary-dark);
    margin-bottom: 8px;
}

.book-trigger-card p {
    margin: 0 0 22px;
    color: var(--muted);
}

.btn-lg {
    font-size: 1.05rem;
    padding: 14px 34px;
}

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

.bk-cal-head h4 {
    margin: 0;
    color: var(--primary-dark);
}

.bk-cal-nav-btn {
    background: #f7ece6;
    border: 1px solid #efe5db;
    border-radius: 6px;
    padding: 6px 12px;
    font-weight: 700;
    font-size: 0.95rem;
    cursor: pointer;
    color: var(--text);
}

.bk-cal-nav-btn:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}

.bk-cal-weekdays,
.bk-cal-days {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
}

.bk-cal-weekdays {
    background: #f7ece6;
    border-bottom: 2px solid #efe5db;
}

.bk-cal-weekday {
    padding: 10px;
    text-align: center;
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--muted);
}

.bk-cal-days {
    border: 1px solid #f1e9e1;
    border-top: none;
    border-radius: 0 0 var(--radius) var(--radius);
}

.bk-cal-day {
    position: relative;
    min-height: 56px;
    padding: 8px 6px;
    border-right: 1px solid #f1e9e1;
    border-bottom: 1px solid #f1e9e1;
    text-align: center;
    font-size: 0.85rem;
    cursor: pointer;
    transition: background var(--dur-1) ease, transform var(--dur-1) ease, box-shadow var(--dur-1) ease;
}

.bk-cal-day:nth-child(7n) {
    border-right: none;
}

.bk-cal-day-out {
    background: #faf7f4;
    cursor: default;
}

.bk-cal-day-num {
    display: inline-block;
    min-width: 24px;
    padding: 2px 0;
    font-weight: 700;
}

.bk-cal-today .bk-cal-day-num {
    background: var(--primary-dark);
    color: #fff;
    border-radius: 50%;
}

.bk-cal-day.is-available:hover,
.bk-cal-day.is-available:focus-visible {
    background: #fdf3ea;
    transform: translateY(-2px);
    box-shadow: 0 4px 10px rgba(51, 40, 43, 0.08);
    z-index: 2;
    outline: none;
}

.bk-cal-day.is-available:hover .bk-cal-day-num,
.bk-cal-day.is-available:focus-visible .bk-cal-day-num {
    color: var(--primary-dark);
    font-weight: 800;
}

.bk-cal-day.is-selected {
    background: var(--primary);
}

.bk-cal-day.is-selected .bk-cal-day-num {
    color: #fff;
    font-weight: 800;
}

.bk-cal-day.is-unavailable {
    background: #faf7f4;
    color: #c9beb6;
    cursor: not-allowed;
}

.bk-cal-day.is-unavailable.reason-full {
    background: #fdf3ea;
    color: #b39483;
}

.bk-cal-day.is-unavailable .bk-cal-day-num {
    opacity: 0.6;
}

.bk-cal-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    margin-top: 12px;
    font-size: 0.8rem;
    color: var(--muted);
}

.bk-cal-legend span::before {
    content: '';
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 3px;
    margin-right: 5px;
}

.bk-cal-legend .lg-avail::before {
    background: var(--primary);
}

.bk-cal-legend .lg-closed::before {
    background: #c9beb6;
}

.bk-cal-legend .lg-full::before {
    background: #f0d9c9;
}

.bk-time-list {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 12px;
}

.bk-time-chip {
    padding: 8px 14px;
    border: 2px solid #efe5db;
    border-radius: 20px;
    background: #fff;
    font-weight: 700;
    cursor: pointer;
    font-family: inherit;
    font-size: 0.9rem;
    transition: transform var(--dur-1) ease, box-shadow var(--dur-1) ease, border-color var(--dur-1) ease, background var(--dur-1) ease, color var(--dur-1) ease;
}

.bk-time-chip:hover {
    border-color: var(--primary);
    transform: translateY(-1px);
    box-shadow: 0 3px 8px rgba(196, 129, 143, 0.2);
}

.bk-time-chip.is-selected {
    background: var(--primary);
    border-color: var(--primary);
    color: #fff;
    transform: translateY(-1px);
    box-shadow: 0 3px 8px rgba(196, 129, 143, 0.35);
}

.bk-card-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 12px;
    margin-top: 4px;
}

.bk-select-card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    text-align: left;
    gap: 4px;
    padding: 16px;
    background: var(--card-bg);
    border: 2px solid #efe5db;
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    cursor: pointer;
    font-family: inherit;
    transition: transform var(--dur-2) ease, box-shadow var(--dur-2) ease, border-color var(--dur-2) ease, background var(--dur-2) ease;
}

.bk-select-card:hover {
    transform: translateY(-2px);
    border-color: var(--primary);
}

.bk-select-card.is-selected {
    border-color: var(--primary);
    background: #fdf3ea;
    box-shadow: 0 4px 12px rgba(196, 129, 143, 0.2);
}

.bk-card-name {
    font-weight: 700;
    color: var(--primary-dark);
    font-size: 1rem;
}

.bk-card-sub {
    color: var(--muted);
    font-size: 0.85rem;
    line-height: 1.35;
}

.bk-card-price {
    margin-top: 4px;
    font-weight: 800;
    color: var(--primary);
    font-size: 0.95rem;
}

.addon-checkboxes {
    display: flex;
    flex-direction: column;
    gap: 6px;
    max-height: 220px;
    overflow-y: auto;
    padding: 8px 10px;
    border: 1px solid #efe5db;
    border-radius: var(--radius);
    background: var(--card-bg);
}

.bk-groomer-grid {
    grid-template-columns: repeat(3, 1fr);
}

.bk-groomer-card {
    align-items: center;
    text-align: center;
}

.bk-card-photo {
    width: 100%;
    max-width: 120px;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: 50%;
    margin: 0 auto 8px;
}

.bk-card-photo-ph {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg);
    border: 2px dashed #efe5db;
    color: var(--muted);
    font-size: 2.2rem;
}

.bk-card-role {
    color: var(--muted);
    font-size: 0.82rem;
    font-weight: 700;
}

/* Dog-size tier card selector */
.bk-size-grid {
    grid-template-columns: repeat(4, 1fr);
}

.bk-size-card {
    align-items: center;
    text-align: center;
    gap: 6px;
    padding: 14px 10px;
}

.bk-size-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 44px;
    color: var(--primary);
    line-height: 0;
}

.bk-size-icon svg {
    width: 24px;
    height: 24px;
}

.bk-size-icon.is-s svg {
    width: 18px;
    height: 18px;
}

.bk-size-icon.is-m svg {
    width: 26px;
    height: 26px;
}

.bk-size-icon.is-l svg {
    width: 34px;
    height: 34px;
}

.bk-size-icon.is-xl svg {
    width: 44px;
    height: 44px;
}

.bk-size-card .bk-card-name {
    font-size: 0.9rem;
}

.bk-size-card .bk-card-sub {
    font-size: 0.75rem;
}

.bk-size-card.is-selected .bk-size-icon {
    color: var(--primary-dark);
}

.bk-size-grid.is-locked .bk-size-card {
    cursor: default;
}

.bk-size-grid.is-locked .bk-size-card:not(.is-selected) {
    opacity: 0.45;
}

.bk-size-grid.is-locked .bk-size-card:hover {
    transform: none;
    border-color: #efe5db;
}

.bk-size-grid.is-locked .bk-size-card.is-selected:hover {
    border-color: var(--primary);
}

.bk-size-grid.field-error {
    outline: 2px solid #d64545;
    outline-offset: 3px;
    border-radius: var(--radius);
}

/* Dog picker tiles (replaces the old dropdown). The hidden <select id="dog">
   still drives price/size/weight/availability; these are just the visuals. */
.bk-dog-grid {
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
}

.bk-dog-grid.field-error {
    outline: 2px solid #d64545;
    outline-offset: 3px;
    border-radius: var(--radius);
}

.bk-dog-card {
    align-items: center;
    text-align: center;
    gap: 6px;
}

.bk-dog-photo {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    overflow: hidden;
    background: #f7efe7;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #c9b3a4;
}

.bk-dog-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.bk-dog-photo svg {
    width: 30px;
    height: 30px;
}

.bk-dog-tier {
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--primary);
    background: rgba(196, 129, 143, 0.12);
    border-radius: 999px;
    padding: 2px 8px;
}

.bk-dog-card--add .bk-dog-photo--add {
    font-size: 1.8rem;
    font-weight: 400;
    line-height: 1;
    color: var(--primary);
    border: 2px dashed #e2d2c6;
    background: transparent;
}

/* The real select is hidden behind the tiles, but its label must stay out of
   the visual flow while remaining available to screen readers. */
.rules-sr-label,
.bk-sr-label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Repeat cadence card selector */
.bk-recur-grid {
    grid-template-columns: repeat(4, 1fr);
}

.bk-recur-card {
    align-items: center;
    text-align: center;
    gap: 6px;
    padding: 14px 8px;
}

.bk-recur-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 36px;
    color: var(--primary);
    line-height: 0;
}

.bk-recur-icon svg {
    width: 22px;
    height: 22px;
}

.bk-recur-card .bk-card-name {
    font-size: 0.85rem;
}

.bk-recur-card .bk-card-sub {
    font-size: 0.72rem;
}

.bk-recur-card.is-selected .bk-recur-icon {
    color: var(--primary-dark);
}

@media (max-width: 640px) {
    .bk-card-grid {
        grid-template-columns: 1fr;
    }
    .bk-groomer-grid {
        grid-template-columns: repeat(2, 1fr);
    }
    .bk-size-grid {
        grid-template-columns: repeat(2, 1fr);
    }
    .bk-recur-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

[hidden] {
    display: none !important;
}

/* ===== Cross-document page transitions ===== */
@view-transition {
    navigation: auto;
}

::view-transition-old(root) {
    animation: page-out var(--dur-4) ease-out both;
}

::view-transition-new(root) {
    animation: page-in var(--dur-4) ease-out both;
}

@keyframes page-out {
    from { opacity: 1; transform: translateX(0); }
    to { opacity: 0; transform: translateX(-30px); }
}

@keyframes page-in {
    from { opacity: 0; transform: translateX(30px); }
    to { opacity: 1; transform: translateX(0); }
}

::view-transition-old(site-header),
::view-transition-new(site-header) {
    animation: none;
}

/* ===== Scroll reveal =====
   --dur-4: a 24px rise a person watches as they scroll to it. This is the one
   place on the site where the duration IS the effect -- too short and the
   element is simply already there, which is the same as having no reveal. */
.js .reveal {
    opacity: 0;
    transform: translateY(24px);
    transition: opacity var(--dur-4) ease, transform var(--dur-4) ease;
}

.js .reveal.in-view {
    opacity: 1;
    transform: none;
}

@media (prefers-reduced-motion: reduce) {
    ::view-transition-old(root),
    ::view-transition-new(root) {
        animation-duration: 0.01ms;
    }

    .js .reveal,
    .js .reveal.in-view {
        opacity: 1;
        transform: none;
        transition: none;
    }

    .wizard-step,
    .wizard-step.is-fading-out,
    .wizard-step.is-fading-in,
    #booking_wizard_modal .modal,
    #booking_wizard_modal.is-closing .modal,
    #upload_wizard_modal .modal,
    #upload_wizard_modal.is-closing .modal,
    #baModal .modal,
    #baModal.is-closing .modal,
    .fade-modal .modal,
    .fade-modal.is-closing .modal,
    .wizard-dot,
    .wizard-step-ind.is-active .wizard-dot,
    .bk-cal-day,
    .bk-time-chip {
        animation: none;
        transition: none;
    }

    .wizard-step-ind.is-active .wizard-dot {
        box-shadow: none;
    }
}

html.js.js-swap .reveal {
    opacity: 1;
    transform: none;
    transition: none;
}

.logo-bubble svg {
    width: 26px;
    height: 26px;
}

.card-icon svg,
.emoji-paw svg,
.team-photo-placeholder svg,
.upload-drop-icon svg {
    width: 1em;
    height: 1em;
}

.btn svg,
.contact-icon,
.svc-duration-line svg,
.svc-meta svg,
.nav-toggle svg {
    width: 1em;
    height: 1em;
    vertical-align: -0.125em;
}

.logo-bubble svg,
.nav-toggle svg,
.card-icon svg,
.emoji-paw svg,
.team-photo-placeholder svg,
.contact-icon,
.upload-drop-icon svg,
.svc-meta svg,
.svc-duration-line svg {
    color: var(--text);
}

.page-footer {
    background: var(--text);
    color: #fff;
    margin-top: 0;
    padding: 28px 0 34px;
}

.page-footer-inner {
    display: flex;
    flex-direction: column;
    gap: 14px;
    align-items: center;
}

.page-footer-links {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 22px;
    justify-content: center;
}

.page-footer-links a {
    color: #f3e9e2;
    text-decoration: none;
    font-size: 0.92rem;
}

.page-footer-links a:hover {
    color: #fff;
    text-decoration: underline;
}

.page-footer-copy {
    color: rgba(255, 255, 255, 0.55);
    font-size: 0.82rem;
}

.policy-prose h2 {
    font-size: 1.35rem;
    margin-top: 1.2rem;
}

.policy-prose h2:first-child {
    margin-top: 0;
}

.policy-prose p {
    max-width: 72ch;
}

/* Contact reveal (homepage About card)

   The two halves -- the button that hides and the list that appears -- are
   animated with `grid-template-rows: 0fr -> 1fr`, not `max-height`.

   `max-height` was the old technique and it was wrong in three ways. It has to
   be given a number, and the number has to be at least the content's real
   height or the last row is clipped mid-transition; the values here were 60px
   and 160px, guessed, and 160px is not obviously enough for two contact rows
   at line-height 1.6 on a narrow card. It also eases against the WRONG
   distance: the browser interpolates the pixel value, so a list shorter than
   the cap finishes early and the remainder of the duration is spent moving
   through empty space, which reads as a stutter. And it animates a property
   that forces layout on every frame.

   `grid-template-rows` needs no number -- `1fr` is whatever the content
   actually is, so nothing can be clipped and the timing is proportional to the
   real distance. It animates off the main thread, so it does not stutter on a
   busy page.

   The cost is the wrapper: `0fr` collapses the ROW, but the row's content is
   still laid out inside it, so the child needs `overflow: hidden` and
   `min-height: 0` or it overflows the collapsed row instead of being hidden by
   it. Both are below, and without them this technique does not work at all --
   it looks like nothing is happening. */
html:not(.js) .contact-reveal-hold {
    /* No JS, no reveal: the button is pointless if nothing happens on click.
       The options list below is the thing that must still be reachable, and it
       is -- it was never hidden outside `.js`. */
    display: none;
}
html.js .contact-reveal-hold,
html.js .contact-reveal-options {
    display: grid;
    grid-template-rows: 1fr;
    transition: grid-template-rows var(--dur-3) ease, opacity var(--dur-3) ease,
                margin var(--dur-3) ease;
}
/* These two lines are what makes the technique work at all, and their absence
   looks like nothing happening rather than like a CSS mistake: `0fr` collapses
   the ROW, but the row's child is still laid out inside it, so a child without
   a clip spills out of the collapsed row and stays visible. The `min-height: 0`
   is the same problem in the other axis -- grid children default to
   `min-height: auto` and refuse to shrink below their content.

   `overflow: hidden` would also clip the browser's own focus ring on the phone
   and email links, because it clips the whole box, ring included. The ring is
   the only focus indicator these links have (nothing here overrides it), so
   clipping it would take a keyboard user's position away. `overflow: clip`
   with `overflow-clip-margin` is not used either: the margin is not animatable
   and the two would have to be kept in step. Instead the clip is only applied
   when the row is genuinely collapsed -- at rest, and mid-transition, where
   there is nothing to focus that is not already off-screen. */
html.js .contact-reveal-hold > *,
html.js .contact-reveal-options > * {
    min-height: 0;
}
html.js .contact-reveal.is-open .contact-reveal-hold > *,
html.js .contact-reveal:not(.is-open) .contact-reveal-options > * {
    overflow: hidden;
}
/* Once fully open there is no clipping left to do, so the ring is free. The
   transition has finished by then, so removing it here cannot be seen. */
html.js .contact-reveal.is-open .contact-reveal-options > * {
    overflow: visible;
}
html.js .contact-reveal.is-open .contact-reveal-hold {
    grid-template-rows: 0fr;
    opacity: 0;
    margin: 0;
    pointer-events: none;
}
html.js .contact-reveal-options {
    grid-template-rows: 0fr;
    opacity: 0;
    transform: translateY(-4px);
    pointer-events: none;
    margin: 0;
}
html.js .contact-reveal.is-open .contact-reveal-options {
    grid-template-rows: 1fr;
    opacity: 1;
    transform: none;
    margin-top: 10px;
    pointer-events: auto;
}
@media (prefers-reduced-motion: reduce) {
    .contact-reveal-hold,
    .contact-reveal-options {
        transition: none !important;
    }
}

/* ===== Admin dashboard ===== */

/* Dashboard header: the title stands alone, with the type scaling with the
   viewport. */
.dash-page .bk-head {
    display: block;
    margin-bottom: 16px;
}

.dash-page .bk-heading {
    font-size: clamp(1.25rem, 1rem + 2.4vw, 1.9rem);
}

/* Only rendered when something needs a decision. */
.dash-attention {
    display: flex;
    flex-wrap: nowrap;
    gap: 10px;
    margin-bottom: 18px;
}

.dash-attention-item {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: clamp(6px, 1vw, 10px);
    background: #fff3d6;
    border: 1px solid #efdfa8;
    border-radius: var(--radius);
    padding: 10px clamp(8px, 1.4vw, 14px);
    text-decoration: none;
    color: #8a6a00;
    font-size: clamp(0.74rem, 0.62rem + 1vw, 0.9rem);
    white-space: nowrap;
    transition: background var(--dur-1) ease;
}

.dash-attention-item:hover { background: #fdf0c8; }

.dash-attention-num {
    font-family: 'Fraunces', serif;
    font-size: clamp(1.05rem, 0.9rem + 1.4vw, 1.4rem);
    line-height: 1;
    color: #7a5c00;
}

.dash-attention-text {
    flex: 1 1 auto;
    min-width: 0;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dash-attention-go {
    font-size: 0.82rem;
    font-weight: 700;
    white-space: nowrap;
}

/* Today's groomer board: a column per groomer, side by side so a busy day
   fits without scrolling. */
.dash-board {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
    gap: 14px;
    align-items: start;
}

.dash-board-col {
    min-width: 0;
    background: #fdf9f4;
    border: 1px solid #f2e7dc;
    border-radius: 10px;
    padding: 10px 12px;
}

.dash-board-col.is-unassigned {
    background: #fff8ef;
    border-color: #efd9bf;
}

.dash-board-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 4px;
    padding-bottom: 6px;
    border-bottom: 1px solid #efe5db;
}

.dash-board-name {
    font-size: 0.9rem;
    font-weight: 700;
    color: var(--primary-dark);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dash-board-col.is-unassigned .dash-board-name { color: #a2601a; }

.dash-board-count {
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--muted);
}

/* Board rows live in narrow columns: let them wrap and give the time its
   natural width instead of the 74px list gutter. */
.dash-board .dash-slot-link { flex-wrap: wrap; gap: 3px 8px; }
.dash-board .dash-slot-when { flex: 0 0 auto; }

.dash-panel {
    background: var(--card-bg);
    border: 1px solid #efe5db;
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 18px;
    margin-bottom: 22px;
}

/* Today and Tomorrow as ONE card: a shared outer edge, with the two days as
   headed regions inside it rather than two more bordered boxes stacked down
   the page. On a phone the vertical cost is what matters -- two cards carried
   two paddings, two borders and two 22px gaps for what reads as one list. */
.dash-primary {
    background: var(--card-bg);
    border: 1px solid #efe5db;
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 18px;
    margin-bottom: 22px;
}

/* The day sections contribute no box of their own now; the wrapper is the
   card. `margin-bottom` is dropped so the wrapper, not the last section,
   governs the gap beneath. */
.dash-primary .dash-panel {
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    padding: 0;
    margin-bottom: 0;
}

.dash-primary .dash-panel + .dash-panel {
    margin-top: 18px;
    padding-top: 18px;
    border-top: 1px solid #efe5db;
}

.dash-panel-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 4px 12px;
    margin-bottom: 8px;
}

.dash-panel-title {
    font-size: 1.2rem;
    color: var(--primary-dark);
}

.dash-panel-count {
    font-size: 0.72rem;
    color: var(--muted);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.dash-group + .dash-group { margin-top: 4px; }

.dash-group-title {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    font-size: 0.88rem;
    color: var(--text);
    margin: 10px 0 2px;
    padding-bottom: 4px;
    border-bottom: 1px dashed #eadfd5;
}

.dash-group-count {
    color: var(--muted);
    font-size: 0.75rem;
    font-weight: 700;
}

.dash-slots {
    list-style: none;
    margin: 0;
}

.dash-slot { border-bottom: 1px solid #f5eee7; position: relative; }

.dash-slot:last-child { border-bottom: none; }

.dash-slot-link {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 9px 6px;
    border-radius: 6px;
    text-decoration: none;
    color: var(--text);
}

.dash-slot-link:hover { background: rgba(196, 129, 143, 0.07); }

.dash-slot-when {
    flex: 0 0 74px;
    display: flex;
    flex-direction: column;
    line-height: 1.3;
}

.dash-slot-time {
    font-size: 0.82rem;
    font-weight: 700;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}

.dash-slot-date {
    font-size: 0.7rem;
    font-weight: 700;
    color: var(--muted);
    text-transform: uppercase;
}

.dash-slot-body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.dash-slot-dog {
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dash-slot-meta {
    font-size: 0.78rem;
    color: var(--muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dash-empty {
    color: var(--muted);
    font-size: 0.9rem;
    padding: 8px 6px 4px;
}

.dash-month { margin-bottom: 22px; }

.dash-kpis {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 1px;
    margin: 6px 0 14px;
    background: #efe5db;
    border: 1px solid #efe5db;
    border-radius: var(--radius);
    overflow: hidden;
}

.dash-kpi {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
    padding: 8px 14px;
    background: #fdf9f4;
    text-decoration: none;
    color: var(--text);
}

.dash-kpi-link { transition: background var(--dur-1) ease; }

.dash-kpi-link:hover { background: #fff; }

.dash-kpi-value {
    font-family: 'Fraunces', serif;
    font-size: 1.05rem;
    line-height: 1.2;
    color: var(--primary-dark);
}

.dash-kpi-label {
    font-size: 0.68rem;
    color: var(--muted);
    font-weight: 600;
}

.dash-month-bottom {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 10px 26px;
}

.dash-subhead {
    font-size: 0.85rem;
    margin: 0 0 8px;
    color: var(--text);
}

.dash-subhead .admin-muted { font-weight: 400; }

.dash-status-links {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.dash-status-links a {
    text-decoration: none;
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--text);
    border: 1px solid #efe5db;
    border-radius: 999px;
    padding: 4px 12px;
    background: var(--card-bg);
}

.dash-status-links a strong { color: var(--primary-dark); margin-left: 4px; }

.dash-status-links a:hover { border-color: var(--primary); }

.dash-top-services ol {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.dash-top-services li {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    font-size: 0.85rem;
    border-bottom: 1px dashed #efe5db;
    padding-bottom: 4px;
}

.dash-top-services li:last-child {
    border-bottom: none;
    padding-bottom: 0;
}

.dash-top-name { font-weight: 700; }

.dash-top-meta {
    color: var(--muted);
    font-size: 0.78rem;
    white-space: nowrap;
}

@media (max-width: 1100px) {
    /* Once the KPI row wraps, drop the single-bar dividers for compact cards
       so a partly-filled last row doesn't show an empty divider block. */
    .dash-kpis {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 8px;
        background: transparent;
        border: none;
        overflow: visible;
    }
    .dash-kpi {
        border: 1px solid #efe5db;
        border-radius: var(--radius);
    }
    .dash-kpi-link:hover { border-color: var(--primary); }
    .dash-month-bottom { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 860px) {
    .dash-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
    .dash-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .dash-slot-link { flex-wrap: wrap; gap: 4px 12px; }
    .dash-slot-when { flex: 1 0 100%; }
}

/* ===== Dashboard: schedule row status badges ===== */
.dash-slot-badges {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    flex-shrink: 0;
    flex-wrap: wrap;
    justify-content: flex-end;
}

/* Status shown as colour, not words: a small filled dot per state (green for
   confirmed, amber for pending, and so on). The word survives for screen
   readers and as a native tooltip, so nothing is lost to a colour-blind or
   non-visual visitor. */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.dash-status {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    flex-shrink: 0;
    background: #c9cdd4;
}

.dash-status--pending { background: #e0a800; }
.dash-status--confirmed { background: #2e9e5b; }
.dash-status--completed { background: #4f46e5; }
.dash-status--cancelled { background: #d64545; }
.dash-status--reserved { background: #5b6472; }
.dash-status--arrived { background: #0369a1; }

/* ===== Customer-present modal ===== */
#customerHereModal .modal { max-width: 900px; }
.modal-loading { color: var(--muted); padding: 18px 4px; margin: 0; text-align: center; }

.cust-head { display: flex; gap: 14px; align-items: center; padding: 10px 0 14px; }
.cust-photo {
    width: 64px; height: 64px; border-radius: 10px; object-fit: cover;
    flex-shrink: 0; background: #f4ece3;
}
.cust-photo-fallback {
    display: flex; align-items: center; justify-content: center;
    font-size: 1.6rem; font-weight: 800; color: var(--primary);
    background: #f9e9de;
}
.cust-head-main { min-width: 0; }
.cust-name { font-size: 1.12rem; font-weight: 800; color: var(--primary-dark); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cust-chips { display: inline-flex; gap: 4px; align-items: center; flex-wrap: wrap; }

.cust-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    gap: 18px;
    align-items: start;
}
.cust-col { min-width: 0; }

.cust-detail-grid { padding: 8px 0 2px; border-top: 1px solid #efe5db; }
.detail-row {
    display: grid;
    grid-template-columns: 120px minmax(0, 1fr);
    gap: 4px 10px;
    padding: 5px 0;
    border-bottom: 1px dashed #f2e7dc;
    font-size: 0.9rem;
    align-items: baseline;
}
.detail-row:last-child { border-bottom: none; }
.detail-label { color: var(--muted); }
.detail-value { font-weight: 600; word-break: break-word; }
.cust-notes { white-space: pre-wrap; font-weight: 400; color: var(--text); }

.cust-section { margin: 14px 0 0; }
.cust-section h4 { margin: 0 0 8px; color: var(--primary-dark); }
.cust-section[hidden] { display: none !important; }

.cust-checkin-btn { font-size: 0.98rem; padding: 10px 14px; }
.cust-hint { margin: 6px 0 0; font-size: 0.78rem; }
.cust-arrived-line { margin: 2px 0 6px; }
.cust-action-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.cust-action-row .btn { margin: 0; }
.cust-links { border-top: 1px dashed #efe5db; padding-top: 10px; }

.cust-pay-col { background: #fdf9f4; border: 1px solid #efe5db; border-radius: 10px; padding: 14px; }
.cust-pay-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.cust-pay-head h4 { margin: 0; color: var(--primary-dark); }
.cust-balance { font-weight: 800; color: var(--primary-dark); }
.cust-pay-totals { border-top: 1px dashed #e7d9ca; padding-top: 6px; }
.cust-pay-line { display: flex; justify-content: space-between; gap: 10px; font-size: 0.9rem; padding: 3px 0; }
.cust-pay-line span:last-child { font-weight: 700; }
.cust-pay-list { list-style: none; margin: 6px 0 0; padding: 0; }
.cust-pay-list li {
    display: flex; justify-content: space-between; gap: 10px;
    font-size: 0.85rem; padding: 3px 0; color: var(--text);
}
.cust-pay-list li span:last-child { font-weight: 700; }
.cust-pay-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }

.btn-block { display: block; width: 100%; text-align: center; box-sizing: border-box; }

.cust-manual-pay { margin-top: 12px; padding-top: 10px; border-top: 1px dashed #e7d9ca; }
.cust-manual-pay[hidden] { display: none !important; }
.cust-manual-pay .btn { margin-top: 8px; }
.cust-helcim-pay { margin-top: 12px; padding-top: 10px; border-top: 1px dashed #e7d9ca; }
.cust-helcim-pay[hidden] { display: none !important; }

.cust-move-row { display: grid; grid-template-columns: 170px minmax(0, 1fr); gap: 10px; margin-bottom: 10px; align-items: end; }
.cust-move-row label {
    display: flex; flex-direction: column; gap: 4px;
    font-size: 0.78rem; font-weight: 700; color: var(--muted);
}
.cust-move-row input[type="date"],
.cust-move-row input[type="number"],
.cust-move-row select {
    width: 100%; box-sizing: border-box; padding: 7px 9px; font-size: 0.9rem;
    border: 1px solid #e2d6c8; border-radius: 8px; background: #fff; color: var(--text);
    font-weight: 500;
}
.cust-move-times-wrap { min-width: 0; }
.cust-move-times { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.cust-time-chip {
    border: 1px solid #e2d6c8; background: #fff; color: var(--text);
    border-radius: 999px; padding: 5px 12px; font-size: 0.85rem; font-weight: 600;
    cursor: pointer;
}
.cust-time-chip:hover { border-color: var(--primary); color: var(--primary); }
.cust-time-chip.is-selected { background: var(--primary); border-color: var(--primary); color: #fff; }
[data-move-status] { margin: 0 0 2px; font-size: 0.82rem; }

.status-badge.status-arrived { background: #e0f2fe; color: #0369a1; }

@media (max-width: 760px) {
    .cust-grid { grid-template-columns: minmax(0, 1fr); }
    .cust-move-row { grid-template-columns: minmax(0, 1fr); }
}

/* =========================================================
   Messages redesign — customer + staff
   ========================================================= */

.section--tight {
    padding: 28px 0 56px;
}

.chat-shell {
    max-width: 880px;
    margin: 0 auto;
}

/* --- Customer welcome hero --- */
.msg-hero {
    background: linear-gradient(135deg, #fbeae4 0%, #f8f0f9 55%, #eef4f8 100%);
    border: 1px solid #f2dcd3;
    border-radius: 20px;
    padding: 26px 28px;
    margin-bottom: 18px;
    box-shadow: var(--shadow);
}

.msg-hero-top {
    display: flex;
    align-items: center;
    gap: 16px;
}

.msg-hero-icon {
    flex: 0 0 auto;
    width: 52px;
    height: 52px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: #fff;
    color: var(--primary-dark);
    box-shadow: 0 2px 10px rgba(169, 106, 120, 0.18);
}

.msg-hero-icon svg {
    width: 28px;
    height: 28px;
}

.msg-hero-eyebrow {
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--primary-dark);
    margin: 0 0 2px;
}

.msg-hero h1 {
    font-size: 1.7rem;
    margin: 0;
    color: var(--text);
}

.msg-hero-copy {
    margin: 14px 0 0;
    color: #5d4e50;
    max-width: 60ch;
}

.msg-hero-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 20px;
    margin-top: 14px;
    font-size: 0.88rem;
    color: var(--muted);
}

.msg-hero-meta a {
    color: var(--muted);
}

/* --- Upcoming visit nudge --- */
.booking-nudge {
    display: flex;
    align-items: center;
    gap: 12px;
    background: #fff;
    border: 1px solid #ead9d0;
    border-radius: 14px;
    padding: 12px 16px;
    text-decoration: none;
    color: var(--text);
    margin-bottom: 18px;
    box-shadow: var(--shadow);
    transition: border-color var(--dur-1) ease, transform var(--dur-1) ease;
}

.booking-nudge:hover {
    border-color: var(--primary);
    transform: translateY(-1px);
}

.booking-nudge-label {
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--secondary);
    flex: 0 0 auto;
}

.booking-nudge-text {
    flex: 1 1 auto;
    font-size: 0.95rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.booking-nudge-arrow {
    color: var(--primary-dark);
    font-weight: 700;
    flex: 0 0 auto;
}

/* --- Chat window chrome --- */
.chat-window,
.chat-thread-window {
    background: var(--card-bg);
    border: 1px solid #efe5db;
    border-radius: 20px;
    box-shadow: var(--shadow);
    overflow: hidden;
    margin-bottom: 18px;
}

.chat-window-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    padding: 14px 20px 0;
}

.chat-window-title {
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.chat-window-sub {
    font-size: 0.85rem;
}

.chat-online-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: #63b37a;
    display: inline-block;
}

/* --- The conversation --- */
.chat-box {
    background: transparent;
    border-radius: 0;
    box-shadow: none;
    padding: 16px 20px 20px;
    max-height: 520px;
    overflow-y: auto;
    margin-bottom: 0;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.chat-msg {
    max-width: 80%;
}

.chat-bubble {
    padding: 11px 16px;
    border-radius: 18px;
    background: #f6ece6;
    color: var(--text);
    box-shadow: 0 1px 3px rgba(51, 40, 43, 0.06);
    line-height: 1.5;
}

.chat-msg.customer .chat-bubble {
    border-bottom-left-radius: 5px;
    background: #f3e2d9;
}

.chat-msg.staff {
    align-items: flex-end;
}

.chat-msg.staff .chat-bubble {
    background: linear-gradient(135deg, var(--primary-dark), var(--primary));
    color: #fff;
    border-bottom-right-radius: 5px;
}

.chat-meta {
    font-size: 0.72rem;
    color: var(--muted);
    margin-top: 5px;
    padding: 0 4px;
}

.chat-msg.staff .chat-meta {
    text-align: right;
}

/* --- Empty state --- */
.chat-empty {
    margin: auto;
    text-align: center;
    padding: 26px 10px;
    max-width: 520px;
}

.chat-empty-bubble {
    background: #fdf8f4;
    border: 1px dashed #e4cfc5;
    border-radius: 18px;
    padding: 22px 20px;
}

.chat-empty-title {
    font-family: 'Fraunces', serif;
    font-size: 1.15rem;
    margin: 0 0 6px;
    color: var(--text);
}

.chat-empty-sub {
    color: var(--muted);
    font-size: 0.92rem;
    margin: 0 0 14px;
}

.chat-quickchips {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
}

.chat-quickchip {
    appearance: none;
    border: 1px solid #e7c9bd;
    background: #fff;
    color: #7d4f45;
    border-radius: 999px;
    padding: 7px 14px;
    font: inherit;
    font-size: 0.84rem;
    cursor: pointer;
    transition: background var(--dur-1) ease, border-color var(--dur-1) ease;
}

.chat-quickchip:hover {
    background: #fbeae4;
    border-color: var(--primary);
}

/* --- Composer --- */
.chat-input-form {
    max-width: none;
}

.chat-input textarea {
    border-radius: 14px;
}

.chat-input .btn {
    border-radius: 999px;
}

/* --- Shared bits: staff inbox --- */
.chat-inbox-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 18px;
}

.chat-inbox-wrap {
    overflow: hidden;
    border-radius: 16px;
    border: 1px solid #efe5db;
    box-shadow: var(--shadow);
}

.chat-inbox-table {
    margin: 0;
}

.chat-inbox-table th {
    font-size: 0.72rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted);
    border-bottom: 1px solid #efe5db;
    padding: 12px 16px;
}

.chat-inbox-row td {
    padding: 14px 16px;
    vertical-align: middle;
    border-bottom: 1px solid #f6ede5;
    background: #fff;
}

.chat-inbox-row--unread td {
    background: #fdf7f3;
}

.chat-person {
    display: flex;
    align-items: center;
    gap: 12px;
}

.chat-avatar {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: linear-gradient(135deg, #e9b7a2, var(--primary));
    color: #fff;
    font-weight: 700;
    font-size: 0.95rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.chat-avatar--lg {
    width: 56px;
    height: 56px;
    font-size: 1.25rem;
}

.chat-person-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.chat-person-name {
    font-weight: 700;
    color: var(--text);
}

.chat-person-sub {
    font-size: 0.82rem;
    color: var(--muted);
}

.chat-preview-cell {
    min-width: 260px;
}

.chat-preview {
    color: var(--muted);
    display: block;
    font-size: 0.9rem;
}

.chat-preview--unread {
    color: var(--text);
    font-weight: 600;
}

.chat-next-chip {
    display: inline-block;
    margin-top: 6px;
    background: #eef4f8;
    color: #41647c;
    border-radius: 999px;
    padding: 3px 10px;
    font-size: 0.75rem;
}

.chat-badge--inbox {
    font-size: 0.8rem;
}

.chat-inbox-actions-col {
    width: 190px;
}

.chat-inbox-actions-inner {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
}

.chat-inbox-empty {
    text-align: center;
    padding: 70px 20px;
    border: 1px dashed #e4cfc5;
    border-radius: 20px;
    background: #fff;
}

.chat-inbox-empty-icon {
    font-size: 2.4rem;
    margin-bottom: 8px;
}

.chat-inbox-empty h3 {
    font-size: 1.25rem;
    margin: 0 0 4px;
}

/* --- Staff thread customer card --- */
.chat-thread-toolbar {
    margin-bottom: 14px;
}

.chat-thread-customer {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    background: linear-gradient(135deg, #fdf6f1, #f6f0f8);
    border: 1px solid #f0dfd6;
    border-radius: 18px;
    padding: 16px 18px;
    margin-bottom: 16px;
}

.chat-thread-customer-main {
    flex: 1 1 auto;
    min-width: 200px;
}

.chat-thread-customer-name {
    font-size: 1.25rem;
    margin: 0;
}

.chat-thread-customer-links {
    font-size: 0.84rem;
    margin-top: 2px;
}

.chat-thread-customer-links a {
    color: var(--secondary);
}

.chat-next-booking {
    flex: 0 1 auto;
    max-width: 360px;
    background: #fff;
    border: 1px solid #ead9d0;
    border-radius: 14px;
    padding: 9px 13px;
    text-decoration: none;
    color: var(--text);
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.chat-next-booking-label {
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--secondary);
}

.chat-next-booking-text {
    font-size: 0.86rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.chat-thread-window {
    background: #fff;
}

/* --- Structured / system messages (used by proposal flow later) --- */
.chat-msg.system {
    align-self: center;
    max-width: 92%;
    align-items: center;
}

.chat-msg.system .chat-bubble {
    background: #f4ede8;
    color: var(--muted);
    font-size: 0.8rem;
    border-radius: 999px;
    text-align: center;
}

.chat-card {
    display: block;
    background: #fff;
    border: 1px solid #eadfd7;
    border-radius: 16px;
    padding: 14px 16px;
    box-shadow: 0 1px 4px rgba(51, 40, 43, 0.05);
}

.chat-card-title {
    font-family: 'Fraunces', serif;
    font-size: 1rem;
    margin: 0 0 8px;
}

.chat-card-row {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    font-size: 0.9rem;
    padding: 3px 0;
}

.chat-card-row dt {
    color: var(--muted);
}

.chat-card-row dd {
    margin: 0;
    font-weight: 600;
}

.chat-card-actions {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 12px;
}

@media (max-width: 860px) {
    .chat-inbox-table,
    .chat-inbox-table tbody {
        display: block;
    }

    .chat-inbox-table thead {
        display: none;
    }

    .chat-inbox-table tr,
    .chat-inbox-table td {
        display: block;
        width: 100%;
    }

    .chat-inbox-actions-inner {
        justify-content: flex-start;
    }

    .chat-next-booking {
        max-width: none;
    }
}

/* ===== Pricing table on a phone (<=640px) =====
   Five columns (Service + S/M/L/XL) cannot fit a 375px screen at desktop
   padding, so the table used to scroll sideways -- and the add-ons made that
   scroll pointless, because their price is identical at every size. Shrinking
   the padding and type here fits the remaining (size-varying) rows on screen
   with no horizontal scroll at all; the flat-rate services are collapsed to a
   single price in the markup, so they contribute only two columns. */
@media (max-width: 640px) {
    .table-wrap {
        padding: 6px;
        overflow-x: visible;
    }

    .size-table thead th {
        font-size: 0.82rem;
        padding: 10px 4px;
    }

    .size-table tbody td {
        padding: 12px 4px;
        font-size: 0.92rem;
    }

    .size-label {
        font-size: 0.88rem;
        text-align: left;
        padding-right: 8px;
    }
}

/* ===== Mobile modal fixes (<=640px) ===== */
@media (max-width: 640px) {
    /* Let the header reflow instead of squeezing title + close + steps. */
    .modal-header {
        flex-wrap: wrap;
        row-gap: 8px;
    }

    /* Drop the step indicator onto its own full-width line and keep the close
       button beside the title (order moves it after the DOM-later button). */
    .wizard-steps {
        order: 3;
        flex: 1 0 100%;
        gap: 10px;
    }

    /* Booking wizard: hide step text labels so the dots fit a phone width. */
    .wizard-dot-label {
        display: none;
    }

    /* Booking detail: stack label above value instead of a fixed label column. */
    .detail-grid,
    .detail-row {
        grid-template-columns: 1fr;
        gap: 2px 0;
    }
}

/* ---------------------------------------------------------------------------
   Admin: Booking Rules page (split view: rule editor tabs + live preview)
   --------------------------------------------------------------------------- */
.rules-messages { margin-bottom: 14px; }

.rules-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    gap: 22px;
    align-items: start;
}

@media (max-width: 1024px) {
    .rules-layout { grid-template-columns: 1fr; }
}

.rules-editors,
.rules-preview {
    background: var(--card-bg);
    border: 1px solid #efe5db;
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 20px 22px;
    min-width: 0;
}

.rules-editors-head h2,
.rules-preview-head h2 {
    font-family: 'Fraunces', serif;
    font-size: 1.25rem;
    margin: 0 0 4px;
}

.rules-editors-head p,
.rules-preview-head p {
    margin: 0 0 16px;
    color: var(--muted);
    font-size: 0.9rem;
}

/* Week navigation for the live calculator. */
.rules-week-nav {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin: 0 0 16px;
}

.rules-week-label {
    font-weight: 600;
    font-size: 0.9rem;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.rules-week-badge {
    background: var(--bg);
    color: var(--muted);
    border-radius: 999px;
    padding: 1px 8px;
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.rules-tabs { margin-bottom: 18px; }

.rules-service-tabs { margin-bottom: 12px; }

/* Size selector: small pill row, distinct from the underline tabs. */
.rules-size-row {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-bottom: 14px;
}

.rules-size-btn {
    appearance: none;
    background: #faf5ef;
    border: 1px solid #efe5db;
    border-radius: 999px;
    padding: 5px 14px;
    font: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--muted);
    cursor: pointer;
}

.rules-size-btn:hover { color: var(--primary-dark); }

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

.rules-panel[hidden],
.rules-preview-block[hidden] { display: none; }

.rules-preview-host { min-height: 80px; position: relative; }

/* While a service/size switch is in flight, htmx adds .htmx-request to the
   indicator (the host). Without a cue the table just blinks, which reads like
   a page reload rather than an in-place update. */
.rules-preview-host.htmx-request > * { opacity: .35; transition: opacity var(--dur-1) ease; }
.rules-preview-host.htmx-request::after {
    content: "Updating…";
    position: absolute;
    top: 12px;
    left: 50%;
    transform: translateX(-50%);
    font-size: .85rem;
    color: var(--muted);
}

.rules-slots {
    display: flex;
    flex-wrap: wrap;
    gap: 3px;
}
.rules-slot {
    display: inline-block;
    background: #fff;
    border: 1px solid #cfe0d6;
    border-radius: 4px;
    padding: 1px 5px;
    white-space: nowrap;
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
}
/* Blocked starts stay in place but greyed out, so the timeline shape reads.
   Each carries a coloured left edge naming the rule that blocked it, so the
   table says *why* at a glance before you even hover. */
.rules-slot--out {
    color: #b3aaa4;
    background: #f4f0ec;
    border-color: #e7ddd4;
    text-decoration: line-through;
    border-left-width: 3px;
    border-left-style: solid;
}

/* Rose: overlaps a booking, or capacity is full. */
.rules-slot--booked { border-left-color: #c4818f; }

/* Amber: the daily break runs through this time. */
.rules-slot--break { border-left-color: #d8a24a; }

/* Slate: too soon — inside the same-day cut-off. */
.rules-slot--cutoff { border-left-color: #8ea3b8; }

/* An offered start is green, matching its hover card. */
.rules-slot--open { border-color: #bcd8c9; background: #f3faf5; }

/* Styled hover card for a start time, replacing the bare browser tooltip.
   position: fixed so it sits above everything and is placed from the chip's
   viewport rect (see booking_rules.js). */
.rules-slot-tip {
    position: fixed;
    z-index: 60;
    width: max-content;
    max-width: 260px;
    padding: 10px 13px;
    border-radius: 10px;
    background: #fffdfb;
    border: 1px solid #eadfd4;
    box-shadow: 0 12px 30px rgba(74, 51, 35, 0.16);
    pointer-events: none;
    font-size: 0.82rem;
    line-height: 1.35;
    animation: rules-tip-in var(--dur-1) ease-out;
}

.rules-slot-tip--ok { border-color: #bcd8c9; }
.rules-slot-tip--bad { border-color: #e3c6cf; }

.rules-slot-tip-time {
    margin: 0;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--text);
}

.rules-slot-tip-status {
    margin: 2px 0 0;
    font-family: 'Fraunces', serif;
    font-size: 0.92rem;
}

.rules-slot-tip--ok .rules-slot-tip-status { color: #3f7d5c; }
.rules-slot-tip--bad .rules-slot-tip-status { color: #a8505f; }

/* Match the slot's coloured left edge so the card and the chip agree. */
