/*
 * hp-booking.css — the native 1:1 booking section.
 * HORIZON-20260901-080. Scope: docs/native-booking-calendar-feasibility-2026-09-01.md
 *
 * ⭐⭐ PHONE FIRST, AND NOT AS A FIGURE OF SPEECH. Picking a time is the primary
 * action on this page and almost every fan does it on a phone, one-handed. So
 * the base rules ARE the small-screen rules and the only media query widens
 * things; there is no desktop layout being squeezed down.
 *
 * ⛔⛔ TOKENS ONLY. Every colour, radius and step is a var(--hp-*) from the
 * tenant's skin, because this renders on every skin in the pack library and not
 * just dark-luxury. A hardcoded colour here is a section that looks correct on
 * one tenant and wrong on the rest. Fallbacks are given for the two shadows and
 * the header offset only, which some skins legitimately do not define.
 *
 * ⛔ SELF-NAMESPACED (.hp-booking*) AND NO DEPENDENCY ARRAY on the enqueue.
 * `wp_enqueue_style()` SILENTLY DROPS a stylesheet whose dependency handle is
 * unregistered — the mechanism that left the CMP banner unstyled on a live site
 * for three weeks. Nothing here needs an ordering guarantee.
 */

/* ── The slot picker ─────────────────────────────────────────────────────── */

.hp-booking-slots {
    margin-top: var(--hp-sp-3);
}

/*
 * ⭐ STICKY DAY HEADINGS. A creator with wide windows produces a long column of
 * times, and scrolling one loses which day you are in — the exact moment
 * somebody books Thursday believing it is Tuesday. The heading holds its place
 * until the next day pushes it out.
 *
 * ⛔ `top` clears the site header. Themes that pin a header set --hp-header-h;
 * those that do not fall back to 0 and the heading sits at the viewport edge,
 * which is correct for them. ⛔ No ancestor of this may set `overflow: hidden`
 * or sticky silently stops working with no error anywhere.
 */
.hp-booking-day {
    margin-top: var(--hp-sp-5);
}

/* ⛔ `:first-of-type`, NOT `:first-child`. The fieldset's first child is its
   `<legend>`, so `:first-child` matched nothing and the first day sat a full
   step lower than every other. */
.hp-booking-day:first-of-type {
    margin-top: var(--hp-sp-2);
}

.hp-booking-day__heading {
    position: sticky;
    top: var(--hp-header-h, 0px);
    z-index: 2;
    margin: 0 0 var(--hp-sp-2);
    padding: var(--hp-sp-2) 0;
    background: var(--hp-bg-surface);
    font-size: var(--hp-text-sm);
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--hp-text-muted);
    border-bottom: 1px solid var(--hp-border);
}

/*
 * ⭐ auto-fill with a 6.5rem floor: three across at 375px, more as the screen
 * grows, and never a lone stretched chip on a row of its own.
 */
.hp-booking-day__times {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr));
    gap: var(--hp-sp-2);
}

/*
 * ⛔⛔ THUMB-SIZED, AND 48px IS THE FLOOR NOT THE TARGET. Anything smaller is a
 * mis-tap, and a mis-tap here books the wrong evening rather than opening the
 * wrong page. The whole chip is the target, not a 20px circle beside it.
 *
 * ⭐ THE LABEL IS A BARE WRAPPER AND THE CHIP IS THE SPAN, so the selected state
 * is a plain ADJACENT SIBLING rule, `input:checked + span`. An earlier version
 * styled the label and reached the checked input with `:has()`, which also
 * worked; the sibling form is kept because it needs no `:has()` support at all
 * and there is nothing here that wants it.
 *
 * ⛔⛔ `position: relative` IS LOAD-BEARING AND IS NOT A STYLE CHOICE. The
 * clipped radio below is `position: absolute`, and without a positioned ancestor
 * it resolves against the initial containing block instead — measured live, that
 * put a 375px-wide input at x=132 and pushed the whole PAGE to 507px of
 * horizontal scroll on a 375px phone. The input is invisible, so the only
 * symptom is a page that slides sideways with nothing in the margin.
 */
.hp-booking-slot {
    position: relative;
    display: block;
    cursor: pointer;
}

.hp-booking-slot__time {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 48px;
    padding: var(--hp-sp-2) var(--hp-sp-3);
    border: 1px solid var(--hp-border);
    border-radius: var(--hp-r-md);
    background: var(--hp-bg-raised);
    color: var(--hp-text);
    font-size: var(--hp-text-base);
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
    text-align: center;
    transition: border-color var(--hp-dur, 150ms) var(--hp-ease, ease),
                background-color var(--hp-dur, 150ms) var(--hp-ease, ease),
                color var(--hp-dur, 150ms) var(--hp-ease, ease);
}

/*
 * ⛔ CLIPPED, NOT `display: none` AND NOT `visibility: hidden`. Both of those
 * take the input out of the accessibility tree and out of keyboard focus order,
 * which would leave the picker unusable by keyboard and unreadable by a screen
 * reader — while looking perfect in a screenshot.
 *
 * ⛔⛔ TWO CLASSES (0-2-0) AND `max-width`, BECAUSE A SINGLE CLASS LOSES.
 * GeneratePress and the child themes size every form control through selector
 * lists like `input[type="radio"]`, which is 0-1-1 and BEATS a lone `.class` at
 * 0-1-0. Measured live: `width: 1px` was overridden and this input computed to
 * **375px**, which is what escaped the label and gave the page 132px of
 * horizontal scroll. `max-width` closes the same hole from the other side, so a
 * theme that sizes with `width: 100%` cannot reopen it.
 * ⛔ Not `!important` — same reasoning as the GeneratePress note in memory:
 * specificity is the tool, and `!important` here would just move the fight.
 */
.hp-booking-slot .hp-booking-slot__input {
    position: absolute;
    top: 0;
    left: 0;
    width: 1px;
    min-width: 0;
    max-width: 1px;
    height: 1px;
    min-height: 0;
    max-height: 1px;
    margin: 0;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
    appearance: none;
    -webkit-appearance: none;
}

.hp-booking-slot:hover .hp-booking-slot__time {
    border-color: var(--hp-border-strong);
}

/*
 * ⭐ FOCUS IS DRAWN ON THE LABEL, because the input it belongs to is clipped.
 * Without this, tabbing through the picker moves an invisible focus ring and the
 * keyboard user cannot see where they are. `:focus-visible` on the input, styled
 * on the label via `:has`, with a plain `:focus-within` fallback underneath for
 * engines that do not support it.
 */
.hp-booking-slot:focus-within .hp-booking-slot__time {
    outline: 2px solid var(--hp-gold, currentColor);
    outline-offset: 2px;
}

/*
 * THE SELECTED STATE. ⛔ It must survive on a skin with no gold: `--hp-gold` is
 * the accent on every pack in the library, and `currentColor` is the honest
 * fallback if a future pack drops it — a chip that is merely inverted still
 * reads as chosen.
 */
.hp-booking-slot__input:checked + .hp-booking-slot__time {
    border-color: var(--hp-gold, currentColor);
    background: var(--hp-gold-muted, var(--hp-bg-overlay));
    color: var(--hp-text);
    font-weight: 700;
    box-shadow: var(--hp-shadow-card, none);
}

/* ── Around the picker ───────────────────────────────────────────────────── */

.hp-booking-request__zone {
    margin-top: var(--hp-sp-4);
    font-size: var(--hp-text-sm);
    color: var(--hp-text-muted);
}

/*
 * ⛔⛔ LOAD-BEARING COPY, NOT A CAPTION. This line is the difference between a
 * fan who knows their time is held and one who turns up twice or not at all.
 * It must stay legible: no opacity trick that can drop it below contrast on a
 * light skin, and a muted token rather than a faded copy of the body colour.
 */
.hp-booking-request__reassurance {
    margin: 0;
    text-align: center;
    font-size: var(--hp-text-sm);
    color: var(--hp-text-muted);
}

/*
 * ⭐ The submit is full width on a phone and stays full width. It is the only
 * action on the form, and a centred pill with dead space either side reads as
 * one option among several.
 */
.hp-booking-request__submit {
    width: 100%;
    justify-content: center;
    min-height: 48px;
}

.hp-booking-alert {
    margin-bottom: var(--hp-sp-6);
    padding: var(--hp-sp-4) var(--hp-sp-5);
    border-radius: var(--hp-r-md);
    border: 1px solid var(--hp-border);
    color: var(--hp-text);
}

.hp-booking-alert--good {
    background: var(--hp-success-muted);
    border-color: var(--hp-success);
}

.hp-booking-alert--bad {
    background: var(--hp-error-muted);
    border-color: var(--hp-error);
}

/* ── Wider screens ───────────────────────────────────────────────────────── */

@media (min-width: 48em) {
    .hp-booking-day__times {
        grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr));
    }
}

/*
 * ⛔ Motion is a preference, not a default. The only transitions here are colour
 * changes, but honouring this costs one rule and the alternative is a section
 * that ignores an accessibility setting the rest of the site respects.
 */
@media (prefers-reduced-motion: reduce) {
    .hp-booking-slot {
        transition: none;
    }
}
