/* ============================================================================
   Aghosha — app components (night edition)

   The dashboards' building blocks: forms, pickers, tables, tabs, pills,
   modals, toasts, the booking calendar, the admin console and /login.

   Colour, type, radii and motion tokens come from src/styles/design.css (the
   design system) and src/styles/site.css (the app's older token names mapped
   onto it). Both load AFTER this file, so nothing here defines a token they
   own; rules here only read them. Dark is the default theme, where the brand
   is gold and text on a brand fill is dark (--brand-ink); light swaps the
   brand to ink with white on it. Never paint #fff on --brand.
   ========================================================================== */

/* Tokens only this file uses. */
:root, :root[data-theme="dark"] {
  /* The booking calendar is one colour at three strengths: the more of the day
     is sold, the stronger the gold. --hourly-fill lives beside this one. */
  --half-fill: color-mix(in srgb, var(--brand) 45%, var(--card));
  --hourly-fill: color-mix(in srgb, var(--brand) 16%, var(--card));
  --hourly-line: color-mix(in srgb, var(--brand) 55%, var(--card));
  /* the skeleton's moving sheen — a white glare on the night canvas */
  --sheen: rgba(255, 255, 255, .06);
  --scrim: rgba(5, 8, 7, .62);
}
:root[data-theme="light"] {
  --half-fill: color-mix(in srgb, var(--brand) 45%, var(--card));
  --hourly-fill: color-mix(in srgb, var(--brand) 16%, var(--card));
  --hourly-line: color-mix(in srgb, var(--brand) 55%, var(--card));
  --sheen: rgba(255, 255, 255, .7);
  --scrim: rgba(18, 18, 18, .42);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--body);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

a { color: var(--brand); text-decoration: none; transition: color .16s var(--ease); }
a:hover { color: var(--brand-mid); }

::selection { background: var(--gold-soft); color: var(--text); }

/* ============================ typography ================================= */

h1, h2, h3, h4 {
  color: var(--text);
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: 1.2;
}
/* h1/h2 take the display face from site.css (Archivo, expanded, uppercase);
   these are the dashboard sizes. */
h1 { font-size: clamp(1.75rem, 1.3rem + 1.5vw, 2.5rem); margin: 0 0 8px; letter-spacing: -.01em; }
h2 { font-size: clamp(1.15rem, 1.05rem + .4vw, 1.4rem); margin: 0 0 4px; letter-spacing: 0; }
h3 { font-size: 17px; font-weight: 700; margin: 0; letter-spacing: -.01em; }

p { margin: 0 0 10px; }

.muted { color: var(--muted); }
b, strong { color: var(--text); font-weight: 650; }

/* Emphasis word in a headline — a soft green wash, never a loud one. */
.grad {
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Tiny uppercase label — "DATE & TIME", stat captions, section eyebrows. */
.eyebrow {
  display: block;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--muted);
}

.stat {
  font-family: var(--font-display);
  font-size: 30px;
  font-weight: 800;
  font-stretch: var(--display-stretch);
  letter-spacing: -.01em;
  color: var(--text);
  line-height: 1.15;
  transition: transform .25s var(--ease);
}

/* Money. The one place terracotta is allowed. */
.price { color: var(--accent); font-weight: 700; letter-spacing: -.01em; }

/* ============================== chrome =================================== */

.container {
  max-width: calc(var(--max) + 2 * var(--gutter));
  margin: 0 auto;
  padding: 30px var(--gutter) 80px;
}

/* ------------------------------ footer ---------------------------------- */

.footer {
  margin-top: 72px;
  padding: 56px 24px 0;
  background: var(--bg-2);
  border-top: 1px solid var(--line);
}
.footer-inner {
  max-width: 1300px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr;
  gap: 44px;
}
.footer h4 {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 16px;
}
.footer .brand { font-size: 20px; margin-bottom: 12px; }
.footer p { color: var(--muted); font-size: 14px; max-width: 42ch; }
.footer-links { display: grid; gap: 11px; }
.footer-links a { color: var(--muted); font-size: 14px; width: fit-content; }
.footer-links a:hover { color: var(--text); }

.footer-social { display: flex; gap: 8px; margin-top: 18px; }
.footer-social a {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--card);
  border: 1px solid var(--line);
  color: var(--muted);
  box-shadow: var(--shadow-xs);
  transition: transform .2s var(--ease), color .2s, box-shadow .2s;
}
.footer-social a:hover { color: var(--text); transform: translateY(-2px); box-shadow: var(--shadow-md); }

.footer-bottom {
  max-width: 1300px;
  margin: 44px auto 0;
  padding: 20px 0 26px;
  border-top: 1px solid var(--line-strong);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  font-size: 13px;
  color: var(--muted);
}
.status-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--brand-mid);
  margin-right: 7px;
  box-shadow: 0 0 0 3px var(--gold-soft);
}

/* ============================== buttons ==================================
   The night-edition button lives in src/styles/design.css (.btn): a pill with
   a tracked uppercase label, a light sweep and a lift on hover. Plain .btn is
   the primary action; each modifier here only sets the three colours the base
   rule paints with (--btn-bg, --btn-fg, --btn-bd), so states stay consistent. */

.btn.ghost { --btn-bg: transparent; --btn-fg: var(--ink); --btn-bd: var(--line-strong); }
.btn.ghost:hover { --btn-bg: var(--surface); }

/* WhatsApp: the glyph keeps its green so the button stays recognisable. */
.btn.ghost.wa:hover { --btn-bd: #25d366; }
.btn.ghost.wa i { color: #25d366; font-size: 17px; }

.btn.gold { --btn-bg: var(--gold-bright); --btn-fg: #15110a; --btn-bd: transparent; }
.btn.gold:hover { --btn-bg: #f6d37f; }

/* Frosted, for use over photographs and the night bands. */
.btn.on-ink, .btn.light {
  --btn-bg: rgba(28, 29, 30, .72); --btn-fg: #f1efe9; --btn-bd: rgba(255, 255, 255, .14);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
}
.btn.on-ink:hover, .btn.light:hover { --btn-bg: rgba(44, 45, 46, .9); }

/* The emphasis CTA: the gold sheen in dark, ink in light. */
.btn.grad { --btn-bd: transparent; background-image: var(--grad); }

/* Destructive and confirm actions carry white ink on a deep fill, ghost or not. */
.btn.bad, .btn.bad.ghost { --btn-bg: var(--bad-fill); --btn-fg: #fff; --btn-bd: transparent; }
.btn.good, .btn.good.ghost { --btn-bg: var(--good-fill); --btn-fg: #fff; --btn-bd: transparent; }
.btn.bad:hover, .btn.good:hover { filter: brightness(1.1); }

.btn.accent { --btn-bg: transparent; --btn-fg: var(--accent); --btn-bd: var(--accent-line); }
.btn.accent:hover { --btn-bg: var(--accent-soft); }

.btn.sm { min-height: 40px; padding: 0 18px; font-size: .78rem; gap: 8px; }
.btn.lg { min-height: 54px; padding: 0 30px; font-size: .88rem; }
.btn.block { width: 100%; }

/* A disabled button must not answer the pointer: no lift, glow or hover fill. */
.btn:disabled, .btn:disabled:hover { opacity: .45; cursor: not-allowed; box-shadow: none; transform: none; filter: none; }
.btn-primary:disabled:hover { --btn-bg: var(--brand); }
.btn:disabled:hover .i-move { transform: none; }
.btn:disabled::after { display: none; }

/* =============================== forms =================================== */

/* Every field reads as the design's .input: a surface box, hairline border,
   14px radius, gold focus ring in dark (ink in light). */
input, textarea {
  background: var(--surface);
  border: 1px solid var(--line-strong);
  color: var(--text);
  min-height: 48px;
  padding: 12px 16px;
  border-radius: var(--r-md);
  font-size: 15px;
  font-family: inherit;
  width: 100%;
  transition: border-color .18s, box-shadow .18s, background-color .18s;
}
input[type="radio"], input[type="checkbox"] {
  width: auto;
  min-width: 0;
  min-height: 0;
  padding: 0; /* the text-field padding above is meaningless on a box */
  accent-color: var(--brand);
  cursor: pointer;
}

/* A checkbox and its text as one clickable row. The plain `label` rule below is
   for field captions — its block display and 14px/7px margins left these rows
   unevenly spaced, with the box riding above the text line. */
label.check-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 9px 10px;
  border-radius: var(--r-sm);
  font-weight: 500;
  font-size: 14px;
  line-height: 1.3;
  cursor: pointer;
  transition: background-color .15s var(--ease);
}
label.check-row:hover { background: var(--brand-soft); }
label.check-row input { margin: 0; width: 16px; height: 16px; flex-shrink: 0; }
label.check-row .pill { margin-left: auto; }
.check-list {
  display: grid;
  gap: 2px;
  max-height: 220px;
  overflow-y: auto;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}

input::placeholder, textarea::placeholder { color: var(--faint); }

input:hover:not(:disabled), textarea:hover:not(:disabled) {
  border-color: var(--ink-3);
}
input:focus, textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 4px var(--brand-soft);
}
input:disabled, textarea:disabled { opacity: .6; cursor: not-allowed; }
input[type="file"] { min-height: 0; padding: 10px 12px; font-size: 13.5px; cursor: pointer; }
input[type="file"]::file-selector-button {
  margin-right: 12px; padding: 7px 14px; border: 1px solid var(--line-strong); border-radius: var(--r-pill);
  background: var(--surface-2); color: var(--ink); font: inherit; font-weight: 600; cursor: pointer;
}

textarea { min-height: 96px; resize: vertical; line-height: 1.55; }

label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  margin: 14px 0 7px;
  letter-spacing: -.005em;
}
label .muted { font-weight: 500; }

/* ---------------------------- password reveal ---------------------------- */

.pwfield { position: relative; }
/* Keep a long password clear of the eye sitting over the input's right edge. */
.pwfield input { padding-right: 44px; }
/* Edge draws its own reveal button on password inputs; ours already sits there,
   so hide the native one and leave a single eye. Scoped to .pwfield so plain
   password inputs elsewhere keep whatever the browser gives them. Kept as two
   rules: a browser that doesn't know one of these pseudo-elements throws out the
   whole selector group, taking the other with it. */
.pwfield input::-ms-reveal { display: none; }
.pwfield input::-ms-clear { display: none; }

.pwfield-eye {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  background: none;
  color: var(--muted);
  font-size: 16px;
  cursor: pointer;
  border-radius: var(--r-md);
  transition: color .18s;
}
.pwfield-eye:hover { color: var(--ink); }
.pwfield-eye:focus-visible {
  outline: none;
  color: var(--ink);
  box-shadow: var(--ring);
}

/* ------------------------- date picker / calendar ------------------------ */

/* No native date/time inputs remain — their popups are OS chrome we can't theme,
   so both the calendar and the time wheels below are rendered by us. */

.datefield { position: relative; }

/* Reads as an input, behaves as a disclosure. */
.datefield-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 48px;
  padding: 12px 16px;
  border-radius: var(--r-md);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 15px;
  text-align: left;
  cursor: pointer;
  transition: border-color .18s, box-shadow .18s;
}
.datefield-btn:hover { border-color: var(--ink-3); }
.datefield-btn.open,
.datefield-btn:focus-visible {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 4px var(--brand-soft);
}
.datefield-btn > i:first-child { color: var(--brand-mid); font-size: 16px; }
.datefield-btn span { flex: 1; }
.datefield-btn span.ph { color: var(--muted); }
.datefield-btn .chev { color: var(--muted); font-size: 16px; transition: transform .2s var(--ease); }
.datefield-btn.open .chev { transform: rotate(180deg); }

/* The popover: a frosted pane floating over the page. */
.datefield-pop {
  position: absolute;
  z-index: 50;
  top: calc(100% + 8px);
  left: 0;
  min-width: 300px;
  padding: 16px;
  border-radius: var(--r-lg);
  /* opaque enough that day numbers never fight whatever sits behind the glass */
  background: var(--pop-strong);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-lg);
  animation: popIn .2s var(--ease) both;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .datefield-pop { background: var(--pop-solid); }
}
/* On a phone it never outgrows the screen; DateField slides it sideways to fit.
   (This used to centre it with translateX(-50%), but popIn ends on
   `transform: none` and wiped that out, leaving it hanging off the right edge.) */
@media (max-width: 640px) {
  .datefield-pop { min-width: min(300px, calc(100vw - 24px)); }
}

/* A modal scrolls its own body, which would clip a floating popover. Inside one,
   the calendar expands inline and pushes the form down instead. */
.modal-card .datefield-pop {
  position: static;
  transform: none;
  width: 100%;
  min-width: 0;
  margin-top: 8px;
  box-shadow: var(--shadow-sm);
}

/* ------------------------------ select ---------------------------------- */

/* Same story as the calendar: a native <select> renders its option list as OS
   chrome, so no amount of styling on the control itself reaches the popup.
   The list below is ours. */

.selectfield { position: relative; }

/* Reads as an input, behaves as a disclosure — deliberately identical to
   .datefield-btn, minus the leading icon. */
.selectfield-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 48px;
  padding: 12px 16px;
  border-radius: var(--r-md);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 15px;
  text-align: left;
  cursor: pointer;
  transition: border-color .18s, box-shadow .18s;
}
.selectfield-btn:hover:not(:disabled) { border-color: var(--ink-3); }
.selectfield-btn.open,
.selectfield-btn:focus-visible {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 4px var(--brand-soft);
}
.selectfield-btn:disabled { opacity: .55; cursor: not-allowed; }
.selectfield-btn > span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.selectfield-btn > span.ph { color: var(--muted); }
.selectfield-btn .chev { color: var(--muted); font-size: 16px; transition: transform .2s var(--ease); }
.selectfield-btn.open .chev { transform: rotate(180deg); }

/* The list: the same frosted pane the calendar floats in. */
.select-pop {
  position: absolute;
  z-index: 50;
  top: calc(100% + 8px);
  left: 0;
  width: 100%;
  min-width: max-content;
  max-height: 264px;               /* ~7 options, then it scrolls */
  overflow-y: auto;
  padding: 6px;
  border-radius: var(--r-md);
  background: var(--pop);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-lg);
  animation: popIn .2s var(--ease) both;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .select-pop { background: var(--pop-solid); }
}

.select-opt {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 12px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--body);
  font: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
  transition: background .14s, color .14s;
}
.select-opt > span { flex: 1; }
.select-opt > i { color: var(--brand-mid); font-size: 16px; }
/* Hover and keyboard cursor are one state — the pointer moves `active`. */
.select-opt.active { background: var(--surface-2); color: var(--text); }
.select-opt.sel { color: var(--text); font-weight: 620; }
.select-opt:focus-visible { outline: none; box-shadow: var(--ring); }

/* Inside a modal the popover would be clipped by the modal's own scroll, so it
   expands inline and pushes the form down — as the calendar does. */
.modal-card .select-pop {
  position: static;
  width: 100%;
  margin-top: 8px;
  box-shadow: var(--shadow-sm);
}

.cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 12px;
}
.cal-head b { font-size: 13px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
.cal-nav {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1px solid transparent;
  background: transparent;
  color: var(--muted);
  font-size: 18px;
  cursor: pointer;
  transition: background .18s, color .18s;
}
.cal-nav:hover { background: var(--surface-2); color: var(--text); }

.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }

.cal-week {
  margin-bottom: 4px;
  color: var(--muted);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.cal-week span { text-align: center; padding: 4px 0; white-space: nowrap; overflow: hidden; text-overflow: clip; }

.cal-day {
  display: grid;
  place-items: center;
  min-width: 0;
  height: 36px;
  white-space: nowrap;
  border: 1px solid transparent;
  border-radius: 10px;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 13px;
  font-weight: 550;
  cursor: pointer;
  transition: background .16s, color .16s, transform .16s var(--ease);
}
.cal-day:hover:not(:disabled) { background: var(--surface-2); }
.cal-day:focus-visible { outline: none; box-shadow: var(--ring); }
.cal-day:disabled { color: var(--faint); cursor: not-allowed; opacity: .75; }
/* today is ringed; the selected day is filled */
.cal-day.today { border-color: var(--gold); font-weight: 700; }
.cal-day.sel {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--brand-ink);
  font-weight: 700;
  transform: scale(1.04);
  box-shadow: 0 4px 12px rgba(0, 0, 0, .24);
}

.cal-foot {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
  display: flex;
  justify-content: center;
}
.cal-foot .btn { width: 100%; }

/* ---------------------------- date + time pair --------------------------- */

/* Two buttons in a row sharing one panel below them. The panel is in normal
   flow, so it can't be clipped by a modal's scroll the way a popover would. */
.datetime { position: relative; }
.datetime-row { display: flex; gap: 8px; align-items: stretch; }
.datetime-row .datefield-btn { flex: 1 1 auto; min-width: 0; }
.datetime-row .datefield-btn span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.datetime-row .time-btn { flex: 0 0 138px; }

.dt-panel {
  margin-top: 8px;
  padding: 16px;
  border-radius: var(--r-lg);
  background: var(--pop);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-md);
  animation: slideIn .2s var(--ease) both;
}

/* ------------------------------ time wheels ------------------------------ */

.time-cols { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; }
.time-col { display: grid; gap: 6px; min-width: 0; }
.time-col .eyebrow { text-align: center; }

/* Each wheel scrolls independently; the selected option is centred on open.
   The mask fades the half-scrolled rows at each end instead of slicing them. */
.time-scroll {
  display: grid;
  gap: 4px;
  max-height: 176px;
  overflow-y: auto;
  padding: 2px;
  scrollbar-width: thin;
  scrollbar-color: var(--line-strong) transparent;
  mask-image: linear-gradient(to bottom, transparent, #000 14%, #000 86%, transparent);
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 14%, #000 86%, transparent);
}
.time-scroll::-webkit-scrollbar { width: 6px; }
.time-scroll::-webkit-scrollbar-track { background: transparent; }
.time-scroll::-webkit-scrollbar-thumb {
  background: var(--line-strong);
  border-radius: 999px;
}
.time-scroll::-webkit-scrollbar-thumb:hover { background: var(--brand-line); }

.time-opt {
  height: 36px;
  border: 1px solid transparent;
  border-radius: 10px;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 13.5px;
  font-weight: 550;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background .16s, color .16s, transform .16s var(--ease);
}
.time-opt:hover { background: var(--surface-2); }
.time-opt:focus-visible { outline: none; box-shadow: var(--ring); }
.time-opt.sel {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--brand-ink);
  font-weight: 700;
  box-shadow: 0 4px 12px rgba(0, 0, 0, .22);
}

/* ---- validation ---- */
.req { color: var(--accent); margin-left: 2px; font-weight: 700; }
input.invalid, select.invalid, textarea.invalid, input[aria-invalid="true"] {
  border-color: var(--bad-line);
  background-color: var(--bad-soft);
}
input.invalid:focus, select.invalid:focus, textarea.invalid:focus {
  border-color: var(--bad);
  box-shadow: 0 0 0 4px var(--bad-soft);
}
.field-error {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-top: 6px;
  font-size: 12px;
  font-weight: 550;
  color: var(--bad);
}

/* A checkbox and its wording on one line — the <label> wraps both, so the words
   are part of the hit area rather than a 14px box being the only target. */
.check-row {
  display: flex; align-items: center; gap: 8px;
  font-size: 14px; font-weight: 500; cursor: pointer;
}

/* ========================= layout primitives ============================= */

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: 24px;
  box-shadow: none;
  transition: box-shadow .28s var(--ease), border-color .28s var(--ease), transform .28s var(--ease);
}

.grid { display: grid; gap: 22px; }
/* auto-FILL, not auto-fit: auto-fit collapses the empty tracks, so a result set
   smaller than one row (a single venue after a narrow filter) stretched that one
   card across the whole grid. auto-fill keeps the tracks, so a lone card is card
   -sized. With a full row the two behave identically.
   The 320px floor keeps 3 roomy cards on a desktop — a 4th column would orphan
   the 5th venue and squeeze the card text into extra lines. */
/* min() so one card never outgrows a phone narrower than 320px + gutters. */
.grid.cols { grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr)); }

.row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.row.between { justify-content: space-between; }

.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin: 40px 0 20px;
}
.section-head p { margin: 3px 0 0; color: var(--muted); font-size: 14px; }

.page-head { margin-bottom: 26px; }
.page-head p { margin: 5px 0 0; color: var(--muted); }

/* Icon tile that leads a section heading, as in the reference's card headers. */
.head-ico {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--gold-soft);
  border: 0;
  color: var(--gold);
  font-size: 17px;
  flex: none;
}

/* ================================ hero ===================================
   The page heroes are the night bands in src/styles/design.css (.hero,
   .page-hero); only the small capsule badge remains here. */

/* The reference's "Eco-Certified" capsule: cream fill, terracotta ink. */
.hero-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 22px;
  padding: 8px 16px 8px 10px;
  border-radius: var(--pill);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  font-size: 13px;
  font-weight: 620;
  color: var(--accent-hover);
}
.hero-badge i {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--accent-fill, var(--accent));
  color: #fff;
  font-size: 11px;
}

/* ---------------------- search bar (frosted, floating) ------------------- */

.searchbar {
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: 940px;
  margin: 34px auto 0;
  padding: 10px 10px 10px 22px;
  border-radius: var(--pill);
  background: var(--glass);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid var(--glass-line);
  box-shadow: var(--shadow-lg);
  transition: box-shadow .3s var(--ease);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .searchbar { background: var(--pop-solid); }
}
.searchbar:focus-within {
  box-shadow: 0 24px 60px rgba(0, 0, 0, .12), 0 0 0 4px rgba(0, 0, 0, .08);
}
.searchbar .search-ico { font-size: 18px; color: var(--brand-mid); display: flex; }
.searchbar .search-input {
  flex: 1;
  min-width: 0;
  font-size: 15px;
  border: 0;
  padding: 11px 4px;
  background: transparent;
  color: var(--text);
}
.searchbar .search-input:hover,
.searchbar .search-input:focus { box-shadow: none; background: transparent; }
.searchbar .btn { border-radius: var(--pill); padding-inline: 24px; }
.searchbar .btn.ghost { box-shadow: none; }

.filter-panel { border-radius: var(--r-lg); }
.filters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 16px;
  align-items: end;
}
.filters label { margin-top: 0; }

/* ============================ stats sentence ============================= */

/* One line of prose instead of a tile band — same figures, far less furniture.
   Sits in the same glass chip vocabulary as .hero-badge so the two read as a
   pair framing the search bar. */
.stats-line {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: fit-content;
  max-width: 100%;
  margin: 40px auto 0;
  padding: 13px 24px;
  border-radius: var(--pill);
  background: var(--glass);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--glass-line);
  box-shadow: var(--shadow-md);
  color: var(--muted);
  font-size: 15px;
  text-align: center;
  text-wrap: balance;
}
/* The figures carry the headline's gradient; tabular digits keep them from
   jittering as filters change the numbers. */
.stats-line b {
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 560px) {
  .stats-line { border-radius: var(--r-lg); padding: 12px 18px; font-size: 14px; }
}

/* ========================== venue (hall) cards =========================== */

.hall-card {
  display: flex;
  flex-direction: column;
  padding: 10px;
  overflow: hidden;
  cursor: pointer;
  color: inherit;
  box-shadow: var(--shadow-sm);
  transition: transform .32s var(--ease), box-shadow .32s var(--ease), border-color .32s var(--ease);
}
a.hall-card { display: flex; text-decoration: none; }
.hall-card:hover {
  transform: translateY(-5px);
  box-shadow: var(--shadow-lg);
  border-color: var(--brand-line);
}

.hall-media {
  position: relative;
  overflow: hidden;
  border-radius: 15px;
  isolation: isolate;
}
.hall-photo {
  height: 208px;
  border-radius: 15px;
  background-size: cover;
  background-position: center;
  background-color: var(--card2);
  transition: transform .7s var(--ease);
}
.hall-card:hover .hall-photo { transform: scale(1.05); }

/* Frosted price tag over the photo — money still reads terracotta. */
.price-chip {
  position: absolute;
  z-index: 2;
  top: 12px;
  right: 12px;
  padding: 7px 13px;
  border-radius: var(--pill);
  background: rgba(252, 252, 249, .9);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, .9);
  color: var(--accent-fill);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -.01em;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .16);
}

.hall-body { padding: 18px 10px 8px; display: flex; flex-direction: column; gap: 10px; flex: 1; }
.hall-body h3 { font-size: 17px; font-weight: 700; }

.rating-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
  font-weight: 650;
  color: var(--text);
  white-space: nowrap;
}
.rating-badge i { color: var(--gold); font-size: 13px; }
.rating-badge .muted { font-weight: 500; }
/* an unrated venue reads as "New", not as a zero-star rating */
.rating-badge.new {
  padding: 3px 10px;
  border-radius: var(--pill);
  background: var(--brand-soft);
  border: 1px solid var(--brand-line);
  color: var(--text);
  font-size: 11.5px;
}

.hall-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 7px 16px;
  font-size: 13px;
  color: var(--muted);
}
.hall-meta span { display: inline-flex; align-items: center; gap: 6px; }
.hall-meta i { color: var(--brand-mid); font-size: 14px; }

.hall-cta {
  display: block;
  margin-top: auto;
  padding: 11px;
  border-radius: var(--r-md);
  border: 1px solid var(--line-strong);
  background: var(--card);
  color: var(--text);
  text-align: center;
  font-size: 13.5px;
  font-weight: 650;
  transition: background .22s var(--ease), color .22s, border-color .22s, box-shadow .22s;
}
.hall-card:hover .hall-cta {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--brand-ink);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .22);
}

.hall-photo-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--grad-soft);
  color: var(--brand-line);
  font-size: 26px;
}

/* ========================= pills / chips / badges ======================== */

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 600;
  padding: 5px 12px;
  border-radius: var(--pill);
  background: var(--card2);
  border: 1px solid var(--line);
  color: var(--muted);
  letter-spacing: -.005em;
  white-space: nowrap;
}
/* Only status values are title-cased — capitalising every pill would turn
   "applies to you" into "Applies To You" and audit actions into "Booking.create". */
.pill.status { text-transform: capitalize; }
.pill.good  { background: var(--good-soft);   color: var(--good);   border-color: var(--good-line); }
.pill.warn  { background: var(--warn-soft);   color: var(--warn);   border-color: var(--warn-line); }
.pill.bad   { background: var(--bad-soft);    color: var(--bad);    border-color: var(--bad-line); }
.pill.brand { background: var(--brand-soft);  color: var(--text);   border-color: var(--brand-line); }
.pill.accent{ background: var(--accent-soft); color: var(--accent-hover); border-color: var(--accent-line); }

/* ============================================================================
   Switch — a single yes/no permission, flipped in place.
   Same tokens as the pills: brand fill when on, a hairline track when off. The
   real <input> stays in the DOM (hidden) so it keeps keyboard and screen-reader
   behaviour; the track is drawn by its sibling.
   ========================================================================== */
.switch { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }
.switch input {
  position: absolute; opacity: 0; width: 0; height: 0;
}
.switch-track {
  position: relative;
  flex: none;
  width: 38px; height: 22px;
  border-radius: var(--pill);
  background: var(--card2);
  border: 1px solid var(--line-strong);
  transition: background .15s var(--ease), border-color .15s var(--ease);
}
.switch-track::after {
  content: '';
  position: absolute; top: 2px; left: 2px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--faint);
  transition: transform .15s var(--ease), background .15s var(--ease);
}
.switch input:checked + .switch-track { background: var(--brand); border-color: var(--brand); }
.switch input:checked + .switch-track::after { transform: translateX(16px); background: var(--brand-ink); }
.switch input:focus-visible + .switch-track { box-shadow: var(--ring); }
.switch input:disabled + .switch-track { opacity: .55; }
.switch:has(input:disabled) { cursor: progress; }
.switch-label { font-size: 12.5px; color: var(--body); }

.stars { color: var(--gold); letter-spacing: 1px; display: inline-flex; gap: 1px; }
.stars i { font-size: 14px; }

.badge-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  margin-left: 4px;
}

/* ===================== availability: sessions & hours ==================== */

.sessions { display: grid; gap: 10px; }
.session {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 14px 16px;
  border-radius: var(--r-md);
  font-size: 14px;
  cursor: pointer;
  border: 1px solid var(--line-strong);
  background: var(--card);
  transition: border-color .2s, background .2s, box-shadow .2s, transform .2s var(--ease);
}
.session:hover {
  border-color: var(--brand-line);
  background: var(--brand-soft);
  transform: translateX(2px);
}
.session .muted { font-size: 12.5px; }
.session.busy {
  cursor: not-allowed;
  color: var(--faint);
  background: var(--card2);
  border-color: var(--line);
  transform: none;
}
.session.busy b { text-decoration: line-through; color: var(--faint); }
.session.busy:hover { border-color: var(--line); background: var(--card2); transform: none; }
.session.sel {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--brand-ink);
  box-shadow: 0 8px 22px rgba(0, 0, 0, .22);
  transform: none;
}
.session.sel b { color: var(--brand-ink); }
.session.sel .muted { color: var(--brand-ink); opacity: .78; }

/* The whole-day shortcut sits under the three sessions. Dashed while unpicked so
   it reads as "all of the above" rather than a fourth session; solid once taken
   up, since at that point it is the booking. */
.session.full-day { border-style: dashed; }
.session.full-day.sel { border-style: solid; }

/* Shut, not sold. Tinted rather than merely greyed, because a closed hour reads
   differently from a booked one at a glance — and the two are not the same news
   for anyone deciding whether to ring the venue. */
.session.busy.blocked { background: var(--warn-soft); border-color: var(--warn-line); }
.session.busy.blocked:hover { background: var(--warn-soft); border-color: var(--warn-line); }
.session.busy.blocked .muted { color: var(--warn); }

/* Says the venue is closed, and why, on a day the manager has taken off sale. */
.slot-notice {
  display: flex; gap: 10px; align-items: flex-start;
  margin-top: 12px; padding: 12px 14px;
  background: var(--warn-soft); border: 1px solid var(--warn-line);
  border-radius: var(--r-md); font-size: 13px;
}
.slot-notice > i { flex-shrink: 0; font-size: 18px; color: var(--warn); }
.slot-notice > div { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.slot-notice b { color: var(--warn); }

/* ------------------------- manager booking calendar --------------------- */

/* NOTE the bcal- prefix: the date-picker popup above already owns .cal-grid,
   .cal-day, .cal-week etc. Sharing those names silently restyled every date
   field in the app, so this calendar keeps its own namespace.

   Compact by design: the grid is a glance-level overview, not where booking
   detail is read — that is the table underneath. */
.bcal-grid {
  /* minmax(0, ...): a bare 1fr would not shrink below the buttons' width, which
     on a phone pushed the days out of line with the weekday row above them and
     Sunday off the card. */
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px;
  /* Fixed rows: leading/trailing pad cells are empty, and letting rows size to
     content made the first row taller than the rest. */
  grid-auto-rows: 42px;
  max-width: 380px;
}
.bcal-head-row { grid-auto-rows: auto; }
.bcal-head-row { margin-bottom: 4px; }
.bcal-weekday {
  text-align: center; font-size: 10px; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
}

.bcal-cell {
  position: relative;
  /* min-width:0 because a grid item defaults to min-width:auto and would refuse
     to shrink to its column; an explicit height rather than aspect-ratio, which
     resolved against the wrong axis here and blew the cells up to 120px. */
  min-width: 0;
  height: 42px;
  display: flex; align-items: center; justify-content: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--card);
  font: inherit; color: var(--text);
  cursor: default;
  transition: filter .15s, box-shadow .15s;
}
.bcal-cell.empty { border: 0; background: none; }
.bcal-cell.has { cursor: pointer; }
.bcal-cell.has:hover { filter: brightness(1.08); }
.bcal-daynum { font-size: 12px; font-weight: 600; line-height: 1; }

/* The whole cell carries the colour: one hue, stronger the more of the day is
   sold. Numerals use the page's text colour on the two lighter fills. */
.bcal-cell.k-full { background: var(--brand);  border-color: var(--brand);  color: var(--brand-ink); }
.bcal-cell.k-half { background: var(--half-fill); border-color: var(--half-fill); color: var(--text); }
.bcal-cell.k-hour { background: var(--hourly-fill); border-color: var(--hourly-line); color: var(--text); }
/* A day the manager took off sale. Listed after the booking fills but never
   applied over one — a booking on a blocked day is still a booking, and the
   component only reaches for this class when the day has none. */
.bcal-cell.blocked { background: var(--blocked-fill); border-color: var(--blocked-fill); color: #fff; }

/* A day with requests nobody has answered yet. A corner dot, not a fill: a
   request has not taken the day, so it must not read like a booking — but the
   manager still has to see there is something to decide, including on a day
   that is already sold. */
.bcal-cell.asks::after {
  content: '';
  position: absolute; top: 4px; right: 4px;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--warn);
  box-shadow: 0 0 0 1.5px var(--card);
}
.bcal-cell.has.asks::after { background: var(--gold-bright); box-shadow: 0 0 0 1.5px var(--night); }

/* Selection and today are rings, not fills, so neither hides the day's colour. */
.bcal-cell.sel { box-shadow: 0 0 0 2px var(--text); }
.bcal-cell.today .bcal-daynum { text-decoration: underline; text-underline-offset: 2px; }

/* Legend swatches mirror the cell fills. */
.bcal-swatch {
  display: inline-block; width: 10px; height: 10px; border-radius: 3px;
  vertical-align: middle;
}
.bcal-swatch.full { background: var(--brand); }
.bcal-swatch.half { background: var(--half-fill); }
.bcal-swatch.hour { background: var(--hourly-fill); box-shadow: inset 0 0 0 1px var(--hourly-line); }
.bcal-swatch.blocked { background: var(--blocked-fill); }
.bcal-swatch.asks { background: var(--warn); border-radius: 50%; width: 8px; height: 8px; }

.bcal-legend {
  display: flex; flex-wrap: wrap; gap: 14px;
  margin-bottom: 10px; font-size: 12px; color: var(--body);
}
.bcal-legend span { display: inline-flex; align-items: center; gap: 6px; }

/* The calendar's venue chooser sits full width on its own row so a long hall
   name is not squeezed against the month controls. (The bookings list uses
   .venue-switch instead — a list of chips, not a dropdown.) */
.venue-filter { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.venue-filter label { font-size: 12px; font-weight: 600; color: var(--muted); white-space: nowrap; }
.venue-filter select { max-width: 280px; }

/* The heading is the month/year jump control. */
.bcal-jump-wrap { position: relative; }
.bcal-jump-btn {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 8px; margin-left: -8px;
  border: 0; border-radius: var(--r-sm);
  background: none; color: var(--text);
  font: inherit; font-family: var(--font-display); font-size: 17px; font-weight: 800;
  font-stretch: var(--display-stretch); text-transform: uppercase; letter-spacing: 0;
  cursor: pointer;
}
.bcal-jump-btn:hover { background: var(--surface-2); }
.bcal-jump-btn i { font-size: 16px; color: var(--muted); }

.bcal-jump {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 30;
  width: 232px; padding: 10px;
  background: var(--card); border: 1px solid var(--line-strong);
  border-radius: var(--r-md); box-shadow: var(--shadow-lg, 0 18px 40px rgba(0, 0, 0, .18));
}
.bcal-jump-year { margin-bottom: 8px; }
.bcal-jump-year b { font-size: 14px; }

.bcal-months { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.bcal-month {
  padding: 7px 0;
  border: 1px solid transparent; border-radius: var(--r-sm);
  background: none; color: var(--text);
  font: inherit; font-size: 12.5px; font-weight: 600;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.bcal-month:hover { background: var(--surface-2); }
/* the month in view is filled; the real current month is only ringed */
.bcal-month.now { border-color: var(--brand-line); }
.bcal-month.sel { background: var(--brand); border-color: var(--brand); color: var(--brand-ink); }

/* Calendar left, the selected day's bookings right. */
.bcal-layout { display: flex; gap: 18px; align-items: flex-start; }
.bcal-main { flex: 0 0 auto; }
.bcal-detail {
  flex: 1 1 0;
  min-width: 0;              /* so long venue names wrap instead of stretching it */
  align-self: stretch;
  display: flex; flex-direction: column;   /* lets the empty state fill the column */
  padding-left: 18px;
  border-left: 1px solid var(--line);
}

/* Nothing selected: centre the prompt in the empty column rather than leaving it
   stranded in the top-left corner. */
.bcal-empty {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; min-height: 150px;
  color: var(--muted); font-size: 13px; text-align: center;
}
.bcal-empty i { font-size: 26px; color: var(--faint); }

.bcal-list { display: grid; gap: 10px; max-height: 340px; overflow-y: auto; }
.bcal-item {
  display: grid; gap: 4px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--card2, var(--card));
  font-size: 13.5px;
}

/* Too narrow for two columns — fall back to the detail underneath. */
@media (max-width: 780px) {
  .bcal-layout { flex-direction: column; }
  .bcal-main { width: 100%; }
  .bcal-detail {
    width: 100%;
    padding-left: 0; border-left: 0;
    padding-top: 14px; border-top: 1px solid var(--line);
  }
}

.slots { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 8px; }
.slot {
  padding: 11px 8px;
  border-radius: var(--r-sm);
  text-align: center;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  border: 1px solid var(--line-strong);
  background: var(--card);
  transition: border-color .16s, background .16s, color .16s, box-shadow .16s;
}
.slot:hover { border-color: var(--brand-line); background: var(--brand-soft); }
.slot.busy {
  cursor: not-allowed;
  text-decoration: line-through;
  color: var(--faint);
  background: var(--card2);
  border-color: var(--line);
}
.slot.busy:hover { border-color: var(--line); background: var(--card2); color: var(--faint); }
/* Shut, not sold — same distinction the sessions make. */
.slot.busy.blocked,
.slot.busy.blocked:hover { background: var(--warn-soft); border-color: var(--warn-line); color: var(--warn); }
.slot.sel {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--brand-ink);
  box-shadow: 0 4px 12px rgba(0, 0, 0, .22);
}

.duration-bar {
  margin-top: 12px;
  padding: 11px 15px;
  border-radius: var(--r-md);
  background: var(--brand-soft);
  border: 1px solid var(--brand-line);
  font-size: 13px;
  color: var(--text);
}

/* The picker's last line: "pick a session" before a choice, the chosen window
   after it. Both live in the same grid cell, so the box is always as tall as the
   taller of the two and does not change height when one replaces the other — the
   fields below the picker must not move when a slot is tapped, or a click aimed
   at one lands in the next. */
.slot-footnote {
  display: grid;
  margin-top: 14px;
  font-size: 13.5px;
}
.slot-footnote > p {
  grid-area: 1 / 1;
  margin: 0;
}

/* -------------------- booking panel (the right rail) -------------------- */

/* NOT sticky. The rail holds this panel AND the "Contact venue" card below it,
   so pinning the panel meant the contact card scrolled up underneath it — and a
   sticky box is *positioned*, so it painted over its static sibling and hid the
   card outright. The panel's whole sticky travel (rail height minus its own)
   happened to equal the gap to that card, so every pixel of the effect was spent
   covering it. Re-pinning this requires the panel to be the only thing in the
   rail. */
.booking-panel { padding: 0; overflow: hidden; }
.booking-panel > .panel-head {
  padding: 20px 24px;
  background: var(--grad-soft);
  border-bottom: 1px solid var(--line);
}
.booking-panel > .panel-head h3 { font-size: 18px; }
.booking-panel > .panel-head p { margin: 3px 0 0; font-size: 13px; color: var(--muted); }
.booking-panel > .panel-body { padding: 22px 24px 24px; }

/* The reference's "Total Estimate": a hairline rule, a caption, a big green
   number, and the currency in terracotta. No dark slab. */
.total-box {
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}
.total-box .total-when { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.total-box .total-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-top: 8px;
}
.total-box b {
  color: var(--text);
  font-size: 32px;
  font-weight: 750;
  letter-spacing: -.035em;
  line-height: 1.1;
}
.total-box .cur {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .1em;
  color: var(--accent);
}

/* Line items above the total (venue, buffer, fees). */
.sum-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 0;
  font-size: 13.5px;
  color: var(--body);
}
.sum-line b { color: var(--text); font-weight: 620; }

.trust-row {
  display: flex;
  justify-content: center;
  gap: 20px;
  margin-top: 14px;
  font-size: 11px;
  font-weight: 650;
  letter-spacing: .06em;
  color: var(--muted);
}
.trust-row span { display: inline-flex; align-items: center; gap: 5px; }
.trust-row i { color: var(--brand-mid); }

/* ============================== tables =================================== */

.table-wrap { overflow-x: auto; border-radius: var(--r-md); }
.table-card { padding: 10px; }

table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 14px; }
thead th {
  background: var(--card2);
  color: var(--muted);
  font-weight: 700;
  font-size: 10.5px;
  letter-spacing: .09em;
  text-transform: uppercase;
  text-align: left;
  padding: 13px 15px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
thead th:first-child { border-radius: var(--r-md) 0 0 var(--r-md); }
thead th:last-child  { border-radius: 0 var(--r-md) var(--r-md) 0; }
td {
  text-align: left;
  padding: 15px;
  border-bottom: 1px solid var(--line);
  color: var(--body);
  vertical-align: middle;
}
td b { color: var(--text); }
tbody tr { transition: background .18s; }
tbody tr:hover { background: var(--tab-hover); }
tbody tr:last-child td { border-bottom: 0; }

.countdown {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  padding: 4px 12px;
  border-radius: var(--pill);
  font-size: 13px;
}

/* =============================== tabs ==================================== */

.tabbar {
  display: inline-flex;
  gap: 4px;
  margin-bottom: 26px;
  flex-wrap: wrap;
  padding: 4px;
  border-radius: var(--pill);
  background: var(--surface-2);
  border: 1px solid var(--line);
}
.tabbar a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 18px;
  border-radius: var(--pill);
  color: var(--ink-2);
  cursor: pointer;
  font-weight: 700;
  font-size: 12.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background .22s var(--ease), color .22s, box-shadow .22s;
}
.tabbar a:hover { color: var(--text); background: var(--tab-hover); }
/* The tab in view is the one inverted pill: cream on the night canvas, ink in
   light. */
.tabbar a.active {
  background: var(--ink);
  color: var(--bg);
  box-shadow: var(--shadow-sm);
}
.tabbar a.active:hover { background: var(--ink); color: var(--bg); }
.tabbar a:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 2px; }

/* ============================================================================
   Venue switcher — which auditorium the list below is showing.
   A chip per venue rather than a dropdown: a manager with three or four halls
   sees all of them and their counts at once, and switches in one click instead
   of open-read-pick. It scrolls sideways rather than wrapping, so a long row
   never pushes the list it belongs to off the first screen.
   ========================================================================= */

.venue-switch {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
  padding-bottom: 4px;           /* the scrollbar's lane, when there is one */
  overflow-x: auto;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.venue-switch button {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-radius: var(--pill);
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--body);
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background .22s var(--ease), border-color .22s, color .22s, box-shadow .22s;
}
.venue-switch button i { font-size: 15px; color: var(--faint); transition: color .22s; }
.venue-switch button:hover {
  border-color: var(--brand-line);
  background: var(--brand-soft);
  color: var(--text);
}
.venue-switch button:hover i { color: var(--brand-mid); }
/* Same tokens the brand pill is built from — proven on both canvases. */
.venue-switch button.active {
  background: var(--brand-soft);
  border-color: var(--brand-line);
  color: var(--text);
  box-shadow: var(--shadow-sm);
}
.venue-switch button.active i { color: var(--brand-mid); }

/* The count rides along so a venue's load is legible without switching to it. */
.venue-switch-count {
  min-width: 20px;
  padding: 0 6px;
  border-radius: var(--pill);
  background: var(--bg-2);
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 700;
  line-height: 19px;
  text-align: center;
}
.venue-switch button.active .venue-switch-count {
  background: var(--brand);
  color: var(--brand-ink);
}

/* A venue's name can run long; the row scrolls, but no single chip may eat the
   width of a phone. */
@media (max-width: 560px) {
  .venue-switch-name {
    max-width: 42vw;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* ============================== modals =================================== */

.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 140;   /* over the fixed header (100) and the phone dock (130) */
  padding: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--scrim);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.modal-card {
  width: 100%;
  max-height: 90vh;
  overflow-y: auto;
  /* A dialog never scrolls sideways. Two things are needed: overflow-wrap so an
     unbreakable string (an uploaded filename, a pasted URL) wraps instead of
     widening the card, and an explicit overflow-x — when one axis is auto the
     other computes from `visible` to `auto`, which is what put a horizontal
     scrollbar under the venue-verification modal. */
  overflow-x: hidden;
  overflow-wrap: anywhere;
  padding: clamp(20px, 3.4vw, 32px);
  border-radius: var(--r-xl);
  background: var(--bg);
  border-color: var(--line);
  box-shadow: var(--shadow-lg);
}
/* nowrap: a long title ("Reschedule · Skyline Conference Hall") would otherwise
   push the close button onto its own line */
.modal-card > .row.between:first-child {
  margin-bottom: 8px;
  flex-wrap: nowrap;
  gap: 14px;
  align-items: flex-start;
}
.modal-card > .row.between:first-child h2 { font-size: clamp(1.3rem, 1.1rem + .8vw, 1.7rem); line-height: 1.1; min-width: 0; padding-top: 4px; }
.modal-card > .row.between:first-child .btn.ghost.sm {
  width: 42px;
  min-height: 42px;
  height: 42px;
  flex: none;
  padding: 0;
  border-radius: 50%;
  font-size: 18px;
  color: var(--ink-2);
}
.modal-card > .row.between:first-child .btn.ghost.sm:hover { color: var(--bad); border-color: var(--bad-line); }

.checkout-venue {
  display: flex;
  gap: 14px;
  align-items: center;
  margin-bottom: 18px;
  padding: 13px;
  border-radius: var(--r-md);
  background: var(--grad-soft);
  border: 1px solid var(--line);
}
.checkout-venue .hall-photo { flex: 0 0 88px; height: 64px; border-radius: 10px; }
.checkout-venue b { display: block; letter-spacing: -.01em; }

/* ------------------------- cancellation modal --------------------------- */

.cancel-summary {
  padding: 15px 17px;
  border-radius: var(--r-md);
  background: var(--card2);
  border: 1px solid var(--line);
  margin-bottom: 18px;
}
/* "the venue will confirm this" — the whole point of the request popup, and
   the note that repeats it on a pending booking tile. */
.await-box {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 15px 17px;
  border-radius: var(--r-md);
  background: var(--warn-soft);
  border: 1px solid var(--warn-line);
}
.await-box > i { color: var(--warn); font-size: 20px; line-height: 1.3; flex: none; }
.await-box b { display: block; color: var(--warn); font-size: 14.5px; }
.await-box p { margin: 3px 0 0; font-size: 13px; color: var(--muted); }
.await-box .row { margin-top: 10px; gap: 8px; }

.refund-box {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 17px 19px;
  border-radius: var(--r-md);
  font-size: 15px;
}
.refund-box b { font-size: 24px; letter-spacing: -.03em; }
.refund-box.good { background: var(--good-soft); border: 1px solid var(--good-line); color: var(--good); }
.refund-box.good b { color: var(--good); }
.refund-box.none { background: var(--warn-soft); border: 1px solid var(--warn-line); color: var(--warn); }
.refund-box.none b { color: var(--warn); }

.policy-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 5px; }
.policy-list li {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: space-between;
  padding: 11px 14px;
  border-radius: var(--r-sm);
  font-size: 13px;
  border: 1px solid transparent;
  color: var(--muted);
}
.policy-list li b { color: var(--text); font-weight: 650; }
.policy-list li.active {
  background: var(--brand-soft);
  border-color: var(--brand-line);
  color: var(--text);
}

/* =========================== venue gallery =============================== */

.gallery-main {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-md);
}
.gallery-main .hall-photo { height: 400px; border-radius: var(--r-lg); }
.gallery-main:hover .hall-photo { transform: scale(1.03); }
.gallery-zoom {
  position: absolute;
  right: 16px;
  bottom: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--pop);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--text);
  font-size: 18px;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity .22s var(--ease), transform .22s var(--ease);
}
.gallery-main:hover .gallery-zoom,
.gallery-main:focus-visible .gallery-zoom { opacity: 1; transform: none; }

.gallery-thumbs { display: flex; gap: 10px; margin-top: 12px; flex-wrap: wrap; }
.gallery-thumb {
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  border-radius: 12px;
  line-height: 0;
  overflow: hidden;
}
.gallery-thumb .hall-photo {
  height: 76px;
  width: 108px;
  border-radius: 12px;
  opacity: .62;
  transition: opacity .22s, transform .35s var(--ease);
}
.gallery-thumb:hover .hall-photo { opacity: 1; transform: scale(1.06); }
.gallery-thumb.active .hall-photo { opacity: 1; box-shadow: 0 0 0 2.5px var(--brand) inset; }

/* ------------------------------ lightbox -------------------------------- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 145;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(5, 8, 7, .94);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  padding: 40px;
  cursor: zoom-out;
}
.lightbox img {
  max-width: 92vw;
  max-height: 88vh;
  border-radius: var(--r-md);
  box-shadow: 0 30px 90px rgba(0, 0, 0, .6);
  cursor: default;
}
.lightbox-close, .lightbox-nav {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(255, 255, 255, .16);
  border-radius: 50%;
  cursor: pointer;
  background: rgba(255, 255, 255, .12);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: #fff;
  transition: background .2s, transform .2s var(--ease);
}
.lightbox-close { top: 22px; right: 26px; width: 42px; height: 42px; font-size: 22px; }
.lightbox-nav { top: 50%; transform: translateY(-50%); width: 48px; height: 48px; font-size: 28px; }
.lightbox-nav.prev { left: 22px; }
.lightbox-nav.next { right: 22px; }
.lightbox-close:hover { background: rgba(255, 255, 255, .26); transform: scale(1.06); }
.lightbox-nav:hover { background: rgba(255, 255, 255, .26); transform: translateY(-50%) scale(1.06); }
.lightbox-count {
  position: absolute;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  padding: 6px 14px;
  border-radius: var(--pill);
  background: rgba(255, 255, 255, .12);
  color: #eef2ee;
  font-size: 13px;
  letter-spacing: .04em;
}

/* ========================= bookings & directory ========================== */

.booking-card { display: flex; gap: 20px; align-items: stretch; padding: 18px; }
.booking-card:hover { box-shadow: var(--shadow-md); border-color: var(--brand-line); }
.booking-thumb { flex: 0 0 172px; display: block; border-radius: var(--r-md); overflow: hidden; }
.booking-thumb .hall-photo { height: 100%; min-height: 122px; border-radius: var(--r-md); }
.booking-thumb:hover .hall-photo { transform: scale(1.05); }
.booking-body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.booking-body h3 { font-size: 17px; }
.booking-body h3 a { color: inherit; text-decoration: none; }
.booking-body h3 a:hover { color: var(--brand-mid); }


.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); gap: 20px; }
.step { text-align: center; padding: 28px 22px; }
.step-ico {
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  margin: 0 auto 16px;
  border-radius: 50%;
  background: var(--gold-soft);
  border: 0;
  color: var(--gold);
  font-size: 22px;
  transition: transform .32s var(--ease), box-shadow .32s var(--ease);
}
.step:hover .step-ico {
  transform: translateY(-3px) rotate(-4deg);
  box-shadow: 0 10px 24px rgba(0, 0, 0, .14);
}
.step h3 { margin-bottom: 8px; }
.step p { color: var(--muted); font-size: 13.5px; margin: 0; }

/* Section band with the deeper wash (full-bleed inside .container). */
.band {
  margin: 64px -24px 0;
  padding: 52px 24px;
  background: var(--bg-2);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.band > * { max-width: 1300px; margin-inline: auto; }

/* ---------------------------- empty states ------------------------------ */

.empty {
  text-align: center;
  padding: 60px 24px;
  border-radius: var(--r-lg);
  border: 1px dashed var(--line-strong);
  background: var(--empty-bg);
  color: var(--muted);
}
.empty i { font-size: 34px; color: var(--gold); display: block; margin-bottom: 14px; }
.empty b { display: block; font-size: 17px; margin-bottom: 4px; }

/* --------------------------- loading states ----------------------------- */

/* Skeletons breathe with a slow sheen instead of a spinner. */
.skeleton {
  position: relative;
  overflow: hidden;
  background: var(--card2);
  border-radius: var(--r-sm);
}
.skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, var(--sheen), transparent);
  animation: shimmer 1.5s infinite;
}
.sk-photo { height: 208px; border-radius: 15px; }
.sk-line { height: 12px; border-radius: 6px; margin-top: 12px; }
.sk-line.w60 { width: 60%; }
.sk-line.w40 { width: 40%; }
.sk-line.tall { height: 34px; border-radius: var(--r-md); margin-top: 18px; }

/* ------------------------------ tooltips -------------------------------- */

[data-tip] { position: relative; }
[data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translate(-50%, 4px);
  padding: 7px 11px;
  border-radius: var(--r-sm);
  background: var(--ink);
  color: var(--bg);
  font-size: 12px;
  font-weight: 550;
  line-height: 1.35;
  letter-spacing: -.005em;
  /* Long tips wrap rather than run off the side of the screen. */
  width: max-content;
  max-width: 240px;
  text-align: center;
  box-shadow: var(--shadow-md);
  pointer-events: none;
  z-index: 30;
  /* Not rendered until wanted: an invisible tip still counts as page width, and
     one near the right edge was making the page scroll sideways. */
  display: none;
}
[data-tip]:hover::after,
[data-tip]:focus-visible::after { display: block; transform: translate(-50%, 0); animation: tipIn .18s var(--ease) both; }
@keyframes tipIn { from { opacity: 0; } to { opacity: 1; } }

/* A tip on something at the left edge of a clipped box (the booking panel is
   overflow:hidden) opens rightwards from its anchor instead of centring on it,
   so its first half is not cut off. */
[data-tip].tip-start::after { left: 0; transform: translate(0, 4px); text-align: left; }
[data-tip].tip-start:hover::after,
[data-tip].tip-start:focus-visible::after { transform: translate(0, 0); }

/* Anything near the top edge (the nav) tips downward instead. */
[data-tip].tip-below::after {
  bottom: auto;
  top: calc(100% + 8px);
  transform: translate(-50%, -4px);
}
[data-tip].tip-below:hover::after,
[data-tip].tip-below:focus-visible::after { transform: translate(-50%, 0); }

/* =============================== toast =================================== */

.toast {
  position: fixed;
  /* Bottom right, out of the way of the page; phones: see below. */
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  right: 24px;
  transform: translateY(16px);
  max-width: min(520px, calc(100vw - 32px));
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--ink);
  color: var(--bg);
  border: 1px solid transparent;
  padding: 14px 24px;
  border-radius: var(--pill);
  box-shadow: var(--shadow-lg);
  font-size: 14px;
  font-weight: 550;
  opacity: 0;
  transition: opacity .3s var(--ease), transform .3s var(--ease);
  z-index: 150;
  /* % not vw (100vw counts the scrollbar gutter); long messages wrap, centred. */
  width: max-content;
  max-width: min(560px, calc(100% - 32px));
  text-align: left;
  line-height: 1.4;
  overflow-wrap: anywhere;
  pointer-events: none;
  border-radius: var(--r-md);
}
.toast i { font-size: 18px; flex: none; }
/* A two-line message in a pill reads as a lozenge; round it less. */
@media (max-width: 560px) {
  .toast { padding: 12px 18px; font-size: 13.5px; }
}
/* Phones and tablets: across the bottom, above the menu dock. */
@media (max-width: 1080px) {
  .toast { left: 16px; right: 16px; width: auto; max-width: none; bottom: calc(92px + env(safe-area-inset-bottom, 0px)); }
}
.toast.show { opacity: 1; transform: none; }
/* Status toasts keep white ink on a deep fill: 4.6:1 or better on each. */
.toast.good { background: var(--good-fill); color: #fff; }
.toast.warn { background: var(--warn-fill); color: #fff; }
.toast.bad  { background: var(--bad-fill); color: #fff; }

/* ============================ page grids ================================= */

.detail-grid { grid-template-columns: 1.55fr 1fr; align-items: start; }
.contact-grid { grid-template-columns: 1fr 1.15fr; gap: 22px; align-items: start; }

/* ============================== icons ==================================== */

/* ---------- account avatar + menu ---------- */
.user-menu { position: relative; display: inline-flex; }
.avatar {
  display: grid; place-items: center;
  width: 36px; height: 36px; padding: 0;
  border: 1px solid var(--brand-line); border-radius: 50%;
  background: var(--grad); color: var(--brand-ink);
  font-size: 13px; font-weight: 700; letter-spacing: .02em;
  font-family: inherit; cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: transform .15s var(--ease), box-shadow .15s var(--ease);
}
.avatar:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); }
.avatar:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.avatar.lg { width: 42px; height: 42px; font-size: 15px; flex-shrink: 0; }

.menu-panel {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 40;
  min-width: 244px; padding: 8px;
  background: var(--pop-solid); border: 1px solid var(--line-strong);
  border-radius: var(--r-lg); box-shadow: var(--shadow-lg);
  animation: popIn .16s var(--ease) both;
}
.menu-head {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 8px 12px; margin-bottom: 6px;
  border-bottom: 1px solid var(--line);
}
.menu-id { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.menu-id b { font-size: 14px; }
.menu-id .muted { font-size: 12px; overflow: hidden; text-overflow: ellipsis; }
.menu-id .pill { align-self: flex-start; margin-top: 3px; font-size: 10px; }

.menu-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 10px 10px; border: 0; border-radius: var(--r-sm);
  background: none; color: var(--text);
  font-family: inherit; font-size: 14px; font-weight: 500; text-align: left; cursor: pointer;
  text-decoration: none; /* the menu holds <a>s as well as <button>s */
}
.menu-item i { font-size: 16px; color: var(--muted); }
.menu-item:hover { background: var(--surface-2); }
.menu-item:hover i { color: var(--gold); }
.menu-item:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: -2px; }
.menu-item.danger { color: var(--bad); }
.menu-item.danger i { color: var(--bad); }
.menu-item.danger:hover { background: var(--bad-soft); }

/* ---------- language switch ---------- */
.lang-menu { position: relative; display: inline-flex; }
/* The two-letter code carries the button on desktop, where the word would
   crowd the header; the mobile menu shows .nav-label instead. */
.lang-code { display: none; font-size: 11px; font-weight: 700; letter-spacing: .04em; }
/* The one .nav-label that earns its place in the desktop bar — see the note in
   LanguageMenu.tsx. Everything else up there stays a glyph. */
.lang-menu .nav-label { display: inline; }
.lang-caret { font-size: 14px; opacity: .75; margin-left: -3px; }
.nav-links.open .lang-code { display: none; }
.lang-panel { min-width: 208px; }
.lang-option { display: flex; flex-direction: column; gap: 1px; }
.lang-option small { font-size: 11px; font-weight: 500; }
/* Malayalam runs taller than Latin at the same size — it needs the room for
   its ascenders, or the vowel signs clip against the line above. */
html[lang="ml"] { line-height: 1.65; }
html[lang="ml"] .btn, html[lang="ml"] .pill { line-height: 1.35; }

/* Consequences spelled out before an irreversible action. */
.danger-note {
  display: flex; gap: 10px; margin-bottom: 16px; padding: 12px 14px;
  background: var(--bad-soft); border: 1px solid var(--bad-line);
  border-radius: var(--r-md);
}
.danger-note i { flex-shrink: 0; color: var(--bad); font-size: 18px; }
.danger-note p { margin: 4px 0 0; font-size: 13px; }
.field-note { display: block; margin-top: 5px; font-size: 12px; color: var(--muted); }
.form-divider {
  margin: 20px 0 0; padding-top: 16px; border-top: 1px solid var(--line);
  font-size: 13px; font-weight: 700;
}

/* ---------- hall form ---------- */
/* A 6-column grid, so every field lands on the same rails no matter how many
   sit in a row. The old flex rows sized each field by its row's count, which is
   why a 5-up row never lined up with a 3-up one. */
/* The form is a stack of titled cards; each card is the grid its fields lay out
   in. Forty-odd fields in one flat grid read as a single wall, and the section
   headers alone were not enough to break it up. */
.hall-form { display: grid; gap: 14px; }
.form-card {
  display: grid; grid-template-columns: repeat(6, 1fr); gap: 16px 14px;
  align-items: start;   /* an inline error grows its own cell, not its neighbours */
  padding: 16px; border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--card2);
}
.hall-form .f { grid-column: span 2; min-width: 0; }   /* a third */
.hall-form .f.half { grid-column: span 3; }
.hall-form .f.full { grid-column: span 6; }
.hall-form label { margin: 0 0 6px; }
.hall-form .field-error { margin-top: 5px; }
/* Inside a card the inputs sit on the page colour, so they stay distinct from
   the card they are on rather than blending into it. */
.form-card input, .form-card textarea, .form-card select { background: var(--surface); }

/* Section headers name each card: Basics / Location / … */
.hall-form .sec {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 10px;
  margin: 0; color: var(--muted);
  font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
}
.hall-form .sec::after { content: ''; flex: 1; height: 1px; background: var(--line); }

/* Actions stay reachable while the (tall) form scrolls under them. */
/* Every button row: spaced and right-aligned. Kept unscoped so dialogs outside
   the hall form (e.g. admin venue verification) get the spacing too. */
.form-actions {
  display: flex; gap: 10px; justify-content: flex-end; flex-wrap: wrap;
}

/* Inside the long hall form the row also docks to the bottom as a sticky footer. */
.hall-form .form-actions {
  grid-column: 1 / -1;
  position: sticky; bottom: calc(-1 * clamp(20px, 3.4vw, 32px)); z-index: 1;
  margin: 6px calc(-1 * clamp(20px, 3.4vw, 32px)) calc(-1 * clamp(20px, 3.4vw, 32px));
  padding: 14px clamp(20px, 3.4vw, 32px);
  background: var(--bg); border-top: 1px solid var(--line);
}
.hall-form .form-actions .btn { min-width: 108px; }
.form-hint { grid-column: 1 / -1; margin: 0; font-size: 13px; }

@media (max-width: 560px) {
  .hall-form .f, .hall-form .f.half { grid-column: span 6; }
  .form-card { padding: 14px 12px; }
}

/* Facilities: one tick box per item on the admin's list, laid out as chips
   that wrap. The whole chip is the <label>, so the words are the hit area. */
.hall-form fieldset.facility-field { border: 0; padding: 0; margin: 0; min-width: 0; }
.hall-form .facility-field legend {
  padding: 0; margin: 0 0 4px;
  font-size: 13px; font-weight: 600; color: var(--text); letter-spacing: -.005em;
}
.facility-checks { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.hall-form label.facility-check {
  display: inline-flex; align-items: center; gap: 8px;
  margin: 0; padding: 7px 14px 7px 11px; min-height: 40px;
  border: 1px solid var(--line-strong); border-radius: 999px; background: var(--surface);
  font-size: 14px; font-weight: 500; line-height: 1.3; cursor: pointer;
  transition: background-color .15s var(--ease), border-color .15s var(--ease);
}
.hall-form label.facility-check:hover { border-color: var(--ink-3); }
.hall-form label.facility-check:has(input:checked) { background: var(--brand-soft); border-color: var(--brand); }
.hall-form label.facility-check:has(input:focus-visible) { outline: 2px solid var(--brand); outline-offset: 2px; }
.hall-form label.facility-check input { margin: 0; width: 16px; height: 16px; flex-shrink: 0; }
/* Off the admin's list: still on this venue until unticked. */
.hall-form label.facility-check.retired { border-style: dashed; }

/* ---------- photo upload (hall form) ---------- */
.dropzone {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  padding: 24px 16px; text-align: center; cursor: pointer;
  background: var(--card2); border: 2px dashed var(--line-strong); border-radius: 12px;
  transition: border-color .15s, background .15s;
}
.dropzone:hover { border-color: var(--gold); }
.dropzone.over { border-color: var(--gold); background: var(--gold-soft); }
.dropzone i { font-size: 26px; color: var(--gold); }
.dropzone p { margin: 0; font-size: 13px; }
.dropzone .muted { font-size: 12px; }
.dropzone .ri-loader-4-line { animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

.photo-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 10px; margin-top: 12px;
}
.photo-thumb {
  position: relative; aspect-ratio: 4 / 3; border-radius: 10px; overflow: hidden;
  border: 1px solid var(--line);
}
.photo-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-remove, .photo-promote {
  position: absolute; top: 4px; display: grid; place-items: center;
  width: 24px; height: 24px; padding: 0; border: 0; border-radius: 50%; cursor: pointer;
  background: rgba(7, 8, 8, .7); color: #fff; font-size: 14px; line-height: 1;
}
.photo-remove { right: 4px; }
.photo-promote { left: 4px; }
.photo-remove:hover { background: var(--bad); }
.photo-promote:hover { background: var(--gold-bright); color: #15110a; }
.photo-cover {
  position: absolute; left: 4px; top: 4px; padding: 2px 7px; border-radius: 999px;
  background: var(--brand); color: var(--brand-ink); font-size: 10px; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
}

/* ---------- admin console ---------- */
/* Its own shell: a night sidebar in both themes (the design's on-night band),
   no booker chrome. Deliberately reads as a back-office tool rather than the
   customer-facing site. */
.admin-shell { display: grid; grid-template-columns: 248px 1fr; min-height: 100vh; }
.admin-side {
  --logo-word: #f3ece1;
  display: flex; flex-direction: column; gap: 10px;
  padding: 22px 14px; background: var(--night); color: var(--on-night-2);
  border-right: 1px solid var(--on-night-line);
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
.admin-brand {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 4px 10px 18px; color: var(--on-night);
}
.admin-brand:hover { color: var(--on-night); }
.admin-brand .logo-svg { height: 26px; width: auto; }
.admin-tag {
  font-size: 10px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
  padding: 3px 9px; border-radius: var(--r-pill); background: var(--gold-soft); color: var(--gold-bright);
}
/* the sidebar is night in both themes, so its tag holds the dark-theme pair */
.admin-side .admin-tag { background: rgba(227, 181, 82, .14); color: #e2b962; }
.admin-nav { display: flex; flex-direction: column; gap: 2px; }
.admin-nav a {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 14px; border-radius: var(--r-pill); color: var(--on-night-2);
  font-size: 14px; font-weight: 600;
  transition: background .15s, color .15s;
}
.admin-nav a i { font-size: 17px; }
.admin-nav a:hover { background: rgba(241, 239, 233, .08); color: var(--on-night); }
.admin-nav a:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: -2px; }
/* gold on night in either theme: the sidebar never changes colour */
.admin-nav a.active { background: var(--gold-bright); color: #15110a; font-weight: 700; }
.admin-badge {
  margin-left: auto; min-width: 20px; padding: 1px 7px; border-radius: var(--r-pill);
  background: var(--bad-fill); color: #fff; font-size: 11px; font-weight: 800; text-align: center;
}
.admin-nav a.active .admin-badge { background: #15110a; color: var(--gold-bright); }

/* The console's own sign-in screen: a card on the night stage. */
.admin-login {
  position: relative; isolation: isolate;
  display: flex; align-items: center; justify-content: center;
  min-height: 100vh; padding: 24px 16px; background: var(--night);
}
.admin-login::before {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(60% 50% at 50% 0%, rgba(227, 181, 82, .12), transparent 70%);
}
.admin-login-card {
  width: 100%; max-width: 440px; padding: clamp(24px, 5vw, 36px);
  display: flex; flex-direction: column; gap: 14px;
  background: var(--bg); color: var(--ink); border: 1px solid var(--line);
  border-radius: var(--r-xl); box-shadow: var(--shadow-lg);
}
.admin-login-card h1 { margin: 6px 0 0; font-size: clamp(1.8rem, 1.5rem + 1vw, 2.3rem); }
.admin-login-card > p { margin: 0; }
.admin-login-brand {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding-bottom: 14px; border-bottom: 1px solid var(--line);
}
.admin-login-logo { display: inline-flex; color: var(--ink); }
.admin-login-logo .logo-svg { height: 24px; width: auto; }
.admin-login-brand .admin-tag { background: var(--gold-soft); color: var(--gold); }
/* Pushed to the far end of the brand row. The card is narrow, so this is one
   of the spots that takes the code rather than the word. */
.admin-login-brand .lang-menu { margin-left: auto; font-size: 14px; font-weight: 600; letter-spacing: normal; }
.admin-login-brand .nav-label { display: none; }
.admin-login-brand .lang-code { display: inline; }
.admin-login-exit { display: inline-flex; align-items: center; gap: 6px; margin-top: 4px; font-size: 13px; color: var(--ink-3); }
.admin-login-exit:hover { color: var(--ink); }

.admin-main { display: flex; flex-direction: column; min-width: 0; }
/* Admin tables sit straight in their card: let the card scroll sideways on
   phones rather than clipping the right-hand columns. */
.admin-main .card:has(> table) { overflow-x: auto; }
@media (max-width: 720px) {
  /* Scroll a readable table rather than squeeze every column to a word. */
  .admin-main .card > table { min-width: 680px; }
}
.admin-top {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  min-height: 68px; padding: 12px 28px; border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20;
  background: var(--glass);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
}
.admin-top > .muted { font-size: 11px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; }
.admin-who { display: flex; align-items: center; gap: 10px; }
.admin-body { padding: 28px 28px 64px; min-width: 0; }
.admin-body h1 { margin-top: 0; }
/* Tables here are wide (8+ columns) — let them scroll inside the card. Not the
   filter card: overflow-x makes overflow-y compute to auto, which would clip
   its select/date popovers instead of letting them float over the table below. */
.admin-body .card:not(.admin-filters) { overflow-x: auto; }
.admin-hint { margin: 4px 0 0; font-size: 13px; }
.admin-tile { color: inherit; display: block; }
.admin-tile:hover { color: inherit; }
.admin-tile .card { transition: border-color .15s, transform .2s var(--ease); }
.admin-tile:hover .card { border-color: var(--gold); transform: translateY(-2px); }
.admin-tile:focus-visible { outline: none; }
.admin-tile:focus-visible .card { border-color: var(--gold-bright); box-shadow: 0 0 0 3px var(--gold-soft); }
.admin-filters { margin-bottom: 22px; }
/* The fields get their own grid so the actions row below can't sit in it: a
   full-width child would occupy the spare auto-fit tracks and stop them
   collapsing, squeezing the fields into part of the card. */
.admin-filters-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 14px 16px;
}
.admin-filters-grid label { margin: 0 0 7px; }
.admin-filters label { margin-top: 0; }
/* A chosen date ("Wed, Jul 1, 2026") is far longer than the "Any date" it
   replaces, and would wrap onto a second line — leaving that one filter taller
   than the fields beside it. Truncate instead, so the row keeps one height
   whether a filter is set or not. */
.admin-filters-grid .datefield-btn > span,
.admin-filters-grid .selectfield-btn > span {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* The search box is plain text while its neighbours carry a 16px icon, whose
   taller line box made them 5px deeper. One floor for all three. */
.admin-filters-grid input,
.admin-filters-grid .datefield-btn,
.admin-filters-grid .selectfield-btn { min-height: 48px; }
/* Managers and Venues filter on search alone, and a single grid item stretches
   the full card. Cap it so it reads as a field, not a banner. */
.admin-filters-grid > div:only-child { max-width: 420px; }
.admin-filters-actions { margin-top: 14px; }
.admin-message p { margin: 10px 0; }
/* Free-text cells (audit details, enquiry messages) must not blow the layout. */
.admin-clamp {
  max-width: 280px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

@media (max-width: 900px) {
  .admin-shell { grid-template-columns: 1fr; }
  .admin-side { position: static; height: auto; padding: 16px 12px 12px; border-right: 0; border-bottom: 1px solid var(--on-night-line); }
  .admin-brand { padding-bottom: 10px; }
  /* one scrolling row of pills rather than a wrapped block */
  .admin-nav { flex-direction: row; overflow-x: auto; scrollbar-width: none; padding-bottom: 2px; }
  .admin-nav::-webkit-scrollbar { display: none; }
  .admin-nav a { flex: none; padding: 9px 14px; }
}

/* Phone: the top bar's name pill, language, theme and logout were one 580px
   row. Drop the static "Platform admin" caption, let the controls wrap, and
   shorten language to its code — as the booker header does. */
@media (max-width: 720px) {
  .admin-top { padding: 10px 16px; gap: 8px; }
  .admin-top > .muted { display: none; }
  .admin-who { flex-wrap: wrap; justify-content: flex-end; gap: 6px; width: 100%; min-width: 0; }
  .admin-who .pill { margin-right: auto; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .admin-who .nav-label { display: none; }
  .admin-who .lang-code { display: inline; }
  .admin-body { padding: 18px 16px 48px; }
}

[class^="ri-"], [class*=" ri-"] { vertical-align: -.125em; line-height: 1; }

/* ============================== motion =================================== */

@keyframes fadeUp  { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes fadeIn  { from { opacity: 0; } to { opacity: 1; } }
@keyframes popIn   { from { opacity: 0; transform: translateY(16px) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes slideIn { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: none; } }
@keyframes pulse   { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@keyframes shimmer { to { transform: translateX(100%); } }

.searchbar { animation: fadeUp .5s .06s var(--ease) both; }
.stats-line { animation: fadeUp .5s .12s var(--ease) both; }
.filter-panel { animation: slideIn .24s var(--ease) both; }
.page-head { animation: fadeUp .38s var(--ease) both; }

/* Cards arrive in a short stagger rather than all at once. */
.grid > * { animation: fadeUp .46s var(--ease) both; }
.grid > *:nth-child(1) { animation-delay: .02s; }
.grid > *:nth-child(2) { animation-delay: .07s; }
.grid > *:nth-child(3) { animation-delay: .12s; }
.grid > *:nth-child(4) { animation-delay: .17s; }
.grid > *:nth-child(5) { animation-delay: .22s; }
.grid > *:nth-child(6) { animation-delay: .27s; }
.grid > *:nth-child(n + 7) { animation-delay: .3s; }

/* Page-level "Loading…" breathes so a slow request doesn't look frozen.
   Scoped to #main's direct child so muted em-dashes in table cells don't pulse. */
#main > p.muted:only-child { animation: pulse 1.4s ease-in-out infinite; }

.modal-backdrop { animation: fadeIn .18s ease both; }
.modal-card { animation: popIn .28s var(--ease) both; }
.lightbox { animation: fadeIn .2s ease both; }
.lightbox img { animation: popIn .3s var(--ease) both; }

.duration-bar, .refund-box, .field-error, .total-box { animation: slideIn .22s var(--ease) both; }
.slot.sel, .session.sel { animation: popIn .2s var(--ease) both; }

.card:hover > .stat { transform: scale(1.03); }

/* Anyone who asked their OS for less motion gets none of it. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* ============================ responsive ================================= */

@media (max-width: 1024px) {
  .footer-inner { grid-template-columns: 1fr 1fr; }
  .footer-inner > :first-child { grid-column: 1 / -1; }
}

@media (max-width: 900px) {
  .detail-grid, .contact-grid { grid-template-columns: 1fr; }
  .booking-panel { position: static; }
  .gallery-main .hall-photo { height: 320px; }
  /* The word is the first thing to go when the header tightens; the code takes
     over. Below 720px the whole bar folds into the menu, which shows the word
     again — that rule lives in the next block and overrides this one. */
  .nav-links .lang-menu .nav-label { display: none; }
  .lang-code { display: inline; }
}

@media (max-width: 720px) {
  .band { margin-inline: -16px; padding-inline: 16px; }
}

@media (max-width: 640px) {
  h1 { font-size: 27px; }
  .hero { padding: 36px 0 26px; }
  .hero .muted { font-size: 15.5px; }

  /* the search pill unrolls into a stacked card on phones */
  .searchbar {
    flex-wrap: wrap;
    border-radius: var(--r-lg);
    padding: 14px;
    gap: 10px;
  }
  .searchbar .search-ico { display: none; }
  .searchbar .search-input {
    flex-basis: 100%;
    border: 1px solid var(--line-strong);
    border-radius: var(--r-md);
    padding: 12px 14px;
  }
  .searchbar .btn { flex: 1; }

  .card { padding: 20px; }
  .facts { grid-template-columns: 1fr; }
  .booking-card { flex-direction: column; }
  .booking-thumb { flex-basis: auto; }
  .booking-thumb .hall-photo { height: 150px; }
  .gallery-main .hall-photo { height: 230px; }
  .gallery-thumb .hall-photo { height: 58px; width: 82px; }
  .modal-card { padding: 22px; border-radius: var(--r-lg); }
  .tabbar { display: flex; width: 100%; overflow-x: auto; }
  .footer-inner { grid-template-columns: 1fr; gap: 30px; }
  .footer-bottom { justify-content: center; text-align: center; }
  .lightbox { padding: 16px; }
  .lightbox-nav { width: 40px; height: 40px; font-size: 24px; }
  /* tooltips would clip on narrow screens */
  [data-tip]::after, [data-tip]:hover::after, [data-tip]:focus-visible::after { display: none; }
}

/* ============================ Compare venues ============================ */
/* Toggle over a browse card's photo — mirrors the price chip on the right. */
.compare-toggle {
  position: absolute;
  z-index: 2;
  top: 12px;
  left: 12px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 11px;
  border-radius: var(--pill);
  background: rgba(252, 252, 249, .9);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, .9);
  color: var(--brand);
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  transition: background .2s var(--ease), color .2s var(--ease), transform .2s var(--ease);
}
.compare-toggle:hover:not(:disabled) { background: var(--card); transform: translateY(-1px); }
.compare-toggle.on { background: var(--brand); color: var(--brand-ink); border-color: var(--brand); }
.compare-toggle:disabled { opacity: .5; cursor: not-allowed; }

/* While the bar floats, the page gets room underneath it so the last row of
   cards and the footer can still scroll clear of it. */
body:has(.compare-bar) .footer { padding-bottom: 120px; }

/* Floating bar that collects the picked venues. */
.compare-bar {
  position: fixed;
  z-index: 60;
  /* Centred with auto margins, NOT transform: popIn ends on `transform: none`
     and, being fill-mode both, that final frame sticks — it was overwriting a
     translateX(-50%) here and leaving the bar hanging half off the right edge
     at every width. Auto margins keep transform free for the animation. */
  left: 0;
  right: 0;
  /* Clears the build badge in the bottom-left corner (.app-version). */
  bottom: calc(36px + env(safe-area-inset-bottom, 0px));
  /* calc on % not vw: 100vw includes the scrollbar gutter and would overflow. */
  width: min(760px, calc(100% - 24px));
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 12px 14px;
  border-radius: var(--pill);
  background: var(--glass);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid var(--glass-line);
  box-shadow: var(--shadow-lg);
  animation: popIn .28s var(--ease) both;
}
.compare-bar-items { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
.compare-bar-ico { color: var(--brand-mid); font-size: 18px; }
.compare-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 190px;
  padding: 5px 6px 5px 12px;
  border-radius: var(--pill);
  background: var(--brand-soft);
  border: 1px solid var(--brand-line);
  color: var(--text);
  font-size: 13px;
  font-weight: 600;
  min-width: 0;
}
.compare-chip-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.compare-chip button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border: none;
  border-radius: 50%;
  background: var(--line);
  color: var(--ink);
  cursor: pointer;
  flex: 0 0 auto;
}
.compare-chip button:hover { background: var(--bad-soft); color: var(--bad); }

/* Side-by-side comparison table inside the modal. */
.cmp-scroll { overflow-x: auto; }
.compare-grid {
  display: grid;
  grid-template-columns: 132px 1fr 1fr;
  min-width: 440px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
}
.cmp-corner { background: var(--card2); }
.cmp-head {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 12px;
  background: var(--card2);
  border-left: 1px solid var(--line);
}
.cmp-head .hall-photo { height: 92px; border-radius: var(--r-sm); margin-bottom: 4px; }
.cmp-name { font-weight: 700; color: var(--text); font-size: 14.5px; line-height: 1.25; }
.cmp-name:hover { color: var(--brand-mid); text-decoration: underline; }
/* display:contents lets each row's three cells flow straight into the grid. */
.cmp-row { display: contents; }
.cmp-label,
.cmp-cell {
  padding: 10px 12px;
  font-size: 13px;
  border-top: 1px solid var(--line);
}
.cmp-label { color: var(--muted); background: var(--card2); }
.cmp-cell { border-left: 1px solid var(--line); }
.cmp-win { color: var(--good); font-weight: 700; background: var(--good-soft); }

.cmp-amenities {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px 20px;
  margin-top: 18px;
}
@media (max-width: 560px) {
  .cmp-amenities { grid-template-columns: 1fr; }
  /* Side-by-side stops fitting: the chips and the actions each take a full row,
     and the buttons split the width evenly rather than being squeezed to the
     right by whatever the venue names left over. */
  .compare-bar {
    border-radius: var(--r-lg);
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  }
  /* The stacked bar is ~150px tall: give the footer room to scroll clear of it,
     and drop the build badge rather than lift the bar higher over the cards. */
  body:has(.compare-bar) .footer { padding-bottom: 190px; }
  body:has(.compare-bar) .app-version { display: none; }
  .compare-bar > .row { width: 100%; }
  .compare-bar > .row > .btn { flex: 1 1 0; justify-content: center; }
  /* Long venue names ellipsis inside the chip instead of forcing the bar wide. */
  .compare-chip { max-width: 100%; min-width: 0; }
}

/* ---------- manager: assets ---------- */
.ast-head { align-items: flex-start; gap: 14px; flex-wrap: wrap; }
/* auto-fit so the three controls collapse to one column on a phone rather than
   being squeezed into unusable slivers. */
.ast-controls {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 0 16px;
  margin: 18px 0 4px;
}
.ast-control label { margin-top: 0; }
.ast-control.grow { grid-column: span 2; }
.ast-summary { align-items: center; flex-wrap: wrap; gap: 10px; margin: 6px 0 14px; }
.ast-note { font-size: 12px; margin-top: 2px; }
/* The condition picker carries the row, so it gets the width; the two buttons
   sit beside it and stay their natural size. */
.ast-actions { display: flex; align-items: center; gap: 8px; justify-content: flex-end; }
.ast-actions .selectfield { min-width: 150px; }

.ast-good { color: var(--good); }
.ast-warn { color: var(--warn); }
.ast-bad { color: var(--bad); }
.ast-muted { color: var(--muted); font-weight: 600; }

@media (max-width: 720px) {
  .ast-control.grow { grid-column: auto; }
  /* Stacked, the picker and its buttons each take the full width — a row of
     three squeezed controls is unusable at this size. */
  .ast-actions { flex-direction: column; align-items: stretch; }
  .ast-actions .selectfield { min-width: 0; }
}

/* ---------- legal: privacy policy ---------- */
/* A document, not a dashboard: one readable column of cards rather than the
   auto-fill grid the rest of the site uses, capped at a comfortable measure so
   the clauses do not run the full width of a desktop. */
.legal {
  display: grid;
  gap: 18px;
  max-width: 820px;
  margin: 0 auto;
}
.legal-section p {
  margin: 10px 0 0;
  font-size: 14.5px;
  line-height: 1.7;
  color: var(--text);
}
/* Nothing else on the site uses a bulleted list, so the marker, the indent and
   the row spacing are all set here. */
.legal-section ul {
  margin: 12px 0 0;
  padding-left: 20px;
  display: grid;
  gap: 9px;
}
.legal-section li {
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--text);
}
.legal-section li::marker { color: var(--brand); }
.legal-section .facts { margin-top: 14px; }


/* ---------------------------- release version ---------------------------- */

/* The web release (W1.4.2) on every page. Fixed to the bottom-left corner and
   click-through, so it never covers a control; quiet enough to ignore, there
   when a tester needs to say which build they are looking at. */
.app-version {
  position: fixed;
  left: 10px;
  bottom: calc(8px + env(safe-area-inset-bottom, 0px));
  z-index: 40;
  padding: 2px 8px;
  border-radius: var(--pill);
  border: 1px solid var(--line);
  background: var(--pop);
  color: var(--muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .02em;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  user-select: none;
}
@media print { .app-version { display: none; } }

/* ------------------------------ payments ------------------------------- */
/* Where a booking's money stands — a pill for the state, the balance under it. */
.pay-summary { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 3px; }
.pay-summary .muted { font-size: 12px; }
/* What a booking owes, line by line, in the record-payment dialog. */
.pay-breakdown {
  display: grid; gap: 6px; margin: 12px 0 4px; padding: 14px 16px;
  border-radius: var(--r-md); background: var(--card2); border: 1px solid var(--line);
}
.pay-breakdown > div { display: flex; justify-content: space-between; gap: 12px; }
.pay-breakdown dt { color: var(--muted); font-size: 13.5px; }
.pay-breakdown dd { margin: 0; font-variant-numeric: tabular-nums; }
.pay-breakdown .total { padding-top: 6px; border-top: 1px solid var(--line); }

/* The footer's phone link: icon + "Call us:" + the number, kept on one line. */
.footer-phone { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.footer-phone-num { white-space: nowrap; font-variant-numeric: tabular-nums; }

/* Assets: which venue a row belongs to, and two short fields side by side. */
.ast-venue { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.ast-venue i { color: var(--brand-mid); }
.ast-form-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; }
@media (max-width: 520px) { .ast-form-pair { grid-template-columns: 1fr; } }

/* Equipment that is out of action, repeated beside the booking button. */
.eq-notice {
  margin-top: 14px; padding: 12px 14px; border-radius: var(--r-md);
  background: var(--warn-soft); border: 1px solid var(--warn-line); font-size: 13.5px;
}
.eq-notice b { display: flex; align-items: center; gap: 6px; color: var(--warn); }
.eq-notice ul { margin: 6px 0; padding-left: 20px; }
.eq-notice li { margin: 2px 0; }
.eq-notice .muted { font-size: 12.5px; }

/* ------------------------- manager: booking report ------------------------ */
/* The report's own card: icon, what the file holds, then the two downloads. */
.report-card { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.report-card .report-ico { width: 42px; height: 42px; margin: 0; font-size: 19px; border-radius: 12px; flex: none; }
.report-card .report-copy { flex: 1 1 260px; min-width: 0; }
.report-card .report-copy p { margin: 2px 0 0; font-size: 13px; }
.report-card .report-actions { gap: 8px; flex-wrap: wrap; }
@media (max-width: 560px) {
  .report-card .report-actions { width: 100%; }
  .report-card .report-actions .btn { flex: 1 1 0; justify-content: center; }
}

/* Revenue-by-venue share column: a thin bar plus the percentage. */
.share-bar { height: 6px; border-radius: 999px; background: var(--line); overflow: hidden; margin-bottom: 4px; }
.share-bar > span { display: block; height: 100%; border-radius: inherit; background: var(--brand); }

/* "Supervisor created": sign-in details at reading size, labels and values aligned. */
.cred-box {
  display: grid; grid-template-columns: auto 1fr; gap: 8px 16px; align-items: baseline;
  margin: 12px 0 0; padding: 14px 16px;
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--card2);
}
.cred-box dt { color: var(--muted); font-size: 13px; }
.cred-box dd {
  margin: 0; font-size: 15px; font-weight: 650; letter-spacing: .02em;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; word-break: break-all;
}

/* Booking request sent: the numbered "what happens next" list and the quiet contact line. */
.next-steps { margin: 0; padding-left: 20px; display: grid; gap: 6px; font-size: 14px; color: var(--body); }
.req-contact { font-size: 13px; text-align: center; margin: 14px 0 0; }
.req-contact a { font-weight: 600; white-space: nowrap; }

/* Manager bookings: the row of filters above the list. */
.filter-bar { display: flex; flex-wrap: wrap; gap: 10px 12px; align-items: flex-end; margin: 12px 0; }
.filter-bar .f { display: grid; gap: 4px; min-width: 150px; flex: 0 1 170px; }
.filter-bar .f.grow { flex: 1 1 200px; }
.filter-bar label { font-size: 12px; color: var(--muted); font-weight: 600; }
.filter-bar .filter-clear { margin-bottom: 4px; }
@media (max-width: 560px) { .filter-bar .f { flex: 1 1 calc(50% - 6px); min-width: 0; } }

/* The building a hall belongs to, under its name on the card. */
.hall-building { margin: 2px 0 0; font-size: 12.5px; display: flex; align-items: center; gap: 4px; }

/* Buildings dialog list. */
.building-list { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 8px; }
.building-list li { padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-md); }

/* ================================ /login ====================================
   The design's .auth split (photo + quote | panel) lives in design.css; these
   are the app's additions: the form stack, the alert boxes for the suspended
   and ID-check states, and fixes the design's static demo did not need. */
.auth-form { display: flex; flex-direction: column; gap: 16px; }
.auth-form .row.between { gap: 10px; }
.auth .input-group > label .muted { font-weight: 500; }
.auth .field-error, .admin-login .field-error { margin-top: 0; }
.auth-box h1 { margin: 0; }
.auth-media .kicker { margin-bottom: 18px; }
.auth-media .accent { color: var(--gold-bright); }
/* The photo holds one size while the form beside it grows and shrinks.
   Stretched to the form's height, its cover crop re-zoomed every time the
   form changed length — picking "List my venue" adds the ID check. */
.auth { align-items: start; }
.auth-media { position: sticky; top: calc(var(--header-h) + env(safe-area-inset-top, 0px)); height: calc(100vh - var(--header-h) - env(safe-area-inset-top, 0px)); height: calc(100dvh - var(--header-h) - env(safe-area-inset-top, 0px)); }
.auth-panel { min-height: calc(100vh - var(--header-h) - env(safe-area-inset-top, 0px)); }
/* The design animates its pill under the tabs with JS; the selected tab
   carries the fill itself here. */
.auth-box .seg button { min-height: 44px; }
.auth-box .seg button[aria-selected="true"] { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-sm), inset 0 0 0 1px var(--line-strong); }
.auth-box .seg button:focus-visible { outline: 2px solid var(--gold-bright); outline-offset: 2px; }
/* The tick sits on the brand fill: dark ink on gold, white on ink. */
.auth .check .box .i { width: auto; height: auto; font-size: 15px; color: var(--brand-ink); }
.auth .role-pick label:has(input:focus-visible) { outline: 2px solid var(--gold-bright); outline-offset: 2px; }
.auth .role-pick label:has(input:checked) strong { color: var(--ink); }
.auth .input-affix { width: 100%; }
.auth .input-affix .input, .admin-login .input-affix .input { padding-left: 56px; }
.admin-login .input-affix { position: relative; display: flex; align-items: center; }
.auth .pwfield input, .admin-login .pwfield input { padding-left: 16px; }
.auth-verified { display: flex; align-items: center; gap: 8px; font-size: .92rem; color: var(--ink-2); }
.auth-verified i { color: var(--success); font-size: 18px; }
.auth-ok { display: inline-flex; align-items: center; gap: 6px; color: var(--success); font-size: 13px; font-weight: 600; }
.auth-alert {
  display: grid; gap: 10px; padding: 16px 18px;
  border-radius: var(--r-md); background: var(--surface-2); border: 1px solid var(--line);
}
.auth-alert > b { display: flex; align-items: center; gap: 8px; }
.auth-alert p { margin: 0; font-size: .9rem; }
.auth-alert.bad { background: var(--bad-soft); border-color: var(--bad-line); }
.auth-alert.bad > b { color: var(--danger); }
.auth .await-box p { color: var(--ink-2); }
@media (max-width: 960px) {
  .auth .auth-panel { padding-top: 32px; padding-bottom: 120px; }
}

/* ============================ dashboard polish ============================
   The manager, bookings and notifications pages sit in .container.app-main. */
.app-main .page-head h1 { margin-bottom: 6px; }
.app-main .page-head p { max-width: 62ch; }
.app-main .section-head h2 { margin: 0; }
.pill { font-weight: 700; }
.pill.brand { background: var(--gold-soft); color: var(--ink); border-color: var(--brand-line); }

/* A native <select> (the calendar's venue filter, a few admin lists) reads as
   the design's field: surface box, hairline, chevron. */
select {
  appearance: none; -webkit-appearance: none;
  min-height: 42px; padding: 8px 40px 8px 14px;
  border: 1px solid var(--line-strong); border-radius: var(--r-md);
  background: var(--surface) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239d9c95' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 12px center / 16px;
  color: var(--text); font: inherit; font-size: 14px; cursor: pointer;
  transition: border-color .18s, box-shadow .18s;
}
select:hover:not(:disabled) { border-color: var(--ink-3); }
select:focus { outline: none; border-color: var(--brand); box-shadow: 0 0 0 4px var(--brand-soft); }

/* Phones: the tab row scrolls sideways as one pill instead of wrapping into a
   blob. */
@media (max-width: 640px) {
  .tabbar { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; border-radius: var(--pill); }
  .tabbar::-webkit-scrollbar { display: none; }
  .tabbar a { flex: none; padding: 9px 15px; }
}
