/* ==========================================================================
   Table booking chart
   Loaded only by booking.html, so it stays out of the other pages' payload.
   ========================================================================== */

.hidden {
    display: none !important;
}

/* ── Status palette ───────────────────────────────────────────────────────── */

/* One definition per status, read by everything that shows one: the table ring,
   the chairs, the label, the glyph and the legend swatch. The three dark values
   also carry the label as text, so each is dark enough to read on the cream page
   background — 4.8:1, 5.3:1 and 4.8:1, all past the 4.5:1 minimum. */
:root {
    --booking-free:         #2E7D32;
    --booking-busy:         #C62828;
    --booking-blocked:      #6E6E6E;
    --booking-free-tint:    rgba(46, 125, 50, 0.10);
    --booking-busy-tint:    rgba(198, 40, 40, 0.09);
    --booking-blocked-tint: rgba(110, 110, 110, 0.09);
}

.table-cell.is-free,
.swatch-free {
    --status: var(--booking-free);
    --tint: var(--booking-free-tint);
    --tint-hover: rgba(46, 125, 50, 0.20);
}

.table-cell.is-busy,
.swatch-busy {
    --status: var(--booking-busy);
    --tint: var(--booking-busy-tint);
}

.table-cell.is-blocked,
.swatch-blocked {
    --status: var(--booking-blocked);
    --tint: var(--booking-blocked-tint);
}

.booking-section {
    padding: 60px 20px;
    background: var(--light-bg);
    min-height: 60vh;
}

.booking-section h1 {
    text-align: center;
    font-size: 2.5rem;
    color: var(--primary-color);
    margin-bottom: 1rem;
}

.booking-intro {
    text-align: center;
    color: var(--text-light);
    max-width: 620px;
    margin: 0 auto 2rem;
    line-height: 1.6;
}

/* ── Legend ───────────────────────────────────────────────────────────────── */

.booking-legend {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: 1.5rem;
    margin-bottom: 1.5rem;
}

.legend-item {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.9rem;
    color: var(--text-color);
    font-weight: 500;
}

/* Drawn the same way as a table on the chart — ring, tint, glyph — so the key
   and the thing it explains look alike. */
.legend-swatch {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border: 2px solid var(--status);
    border-radius: 50%;
    background: var(--tint);
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--status);
}

/* Dashed, matching how the chart rings a table that is out of service. */
.swatch-blocked {
    border-style: dashed;
}

/* ── Window label ─────────────────────────────────────────────────────────── */

.booking-window {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.booking-window-label {
    font-weight: 600;
    color: var(--primary-color);
    font-size: 1.05rem;
    text-align: center;
}

.btn-refresh {
    background: var(--white);
    border: 2px solid var(--border-color);
    border-radius: var(--radius-full);
    padding: 0.5rem 1.25rem;
    font-family: inherit;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text-color);
    cursor: pointer;
    min-height: 40px;
    transition: all var(--transition-fast);
}

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

.btn-refresh:disabled {
    opacity: 0.55;
    cursor: default;
}

.booking-status {
    text-align: center;
    color: var(--text-light);
    min-height: 1.5rem;
    margin-bottom: 1.5rem;
    font-size: 0.95rem;
}

.booking-status.is-error {
    color: #C62828;
    font-weight: 500;
}

/* ── The floor plan ───────────────────────────────────────────────────────── */

.table-grid {
    display: grid;
    /* --cols and --rows are the canvas the admin set, in cells. Both are tracks
       rather than a table count: the plan has gaps in it, and a wide table covers
       two columns. */
    grid-template-columns: repeat(var(--cols, 4), minmax(0, 1fr));
    /* --cell-h is measured by sizeGrid() and is the column width, which is what a
       square cell's height already works out to. A row made only of wide tiles has
       no square tile to set that height, so the grid is told it instead. */
    grid-template-rows: repeat(var(--rows, 4), var(--cell-h, auto));
    gap: clamp(0.5rem, 1.5vw, 1rem);
    /* No max-width and no margin: both moved to .room-frame, which wraps this grid
       along with the room's walls. Kept here they would cap the grid inside a
       full-width frame and the walls would drift away from the plan's edges. */
}

/* The room frame's metrics are the booking page's, not the admin's. The frame
   itself — the walls, the patterns, the label — is shared; only the width differs. */
.room-frame {
    max-width: 780px;
    margin: 0 auto 2rem;
}

.table-cell {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 1 / 1;
    padding: 0;
    border: none;
    /* Nothing is drawn behind the table — no tile, no plate, just the table and
       its chairs sitting on the page. A <button> would otherwise paint its own
       grey, so the background is cleared explicitly. */
    background: none;
    /* Round, so the focus ring circles the table instead of boxing it. */
    border-radius: 50%;
    font-family: inherit;
    font-size: clamp(0.75rem, 1.6vw, 0.95rem);
    font-weight: 700;
    color: var(--status);
    cursor: pointer;
    transition: transform var(--transition-fast);

    /* Chair orbit, as a share of the chair's own width. A 24% chair at 125% sits
       30% out — its seat front just clear of the 27% table rim — and its back
       reaches 42%, still inside the cell. */
    --orbit: 125%;
}

/* ── Table top ───────────────────────────────────────────────────────────── */

.table-top {
    position: relative;
    z-index: 1;             /* over the chair ring, so the rim stays unbroken */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.05rem;
    width: 54%;
    height: 54%;
    border: 3px solid var(--status);
    border-radius: 50%;
    background: var(--tint);
}

/* Dashed rather than solid, so "out of service" doesn't rest on the grey. */
.table-cell.is-blocked .table-top {
    border-style: dashed;
}

.table-cell .cell-label {
    line-height: 1.05;
}

/* Only rendered past six seats, where the ring stops being countable. Bare text
   is enough now: on a light tint the label colour is legible on its own. */
.table-cell .cell-seats {
    font-size: 0.6em;
    font-weight: 700;
    line-height: 1;
}

/* The glyph carries the same meaning as the colour, so the chart still reads
   correctly with red-green colour deficiency. */
.cell-glyph {
    font-size: 0.85em;
    line-height: 1;
}

.cell-glyph::before {
    content: '\2713';
}

.table-cell.is-busy .cell-glyph::before,
.table-cell.is-blocked .cell-glyph::before {
    content: '\2717';
}

/* ── Chairs ──────────────────────────────────────────────────────────────── */

/* One span per seat. --n is how many chairs are on the ring, --i is this chair's
   index. Rotate out from the centre, then step back along the orbit. The
   rotation is kept rather than undone: it swings each chair's flat front round
   to face the table, so the ring reads as chairs however many there are. */
.chairs {
    position: absolute;
    inset: 0;
    pointer-events: none;
    --step: calc(360deg / var(--n, 4));
}

/* The box is square and invisible — it does nothing but carry the seat around
   the orbit. The chair itself is the half-disc inside its top half: round across
   the back, flat along the front. Sitting on the box's centre line, that front
   lands exactly at --orbit and the back half a chair width further out. */
.chair {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 24%;
    height: 24%;
    /* This chair's angle on the ring. Named because the wide-table rule below has to
       read it directly — rotating a square about the centre cannot produce an
       ellipse, so that path places the chair from the angle instead. */
    --a: calc(var(--i) * var(--step));
    transform:
        translate(-50%, -50%)
        rotate(var(--a))
        translateY(calc(var(--orbit) * -1));
}

.chair::before {
    content: '';
    position: absolute;
    inset: 0 0 50% 0;
    border: 2px solid var(--status);
    border-radius: 50% 50% 0 0 / 100% 100% 0 0;
    background: var(--tint);
}

/* ── Wide tables ─────────────────────────────────────────────────────────── */

/* A table two columns wide is a wider table, not a bigger one, and that is the whole
   rule: every percentage stays exactly as it was, and only the axis it is measured
   against changes. The top keeps its 54% width and 54% height, so across two columns
   it becomes an ellipse twice as wide as it is tall — a 6-top seating six along a long
   table rather than six round a small one. */
.table-cell.is-wide {
    /* aspect-ratio has to go. Left on, a two-track cell becomes twice as tall, and
       since every child is a percentage of the cell, releasing it is what makes the
       table wider instead of everything inside it bigger. The height then comes from
       the grid's --cell-h. The span itself is inline, as `C / span 2`. */
    aspect-ratio: auto;
}

/* A chair on the round ring is 24% of a square cell. A wide cell is two columns
   across and one column tall, so the same chair is 12% across and 24% down — both
   come to roughly 24% of a single column, which keeps a wide table's chairs the size
   of everyone else's. Unguarded: the sizing alone needs no trigonometry, it just
   leaves the chairs sitting on the round ring's smaller circle. */
.table-cell.is-wide .chair {
    width: 12%;
    height: 24%;
}

/* Placing the ring does need the angle itself. Rotating a square about its centre
   traces a circle, and the table is an ellipse now, so only a sine and a cosine can
   follow it. Both keep the ring's original 30% orbit, measured against each axis in
   turn: 30% against a 27% rim is the same 3% of clearance the round ring documents,
   so the chairs clear the ellipse exactly as they clear the circle. --a still runs
   clockwise from north as it does round the ring, so the chair's own rotation is
   unchanged — only where it sits differs. */
@supports (width: calc(1px * cos(0deg))) {
    .table-cell.is-wide .chair {
        left: calc(50% + sin(var(--a)) * 30%);
        top:  calc(50% - cos(var(--a)) * 30%);
        transform: translate(-50%, -50%) rotate(var(--a));
    }
}

/* ── Status ──────────────────────────────────────────────────────────────── */

.table-cell.is-busy,
.table-cell.is-blocked {
    cursor: not-allowed;
}

.table-cell.is-free:hover,
.table-cell.is-free:focus-visible {
    transform: translateY(-3px);
}

/* Table and chairs lean towards the cursor together. */
.table-cell.is-free:hover .table-top,
.table-cell.is-free:hover .chair::before {
    background: var(--tint-hover);
}

.table-cell:focus-visible {
    outline: 3px solid var(--primary-color);
    outline-offset: 4px;
}

/* With no plate to outline, the selection rings the table and its chairs. */
.table-cell.is-selected::after {
    content: '';
    position: absolute;
    inset: 0;
    border: 2px solid var(--primary-color);
    border-radius: 50%;
    box-shadow: 0 0 0 4px rgba(139, 69, 19, 0.12);
    pointer-events: none;
}

.booking-hint {
    text-align: center;
    color: var(--text-light);
    font-size: 0.9rem;
}

.booking-hint a {
    color: var(--primary-color);
    font-weight: 600;
}

/* ── Modal ────────────────────────────────────────────────────────────────── */

/* Above the navbar, which sits at z-index 1000 */
.modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(0, 0, 0, 0.55);
    overflow-y: auto;
}

.modal {
    position: relative;
    background: var(--white);
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-hover);
    width: 100%;
    max-width: 520px;
    max-height: 92vh;
    overflow-y: auto;
    padding: 2rem;
    animation: bookingModalIn 200ms ease-out;
}

@keyframes bookingModalIn {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
    .modal { animation: none; }
}

.booking-modal h2 {
    color: var(--primary-color);
    font-size: 1.5rem;
    margin-bottom: 1.5rem;
    padding-right: 2rem;
}

.modal-close {
    position: absolute;
    top: 0.75rem;
    right: 0.75rem;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    border-radius: var(--radius-full);
    font-size: 1.75rem;
    line-height: 1;
    color: var(--text-light);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.modal-close:hover {
    background: var(--light-bg);
    color: var(--primary-color);
}

.form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1rem;
}

.form-group .optional {
    font-weight: 400;
    color: var(--text-light);
    font-size: 0.85em;
}

/* Honeypot — off-screen rather than display:none, which some bots skip */
.hp-field {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.btn-block {
    width: 100%;
}

/* styles.css has no disabled treatment for .btn (admin.css does, but this page
   doesn't load it), so a blocked submit would otherwise look clickable. */
.btn:disabled,
.btn[disabled] {
    opacity: 0.55;
    cursor: not-allowed;
    box-shadow: none;
}

.modal-error {
    background: #FDECEA;
    border: 1px solid #F5C6C2;
    border-left: 4px solid #C62828;
    color: #8E1F1A;
    padding: 0.75rem 1rem;
    border-radius: var(--radius-sm);
    margin-bottom: 1rem;
    font-size: 0.9rem;
    line-height: 1.5;
}

/* ── Submit bar ───────────────────────────────────────────────────────────── */

/* The form is taller than the modal on a phone, so the last step sat below the fold:
   the customer filled everything in and then had to go looking for the button, and an
   error raised by a rejected submit appeared above the part of the form they had just
   scrolled past. Holding the button (and its error) at the foot of the modal keeps the
   end of the form reachable from wherever it is being read.

   The modal's own bottom padding is handed to this bar — .modal is the scroll container,
   and a sticky box can never travel beyond its containing block, so that padding is
   exactly the gap the bar could not cross. --modal-pad-x mirrors the modal's horizontal
   padding in each breakpoint, and the bar cancels it to bleed to the edges: the form
   then passes beneath an opaque plate instead of past a button floating over text. */
.booking-modal {
    --modal-pad-x: 2rem;
    padding-bottom: 0;
}

.booking-submit {
    position: sticky;
    bottom: 0;
    z-index: 1;
    margin: 0 calc(-1 * var(--modal-pad-x));
    padding: 0.85rem var(--modal-pad-x);
    background: var(--white);
    border-top: 1px solid var(--border-color);
    /* Bleeding to the modal's edges puts the bar's square corners over the modal's
       rounded ones, and the white would spill into the dark overlay behind them. */
    border-radius: 0 0 var(--radius-xl) var(--radius-xl);
}

/* The bar sits at the modal's edge now, so the line below it supplies the breathing
   room .modal's own padding used to. */
.booking-terms {
    padding-bottom: 1rem;
}

.booking-slot-note {
    font-size: 0.9rem;
    line-height: 1.5;
    margin: -0.5rem 0 1.25rem;
    padding: 0.7rem 0.9rem;
    border-radius: var(--radius-sm);
    background: var(--light-bg);
    color: var(--text-color);
}

.booking-slot-note.is-free {
    background: #E8F5E9;
    color: #1B5E20;
}

.booking-slot-note.is-taken {
    background: #FDECEA;
    color: #8E1F1A;
}

.booking-alts {
    list-style: none;
    margin: -0.75rem 0 1.25rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.booking-alts li {
    margin: 0;
}

.booking-alts button {
    background: var(--white);
    border: 2px solid var(--border-color);
    border-radius: var(--radius-full);
    padding: 0.35rem 0.9rem;
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-color);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.booking-alts button:hover {
    border-color: var(--primary-color);
    color: var(--primary-color);
}

.booking-terms {
    text-align: center;
    font-size: 0.82rem;
    color: var(--text-light);
    margin-top: 0.9rem;
    line-height: 1.5;
}

/* ── Result panel (replaces the form after submitting) ────────────────────── */

.booking-result {
    text-align: center;
    padding: 1rem 0;
}

.booking-result .result-icon {
    font-size: 3rem;
    line-height: 1;
    margin-bottom: 1rem;
}

.booking-result.is-success .result-icon { color: #2E7D32; }
.booking-result.is-pending .result-icon { color: var(--secondary-color); }

.booking-result h3 {
    color: var(--primary-color);
    font-size: 1.35rem;
    margin-bottom: 0.75rem;
}

.booking-result p {
    color: var(--text-color);
    line-height: 1.6;
    margin-bottom: 0.75rem;
}

.booking-result .result-summary {
    background: var(--light-bg);
    border-radius: var(--radius-md);
    padding: 1rem;
    margin: 1.25rem 0;
    text-align: left;
    font-size: 0.95rem;
}

.booking-result .result-summary div {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.3rem 0;
}

.booking-result .result-summary dt {
    color: var(--text-light);
}

.booking-result .result-summary dd {
    font-weight: 600;
    color: var(--text-color);
    text-align: right;
}

/* ── Small screens ────────────────────────────────────────────────────────── */

@media (max-width: 560px) {
    .booking-section {
        padding: 40px 16px;
    }

    .booking-section h1 {
        font-size: 2rem;
    }

    .form-row {
        grid-template-columns: 1fr;
        gap: 0;
    }

    .modal {
        padding: 1.5rem 1.25rem;
    }

    /* Restated because the .modal shorthand above resets the bottom padding the submit
       bar needs to reach the modal's edge (see .booking-submit). */
    .booking-modal {
        --modal-pad-x: 1.25rem;
        padding-bottom: 0;
    }

    .table-grid {
        gap: 0.4rem;
    }

    /* Thinner rings: on a ~73px cell a 3px stroke reads as a heavy outline. */
    .table-top {
        border-width: 2px;
    }

    .chair::before {
        border-width: 1.5px;
    }

    /* The circle is only ~39px across here, and a fourth line of text would run
       past its edge. The seat count is still in the tooltip and the modal. */
    .table-cell .cell-seats {
        display: none;
    }
}
