/* ==========================================================================
   Lilibet's — first-party booking engine prototype

   Light theme. The page is nothing but the reservation form: no site chrome,
   no marketing sections. It is designed to sit inside an existing site (or an
   iframe-free /reservations route) and inherit its surroundings, so the
   surfaces stay near-white and the gold does the branding.
   ========================================================================== */
/* ── Reset: the host's stylesheet does not reach in ──────────────────────── */
/*
   `all: revert` rolls every property on every element inside the widget back
   past the author origin to the browser's own defaults, so the engine renders
   as though the surrounding site's CSS did not exist.

   This is not defensive tidying. Measured against the live site's own
   stylesheets — the Lilibet's theme, WooCommerce and Gravity Forms, loaded
   after ours — 126 computed properties across 30 elements were being repainted
   by rules the widget never asked for. One bare rule in the theme did most of
   it:

       button { padding: 13px 24px; letter-spacing: 2px; text-transform: uppercase;
                position: relative; vertical-align: middle; width: fit-content }

   `.sr-stepper__btn` is more specific than that and still lost, because it does
   not *declare* padding — and an undeclared property is not a defended one. Its
   48px of inherited side padding pushed a 36px box out to 50px, so the round
   increment buttons rendered as ellipses. Nothing about the specificity was
   wrong; the rule was simply silent on the property that mattered.

   Inheritance is weaker still: it loses to any rule at all, so every value the
   widget was leaving to its ancestors was the host's to change. Reverting first
   means the engine only ever inherits from itself.

   This rule ties with the component rules below, all of which come later in the
   file and therefore win. That is the contract: it stays at the top, and
   nothing above it may set a property it expects to survive — which is why
   `box-sizing` moved underneath.

   Custom properties are outside `all` by definition, so the Appearance tokens
   and the full-bleed offsets measured in JS both survive it.

   SVG is held out of it entirely, and that exclusion is load-bearing. SVG2
   makes the geometry attributes — `d`, `x`, `y`, `width`, `height`, `r`, `cx`,
   `cy` — into real CSS properties, so `all: revert` does not merely restyle a
   `<path d="M8 2v4...">`, it sets `d` to `none` and erases the shape. Every
   icon in the engine disappeared. `:where()` keeps the exclusion weightless, so
   the rule still sits at exactly one class above the component rules below.
*/
:root .sr-booking,
:root .sr-booking *:not(:where(svg, svg *)),
:root .sr-booking *:not(:where(svg, svg *))::before,
:root .sr-booking *:not(:where(svg, svg *))::after,
:root .sr-modal,
:root .sr-modal *:not(:where(svg, svg *)),
:root .sr-modal *:not(:where(svg, svg *))::before,
:root .sr-modal *:not(:where(svg, svg *))::after { all: revert; }
:root .sr-booking, :root .sr-booking *, :root .sr-booking *::before, :root .sr-booking *::after,
:root .sr-modal, :root .sr-modal *, :root .sr-modal *::before, :root .sr-modal *::after { box-sizing: border-box; }
/* The `hidden` attribute must always win. Several components below set an
   explicit `display` (.sr-inspector is flex, .sr-hold is flex), and an author rule
   beats the UA stylesheet's `[hidden] { display: none }` — which silently left
   the inspector panel open and intercepting every click on the right-hand side
   of the page. Toggling `hidden` in JS is the app's only hide mechanism, so
   this rule is load-bearing, not defensive. */
:root .sr-booking [hidden], :root .sr-manage [hidden], :root .sr-inspector[hidden], :root .sr-inspector-fab[hidden] { display: none !important; }
/* Same reason, one level up: the modal sets `display: flex` below, and an
   author rule beats the UA stylesheet — so a modal that ships `hidden` would
   render over the page on every load of every page on the site. */
:root .sr-modal[hidden] { display: none !important; }
:root .sr-booking {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 16px;
  /* Weight and tracking are stated rather than left to inherit. In the
     prototype these came from the browser's defaults on <body>; inside a theme
     they come from the theme, and a theme that sets a 300 body weight quietly
     restyles the whole engine. */
  font-weight: 400;
  letter-spacing: normal;
  line-height: 1.6;
  color: var(--on-light);

  /* Transparent by default, so the widget takes the background of whatever it
     is dropped into. The prototype ran on its own page and could assume the
     cream canvas; a plugin cannot, and a block of off-white inside a themed
     section reads as a pasted-in iframe. Set a colour under
     Appearance → Widget background to paint it. */
  background: var(--sr-bg, transparent);
  -webkit-font-smoothing: antialiased;
}
/* Every selector in this file opens with `:root `, which is one class of
   specificity the host cannot easily out-argue: it lifts the whole stylesheet
   above the `input[type="text"] { ... }` and `[type="button"] { ... }` rules
   that themes and form plugins reach in with, and which beat a bare
   `.sr-component` on a tie. Ten themes were measured; those two shapes were
   what was left after the revert. Because every rule moves by the same amount,
   the file's internal cascade is exactly as it was.
 
   It is also the level the venue's own CSS has to write at. The Appearance
   custom-CSS box is scoped to match automatically; a stylesheet loaded by URL
   has to say `:root` itself, and the Appearance tab says so.
 
   These resets sit at one further class of specificity — `.sr-booking` scopes
   them, `:where()` keeps the element itself weightless.
 
   Both halves matter. Written as `.sr-booking button` they would be (0,1,1) and
   outrank every component class below: that is what turned every call to action
   black, because `color: inherit` beat `.sr-btn { color: var(--btn-fg) }`.
   Written as `:where(.sr-booking) button` they would be (0,0,1) and lose to any
   theme that styles bare elements, which is how the engine picked up the
   theme's heading tracking.
 
   At (0,1,0) they beat the theme and tie with our own components — and every
   component below is later in the file, so it wins the tie. Keep them here, at
   the top. */
:root .sr-booking :where(img) { max-width: 100%; display: block; }
:root .sr-booking :where(a) { color: inherit; text-decoration: none; }
/* Form controls do not inherit type from their ancestors — the browser hands
   them their own 13.33px Arial — so the revert above leaves them looking like a
   1998 form unless we say otherwise. Buttons were already covered here; inputs,
   selects and textareas were not, which is why the guests counter has been
   set in Arial on every site whose theme did not happen to fix it for us.
   `appearance` is deliberately left alone: setting it to `none` here would
   erase the checkboxes on the details step. */
/* The revert skips SVG, so the icons keep their own geometry and their
   `fill="none" stroke="currentColor"` — presentation attributes, which the
   cascade treats as author declarations at zero specificity and which any
   author rule outranks. That leaves the host's `svg { ... }` rules to deal
   with, so this states the handful of box properties a theme reaches for,
   rather than reverting the lot and taking the drawing with it. Every icon in
   the plugin is a stroked outline; one that wants a fill should ask by class. */
:root .sr-booking :where(svg) {
  display: inline-block;
  vertical-align: middle;
  margin: 0;
  padding: 0;
  border: 0;
  max-width: none;
  max-height: none;
  box-shadow: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* The shapes inside are out of the revert's reach as well, so a host rule like
   `main * { max-width: 320px }` still lands on them. None of these have any
   effect on how a `<path>` draws, but neutralising them keeps "the host
   changes nothing" literally true, which is worth more than the argument about
   which properties count. Geometry is deliberately absent: setting `width` or
   `d` here is what broke the icons in the first place. */
:root .sr-booking :where(svg *) {
  max-width: none;
  max-height: none;
  min-width: 0;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  box-shadow: none;
}
:root .sr-booking :where(button, input, select, textarea, optgroup) {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  margin: 0;
}
:root .sr-booking :where(h1, :root h2, :root h3, :root h4) {
  font-family: var(--font-display);
  font-weight: 400;
  /* Themes almost always track their headings. Inherited tracking would not
     reach a heading the theme styles directly, so it is restated here — the
     components below that want their own still set it. */
  letter-spacing: normal;
  line-height: 1.12;
  margin: 0;
  font-optical-sizing: auto;
}
:root .sr-booking :where(:focus-visible) {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}
/* ── Shared type ─────────────────────────────────────────────────────────── */
:root .sr-section-title {
  font-size: clamp(28px, 4vw, 44px);
  letter-spacing: -0.015em;
}
:root .sr-section-title em { font-style: italic; color: var(--gold); }
:root .sr-section-lede {
  font-size: 16.5px;
  color: var(--on-light-muted);
  max-width: 54ch;
  margin: 16px auto 0;
}
:root .sr-section-lede a { color: var(--gold); text-decoration: underline; text-underline-offset: 3px; }
/* ── Buttons ─────────────────────────────────────────────────────────────── */
:root .sr-btn {
  --btn-bg: var(--gold);
  --btn-fg: var(--cta-fg);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 15px 30px;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
:root .sr-btn:hover:not(:disabled) { background: var(--gold-hover); }
:root .sr-btn:active:not(:disabled) { transform: translateY(1px); }
:root .sr-btn:disabled { opacity: 0.45; cursor: not-allowed; }
:root .sr-btn--ghost {
  background: transparent;
  border-color: var(--border);
  color: var(--gold);
}
:root .sr-btn--ghost:hover:not(:disabled) { background: var(--gold); color: var(--cta-fg); border-color: var(--gold); }
:root .sr-btn--sm { padding: 10px 18px; font-size: 10.5px; }
:root .sr-btn--block { width: 100%; }
:root .sr-btn.sr-is-busy { pointer-events: none; opacity: 0.75; }
:root .sr-btn.sr-is-busy::after {
  content: '';
  width: 13px; height: 13px;
  border: 2px solid rgba(255,255,255,0.4);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }
:root .sr-inline-btn {
  background: none;
  border: 0;
  padding: 0;
  color: var(--gold);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  font: inherit;
}
/* `pulse` is still used by the hold-countdown dot below. */

@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
/* ── Masthead ────────────────────────────────────────────────────────────── */
/* Current page — a marker, not a link. */
/* ── Page frame ──────────────────────────────────────────────────────────── */
/* ── Engine shell ────────────────────────────────────────────────────────── */
/* Deliberately NOT `overflow: hidden` — the date popover is anchored inside the
   search step and would be clipped. The rail carries its own top radius instead,
   since it is the only differently-coloured element touching an engine corner. */
:root .sr-engine {
  max-width: 1000px;
  margin: 0 auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-md);
}
/* Progress rail */
:root .sr-rail {
  display: flex;
  list-style: none;
  margin: 0;
  padding: 0;
  border-bottom: 1px solid var(--border);
  border-radius: calc(var(--r-lg) - 1px) calc(var(--r-lg) - 1px) 0 0;
  background: var(--canvas);
  overflow: hidden;
}
:root .sr-rail__item {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 15px 10px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--on-light-faint);
  border-right: 1px solid var(--border-soft);
  transition: color var(--t-med) var(--ease), background var(--t-med) var(--ease);
}
:root .sr-rail__item:last-child { border-right: 0; }
:root .sr-rail__num {
  display: grid;
  place-items: center;
  width: 24px; height: 24px;
  border: 1px solid currentColor;
  border-radius: 50%;
  flex: none;
}
:root .sr-rail__num svg { width: 13px; height: 13px; }
:root .sr-rail__item.sr-is-active { color: var(--gold); background: var(--surface); }
:root .sr-rail__item.sr-is-done { color: var(--on-light-muted); }
:root .sr-rail__item.sr-is-done .sr-rail__num {
  background: var(--gold);
  border-color: var(--gold);
  color: #fff;
}
/* Completed steps swap the step icon for a tick. */
:root .sr-rail__item.sr-is-done .sr-rail__num svg { display: none; }
:root .sr-rail__item.sr-is-done .sr-rail__num::after { content: '✓'; font-size: 12px; }
/* Four labels need roughly 560px between them. Below that the rail falls back
   to icons — above it, keep the words: an icon-only progress rail tells a guest
   nothing about what is coming. */
@container sr (max-width: 600px) {
:root .sr-rail__label { display: none; }
:root .sr-rail__item { padding: 13px 6px; }
}
/* Hold countdown */
:root .sr-hold {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 11px;
  background: var(--warn-tint);
  border-bottom: 1px solid #eddcbf;
  font-size: 13px;
  color: #7d541f;
}
:root .sr-hold strong { font-variant-numeric: tabular-nums; color: #593a12; }
:root .sr-hold__pulse {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--warn);
  animation: pulse 1.6s var(--ease) infinite;
}
:root .sr-hold.sr-is-urgent { background: var(--danger-tint); border-color: #f0d3ce; color: #8c2a23; }
:root .sr-hold.sr-is-urgent .sr-hold__pulse { background: var(--danger); }
:root .sr-hold.sr-is-urgent strong { color: #6f211b; }
/* Steps */
:root .sr-step { padding: clamp(20px, 3.4vw, 34px); }

/* ── Step transition ─────────────────────────────────────────────────────── */
/* `position: relative` with no z-index of its own: it gives the overlay
   something to fill without creating a stacking context, so the date popover's
   escape hatch — `.sr-booking:has(.sr-calendar:not([hidden]))` lifting the whole
   widget above a theme's sticky header — still works from outside the engine. */
:root .sr-engine { position: relative; }

:root .sr-busy {
  position: absolute;
  inset: 0;
  /* Below the calendar's 70. The two are never open together, but the calendar
     is the thing that must win if they ever are. */
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-lg);
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  animation: sr-busy-in var(--t-fast) var(--ease-out);
}

/* Sticky as well as centred. The slots step runs to several screens on a busy
   day, and a panel centred in the engine would sit somewhere below the fold —
   so the guest would be blocked by an overlay whose explanation they cannot
   see. Centred while the engine fits, clamped into view once it does not. */
:root .sr-busy__panel {
  position: sticky;
  top: 24px;
  bottom: 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 24px 28px;
  text-align: center;
}
:root .sr-busy__spinner {
  width: 26px;
  height: 26px;
  border: 2px solid var(--border);
  border-top-color: var(--gold);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
:root .sr-busy__text {
  margin: 0;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--on-light-muted);
}

@keyframes sr-busy-in { from { opacity: 0; } to { opacity: 1; } }

/* The same spinner inline, for a wait that belongs to one block rather than to
   the whole step — the card form arriving while the policy stays readable. */
:root .sr-loading-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-size: 13px;
  color: var(--on-light-muted);
}
:root .sr-loading-row .sr-busy__spinner { width: 16px; height: 16px; }
:root .sr-step__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 22px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--border-soft);
}
:root .sr-step__summary { margin: 0; font-size: 14px; color: var(--on-light-muted); }
:root .sr-step__summary strong { color: var(--on-light); font-weight: 600; }
:root .sr-linkback {
  background: none;
  border: 0;
  padding: 0;
  color: var(--gold);
  font-size: 12.5px;
  cursor: pointer;
  transition: color var(--t-fast) var(--ease);
}
:root .sr-linkback:hover { color: #7d6740; }
/* ── Search bar ──────────────────────────────────────────────────────────── */
/* Information architecture: Date → Guests → Service → Find a table. Date takes
   the flexible space; Guests, Service and the button are each only as wide as
   their content. */
:root .sr-searchbar {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  gap: 16px;
  align-items: end;
}
/* Below the desktop row: Date spans the top, then Guests + Service share a row,
   and the button takes a full row of its own. */
@container sr (max-width: 900px) {
:root .sr-searchbar { grid-template-columns: auto 1fr; }
:root .sr-field--date { grid-column: 1 / -1; }
:root .sr-field--guests { grid-column: 1; }
:root .sr-field--service { grid-column: 2; }
:root .sr-btn--search { grid-column: 1 / -1; }
}

/* On a phone the guests stepper and the three service buttons cannot share a
   row without spilling past the edge, so everything gets its own. The segmented
   control stretches rather than sitting at its intrinsic width, which also
   makes the three targets comfortably tappable. */
@container sr (max-width: 560px) {
:root .sr-searchbar { grid-template-columns: 1fr; }
:root .sr-field--date,
:root .sr-field--guests,
:root .sr-field--service,
:root .sr-btn--search { grid-column: 1; }
:root .sr-stepper { display: flex; justify-content: space-between; }
:root .sr-segset { display: flex; }
:root .sr-seg { flex: 1; padding: 0 8px; }
}
:root .sr-field { display: grid; gap: 8px; }
:root .sr-field > label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--on-light-faint);
}
/* Guests: two round increment buttons flanking the count. The buttons carry the
   interaction; the wrapper is a quiet field frame the same height as its
   neighbours. Palette per brief: warm cream idle, deepening on hover/press. */
:root .sr-stepper {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 52px;
  padding: 0 7px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface);
}
:root .sr-stepper__btn {
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: #f2ece5;
  border: 1px solid #e8dfd1;
  color: var(--gold);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
:root .sr-stepper__btn:hover:not(:disabled) { background: #d1c3b5; border-color: #b9a997; }
:root .sr-stepper__btn:active:not(:disabled) { background: #b9a997; border-color: #b9a997; }
:root .sr-stepper__btn:disabled { opacity: 0.45; cursor: not-allowed; }
:root .sr-stepper__val {
  width: 32px;
  height: 100%;
  border: 0;
  background: none;
  text-align: center;
  color: var(--on-light);
  font-size: 16px;
  font-variant-numeric: tabular-nums;
  cursor: default;
}
:root .sr-stepper__val:focus { outline: none; }
:root .sr-datepick {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  height: 52px;
  padding: 0 16px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--on-light);
  font-size: 15px;
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease);
}
:root .sr-datepick:hover { border-color: var(--gold); }
:root .sr-datepick svg { color: var(--gold); flex: none; }
/* Service: a segmented Any / Lunch / Dinner toggle. Non-active segments are
   white; hover lifts to warm cream; the active segment is muddy bronze —
   lighter than the gold CTA so it reads as "chosen", not "click me". */
:root .sr-segset {
  display: inline-flex;
  height: 52px;
  padding: 4px;
  gap: 4px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface);
}
:root .sr-seg {
  padding: 0 16px;
  border: 1px solid transparent;
  border-radius: 2px;
  background: var(--surface);
  color: var(--on-light-muted);
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease);
}
:root .sr-seg:hover:not(.sr-is-on) { background: var(--chip-hover); color: var(--on-light); }
:root .sr-seg.sr-is-on {
  background: var(--chip-active);
  border-color: var(--chip-active-line);
  color: var(--on-light);
  font-weight: 600;
}
:root .sr-btn--search { height: 52px; }
/* ── Calendar ────────────────────────────────────────────────────────────── */
/* A popover anchored under the date button, not an accordion. Opening it must
   not reflow the search bar or shift the buttons under the user's cursor. */
:root .sr-field--date { position: relative; }

/* While the popover is open the whole widget has to out-rank the page.

   The calendar's own z-index only orders it against its siblings; it cannot
   help against a theme's sticky header, which is routinely z-index 999 or
   9999. Raising the engine as a group keeps the internal order intact — the
   inspector is still above the calendar — while lifting all of it clear of the
   page furniture, and only for as long as something is actually open.

   `position: relative` is required for z-index to apply at all here, and with
   no offsets it moves nothing. */
:root .sr-booking:has(.sr-calendar:not([hidden])) {
  position: relative;
  z-index: var(--sr-layer, 1000);
}

:root .sr-calendar {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 70;
  width: 340px;
  max-width: calc(100vw - 2 * var(--gutter));
  padding: 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
  animation: drop var(--t-fast) var(--ease-out);
}

@keyframes drop { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

/* Anchored above the field instead, when opening downwards would push the
   calendar off the bottom of the screen. The engine measures the room and sets
   this class; CSS alone cannot know how much viewport is left. */
:root .sr-calendar.sr-is-above {
  top: auto;
  bottom: calc(100% + 8px);
  animation-name: rise;
}

@keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
/* On mobile the date field sits in column 2, so a left-anchored popover would
   spill off the right edge. Hug the field's right edge and grow leftward — its
   right edge is the search bar's right gutter, so it always stays on screen. */
@container sr (max-width: 900px) {
:root .sr-calendar { left: auto; right: 0; }
}
:root .sr-calendar__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
  color: var(--on-light);
  font-family: var(--font-display);
  font-size: 17px;
}
:root .sr-calendar__nav {
  width: 32px; height: 32px;
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  color: var(--gold);
  font-size: 17px;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease);
}
:root .sr-calendar__nav:hover:not(:disabled) { background: var(--canvas); }
:root .sr-calendar__nav:disabled { color: var(--border); cursor: not-allowed; }
:root .sr-calendar__dow, :root .sr-calendar__grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}
:root .sr-calendar__dow {
  margin-bottom: 6px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--on-light-faint);
  text-align: center;
}
:root .sr-cal-day {
  position: relative;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: none;
  color: var(--on-light);
  font-size: 13.5px;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
:root .sr-cal-day:hover:not(:disabled) { background: rgba(156,130,86,0.12); border-color: var(--gold); }
:root .sr-cal-day:disabled { color: #cdc5b6; cursor: not-allowed; }
:root .sr-cal-day.sr-is-empty { visibility: hidden; }
:root .sr-cal-day.sr-is-selected { background: var(--gold); border-color: var(--gold); color: #fff; font-weight: 600; }
/* ── Slots ───────────────────────────────────────────────────────────────── */
:root .sr-slots-out { display: grid; gap: 18px; }
/* Social-proof bar — the "table held for 5:00" bar, repurposed while the guest
   is still choosing. Informational gold, not the urgent warn tone of the hold. */
:root .sr-viewbar {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 11px 15px;
  border: 1px solid #ece3d0;
  border-radius: var(--r-md);
  background: rgba(156,130,86,0.07);
  font-size: 13px;
  color: var(--on-light-muted);
}
:root .sr-viewbar svg { width: 16px; height: 16px; color: var(--gold); flex: none; }
:root .sr-viewbar strong { color: var(--on-light); font-weight: 600; }
/* Step 2 is table-first: one product card per seating area. A landscape thumb
   sits beside the title + description in a top row; the full-width timetable
   runs beneath. (The image no longer stretches to the card's full height now
   that lunch + dinner share one card.) */
:root .sr-tablecard {
  display: grid;
  gap: 18px;
  padding: 20px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
}
:root .sr-tablecard__top {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 20px;
  align-items: start;
}
:root .sr-tablecard__thumb {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: var(--r-sm);
  display: block;
}
:root .sr-tablecard__meta { display: grid; gap: 7px; }
/* The blurb arrives as plain text with its paragraph breaks kept as newlines,
   because the API sends HTML and the front end escapes everything it prints.
   `pre-line` is what turns those newlines back into paragraphs while still
   wrapping and collapsing runs of spaces. */
:root .sr-tablecard [data-desc] {
  white-space: pre-line;
  font-size: 13.5px;
  color: var(--on-light-muted);
  margin: 0;
}
:root .sr-tablecard__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
}
:root .sr-tablecard__head h3 { font-size: 21px; }
:root .sr-tablecard__dur {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--gold);
  white-space: nowrap;
}
:root .sr-tablecard__meta p {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--on-light-muted);
}
:root .sr-area__more {
  background: none; border: 0; padding: 0;
  color: var(--gold);
  font-size: 12.5px;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}
/* The day's timetable inside a card: a labelled row per shift. */
:root .sr-timetable { display: grid; gap: 14px; }
:root .sr-timetable__shift {
  display: grid;
  grid-template-columns: 62px 1fr;
  gap: 12px;
  align-items: start;
}
:root .sr-timetable__label {
  padding-top: 8px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--on-light-faint);
}
:root .sr-timetable__shift + .sr-timetable__shift { padding-top: 14px; border-top: 1px solid var(--border-soft); }
/* Time slots are compact pills laid out on a grid that stretches them to fill
   the row — so there's never a ragged gap between the last pill and the edge. */
:root .sr-times {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(58px, 1fr));
  gap: 7px;
}
:root .sr-time-btn {
  padding: 8px 6px;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--on-light);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  text-align: center;
  min-width: 0;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease);
}
:root .sr-time-btn:hover { background: var(--chip-hover); border-color: var(--chip-active); color: var(--on-light); }
:root .sr-time-btn.sr-is-selected {
  background: var(--chip-active);
  border-color: var(--chip-active-line);
  color: var(--on-light);
  font-weight: 600;
}
/* Late request-only slots — dashed to read as "enquire", not "instant". */
:root .sr-time-btn--request { border-style: dashed; color: var(--on-light-muted); }
/* Filled slots stay visible so the timetable reads honestly — greyed, struck,
   not interactive. */
:root .sr-time-btn--filled {
  border-style: dashed;
  border-color: var(--border-soft);
  background: var(--canvas);
  color: #bcb3a3;
  text-decoration: line-through;
  cursor: not-allowed;
}
/* The Evening row: the late request chip(s) sit inline with a contact line, so
   the guest sees at a glance that a late table is booked by phone. */
:root .sr-timetable__shift--evening .sr-timetable__label { color: var(--gold); }
:root .sr-evening { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
:root .sr-times--evening { display: flex; gap: 7px; }
:root .sr-times--evening .sr-time-btn { min-width: 72px; flex: none; }
:root .sr-evening__note {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--on-light-muted);
}
:root .sr-evening__tel {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 2px;
  color: var(--gold);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}
:root .sr-evening__tel svg { width: 15px; height: 15px; flex: none; }
:root .sr-evening__tel:hover { text-decoration: underline; text-underline-offset: 3px; }
/* Below desktop the card's top row stacks: image above the title + description. */
@container sr (max-width: 720px) {
:root .sr-tablecard__top { grid-template-columns: 1fr; }
:root .sr-tablecard__thumb { aspect-ratio: 16 / 9; }
}
/* On phones the shift label sits above its times, and pills go to four even
   columns so there's no ragged edge. */
@container sr (max-width: 520px) {
:root .sr-tablecard { padding: 16px; gap: 16px; }
:root .sr-timetable__shift { grid-template-columns: 1fr; gap: 7px; }
:root .sr-timetable__label { padding-top: 0; }
:root .sr-times { grid-template-columns: repeat(4, 1fr); gap: 6px; }
:root .sr-time-btn { padding: 8px 4px; font-size: 12.5px; }
:root .sr-evening { gap: 10px; }
}
/* Empty / error states */
:root .sr-empty {
  text-align: center;
  padding: 40px 20px;
  border: 1px dashed var(--border);
  border-radius: var(--r-md);
  background: var(--canvas);
}
:root .sr-empty h3 { font-size: 21px; margin-bottom: 8px; }
:root .sr-empty p { margin: 0 auto 20px; font-size: 14px; color: var(--on-light-muted); max-width: 44ch; }
:root .sr-empty__alts { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; }
:root .sr-skeleton { display: grid; gap: 10px; }
:root .sr-skeleton__row {
  height: 46px;
  border-radius: var(--r-sm);
  background: linear-gradient(90deg, var(--canvas) 0%, var(--border-soft) 50%, var(--canvas) 100%);
  background-size: 200% 100%;
  animation: shimmer 1.3s linear infinite;
}
:root .sr-skeleton__row:nth-child(1) { width: 40%; }
:root .sr-skeleton__row:nth-child(2) { height: 90px; }
:root .sr-skeleton__row:nth-child(3) { height: 90px; }

@keyframes shimmer { to { background-position: -200% 0; } }
/* ── Forms ───────────────────────────────────────────────────────────────── */
:root .sr-split {
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 30px;
  align-items: start;
}
@container sr (max-width: 880px) {
:root .sr-split { grid-template-columns: 1fr; }
/* Form FIRST, then the summary + its CTA (natural DOM order). Sticky would put
     the tall card on top of the inputs; static keeps it a review the guest
     reaches on the way to the button. */
:root .sr-summary-rail { position: static; top: auto; }
}
:root .sr-form { display: grid; gap: 16px; }
:root .sr-form__title {
  font-size: 24px;
  margin-bottom: 2px;
}
:root .sr-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@container sr (max-width: 520px) {
:root .sr-grid-2 { grid-template-columns: 1fr; }
}
:root .sr-input { display: grid; gap: 7px; }
:root .sr-input label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--on-light-faint);
}
:root .sr-input .sr-opt { text-transform: none; letter-spacing: 0; font-weight: 400; opacity: 0.8; }
:root .sr-input input, :root .sr-input select, :root .sr-input textarea {
  width: 100%;
  padding: 13px 15px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--on-light);
  font-family: var(--font-sans);
  font-size: 15px;
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
:root .sr-input textarea { resize: vertical; line-height: 1.55; }
:root .sr-input input::placeholder, :root .sr-input textarea::placeholder { color: #a8a093; }
:root .sr-input input:focus, :root .sr-input select:focus, :root .sr-input textarea:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(156,130,86,0.14);
}
:root .sr-input select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%239c8256' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 40px;
}
:root .sr-input.sr-has-error input, :root .sr-input.sr-has-error select, :root .sr-input.sr-has-error textarea {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px rgba(163,52,44,0.1);
}
:root .sr-input__err {
  font-size: 12px;
  color: var(--danger);
  letter-spacing: 0;
  text-transform: none;
  font-weight: 400;
}
:root .sr-chips { border: 0; padding: 0; margin: 0; display: grid; gap: 9px; }
:root .sr-chips legend {
  padding: 0;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--on-light-faint);
}
:root .sr-chips legend .sr-opt { text-transform: none; letter-spacing: 0; font-weight: 400; opacity: 0.8; }
:root .sr-chips__row { display: flex; flex-wrap: wrap; gap: 7px; }
:root .sr-chip {
  padding: 8px 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--on-light-muted);
  font-size: 12.5px;
  cursor: pointer;
  transition: all var(--t-fast) var(--ease);
}
:root .sr-chip:hover { background: var(--chip-hover); border-color: var(--chip-active); color: var(--on-light); }
:root .sr-chip.sr-is-on { background: var(--chip-active); border-color: var(--chip-active-line); color: var(--on-light); font-weight: 600; }
:root .sr-check {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  font-size: 13.5px;
  color: var(--on-light-muted);
  cursor: pointer;
  line-height: 1.5;
}
:root .sr-check input {
  width: 17px; height: 17px;
  margin: 2px 0 0;
  accent-color: var(--gold);
  flex: none;
  cursor: pointer;
}
:root .sr-check.sr-has-error span { color: var(--danger); }
:root .sr-notice {
  padding: 13px 15px;
  border-left: 2px solid var(--gold);
  background: rgba(156,130,86,0.08);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  font-size: 13.5px;
  color: var(--on-light-muted);
  line-height: 1.55;
}
:root .sr-notice strong { color: var(--on-light); display: block; }
:root .sr-fineprint { margin: -6px 0 0; font-size: 12px; color: var(--on-light-faint); }
:root .sr-fineprint code {
  background: var(--canvas);
  border: 1px solid var(--border-soft);
  padding: 1px 5px;
  border-radius: var(--r-xs);
  font-size: 11.5px;
}
:root .sr-policy {
  max-height: 168px;
  overflow-y: auto;
  padding: 15px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--canvas);
  font-size: 12.5px;
  line-height: 1.65;
  color: var(--on-light-muted);
}
:root .sr-policy h5 {
  margin: 0 0 5px;
  font-family: var(--font-sans);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--gold);
}
/* The policy text arrives flattened by SR_Content::to_text — the venue writes
   it in SevenRooms' rich-text editor, so the API sends markup and the front end
   escapes everything it prints. `pre-line` turns the paragraph breaks that
   survived as newlines back into paragraphs. */
:root .sr-policy p { margin: 0 0 13px; white-space: pre-line; }
:root .sr-policy p:last-child { margin-bottom: 0; }
:root .sr-form-error {
  padding: 12px 15px;
  border-radius: var(--r-sm);
  background: var(--danger-tint);
  border: 1px solid #eccfcb;
  color: #8c2a23;
  font-size: 13.5px;
}
/* ── Summary card ────────────────────────────────────────────────────────── */
/* The right rail now carries the summary card AND the step's primary action,
   pinned together so the CTA stays above the fold as the form scrolls. */
:root .sr-summary-rail {
  position: sticky;
  top: calc(var(--header-h) + 16px);
  display: grid;
  gap: 16px;
  align-content: start;
}
:root .sr-summary {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--canvas);
  overflow: hidden;
}
:root .sr-summary__img { width: 100%; height: 128px; object-fit: cover; }
:root .sr-summary__body { padding: 18px; }
:root .sr-summary__title {
  font-size: 19px;
  margin-bottom: 3px;
}
:root .sr-summary__area {
  font-size: 11px;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--gold);
  margin: 0 0 16px;
}
:root .sr-summary__rows { display: grid; gap: 10px; }
:root .sr-summary__row {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  font-size: 13.5px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}
:root .sr-summary__row:last-child { border-bottom: 0; padding-bottom: 0; }
:root .sr-summary__row dt { color: var(--on-light-faint); margin: 0; }
:root .sr-summary__row dd { margin: 0; color: var(--on-light); text-align: right; font-weight: 500; }
/* ── Confirmation ────────────────────────────────────────────────────────── */
:root .sr-done { text-align: center; padding: 14px 0 8px; }
:root .sr-done__mark {
  width: 62px; height: 62px;
  margin: 0 auto 22px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--gold);
  background: rgba(156,130,86,0.1);
  color: var(--gold);
  font-size: 27px;
  animation: pop var(--t-slow) var(--ease-out);
}

@keyframes pop { from { transform: scale(0.6); opacity: 0; } to { transform: none; opacity: 1; } }
:root .sr-done h2 { font-size: clamp(26px, 3.4vw, 38px); margin-bottom: 10px; }
/* The second line stays gold — it is the emphasis — but upright. The italic
   read as a different typeface next to the display face's own slant. */
:root .sr-done h2 em { font-style: normal; color: var(--gold); }
:root .sr-done__lede { color: var(--on-light-muted); font-size: 15.5px; max-width: 48ch; margin: 0 auto 26px; }
:root .sr-done__ref {
  display: inline-block;
  padding: 7px 16px;
  border: 1px dashed var(--border);
  border-radius: var(--r-sm);
  font-size: 13px;
  letter-spacing: 0.1em;
  color: var(--gold);
  margin-bottom: 28px;
}
:root .sr-done__card {
  max-width: 420px;
  margin: 0 auto 26px;
  text-align: left;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--canvas);
  overflow: hidden;
}
:root .sr-done__actions { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
:root .sr-done__tracked {
  max-width: 560px;
  margin: 32px auto 0;
  padding: 18px;
  border: 1px solid #cfdfd0;
  border-radius: var(--r-md);
  background: var(--ok-tint);
  text-align: left;
}
:root .sr-done__tracked h4 {
  font-family: var(--font-sans);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: #3f6642;
  margin-bottom: 10px;
}
:root .sr-done__tracked ul { margin: 0; padding-left: 18px; font-size: 13px; color: var(--on-light-muted); line-height: 1.7; }
:root .sr-done__tracked code { color: #3f6642; font-size: 12px; }
/* ── Footer ──────────────────────────────────────────────────────────────── */
/* ── Tracking inspector ──────────────────────────────────────────────────── */
:root .sr-inspector-fab {
  position: fixed;
  right: 20px; bottom: 20px;
  z-index: 90;
  width: 50px; height: 50px;
  display: grid;
  place-items: center;
  border: 1px solid var(--gold);
  border-radius: 50%;
  background: var(--surface);
  color: var(--gold);
  cursor: pointer;
  box-shadow: var(--shadow-md);
  transition: transform var(--t-fast) var(--ease), background var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease);
}
:root .sr-inspector-fab:hover { transform: translateY(-2px); background: var(--gold); color: #fff; }
:root .sr-inspector-fab__count {
  position: absolute;
  top: -5px; right: -5px;
  min-width: 20px;
  padding: 0 5px;
  height: 20px;
  display: grid;
  place-items: center;
  border-radius: var(--r-pill);
  background: var(--claret);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
:root .sr-inspector {
  position: fixed;
  top: 0; right: 0;
  z-index: 100;
  width: min(440px, 100vw);
  height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-left: 1px solid var(--border);
  box-shadow: -20px 0 60px rgba(20,16,12,0.14);
  animation: slidein var(--t-med) var(--ease-out);
}

@keyframes slidein { from { transform: translateX(100%); } to { transform: none; } }
:root .sr-inspector__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  padding: 20px;
  border-bottom: 1px solid var(--border);
}
:root .sr-inspector__head h2 { font-size: 20px; margin-bottom: 5px; }
:root .sr-inspector__head p { margin: 0; font-size: 12.5px; color: var(--on-light-faint); line-height: 1.5; }
:root .sr-inspector__close {
  width: 32px; height: 32px;
  flex: none;
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  color: var(--on-light-muted);
  font-size: 21px;
  line-height: 1;
  cursor: pointer;
}
:root .sr-inspector__close:hover { background: var(--canvas); color: var(--on-light); }
:root .sr-inspector__tabs { display: flex; border-bottom: 1px solid var(--border); background: var(--canvas); }
:root .sr-inspector__tab {
  flex: 1;
  padding: 12px 8px;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--on-light-faint);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
              background var(--t-fast) var(--ease);
}
:root .sr-inspector__tab:hover { color: var(--on-light); }
:root .sr-inspector__tab.sr-is-on { color: var(--gold); border-bottom-color: var(--gold); background: var(--surface); }
:root .sr-inspector__body { flex: 1; overflow-y: auto; padding: 18px 20px; }
:root .sr-inspector__hint { margin: 0 0 14px; font-size: 12.5px; color: var(--on-light-faint); line-height: 1.6; }
:root .sr-inspector__foot { padding: 14px 20px; border-top: 1px solid var(--border); }
:root .sr-evlog { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
:root .sr-evlog__item {
  padding: 11px 13px;
  border: 1px solid var(--border-soft);
  border-left: 2px solid var(--gold);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  background: var(--canvas);
  animation: drop var(--t-fast) var(--ease-out);
}
:root .sr-evlog__item--goal { border-left-color: var(--ok); background: var(--ok-tint); border-color: #d9e6da; }
:root .sr-evlog__top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
:root .sr-evlog__name {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px;
  color: #7d6740;
  word-break: break-all;
}
:root .sr-evlog__item--goal .sr-evlog__name { color: #3f6642; }
:root .sr-evlog__time { font-size: 10.5px; color: var(--on-light-faint); font-variant-numeric: tabular-nums; flex: none; }
:root .sr-evlog__params {
  margin: 7px 0 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  line-height: 1.65;
  color: var(--on-light-muted);
  word-break: break-word;
}
:root .sr-evlog__params b { color: var(--on-light-faint); font-weight: 400; }
:root .sr-evlog__empty { font-size: 13px; color: var(--on-light-faint); }
:root .sr-code {
  margin: 0;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--canvas);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px;
  line-height: 1.65;
  color: #4a4235;
  white-space: pre-wrap;
  word-break: break-word;
}
@media (prefers-reduced-motion: reduce) {
:root .sr-booking *, :root .sr-booking *::before, :root .sr-booking *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}
/* ==========================================================================
   Plugin additions — the pieces the static prototype did not need.
   ========================================================================== */

:root .sr-booking {
  --sr-max: 1120px;
  max-width: var(--sr-max);
  margin: 0 auto;
  padding: 0;

  /* The engine responds to the width it is given, not the width of the window.
     Themes put it in a 645px content column, a full-bleed section, or a
     sidebar, and every internal breakpoint below is a @container query against
     this. */
  container-type: inline-size;
  container-name: sr;
}

/* Let the engine use the width a block theme offers when the author asks for it. */
:root .sr-booking.alignwide { max-width: var(--wp--style--global--wide-size, var(--sr-max)); }
:root .sr-booking.alignfull { max-width: none; }

:root .sr-reserve-head {
  text-align: center;
  margin: 0 auto 26px;
  max-width: 62ch;
}

:root .sr-reserve-foot {
  text-align: center;
  margin: 22px 0 0;
  font-size: 14px;
  color: var(--on-light-muted);
}
:root .sr-reserve-foot a { color: var(--gold); text-decoration: underline; text-underline-offset: 3px; }

/* Mock mode has to be unmistakable. A demo booking that looks real is how a
   staging site ends up seating phantom guests. */
:root .sr-demo-flag {
  margin: 0 0 16px;
  padding: 10px 16px;
  border-radius: 8px;
  background: var(--warn-tint, #fdf5e3);
  border: 1px solid #ecd9ae;
  color: #7a5c17;
  font-size: 13px;
  text-align: center;
}

:root .sr-notice {
  padding: 12px 14px;
  border-radius: 8px;
  background: var(--canvas);
  border: 1px solid var(--border-soft);
  font-size: 14px;
  line-height: 1.55;
  margin-bottom: 14px;
}
:root .sr-notice strong { display: block; color: var(--on-light); }
:root .sr-notice p { margin: 4px 0 0; color: var(--on-light-muted); }

:root .sr-flash {
  margin: 0;
  padding: 12px 18px;
  background: var(--danger-tint, #fbeceb);
  border-bottom: 1px solid #f0d3ce;
  color: #8c2a23;
  font-size: 14px;
}

/* Stripe mounts its own iframe here; the height is theirs, not ours. */
:root .sr-card-block { margin-bottom: 18px; }
:root .sr-stripe-mount { min-height: 44px; }

:root .sr-manage .sr-engine { max-width: 720px; margin: 0 auto; }
:root .sr-form--lookup { max-width: none; }
:root .sr-manage-result { margin-top: 24px; display: grid; gap: 16px; }
:root .sr-manage-result .sr-summary { max-width: none; }

/* The reference is the one string a guest may need to read back to us, so give
   it tabular figures and room to breathe rather than burying it in a sentence. */
:root .sr-done__code {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.08em;
  font-weight: 600;
}

/* Late tables are usually request-only. A dashed pill on its own does not say
   why it behaves differently from the one beside it. */
:root .sr-evening-note {
  grid-column: 2;
  margin: 6px 0 0;
  font-size: 12.5px;
  color: var(--on-light-muted);
}

@container sr (max-width: 520px) {
:root .sr-evening-note { grid-column: 1; }
}

/* ==========================================================================
   Full-bleed booking page

   Applied only on the page the plugin owns (body.sr-page--fullscreen), so a
   booking block dropped into an ordinary page still behaves like a block.

   The engine breaks out of whatever column the theme put it in and fills the
   screen below the header. `--sr-header-offset` is measured at runtime from
   the engine's own position, because the header's height is the theme's
   business and there is no reliable way to know it from CSS alone.
   ========================================================================== */

:root .sr-page--fullscreen .sr-booking {
  --sr-header-offset: 0px;
  --sr-gap-above: 0px;
  --sr-bleed-left: 0px;

  max-width: none;
  /* The 100vw pair is the pre-JS fallback and is right for a theme with no
     gutter. Once measured, the custom properties describe the real inset and
     the real viewport width, which a padded full-width parent otherwise makes
     unreachable from CSS alone. */
  width: var(--sr-viewport-width, 100vw);
  margin-left: calc(-1 * var(--sr-bleed-left, calc(50vw - 50%)));
  margin-right: 0;
  min-height: calc(100svh - var(--sr-header-offset));

  /* The bottom is deliberately deeper than the top. Two things live down there
     that the top does not have to carry: the date popover, which opens under
     the search bar and is 300-odd pixels tall, and the contact line under the
     engine. Without the extra room the page ends flush against whichever of
     them is last, and on a short screen the calendar ran off the document
     entirely. The engine flips the popover upwards when even this is not
     enough. */
  padding: clamp(20px, 4vw, 48px) clamp(16px, 4vw, 48px) clamp(48px, 8vw, 96px);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Pull back up through whatever the theme put between its header and the
   content, so the engine starts where the header stops.

   This needs !important, which is worth explaining. WordPress generates its own
   layout rules into the page — `.wp-block-post-content.is-layout-constrained >
   :first-child { margin-block-start: 0 }` — at a specificity that beats any
   sensible selector here, and it targets the same logical property. The
   override is one declaration, on one element, on the one page the plugin owns.
   Anything less blunt loses to a rule the theme did not even write. */
:root body.sr-page--fullscreen .sr-booking {
  margin-block-start: calc(-1 * var(--sr-gap-above, 0px)) !important;

  /* Core's constrained-layout rule sets `margin-left: auto !important` on every
     non-aligned child, which pins the engine inside the theme's gutter no
     matter what this stylesheet asks for. Same reasoning as the block above:
     one element, one page, and nothing quieter can win. */
  margin-inline-start: calc(-1 * var(--sr-bleed-left, 0px)) !important;
  margin-inline-end: 0 !important;
}

/* The engine itself stays readable — full bleed is the ground, not the form. */
:root .sr-page--fullscreen .sr-engine {
  width: 100%;
  max-width: 1120px;
  margin: 0 auto;
}

:root .sr-page--fullscreen .sr-demo-flag,
:root .sr-page--fullscreen .sr-reserve-head,
:root .sr-page--fullscreen .sr-reserve-foot {
  width: 100%;
  max-width: 1120px;
  margin-left: auto;
  margin-right: auto;
}

/* The page title is the theme's, and on a booking page it is noise above a
   form that already says what it is. Covers the block-theme and classic-theme
   conventions; a theme with its own idea can be added by the venue. */
:root .sr-page--fullscreen .wp-block-post-title,
:root .sr-page--fullscreen .entry-title,
:root .sr-page--fullscreen .page-title,
:root .sr-page--fullscreen .wp-block-query-title {
  display: none;
}

/* Once the flow is past the fold there is nothing to centre. */
:root .sr-page--fullscreen .sr-booking:has(.sr-engine[data-step="slots"]),
:root .sr-page--fullscreen .sr-booking:has(.sr-engine[data-step="details"]),
:root .sr-page--fullscreen .sr-booking:has(.sr-engine[data-step="payment"]) {
  justify-content: flex-start;
}

/* The manage page rides on the same `.sr-booking` root, so everything above
   already applies to it. Two things need saying separately.

   First, the width. Full bleed is the ground, not the form, and a two-field
   lookup does not want 1120px of it. This has to out-specify the shared
   `.sr-page--fullscreen .sr-engine` rule above rather than rely on the earlier
   `.sr-manage .sr-engine`, which ties on specificity and loses on source
   order. */
:root .sr-page--fullscreen .sr-manage .sr-engine {
  max-width: 720px;
}

/* Second, the centring. The lookup form is short, so it sits centred like the
   first step of the booking flow — but once a booking is on screen the panel
   is tall enough to want the top of the page, exactly as the later booking
   steps do. There is no `data-step` here to key off, so the result itself is
   the signal. */
:root .sr-page--fullscreen .sr-manage:has(.sr-manage-result),
:root .sr-page--fullscreen .sr-manage:has(.sr-form-error) {
  justify-content: flex-start;
}

/* ==========================================================================
   Two layout bugs worth naming, because both are easy to reintroduce.
   ========================================================================== */

/* 1. Selecting a control made its label bold, and bold glyphs are wider, so an
      intrinsically sized control resized as the selection moved — the
      segmented control shifted by up to 3px per toggle.

      The fix reserves the bold width in both states with a hidden copy of the
      label, so the box is measured once at its widest. The element becomes a
      column flex container purely so the ghost can sit under the label without
      disturbing how the label is centred; the ghost is zero-height, so it
      contributes width and nothing else. */
:root .sr-seg,
:root .sr-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

:root .sr-seg::after,
:root .sr-chip::after {
  content: attr(data-label);
  height: 0;
  overflow: hidden;
  visibility: hidden;
  font-weight: 600;
  pointer-events: none;
}

/* The reserved width holds the box steady, but it must not become a floor: a
   flex item will not shrink below its content, so without this the three
   service buttons stop fitting before the panel does. When the row is stretched
   to equal columns the reservation is redundant anyway — every button is the
   same width whatever it says. */
:root .sr-seg,
:root .sr-chip {
  min-width: 0;
}

:root .sr-seg {
  overflow: hidden;
  white-space: nowrap;
}

/* Below this the three labels genuinely do not fit at the normal size. Shrink
   them together, so both states still measure the same and nothing jitters. */
@container sr (max-width: 400px) {
:root .sr-seg { padding: 0 4px; font-size: 13px; }
:root .sr-segset { padding: 3px; gap: 2px; }
}

/* Time pills and calendar days sit in fixed grid tracks, so their boxes cannot
   resize — but proportional digits still jiggle inside them when the weight
   changes. Tabular figures hold every digit to the same advance width. */
:root .sr-time-btn,
:root .sr-cal-day,
:root .sr-stepper__val {
  font-variant-numeric: tabular-nums;
}

/* 2. Grid and flex items default to `min-width: auto`, which is the intrinsic
      minimum of their contents rather than something the layout may shrink.
      For an <input> that minimum is its default twenty-character size, so
      below roughly 300px a field would push straight out through the side of
      the panel — visible when the engine sits in a theme's own column rather
      than full-bleed, where there is less room to absorb it. */
:root .sr-searchbar > *,
:root .sr-split > *,
:root .sr-grid-2 > *,
:root .sr-field > *,
:root .sr-form > *,
:root .sr-step__bar > *,
:root .sr-tablecard__top > *,
:root .sr-tablecard__meta > *,
:root .sr-timetable__shift > *,
:root .sr-evening > *,
:root .sr-summary__row > *,
:root .sr-chips > * {
  min-width: 0;
}

:root .sr-input input,
:root .sr-input select,
:root .sr-input textarea,
:root .sr-datepick,
:root .sr-stepper,
:root .sr-segset {
  min-width: 0;
  max-width: 100%;
}

/* The chosen date is the one label with no natural upper bound — "Wednesday 24
   September" is long, and it must give way rather than widen the field. */
:root .sr-datepick [data-date-label] {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ==========================================================================
   Modal

   The same engine, floated over somebody else's page. The markup inside is
   identical to the shortcode's — this is a container, not a second skin — so
   everything below styles the container and gets out of the way.

   Note the media queries. The rest of this file uses container queries
   deliberately, because the engine is given a width by whatever dropped it in
   and the viewport is a poor proxy for that. Here the dialog *is* sized by the
   viewport, so the viewport is the honest thing to ask.
   ========================================================================== */

:root .sr-modal {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;

  /* A theme's sticky header is routinely 999 or 9999, and a cookie banner can
     be higher still. A dialog that opens *under* the page furniture is worse
     than no dialog, so this starts above the range themes use rather than
     alongside it. `--sr-layer` orders the engine against the page; this orders
     the modal against everything. */
  z-index: var(--sr-modal-layer, 99999);
}

:root .sr-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20, 16, 12, 0.55);
}

:root .sr-modal__dialog {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  background: var(--canvas);
  color: var(--on-light);

  /* The dialog takes focus on open so the screen reader announces it, and a
     focus ring around the whole window is noise — the announcement is the
     affordance here, not the outline. */
  outline: none;
}

:root .sr-modal--fullscreen .sr-modal__dialog {
  height: 100%;
  max-width: none;
}

:root .sr-modal--panel .sr-modal__dialog {
  max-width: 1180px;
  /* svh, not vh: on mobile Safari `vh` is the *expanded* viewport, so a 92vh
     dialog is taller than the screen for as long as the address bar is
     showing, and the bottom of the form sits under it. */
  max-height: min(92svh, 1000px);
  margin: 24px;
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

:root .sr-modal__body {
  flex: 1 1 auto;
  overflow-y: auto;
  /* Stops a flick at the end of the list scrolling the page behind the dialog,
     which is the other half of the scroll lock JS puts on the body. */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: clamp(48px, 6vw, 64px) clamp(16px, 4vw, 40px) clamp(32px, 6vw, 56px);
}

/* Top right, above the scrolling content rather than inside it: a close button
   that scrolls away is a trap for anyone who has scrolled down and does not
   know Escape works. */
:root .sr-modal__close {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--on-light-muted);
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: color 0.15s ease, border-color 0.15s ease;
}
:root .sr-modal__close:hover { color: var(--on-light); border-color: var(--on-light-faint); }
:root .sr-modal__close:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
:root .sr-modal__close svg { width: 20px; height: 20px; }

:root .sr-modal .sr-booking { margin: 0 auto; }

/* A fullscreen dialog is as tall as the window and the search step is not, so
   without this the form sits against the top edge with half a screen of empty
   canvas under it. The booking page solves the same problem with
   `justify-content: center`; here the box also scrolls once the guest reaches
   the times, and centring a scroll container clips the top of anything taller
   than it. `margin: auto` on the child centres while it fits and yields the
   moment it does not. */
/* The explicit column is the load-bearing part, and it took two wrong guesses
   to find out why.

   `.sr-booking` is `container-type: inline-size`, which applies inline-size
   containment: the element's own contents are not allowed to contribute to its
   inline size. In normal block layout that is invisible, because the width
   comes down from the parent. But a flex item, or a grid item in an `auto`
   track, is sized *from its content* — and a contained element answers that
   question with zero. The engine collapsed to 0px wide, which then fired its
   own narrowest container query and shredded the layout inside it.

   `minmax(0, 1fr)` sizes the track from the body instead of from the item, so
   nothing ever asks the engine how wide it would like to be. Its own
   `max-width: 1120px` and auto margins then do the centring, as they do
   everywhere else.

   `safe` matters too: plain `center` centres the block even when it is taller
   than the box, which pushes the top of a long times list above the scrollable
   area where it cannot be reached. `safe` falls back to start the moment it
   overflows, and a browser that does not know the keyword drops the
   declaration and gets that same top-aligned behaviour. */
:root .sr-modal--fullscreen .sr-modal__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: safe center;
}
:root .sr-modal--fullscreen .sr-modal__body > .sr-booking { width: 100%; }

/* A centred panel needs somewhere to be centred. Below this there is no room
   either side, so the popup becomes the fullscreen treatment — the same
   decision a phone forces on every dialog. */
@media (max-width: 640px) {
  :root .sr-modal--panel .sr-modal__dialog {
    max-width: none;
    max-height: none;
    height: 100%;
    margin: 0;
    border-radius: 0;
  }
}

@media (prefers-reduced-motion: no-preference) {
  :root .sr-modal__backdrop { animation: sr-modal-fade 0.18s ease-out; }
  :root .sr-modal__dialog { animation: sr-modal-rise 0.22s cubic-bezier(0.2, 0.7, 0.3, 1); }
}

@keyframes sr-modal-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes sr-modal-rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }

/* ── Bot challenge ──────────────────────────────────────────────────────────
   Cloudflare paints the widget itself; all this does is give it somewhere to
   sit when it appears. It is mounted in interaction-only mode, so on almost
   every booking this element stays hidden and occupies nothing — the margin
   below only ever applies to the visit where a guest is actually challenged. */
:root .sr-booking .sr-turnstile {
  display: flex;
  justify-content: center;
  margin: 16px 0 0;
}

:root .sr-booking .sr-turnstile[hidden] {
  display: none;
}
