/* Lecker Asia — staff reservations dashboard.
   iPad-first host-stand tool. 8px grid, high-contrast, calm.

   REBRAND: this dashboard now wears the Lecker Asia website's design system
   (leckerasia-preview.pages.dev) so the two read as one brand. Ported verbatim
   from that site: the self-hosted Zilla Slab type family, the monochrome
   white/black palette, hairline #ddd rules, square corners, and the black
   "Lecker Asia" wordmark. Everything reads as the restaurant's site.

   Where brand and floor-utility conflict, utility wins (the site's house rule
   inverted for a working tool): the reservation STATUS colours (confirm green,
   seat amber, new blue, cancel grey, error red) are kept — they are the only
   colour on an otherwise monochrome page, which is exactly what makes a booking's
   state readable across a busy floor at a glance. Touch targets stay >=44px
   (primary actions 56px). Zero external requests (fonts are self-hosted). */

/* ---- self-hosted fonts, copied from the Lecker Asia site (fonts/) -------- */
@font-face {
  font-family: 'Zilla Slab';
  font-style: normal; font-weight: 400; font-display: swap;
  src: url(/fonts/zilla-slab-400.woff2) format('woff2');
}
@font-face {
  font-family: 'Zilla Slab';
  font-style: normal; font-weight: 600; font-display: swap;
  src: url(/fonts/zilla-slab-600.woff2) format('woff2');
}
@font-face {
  font-family: 'Zilla Slab';
  font-style: normal; font-weight: 700; font-display: swap;
  src: url(/fonts/zilla-slab-700.woff2) format('woff2');
}

:root {
  /* spacing — everything snaps to 8 */
  --s1: 8px;  --s2: 16px; --s3: 24px; --s4: 32px; --s5: 40px; --s6: 48px;

  /* surfaces — ported from the site: white page, faint tint, hairline rules */
  --bg: #fafafa;
  --surface: #ffffff;
  --surface-2: #f4f2ec;
  --ink: #000000;
  --ink-2: #555555;
  --ink-3: #8a8a8a;
  --line: #dddddd;
  --line-strong: #c9c9c9;

  /* the site has NO accent: interactive/brand elements are ink (black). */
  --accent: #000000;
  --accent-press: #333333;
  --on-accent: #ffffff;

  /* status hues (text / soft bg / hairline) — KEPT for floor legibility.
     These are the only colour on the page; they make a booking's state pop. */
  --new-ink: #1f5aa8;     --new-bg: #eef4fb;   --new-line: #cfe0f5;
  --conf-ink: #1f6f5c;    --conf-bg: #e6f1ec;  --conf-line: #c4e2d5;
  --seat-ink: #9a5a00;    --seat-bg: #fbefd8;  --seat-line: #f0dcae;
  --canc-ink: #7a7d78;    --canc-bg: #f0efeb;  --canc-line: #ddd9d0;
  --proc-ink: #6b6f79;    --proc-bg: #eeeef1;  --proc-line: #dddde2;
  --err-ink:  #a83232;    --err-bg:  #fbe9e9;  --err-line: #f2cccc;

  /* square corners, to match the site (which is strictly border-radius: 0) */
  --radius: 2px;
  --radius-sm: 2px;
  --font: "Zilla Slab", Georgia, "Times New Roman", serif;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--font);
  color: var(--ink);
  background: var(--bg);
  line-height: 1.4;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
button { font-family: inherit; }
/* iPad Safari: buttons and tap targets rely on rapid, repeated taps during
   service (floor actions, table picker, drag-block starts). Without this,
   Safari's double-tap-to-zoom gesture can hijack a fast second tap. Applies
   to every <button> in the app (.btn/.act/.chip/.segbtn/.tblock/.calevent/
   .wchip/.uchip/.daypill/.wlbtn/.uauto/.dayjump__btn/.weekstep/.modal__x are
   all real <button> elements) so this one rule covers the whole floor. */
button { touch-action: manipulation; }

.wrap {
  width: min(1240px, 100%);
  margin-inline: auto;
  padding-inline: clamp(16px, 4vw, 32px);
}

/* ---------- top bar ---------- */
/* Solid white with a hairline bottom rule, mirroring the site header (no blur,
   no translucency). Still sticky — useful on a scrolling floor tool. */
.topbar {
  position: sticky; top: 0; z-index: 20;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}
.topbar__row {
  display: flex; align-items: center; gap: var(--s2);
  min-height: 72px; padding-block: var(--s2);
  flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: 12px; margin-right: auto; }
.brand__mark {
  width: 40px; height: 40px; border-radius: 2px; flex: none;
  background: var(--ink); color: var(--on-accent);
  display: grid; place-items: center; font-weight: 700; letter-spacing: .5px;
  font-size: 16px;
}
/* the wordmark: Zilla Slab 700, exactly the site's "Lecker Asia" brand type */
.brand__name { font-weight: 700; font-size: 22px; letter-spacing: -.01em; line-height: 1.05; }
.brand__sub { font-size: 13px; color: var(--ink-2); font-weight: 500; margin-top: 1px; }

.livedot {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13px; color: var(--ink-2); font-weight: 600; white-space: nowrap;
}
.livedot i {
  width: 8px; height: 8px; border-radius: 50%; background: var(--conf-ink);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--conf-ink) 60%, transparent);
  animation: pulse 2.4s ease-out infinite;
}
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--conf-ink) 55%, transparent); }
  70% { box-shadow: 0 0 0 7px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) { .livedot i { animation: none; } }

.btn {
  appearance: none; border: 1px solid var(--line-strong); background: var(--surface);
  color: var(--ink); font-weight: 600; font-size: 15px;
  border-radius: var(--radius-sm); padding: 10px 16px; min-height: 44px;
  cursor: pointer; transition: background .12s ease, border-color .12s ease, transform .04s ease;
}
.btn:hover { background: var(--surface-2); }
.btn:active { transform: translateY(1px); }
/* .btn also lands on an <a> (topbar "Kitchen" link) — button reset alone
   doesn't give an anchor the same box/typography, so pin the rest here. */
a.btn { display: inline-flex; align-items: center; text-decoration: none; box-sizing: border-box; }
.btn--ghost { background: transparent; border-color: transparent; color: var(--ink-2); }
.btn--ghost:hover { background: var(--surface-2); color: var(--ink); }
/* primary = the site's inverted black button */
.btn--primary { background: var(--ink); color: #fff; border-color: var(--ink); }
.btn--primary:hover { background: var(--accent-press); border-color: var(--accent-press); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* ---------- search (Feature: header search) ---------- */
/* Comes AFTER .btn/.btn--ghost on purpose: the toggle carries "btn btn--ghost
   searchbox__toggle" and needs to win the icon-only sizing/padding override —
   equal-specificity classes resolve by source order in CSS. */
.searchbox { position: relative; }
.searchbox__toggle { width: 44px; height: 44px; min-width: 44px; padding: 0; display: grid; place-items: center; }
.searchbox__toggle svg { width: 20px; height: 20px; }
.searchbox__toggle[aria-expanded="true"] { background: var(--surface-2); color: var(--ink); }
.searchbox__panel {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 25;
  width: min(360px, 88vw);
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(0,0,0,.14); padding: 10px;
}
.searchbox__input {
  width: 100%; font-family: inherit; font-size: 16px; padding: 11px 14px; min-height: 44px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--surface);
  color: var(--ink);
}
.searchbox__input:focus { outline: 2px solid var(--ink); outline-offset: 1px; border-color: var(--ink); }
.searchbox__results { margin-top: 8px; max-height: min(420px, 60vh); overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
.searchresult {
  appearance: none; width: 100%; text-align: left; cursor: pointer; font-family: inherit;
  border: 1px solid transparent; border-radius: var(--radius-sm); background: transparent;
  padding: 8px 10px; min-height: 44px; display: flex; flex-direction: column; gap: 2px;
}
.searchresult:hover { background: var(--surface-2); border-color: var(--line); }
.searchresult__name { font-size: 15px; font-weight: 700; color: var(--ink); }
.searchresult__meta { font-size: 12.5px; color: var(--ink-2); font-weight: 600; display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.searchresult__meta svg { width: 12px; height: 12px; opacity: .55; vertical-align: -1px; }
.searchresult__pill { font-size: 11px; padding: 2px 8px; }
.searchresult--empty { color: var(--ink-3); font-weight: 600; font-style: italic; cursor: default; padding: 12px 10px; }
.searchresult--empty:hover { background: transparent; }
/* left/right anchoring past this point is decided in JS (positionSearchPanel,
   CSSOM only) so the panel stays on-screen wherever the toggle lands in the
   header's flex-wrap — this is just the fallback before JS runs. */
@media (max-width: 480px) { .searchbox__panel { width: min(340px, 92vw); } }

/* ---------- day nav ---------- */
.daynav { display: flex; align-items: center; gap: var(--s2); padding-block: var(--s2); flex-wrap: wrap; }
.dayjump { display: flex; align-items: center; gap: 8px; }
.dayjump__btn {
  width: 48px; height: 48px; border-radius: 2px; font-size: 22px; line-height: 1;
  display: grid; place-items: center; padding: 0;
}
.daylabel { min-width: 168px; }
.daylabel__day { font-size: 22px; font-weight: 700; letter-spacing: -.01em; }
.daylabel__date { font-size: 13px; color: var(--ink-2); font-weight: 500; }

.chips { display: flex; gap: 8px; flex-wrap: wrap; margin-left: auto; }
.chip {
  border: 1px solid var(--line-strong); background: var(--surface);
  border-radius: 2px; padding: 9px 15px; min-height: 44px;
  font-size: 14px; font-weight: 600; color: var(--ink-2); cursor: pointer;
  display: inline-flex; align-items: center; gap: 8px;
}
.chip:hover { background: var(--surface-2); }
/* selected filter = inverted black, matching the site's inverted button style */
.chip[aria-pressed="true"] { background: var(--ink); color: #fff; border-color: var(--ink); }
.chip__count {
  font-size: 12.5px; font-weight: 700; padding: 1px 8px; border-radius: 999px;
  background: var(--surface-2); color: var(--ink-2); min-width: 22px; text-align: center;
}
.chip[aria-pressed="true"] .chip__count { background: rgba(255,255,255,.22); color: #fff; }

/* quick upcoming-day pills */
.dayrail { display: flex; gap: 8px; overflow-x: auto; padding: 4px 0 var(--s2); scrollbar-width: thin; overscroll-behavior-x: contain; }
.daypill {
  flex: none; border: 1px solid var(--line); background: var(--surface);
  border-radius: 2px; padding: 8px 14px; min-height: 56px; cursor: pointer; text-align: left;
  display: flex; flex-direction: column; justify-content: center; gap: 1px; min-width: 84px;
}
.daypill:hover { border-color: var(--line-strong); }
/* selected day = black hairline + faint tint, monochrome (no accent) */
.daypill[aria-pressed="true"] { border-color: var(--ink); background: var(--surface-2); }
.daypill__dow { font-size: 12px; font-weight: 700; color: var(--ink-2); text-transform: uppercase; letter-spacing: .04em; }
.daypill__num { font-size: 18px; font-weight: 700; }
.daypill__count { font-size: 11.5px; color: var(--ink-3); font-weight: 600; }
.daypill[aria-pressed="true"] .daypill__dow,
.daypill[aria-pressed="true"] .daypill__num,
.daypill[aria-pressed="true"] .daypill__count { color: var(--ink); }

/* ---------- demo banner ---------- */
.demobar {
  background: repeating-linear-gradient(45deg, #fbefd8, #fbefd8 12px, #f7e8c8 12px, #f7e8c8 24px);
  color: #7a4b00; border: 1px solid var(--seat-line);
  border-radius: 2px; padding: 10px 16px; margin-top: var(--s2);
  font-size: 14px; font-weight: 600; text-align: center;
}

/* ---------- card grid ---------- */
.board { padding-block: var(--s3) var(--s6); }
.section__head { display: flex; align-items: baseline; gap: 10px; margin: var(--s3) 0 var(--s2); }
.section__title { font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--ink-2); }
.section__rule { flex: 1; height: 1px; background: var(--line); }

.grid {
  display: grid; gap: var(--s2);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr));
  align-items: start;
}

/* Cards: hairline border, no drop shadow — the site leans on rules, not shadow.
   Left status stripe kept as the fast colour cue for a booking's state. */
.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--s2);
  display: flex; flex-direction: column; gap: var(--s2);
  border-left: 4px solid var(--line-strong);
}
.card[data-floor="confirmed"] { border-left-color: var(--conf-ink); }
.card[data-floor="seated"]    { border-left-color: var(--seat-ink); }
.card[data-floor="cancelled"] { border-left-color: var(--canc-line); opacity: .72; }
.card[data-floor="new"]       { border-left-color: var(--new-ink); }

.card__top { display: flex; align-items: flex-start; gap: var(--s2); }
.card__time { display: flex; flex-direction: column; gap: 2px; }
.card__time b { font-size: 28px; font-weight: 700; letter-spacing: -.02em; line-height: 1; }
.card__time small { font-size: 12px; color: var(--ink-3); font-weight: 600; }
.card__party {
  margin-left: auto; display: inline-flex; align-items: center; gap: 7px;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 2px; padding: 6px 13px; font-weight: 700; font-size: 16px; white-space: nowrap;
}
.card__party svg { width: 17px; height: 17px; opacity: .6; }

.card__name { font-size: 21px; font-weight: 700; letter-spacing: -.01em; line-height: 1.2; }
.card__name.is-missing { color: var(--ink-3); font-style: italic; font-weight: 600; }

.meta { display: flex; flex-wrap: wrap; gap: 8px 14px; font-size: 14px; color: var(--ink-2); }
/* links: black + underline, exactly the site's link treatment (no accent hue) */
.meta a { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; font-weight: 700; }
.meta a:hover { color: var(--ink-2); }
.meta__item { display: inline-flex; align-items: center; gap: 6px; }
.meta__item svg { width: 15px; height: 15px; opacity: .55; }

.badge {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 700; padding: 4px 10px; border-radius: 2px;
  border: 1px solid transparent; text-transform: uppercase; letter-spacing: .03em;
}
.badge--phone { background: var(--surface-2); color: var(--ink-2); border-color: var(--line); }
.badge--web   { background: var(--surface-2); color: var(--ink-2); border-color: var(--line); }
.badge svg { width: 13px; height: 13px; }

.note {
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 10px 12px; font-size: 14px; color: var(--ink); line-height: 1.45;
}
.note b { font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-2); display: block; margin-bottom: 3px; }
.note--flag { background: #fdf4e7; border-color: var(--seat-line); }
.note--flag b { color: var(--seat-ink); }

/* status pill + actions */
.statusrow { display: flex; align-items: center; gap: 10px; }
.pill {
  font-size: 12.5px; font-weight: 700; padding: 5px 12px; border-radius: 2px;
  border: 1px solid transparent; text-transform: uppercase; letter-spacing: .04em;
}
.pill--new  { color: var(--new-ink); background: var(--new-bg); border-color: var(--new-line); }
.pill--confirmed { color: var(--conf-ink); background: var(--conf-bg); border-color: var(--conf-line); }
.pill--seated { color: var(--seat-ink); background: var(--seat-bg); border-color: var(--seat-line); }
.pill--cancelled { color: var(--canc-ink); background: var(--canc-bg); border-color: var(--canc-line); }
.pill--processing { color: var(--proc-ink); background: var(--proc-bg); border-color: var(--proc-line); }
.pill--awaiting { color: var(--seat-ink); background: var(--seat-bg); border-color: var(--seat-line); }
.pill--error { color: var(--err-ink); background: var(--err-bg); border-color: var(--err-line); }

.actions { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; margin-top: 2px; }
.act {
  appearance: none; border: 1.5px solid var(--line-strong); background: var(--surface);
  color: var(--ink); font-weight: 700; font-size: 15px; border-radius: 2px;
  min-height: 56px; padding: 8px; cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 7px;
  transition: background .12s ease, border-color .12s ease, transform .04s ease, color .12s ease;
}
.act svg { width: 18px; height: 18px; }
.act:active { transform: translateY(1px); }
.act:hover { background: var(--surface-2); }
/* pressed states keep their status colour — the point of the tool */
.act[aria-pressed="true"][data-act="confirmed"] { background: var(--conf-ink); border-color: var(--conf-ink); color: #fff; }
.act[aria-pressed="true"][data-act="seated"]    { background: var(--seat-ink); border-color: var(--seat-ink); color: #fff; }
.act[aria-pressed="true"][data-act="cancelled"] { background: var(--canc-ink); border-color: var(--canc-ink); color: #fff; }
.act:disabled { opacity: .5; cursor: default; }

.card--processing { border-left-color: var(--proc-line); }
.processing-hint { font-size: 13px; color: var(--ink-3); font-weight: 600; }

/* ---------- states (empty / loading / error) ---------- */
.state {
  text-align: center; padding: clamp(48px, 12vh, 96px) var(--s3);
  max-width: 480px; margin-inline: auto;
}
.state svg { width: 56px; height: 56px; color: var(--ink-3); margin-bottom: var(--s2); }
.state h2 { font-size: 24px; font-weight: 700; margin: 0 0 8px; letter-spacing: -.01em; }
.state p { font-size: 15px; color: var(--ink-2); margin: 0 auto; max-width: 42ch; }
.state .btn { margin-top: var(--s3); }
.state--error svg { color: var(--err-ink); }

.spinner {
  width: 40px; height: 40px; border-radius: 50%; margin: 0 auto var(--s2);
  border: 3px solid var(--line); border-top-color: var(--ink); animation: spin 1s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation: none; } }

.hidden { display: none !important; }

/* ==========================================================================
   COMPACT BOOKING TABLE  (replaces the old card grid — dense + scannable,
   one row per booking, tap a row to expand full detail)
   ========================================================================== */
.state--sm { padding: var(--s5) var(--s3); }

.btable-wrap {
  width: 100%; overflow-x: auto;               /* never push the page sideways */
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
  -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain;
}
.btable { width: 100%; border-collapse: collapse; font-size: 15px; }
.btable thead th {
  text-align: left; font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--ink-3); padding: 10px 14px;
  border-bottom: 1px solid var(--line); white-space: nowrap; background: var(--surface);
}
.btable td { padding: 0 14px; border-bottom: 1px solid var(--line); vertical-align: middle; }

/* summary row — the tappable line. Min height keeps a comfortable touch target. */
.brow { cursor: pointer; }
.brow > td { height: 54px; }
.brow:hover { background: var(--surface-2); }
.brow:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
.brow.is-open { background: var(--surface-2); }
.brow.is-open > td { border-bottom-color: transparent; }
/* thin left status stripe on the time cell — the fast colour cue */
.brow > .c-time { border-left: 4px solid var(--line-strong); }
.brow[data-floor="confirmed"] > .c-time { border-left-color: var(--conf-ink); }
.brow[data-floor="seated"]    > .c-time { border-left-color: var(--seat-ink); }
.brow[data-floor="new"]       > .c-time { border-left-color: var(--new-ink); }
.brow[data-floor="cancelled"] > .c-time { border-left-color: var(--canc-line); }
.brow[data-floor="cancelled"] .tcell b,
.brow[data-floor="cancelled"] .ncell { color: var(--ink-3); text-decoration: line-through; }
.brow[data-floor="awaiting"]  > .c-time { border-left-color: var(--seat-ink); }
.brow[data-floor="error"]     > .c-time { border-left-color: var(--err-ink); }
.brow[data-floor="processing"] > .c-time { border-left-color: var(--proc-line); }

.c-time { width: 96px; white-space: nowrap; }
.tcell { display: inline-flex; align-items: baseline; gap: 4px; }
.tcell b { font-size: 18px; font-weight: 700; letter-spacing: -.01em; }
.tcell small { font-size: 11px; color: var(--ink-3); font-weight: 700; }
.cell-sub { display: block; font-size: 11px; color: var(--ink-3); font-weight: 600; margin-top: 1px; }
.cell-sub--warn { color: var(--seat-ink); }

.c-party { width: 64px; }
.pcell { display: inline-flex; align-items: center; gap: 6px; font-size: 16px; }
.pcell svg { width: 15px; height: 15px; opacity: .5; }
.pcell b { font-weight: 700; }

.c-name { min-width: 140px; }
.ncell { font-size: 16px; font-weight: 700; letter-spacing: -.01em; }
.is-missing { color: var(--ink-3); font-style: italic; font-weight: 600; }
.flagdot {
  display: inline-block; margin-left: 6px; width: 16px; height: 16px; line-height: 16px;
  text-align: center; font-size: 12px; font-weight: 800; border-radius: 999px;
  background: var(--surface-2); color: var(--ink-3); vertical-align: middle;
}
.flagdot--warn { background: var(--seat-bg); color: var(--seat-ink); }

.c-src { width: 84px; }
.srcicon { display: inline-flex; align-items: center; gap: 6px; color: var(--ink-2); font-size: 13px; font-weight: 600; }
.srcicon svg { width: 15px; height: 15px; opacity: .6; }

.c-status { width: 60px; }
.sicon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 999px; border: 1px solid transparent;
}
.sicon svg { width: 17px; height: 17px; }
.sicon--new       { color: var(--new-ink);  background: var(--new-bg);  border-color: var(--new-line); }
.sicon--confirmed { color: var(--conf-ink); background: var(--conf-bg); border-color: var(--conf-line); }
.sicon--seated    { color: var(--seat-ink); background: var(--seat-bg); border-color: var(--seat-line); }
.sicon--cancelled { color: var(--canc-ink); background: var(--canc-bg); border-color: var(--canc-line); }
.sicon--awaiting  { color: var(--seat-ink); background: var(--seat-bg); border-color: var(--seat-line); }
.sicon--error     { color: var(--err-ink);  background: var(--err-bg);  border-color: var(--err-line); }
.sicon--processing{ color: var(--proc-ink); background: var(--proc-bg); border-color: var(--proc-line); }

.c-contact { width: 160px; }
.tel { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; font-weight: 700; font-size: 14px; white-space: nowrap; }
.tel:hover { color: var(--ink-2); }

.c-exp { width: 44px; text-align: center; }
.chev { display: inline-flex; color: var(--ink-3); transition: transform .15s ease; }
.chev svg { width: 20px; height: 20px; }
.brow.is-open .chev { transform: rotate(180deg); color: var(--ink); }

/* ---- expanded detail row ---- */
.drow > td { padding: 0; background: var(--surface-2); border-bottom: 2px solid var(--line-strong); }
.detail { padding: var(--s2) 18px var(--s3); display: flex; flex-direction: column; gap: var(--s2); }
.dl { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px 24px; margin: 0; }
.dl__row { display: flex; flex-direction: column; gap: 2px; }
.dl__row--wide { grid-column: 1 / -1; }
.dl__row dt { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-3); }
.dl__row dd { margin: 0; font-size: 15px; color: var(--ink); font-weight: 600; }
.dl__row--warn dd { color: var(--seat-ink); }

.dactions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.dactions .act { flex: 1 1 140px; max-width: 220px; }
.dactions--note { gap: 12px; }

.rawblock { border-top: 1px solid var(--line); padding-top: var(--s2); }
.rawblock__h { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-3); margin-bottom: 6px; }
.rawblock pre {
  margin: 0; white-space: pre-wrap; word-break: break-word; font-size: 13px;
  line-height: 1.5; color: var(--ink-2);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 10px 12px; max-height: 220px; overflow: auto;
}

/* On a phone-width screen hide the source label text; icon carries it. */
@media (max-width: 560px) {
  .srcicon__l { display: none; }
  .c-contact { width: auto; }
}

/* ==========================================================================
   NEW BOOKING MODAL
   ========================================================================== */
.modal { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; padding: var(--s2); }
.modal__backdrop { position: absolute; inset: 0; background: rgba(0,0,0,.42); }
.modal__panel {
  position: relative; width: min(560px, 100%); max-height: 92dvh; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius);
  padding: var(--s3); box-shadow: 0 12px 40px rgba(0,0,0,.18);
  /* scrolling to the end of the modal's own list must not chain into the
     page behind it — the classic iOS "scrolled past the form, now the
     board behind it moved" glitch, worst with the keyboard open. */
  overscroll-behavior: contain;
}
/* Lock the page behind any open modal (fixed panels don't stop iOS Safari
   from scrolling the body underneath a finger that lands on the backdrop).
   :has() is supported in Safari 17.4+/iPadOS 17.4+, our target range. */
body:has(.modal:not(.hidden)) { overflow: hidden; }
.modal__head { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); }
.modal__head h2 { font-size: 26px; font-weight: 700; margin: 0; letter-spacing: -.01em; }
.modal__x {
  appearance: none; border: 1px solid var(--line); background: var(--surface); color: var(--ink-2);
  width: 40px; height: 40px; border-radius: var(--radius); font-size: 17px; cursor: pointer;
}
.modal__x:hover { background: var(--surface-2); color: var(--ink); }
.modal__sub { font-size: 14px; color: var(--ink-2); margin: 6px 0 var(--s3); }

.field { margin-bottom: var(--s2); }
.field label { display: block; font-size: 13px; font-weight: 700; color: var(--ink-2); margin-bottom: 6px; }
.field__opt { color: var(--ink-3); font-weight: 600; text-transform: none; letter-spacing: 0; }
.field input, .field textarea {
  width: 100%; font-family: inherit; font-size: 16px; padding: 12px 14px; min-height: 52px;
  border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--surface);
  color: var(--ink);
}
.field textarea { min-height: 64px; resize: vertical; line-height: 1.4; }
.field input:focus, .field textarea:focus { outline: 2px solid var(--ink); outline-offset: 1px; border-color: var(--ink); }
.field.has-err input, .field.has-err textarea { border-color: var(--err-ink); }
.field__err { display: block; font-size: 13px; color: var(--err-ink); font-weight: 600; margin-top: 5px; min-height: 1px; }
.field-row { display: grid; grid-template-columns: 96px 1fr 1fr; gap: var(--s2); }
@media (max-width: 460px) { .field-row { grid-template-columns: 1fr 1fr; } .field-row .field:first-child { grid-column: 1 / -1; } }

.modal__err { font-size: 14px; color: var(--err-ink); font-weight: 600; min-height: 20px; margin-bottom: 4px; }
.modal__actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: var(--s1); }
.modal__actions .btn { min-height: 52px; padding-inline: 22px; }

/* ---------- login ---------- */
/* Reads as the Lecker Asia site: white hairline card (no heavy shadow), black
   "LA" wordmark mark, Zilla Slab headings, black submit button (the site's own
   inverted-button style). */
.login-page { min-height: 100dvh; display: grid; place-items: center; padding: var(--s3); }
.login {
  width: min(420px, 100%); background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: clamp(28px, 5vw, 40px);
}
.login__mark {
  width: 60px; height: 60px; border-radius: 2px; background: var(--ink); color: #fff;
  display: grid; place-items: center; font-weight: 700; font-size: 22px; margin-bottom: var(--s3);
  letter-spacing: .5px;
}
.login h1 { font-size: 30px; font-weight: 700; margin: 0 0 4px; letter-spacing: -.01em; }
.login p { font-size: 15px; color: var(--ink-2); margin: 0 0 var(--s3); line-height: 1.5; }
.login label { display: block; font-size: 13px; font-weight: 700; color: var(--ink-2); margin-bottom: 8px; }
.login input {
  width: 100%; font-size: 17px; padding: 14px 16px; min-height: 56px;
  border: 1px solid var(--ink); border-radius: 2px; background: var(--surface);
  color: var(--ink); font-family: inherit;
}
.login input:focus { outline: 2px solid var(--ink); outline-offset: 2px; }
.login__submit {
  width: 100%; margin-top: var(--s2); min-height: 56px; border: 1px solid var(--ink);
  background: var(--ink); color: #fff; font-weight: 700; font-size: 17px;
  border-radius: 2px; cursor: pointer; transition: opacity .15s ease;
}
.login__submit:hover { opacity: .82; }
.login__submit:disabled { opacity: .6; cursor: default; }
.login__err { margin-top: var(--s2); font-size: 14px; color: var(--err-ink); font-weight: 600; min-height: 20px; }

:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ==========================================================================
   VIEW TOGGLE  (Calendar / List  ·  Day / Week) — segmented, monochrome
   ========================================================================== */
.viewtoggle {
  display: inline-flex; border: 1px solid var(--line-strong); border-radius: 2px;
  overflow: hidden; background: var(--surface);
}
.viewtoggle--scale { border-color: var(--line); }
.segbtn {
  appearance: none; border: 0; background: transparent; cursor: pointer;
  font-family: inherit; font-weight: 700; font-size: 14px; color: var(--ink-2);
  padding: 0 16px; min-height: 44px; letter-spacing: -.01em;
}
.segbtn + .segbtn { border-left: 1px solid var(--line); }
.segbtn:hover { background: var(--surface-2); color: var(--ink); }
/* selected segment = the site's inverted black button */
.segbtn[aria-pressed="true"] { background: var(--ink); color: #fff; }
.viewtoggle--scale .segbtn { min-height: 40px; padding: 0 13px; font-size: 13px; }

/* ==========================================================================
   CALENDAR — DAY VIEW  (hour grid + placed event cards)
   ========================================================================== */
.calwrap { display: flex; flex-direction: column; gap: var(--s2); }

/* bookings without a clock time — surfaced above the grid, never lost */
.calunsched {
  border: 1px dashed var(--line-strong); border-radius: var(--radius);
  background: var(--surface); padding: 10px 12px;
}
.calunsched__h { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-3); margin-bottom: 8px; }
.calunsched__row { display: flex; flex-wrap: wrap; gap: 8px; }
.uchip {
  appearance: none; cursor: pointer; text-align: left; font-family: inherit;
  border: 1px solid var(--line-strong); border-left-width: 4px; border-radius: 2px;
  background: var(--surface); padding: 7px 12px; display: flex; flex-direction: column; gap: 1px;
}
.uchip:hover { background: var(--surface-2); }
.uchip__n { font-size: 14px; font-weight: 700; color: var(--ink); }
.uchip__meta { font-size: 12px; color: var(--ink-2); font-weight: 600; display: inline-flex; align-items: center; gap: 4px; }
.uchip__meta svg { width: 12px; height: 12px; opacity: .55; }
.uchip--confirmed { border-left-color: var(--conf-ink); }
.uchip--seated    { border-left-color: var(--seat-ink); }
.uchip--new       { border-left-color: var(--new-ink); }
.uchip--cancelled { border-left-color: var(--canc-line); opacity: .7; }
.uchip--awaiting  { border-left-color: var(--seat-ink); }
.uchip--error     { border-left-color: var(--err-ink); }
.uchip--processing{ border-left-color: var(--proc-line); }

/* the grid: an absolutely-positioned overlay of events on top of hour rules */
.calgrid {
  position: relative; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden;
}
.calhours { position: absolute; inset: 0; }
.calhour { position: absolute; left: 0; right: 0; height: 0; border-top: 1px solid var(--line); }
.calhour:first-child { border-top-color: transparent; }
.calhour__l {
  position: absolute; top: 2px; left: 8px; font-size: 11px; font-weight: 700;
  color: var(--ink-3); text-transform: uppercase; letter-spacing: .03em; background: var(--surface); padding-right: 4px;
}
/* events sit in a lane that starts after the hour gutter */
.calevents { position: absolute; top: 0; bottom: 0; left: 58px; right: 6px; }

.calevent {
  position: absolute; appearance: none; cursor: pointer; font-family: inherit;
  text-align: left; overflow: hidden;
  border: 1.5px solid var(--line-strong); border-left-width: 4px; border-radius: 2px;
  background: var(--surface); padding: 5px 8px;
  display: flex; flex-direction: column; gap: 1px;
  transition: transform .05s ease, box-shadow .12s ease;
}
.calevent:hover { box-shadow: 0 2px 10px rgba(0,0,0,.12); z-index: 3; }
.calevent:active { transform: translateY(1px); }
.calevent__t { font-size: 12px; font-weight: 700; letter-spacing: -.01em; line-height: 1.1; }
.calevent__n { font-size: 14px; font-weight: 700; color: var(--ink); line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.calevent__p { font-size: 12px; font-weight: 700; color: var(--ink-2); display: inline-flex; align-items: center; gap: 3px; }
.calevent__p svg { width: 12px; height: 12px; opacity: .55; }
.calevent__flag { position: absolute; top: 4px; right: 6px; font-size: 16px; line-height: 1; color: var(--ink-3); }
/* Guest note marker (Feature: Guest notes) — opposite corner from the special-
   request dot so the two never collide. */
.calevent__flag--note { left: 4px; right: auto; font-size: 13px; }

/* NEW = hollow blue outline (not yet locked in). CONFIRMED = solid green fill —
   the visual "filed onto the calendar". Seated = amber. Cancelled = struck. */
.calevent--new       { border-color: var(--new-line);  border-left-color: var(--new-ink); background: var(--new-bg); }
.calevent--new .calevent__t { color: var(--new-ink); }
.calevent--confirmed { border-color: var(--conf-ink); border-left-color: var(--conf-ink); background: var(--conf-ink); }
.calevent--confirmed .calevent__t,
.calevent--confirmed .calevent__n,
.calevent--confirmed .calevent__p { color: #fff; }
.calevent--confirmed .calevent__p svg { opacity: .85; }
.calevent--seated    { border-color: var(--seat-ink); border-left-color: var(--seat-ink); background: var(--seat-bg); }
.calevent--seated .calevent__t { color: var(--seat-ink); }
.calevent--cancelled { border-color: var(--canc-line); border-left-color: var(--canc-line); background: var(--canc-bg); opacity: .68; }
.calevent--cancelled .calevent__n { text-decoration: line-through; color: var(--ink-3); }
.calevent--awaiting  { border-color: var(--seat-line); border-left-color: var(--seat-ink); background: var(--seat-bg); }
.calevent--error     { border-color: var(--err-line);  border-left-color: var(--err-ink);  background: var(--err-bg); }
.calevent--processing{ border-color: var(--proc-line); border-left-color: var(--proc-line); background: var(--proc-bg); }

/* ==========================================================================
   DAY VIEW = THE TABLE GRID
   One column per active table (plus an Unassigned lane), time down the page.
   A booking block spans its turn time (90 min to a party of 4, 120 from 5).
   ========================================================================== */
.tgridscroll {
  overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
  /* keep an at-the-edge horizontal pan inside the grid — don't let iOS
     rubber-band it into a page-level bounce/scroll */
  overscroll-behavior-x: contain;
}
.tgrid { min-width: max-content; width: 100%; }
.tgridrow { display: flex; align-items: stretch; }
.tgridrow--head { border-bottom: 1px solid var(--line-strong); background: var(--surface-2); }
.tgridrow--body { position: relative; }

/* the hour gutter, matched in both rows so labels line up with the columns */
.tgutterhead, .tgutter { flex: 0 0 58px; width: 58px; }
.tgutter { position: relative; border-right: 1px solid var(--line); }

/* Floor plan trigger, anchored in the grid's otherwise-empty top-left corner
   cell — where the time axis meets the table-header row. Lives ONLY in the
   head row, never the hour-labelled body row, so it can't cover the first
   hour label. */
.tgutterhead { display: flex; align-items: center; justify-content: center; padding: 0; }
.gridlegendbtn {
  appearance: none; cursor: pointer; border: 1px solid var(--line-strong);
  background: var(--surface); color: var(--ink-2); border-radius: 2px;
  width: 44px; height: 44px; min-width: 44px; min-height: 44px;
  display: grid; place-items: center; padding: 0;
}
.gridlegendbtn:hover { background: var(--surface-2); color: var(--ink); }
.gridlegendbtn svg { width: 20px; height: 20px; }

.tcolhead, .tcolbody { flex: 1 1 0; min-width: 116px; }
/* the Unassigned lane is wider — it carries the Auto-assign action */
.tcolhead--uns, .tcolbody--uns { flex: 1.5 1 0; min-width: 208px; }

.tcolhead {
  display: flex; align-items: center; gap: 6px; padding: 8px 10px;
  border-left: 1px solid var(--line); min-height: 42px;
}
.tcolhead__n { font-size: 13px; font-weight: 700; color: var(--ink); white-space: nowrap; }
.tcolhead__s { font-size: 11.5px; font-weight: 700; color: var(--ink-2); display: inline-flex; align-items: center; gap: 3px; }
.tcolhead__s svg { width: 12px; height: 12px; opacity: .55; }
.tcolhead__c { margin-left: auto; font-size: 11.5px; font-weight: 700; color: var(--ink-3); }
.tcolhead--uns { background: repeating-linear-gradient(45deg, transparent, transparent 6px, rgba(0,0,0,.03) 6px, rgba(0,0,0,.03) 12px); }
.tcolhead--uns .tcolhead__n { color: var(--ink-2); }

.tcolbody { position: relative; border-left: 1px solid var(--line); overflow: hidden; }
/* Empty space in a real table's column is a click target: tap a timeslot to
   start a booking pinned to that table/time (see openBookOnTable in app.js).
   Excluded from the Unassigned lane, which has no single table to bind to. */
.tcolbody:not(.tcolbody--uns) { cursor: pointer; }
.tcolbody--uns { background: repeating-linear-gradient(45deg, transparent, transparent 6px, rgba(0,0,0,.02) 6px, rgba(0,0,0,.02) 12px); }
.tcolbody.has-conflict { background: var(--err-bg); }

/* a booking block inside a table column (positioned via CSSOM — see app.js) */
.tblock {
  position: absolute; appearance: none; cursor: pointer; font-family: inherit;
  text-align: left; overflow: hidden;
  border: 1.5px solid var(--line-strong); border-left-width: 4px; border-radius: 2px;
  background: var(--surface); padding: 4px 7px;
  display: flex; flex-direction: column; gap: 1px;
  transition: transform .05s ease, box-shadow .12s ease;
}
.tblock:hover { box-shadow: 0 2px 10px rgba(0,0,0,.12); z-index: 3; }
.tblock:active { transform: translateY(1px); }
.tblock.is-conflict { outline: 2px solid var(--err-ink); outline-offset: -2px; }
/* a party no single table can seat — left in the Unassigned lane on purpose */
.tblock.is-toolarge { border-color: var(--seat-line); border-left-color: var(--seat-ink); background: var(--seat-bg); }
.calevent__big {
  font-size: 10.5px; font-weight: 800; letter-spacing: .02em; line-height: 1.15;
  color: var(--seat-ink); text-transform: uppercase; margin-top: 1px;
}

/* Auto-assign action on the Unassigned lane header */
.uauto {
  appearance: none; font-family: inherit; font-size: 11px; font-weight: 800;
  text-transform: uppercase; letter-spacing: .04em; cursor: pointer;
  border: 1.5px solid var(--line-strong); border-radius: 2px;
  background: var(--surface); color: var(--ink); padding: 3px 7px; white-space: nowrap;
}
.uauto:hover:not(:disabled) { background: var(--ink); color: var(--surface); border-color: var(--ink); }
.uauto:disabled { opacity: .4; cursor: default; }
.tblock .calevent__n { font-size: 13px; }
.tblock.flash { animation: evflash .9s ease-out; z-index: 4; }

/* ==========================================================================
   MANUAL REASSIGN — drag a block to another table column, or tap-to-move.
   Highlights are ADVISORY: green = the party fits a table that is free then,
   amber = it doesn't (too small and/or already busy). Both are droppable; the
   amber ones simply warn, and the grid then renders the conflict honestly.
   All geometry is applied via CSSOM in app.js — the CSP blocks inline style="".
   ========================================================================== */
.dragghost {
  position: fixed; z-index: 90; pointer-events: none;
  font-family: inherit; text-align: left; overflow: hidden;
  border: 2px solid var(--ink); border-left-width: 4px; border-radius: 2px;
  background: var(--surface); padding: 4px 7px;
  display: flex; flex-direction: column; gap: 1px;
  box-shadow: 0 12px 30px rgba(0,0,0,.32); opacity: .96;
}
.dragghost__t { font-size: 11px; font-weight: 800; color: var(--ink-2); }
.dragghost__n { font-size: 13px; font-weight: 700; color: var(--ink); }
.dragghost__p { font-size: 11.5px; font-weight: 700; color: var(--ink-2); display: inline-flex; align-items: center; gap: 3px; }
.dragghost__p svg { width: 12px; height: 12px; opacity: .55; }

/* iOS Safari fires its own long-press text-selection / callout ("Copy",
   "Look Up") on anything holdable, which fights our own long-press-to-drag
   gesture on grid blocks. Block it here — same treatment on the calendar's
   other draggable-looking chips (.calevent/.wchip/.uchip) for consistency,
   even though only .tblock is actually draggable today. */
.tblock, .calevent, .wchip, .uchip {
  -webkit-user-select: none; user-select: none;
  -webkit-touch-callout: none;
}
.tblock.is-dragging { opacity: .3; }
.tblock.is-moving-src { outline: 2px dashed var(--ink); outline-offset: -2px; }
.tgrid.is-moving .tblock { cursor: grabbing; }

/* drop targets (these must beat .tcolbody.has-conflict, so they come later) */
.tcolbody.is-dropok   { background: var(--conf-bg); box-shadow: inset 0 0 0 2px var(--conf-line); }
.tcolbody.is-dropwarn { background: var(--seat-bg); box-shadow: inset 0 0 0 2px var(--seat-line); }
.tcolbody.is-dropfrom { background: var(--surface-2); box-shadow: inset 0 0 0 2px var(--line-strong); }
.tcolbody.is-dropbest { box-shadow: inset 0 0 0 3px var(--conf-ink); }
.tcolbody.is-drophot.is-dropok   { box-shadow: inset 0 0 0 3px var(--conf-ink); }
.tcolbody.is-drophot.is-dropwarn { box-shadow: inset 0 0 0 3px var(--seat-ink); }
.tcolbody.is-drophot.is-dropfrom { box-shadow: inset 0 0 0 3px var(--ink-3); }

/* the tap-to-move instruction bar */
.movebar {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 85;
  display: flex; align-items: center; gap: 12px;
  background: var(--ink); color: #fff; border-radius: 2px;
  font-size: 15px; font-weight: 700; padding: 10px 14px;
  box-shadow: 0 8px 28px rgba(0,0,0,.28); max-width: calc(100vw - 32px);
}
.movebar__t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.movebar__x {
  appearance: none; font-family: inherit; font-size: 12px; font-weight: 800;
  text-transform: uppercase; letter-spacing: .04em; cursor: pointer; white-space: nowrap;
  background: transparent; color: #fff; border: 1.5px solid rgba(255,255,255,.55);
  border-radius: 2px; padding: 5px 9px;
}
.movebar__x:hover { background: rgba(255,255,255,.14); }

/* an honest note above the grid (defaults in use / no active tables) */
.gridnote {
  font-size: 13px; font-weight: 600; color: var(--ink-2);
  border: 1px dashed var(--line-strong); border-radius: var(--radius);
  background: var(--surface); padding: 9px 12px;
}
.gridnote--warn { border-color: var(--seat-line); background: var(--seat-bg); color: var(--seat-ink); }

/* ---- table assignment picker (in the booking detail) ---- */
.tassign { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.tassign__l { font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-3); }
.tassign__s {
  appearance: none; font-family: inherit; font-size: 14px; font-weight: 600;
  border: 1.5px solid var(--line-strong); border-radius: 2px; background: var(--surface);
  color: var(--ink); padding: 7px 10px; min-height: 38px;
}
.tassign__hint { font-size: 12px; font-weight: 600; color: var(--ink-3); }

/* ---- table settings rows ---- */
.tlist { display: flex; flex-direction: column; gap: 6px; margin: 10px 0; }
.tlist__h { font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-3); margin-top: 14px; }
.tempty { font-size: 14px; color: var(--ink-3); font-weight: 600; padding: 6px 0; }
.trow {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 8px 10px; background: var(--surface);
}
.trow.is-off { opacity: .6; background: var(--surface-2); }
.trow__name {
  flex: 1 1 120px; min-width: 90px; font-family: inherit; font-size: 15px; font-weight: 700;
  border: 1.5px solid var(--line-strong); border-radius: 2px; padding: 7px 9px; min-height: 38px; background: var(--surface); color: var(--ink);
}
.trow__size { display: flex; align-items: center; gap: 5px; }
.trow__size input {
  width: 68px; font-family: inherit; font-size: 15px; font-weight: 700;
  border: 1.5px solid var(--line-strong); border-radius: 2px; padding: 7px 9px; min-height: 38px; background: var(--surface); color: var(--ink);
}
.trow__size span { font-size: 12px; font-weight: 700; color: var(--ink-3); }
.btn--sm { min-height: 38px; padding: 0 12px; font-size: 13px; }
.btn--danger { color: var(--err-ink); border-color: var(--err-line); }
.btn--danger:hover { background: var(--err-bg); }
.tadd {
  display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap;
  border-top: 1px solid var(--line); padding-top: 14px; margin-top: 14px;
}
.tadd .field { margin: 0; flex: 1 1 130px; }
.tadd #t-newsize { width: 90px; }

/* the confirm pulse — draws the eye to the booking that just moved */
@keyframes evflash { 0% { box-shadow: 0 0 0 0 var(--conf-ink); } 100% { box-shadow: 0 0 0 6px transparent; } }
.calevent.flash, .wchip.flash { animation: evflash .9s ease-out; z-index: 4; }
@media (prefers-reduced-motion: reduce) { .calevent.flash, .wchip.flash { animation: none; } }

/* ==========================================================================
   CALENDAR — WEEK VIEW  (7 day columns of compact chips)
   ========================================================================== */
.weekwrap {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(150px, 1fr);
  gap: 8px; overflow-x: auto; -webkit-overflow-scrolling: touch; padding-bottom: 6px;
  overscroll-behavior-x: contain;
}
.wcol { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); display: flex; flex-direction: column; min-width: 0; }
.wcol.is-sel { border-color: var(--ink); }
.wcol__h {
  appearance: none; cursor: pointer; font-family: inherit; text-align: left;
  border: 0; border-bottom: 1px solid var(--line); background: var(--surface-2);
  padding: 8px 10px; display: flex; align-items: baseline; gap: 6px;
}
.wcol.is-sel .wcol__h { background: var(--ink); }
.wcol.is-sel .wcol__h .wcol__dow, .wcol.is-sel .wcol__h .wcol__num, .wcol.is-sel .wcol__h .wcol__c { color: #fff; }
.wcol__dow { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-2); }
.wcol__num { font-size: 17px; font-weight: 700; color: var(--ink); }
.wcol__c { margin-left: auto; font-size: 12px; font-weight: 700; color: var(--ink-3); }
.wcol__body { padding: 8px; display: flex; flex-direction: column; gap: 6px; min-height: 60px; }
.wempty { color: var(--ink-3); font-size: 13px; text-align: center; padding: 8px 0; }
.wuns { font-size: 11px; color: var(--ink-3); font-weight: 600; text-align: center; padding-top: 2px; }

.wchip {
  appearance: none; cursor: pointer; font-family: inherit; text-align: left;
  border: 1px solid var(--line-strong); border-left-width: 4px; border-radius: 2px;
  background: var(--surface); padding: 6px 8px; display: flex; flex-direction: column; gap: 1px; min-width: 0;
}
.wchip:hover { background: var(--surface-2); }
.wchip__t { font-size: 12px; font-weight: 700; letter-spacing: -.01em; }
.wchip__n { font-size: 13px; font-weight: 700; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wchip__p { font-size: 11px; font-weight: 700; color: var(--ink-2); display: inline-flex; align-items: center; gap: 3px; }
.wchip__p svg { width: 11px; height: 11px; opacity: .55; }
.wchip--new       { border-left-color: var(--new-ink); }
.wchip--new .wchip__t { color: var(--new-ink); }
.wchip--confirmed { border-color: var(--conf-ink); border-left-color: var(--conf-ink); background: var(--conf-bg); }
.wchip--confirmed .wchip__t { color: var(--conf-ink); }
.wchip--seated    { border-left-color: var(--seat-ink); background: var(--seat-bg); }
.wchip--seated .wchip__t { color: var(--seat-ink); }
.wchip--cancelled { border-left-color: var(--canc-line); opacity: .68; }
.wchip--cancelled .wchip__n { text-decoration: line-through; color: var(--ink-3); }
.wchip--awaiting  { border-left-color: var(--seat-ink); }
.wchip--error     { border-left-color: var(--err-ink); }
.wchip--processing{ border-left-color: var(--proc-line); }

/* "N need a date" link in the calendar header */
.reviewlink {
  appearance: none; border: 1px solid var(--seat-line); background: var(--seat-bg);
  color: var(--seat-ink); font-family: inherit; font-weight: 700; font-size: 12px;
  border-radius: 2px; padding: 5px 10px; cursor: pointer; white-space: nowrap;
}
.reviewlink:hover { background: #f7e8c8; }

/* ==========================================================================
   DETAIL POPOVER  (tap a calendar event) — reuses the table's detail panel
   ========================================================================== */
.dmodal { padding: 0; width: min(560px, 100%); max-height: 92dvh; overflow-y: auto; overscroll-behavior: contain; }
.dmodal__head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s2);
  padding: var(--s2) var(--s2) 0;
}
.dmodal__t { font-size: 13px; font-weight: 700; color: var(--ink-2); text-transform: uppercase; letter-spacing: .03em; }
.dmodal__n { font-size: 26px; font-weight: 700; letter-spacing: -.01em; line-height: 1.1; margin-top: 2px; }
/* the reused .detail panel already brings the dl + actions + raw request */
.dmodal .detail { padding: var(--s2); }
.dmodal .drow { display: block; }

/* ==========================================================================
   TOASTS  (obvious immediate feedback on a status change)
   ========================================================================== */
.toasts {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%);
  z-index: 80; display: flex; flex-direction: column; gap: 8px; align-items: center;
  pointer-events: none; width: max-content; max-width: calc(100vw - 32px);
}
.toast {
  pointer-events: auto; background: var(--ink); color: #fff;
  font-weight: 700; font-size: 15px; padding: 12px 18px; border-radius: 2px;
  box-shadow: 0 8px 28px rgba(0,0,0,.28);
  opacity: 0; transform: translateY(10px); transition: opacity .22s ease, transform .22s ease;
  border-left: 4px solid #fff;
}
.toast.is-in { opacity: 1; transform: translateY(0); }
.toast--confirmed { border-left-color: var(--conf-line); }
.toast--seated    { border-left-color: var(--seat-line); }
.toast--cancelled { border-left-color: var(--canc-line); }
.toast--err { background: var(--err-ink); border-left-color: #fff; }
/* an ALLOWED but flagged manual move (too small / double-booked) */
.toast--warn { border-left-color: var(--seat-ink); }
@media (prefers-reduced-motion: reduce) { .toast { transition: opacity .01s; } }

/* ---- narrow screens ---- */
@media (max-width: 640px) {
  .calevents { left: 50px; }
  .viewtoggle--scale { display: inline-flex; }
  /* the pill rail scrolls internally rather than wrapping the whole row, so
     Prev | pills | Today Next stays one horizontal cluster even at 390px */
  .weekbar__row { flex-wrap: nowrap; }
  .weekbar__row .dayrail { overflow-x: auto; }
  .weekstep span { display: none; }
  .weekstep { min-width: 44px; justify-content: center; padding: 0 10px; }
}

/* ============================================================================
   FLOOR LIFECYCLE (dashboard-owned): New -> Arrived -> Seated -> Done, with
   No-show / Cancel off-ramps. Each colour distinguishable at a glance:
   New = blue outline · Arrived = amber filled · Seated = solid green ·
   Done = muted grey + check · No-show = red strike · Cancel = grey strike.
   ============================================================================ */
:root { --arr-ink: #b8731a; --arr-fill: #c9801e; --arr-bg: #f7ecd9; }

/* Incomplete-tab count badge on the segmented control */
.segbtn__badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px; margin-left: 7px;
  border-radius: 9px; background: var(--err-ink); color: #fff;
  font-size: 11.5px; font-weight: 800; vertical-align: middle;
}
.segbtn[aria-pressed="true"] .segbtn__badge { background: #fff; color: var(--ink); }

/* ---- week navigation: Prev | day pills | Today Next, one cluster ----
   David, 2026-07-29: Prev used to sit far from Today/Next (separated by the
   range label). Today/Next now sit directly against the day-pill rail so
   Prev | pills | Today Next reads as a single control. The range/week-tag
   text moves to a small caption line above the cluster instead of wedging
   between the buttons. */
.weekbar { padding: 2px 0 8px; }
.weekbar__range { display: flex; align-items: baseline; gap: 8px; padding: 0 0 4px 2px; }
.weekbar__dates { font-size: 14px; font-weight: 800; color: var(--ink); letter-spacing: -.01em; }
.weekbar__tag { font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-3); }
.weekbar__tag.is-now { color: var(--conf-ink); }
.weekbar__row { display: flex; align-items: center; gap: 8px; }
.weekbar__row .dayrail { flex: 1 1 auto; min-width: 0; padding: 4px 0; }
.weekstep {
  appearance: none; cursor: pointer; font-family: inherit; font-weight: 700; font-size: 13px;
  display: inline-flex; align-items: center; gap: 3px; flex: none;
  border: 1px solid var(--line-strong); background: var(--surface); color: var(--ink-2);
  min-height: 44px; padding: 0 12px; border-radius: 2px;
}
.weekstep:hover { background: var(--surface-2); color: var(--ink); }
.weekstep:disabled { opacity: .4; cursor: default; }
.weekstep svg { width: 15px; height: 15px; }
#prevWeek svg { transform: rotate(90deg); }
#nextWeek svg { transform: rotate(-90deg); }
#thisWeek { margin-left: 2px; }
#nextWeek { margin-left: -2px; }
.daypill.is-today { border-color: var(--ink); }
.daypill.is-past { opacity: .5; }

/* ---- calendar day-grid events ---- */
.calevent--arrived { border-color: var(--arr-ink); border-left-color: var(--arr-ink); background: var(--arr-fill); }
.calevent--arrived .calevent__t,
.calevent--arrived .calevent__n,
.calevent--arrived .calevent__p { color: #fff; }
.calevent--arrived .calevent__p svg { opacity: .85; }
.calevent--seated { border-color: var(--conf-ink); border-left-color: var(--conf-ink); background: var(--conf-ink); }
.calevent--seated .calevent__t,
.calevent--seated .calevent__n,
.calevent--seated .calevent__p { color: #fff; }
.calevent--seated .calevent__p svg { opacity: .85; }
.calevent--done { border-color: var(--canc-line); border-left-color: var(--canc-ink); background: var(--canc-bg); opacity: .9; }
.calevent--done .calevent__t { color: var(--canc-ink); }
.calevent--done .calevent__n { color: var(--ink-2); }
.calevent--done .calevent__n::after { content: " \2713"; color: var(--conf-ink); font-weight: 800; }
.calevent--no_show { border-color: var(--err-line); border-left-color: var(--err-ink); background: var(--err-bg); }
.calevent--no_show .calevent__t { color: var(--err-ink); }
.calevent--no_show .calevent__n { text-decoration: line-through; color: var(--err-ink); }
.calevent--cancel { border-color: var(--canc-line); border-left-color: var(--canc-line); background: var(--canc-bg); opacity: .7; }
.calevent--cancel .calevent__n { text-decoration: line-through; color: var(--ink-3); }

/* ---- week-scale chips ---- */
.wchip--arrived { border-color: var(--arr-ink); border-left-color: var(--arr-ink); background: var(--arr-bg); }
.wchip--arrived .wchip__t { color: var(--arr-ink); }
.wchip--done { border-left-color: var(--canc-ink); opacity: .9; }
.wchip--done .wchip__t { color: var(--canc-ink); }
.wchip--no_show { border-left-color: var(--err-ink); }
.wchip--no_show .wchip__n { text-decoration: line-through; color: var(--err-ink); }
.wchip--cancel { border-left-color: var(--canc-line); opacity: .68; }
.wchip--cancel .wchip__n { text-decoration: line-through; color: var(--ink-3); }

/* ---- unscheduled chips (defensive fallback) ---- */
.uchip--arrived { border-left-color: var(--arr-ink); }
.uchip--done    { border-left-color: var(--canc-ink); }
.uchip--no_show { border-left-color: var(--err-ink); }
.uchip--cancel  { border-left-color: var(--canc-line); opacity: .7; }

/* ---- status glyphs in the list ---- */
.sicon--arrived { color: #fff; background: var(--arr-fill); border-color: var(--arr-ink); }
.sicon--done    { color: var(--canc-ink); background: var(--canc-bg); border-color: var(--canc-line); }
.sicon--no_show { color: var(--err-ink); background: var(--err-bg); border-color: var(--err-line); }
.sicon--cancel  { color: var(--canc-ink); background: var(--canc-bg); border-color: var(--canc-line); }

/* ---- pills ---- */
.pill--arrived { color: #fff; background: var(--arr-fill); border-color: var(--arr-ink); }
.pill--done    { color: var(--canc-ink); background: var(--canc-bg); border-color: var(--canc-line); }
.pill--no_show { color: var(--err-ink); background: var(--err-bg); border-color: var(--err-line); }
.pill--cancel  { color: var(--canc-ink); background: var(--canc-bg); border-color: var(--canc-line); }

/* ---- floor action buttons (outline, subtle accent by verb) ---- */
.act--arrived  { color: var(--arr-ink); }
.act--seated   { color: var(--conf-ink); }
.act--done     { color: var(--ink-2); }
.act--no_show,
.act--cancel   { color: var(--err-ink); }
.act--reopen   { color: var(--ink-2); }
.act--complete { color: var(--new-ink); }

/* ============================================================================
   INCOMPLETE LIST
   ============================================================================ */
.incomplete-lede { font-size: 14px; color: var(--ink-2); margin: 0 0 var(--s3); max-width: 62ch; line-height: 1.5; }
.inclist { display: flex; flex-direction: column; gap: 12px; }
.inccard {
  background: var(--surface); border: 1px solid var(--line);
  border-left: 3px solid var(--seat-ink); border-radius: 2px; padding: 14px 16px;
}
.inccard__top { display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: baseline; justify-content: space-between; }
.inccard__who b { font-size: 16px; }
.inccard__who i { color: var(--ink-3); font-weight: 600; }
.inccard__meta { display: block; font-size: 12.5px; color: var(--ink-3); font-weight: 600; margin-top: 2px; }
.inccard__orig { font-size: 13px; color: var(--ink-2); margin-top: 8px; }
.inccard__orig b { color: var(--ink); }
.inccard__raw { margin-top: 10px; font-size: 13px; }
.inccard__raw summary { cursor: pointer; color: var(--ink-2); font-weight: 600; }
.inccard__raw pre { margin: 6px 0 0; white-space: pre-wrap; background: var(--surface-2); border: 1px solid var(--line); padding: 10px; border-radius: 2px; font-size: 12.5px; }
.inccard__actions { margin-top: 12px; }
.inccard__actions .btn { display: inline-flex; align-items: center; gap: 7px; }
.inccard__actions .btn svg { width: 18px; height: 18px; flex: none; }

.missrow { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.misslabel { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-3); margin-right: 2px; }
.misstag {
  font-size: 12px; font-weight: 700; color: var(--err-ink);
  background: var(--err-bg); border: 1px solid var(--err-line);
  padding: 2px 8px; border-radius: 10px;
}

/* completion-attempt (WhatsApp follow-up) status line */
.attempt { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--ink-2); margin-top: 10px; }
.attempt__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ink-3); flex: none; }
.attempt--pending .attempt__dot { background: var(--seat-ink); }
.attempt--pending { color: var(--seat-ink); }
.attempt--failed .attempt__dot { background: var(--err-ink); }
.attempt--failed { color: var(--err-ink); }
.attempt--done .attempt__dot { background: var(--conf-ink); }
.attempt--processing .attempt__dot { background: var(--proc-ink); }
.attempt--none .attempt__dot { background: var(--ink-3); }

.dactions--incomplete { flex-direction: column; align-items: stretch; gap: 10px; }
.dactions--incomplete .act--complete { align-self: flex-start; }

.modal__hint { font-size: 13px; color: var(--seat-ink); background: var(--seat-bg); border: 1px solid var(--seat-line); padding: 8px 12px; border-radius: 2px; margin: 0 0 var(--s3); }

.toast--new     { border-left-color: var(--new-line); }
.toast--arrived { border-left-color: var(--arr-fill); }
.toast--done    { border-left-color: var(--canc-line); }
.toast--no_show { border-left-color: var(--err-line); }
.toast--cancel  { border-left-color: var(--canc-line); }

/* ==========================================================================
   FEATURE 4 — WALK-INS + WAITLIST
   The waitlist is its OWN lane above the grid, deliberately not the Unassigned
   column: unassigned = "staff parked it", waitlist = "a party is standing here
   waiting". Warm (seat) hue so it reads as pressure on the room.
   ========================================================================== */
.modal__panel--sm { width: min(440px, 100%); }

.wlpanel {
  border: 1px solid var(--seat-line); border-left: 4px solid var(--seat-ink);
  border-radius: var(--radius); background: var(--seat-bg); padding: 10px 12px;
}
.wlpanel__h {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  color: var(--seat-ink); margin-bottom: 8px;
}
.wlpanel__row { display: flex; flex-wrap: wrap; gap: 8px; }

.wlitem {
  display: flex; align-items: stretch; gap: 0;
  border: 1px solid var(--seat-line); border-radius: 2px; background: var(--surface);
  overflow: hidden;
}
.wlitem.is-nofit { border-color: var(--err-line); }
.wlitem__main {
  appearance: none; cursor: pointer; text-align: left; font-family: inherit;
  background: transparent; border: 0; padding: 7px 12px;
  display: flex; flex-direction: column; gap: 1px; min-width: 132px;
}
.wlitem__main:hover { background: var(--surface-2); }
.wlitem__n { font-size: 14px; font-weight: 700; color: var(--ink); }
.wlitem__meta {
  font-size: 12px; color: var(--ink-2); font-weight: 600;
  display: inline-flex; align-items: center; gap: 4px;
}
.wlitem__meta svg { width: 12px; height: 12px; opacity: .55; }
.wlitem__est { font-size: 12px; font-weight: 700; color: var(--seat-ink); }
.wlitem__est--none { color: var(--err-ink); }
.wlitem__acts {
  display: flex; flex-direction: column; border-left: 1px solid var(--line);
}
.wlbtn {
  appearance: none; font-family: inherit; cursor: pointer; white-space: nowrap;
  font-size: 11.5px; font-weight: 700; letter-spacing: .02em;
  background: var(--surface); color: var(--ink-2); border: 0; padding: 6px 12px;
  border-bottom: 1px solid var(--line); flex: 1 1 0; text-align: left;
}
.wlitem__acts .wlbtn:last-child { border-bottom: 0; }
.wlbtn:hover { background: var(--ink); color: var(--surface); }
.wlbtn--seat { color: var(--conf-ink); }

/* ==========================================================================
   FEATURE 5 — DAY PACING / COVER COUNTS
   A compact, collapsible strip above the grid: covers per service hour against
   the room's seat capacity, plus the day's totals. DISPLAY ONLY — it never
   blocks a booking.

   Colour: seated = confirm green, booked = new blue, waiting = seat amber (the
   same amber the waitlist lane already owns, so "waiting" reads consistently).
   Over-capacity therefore CANNOT also be amber without colliding, so it is the
   error red hatch — the strongest flag on the page, which is what an
   overbooked hour deserves.

   Bar heights are set via CSSOM in positionPacing(); the CSP forbids inline
   style="" (same constraint as the calendar blocks).
   ========================================================================== */
.pace {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden;
}
.pace.has-over { border-color: var(--err-line); }
.pace__h {
  appearance: none; font-family: inherit; cursor: pointer; width: 100%;
  display: flex; align-items: center; gap: 10px; text-align: left;
  background: transparent; border: 0; padding: 9px 12px; min-height: 44px;
}
.pace__h:hover { background: var(--surface-2); }
.pace__title {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink);
}
.pace__sum { font-size: 12.5px; font-weight: 600; color: var(--ink-2); }
.pace.has-over .pace__sum { color: var(--err-ink); font-weight: 700; }
.pace__chev { margin-left: auto; display: inline-flex; color: var(--ink-3); }
.pace__chev svg { width: 16px; height: 16px; transform: rotate(-90deg); transition: transform .15s ease; }
.pace.is-open .pace__chev svg { transform: rotate(0deg); }
.pace__body { display: none; padding: 0 12px 10px; }
.pace.is-open .pace__body { display: block; }

.pace__stats {
  display: flex; flex-wrap: wrap; gap: 6px;
  border-top: 1px solid var(--line); padding-top: 10px; margin-bottom: 10px;
}
.pstat {
  border: 1px solid var(--line); border-radius: 2px; background: var(--surface-2);
  padding: 5px 10px; display: flex; align-items: baseline; gap: 6px;
}
.pstat.is-bad { border-color: var(--err-line); background: var(--err-bg); }
.pstat__v { font-size: 17px; font-weight: 700; color: var(--ink); line-height: 1.1; }
.pstat.is-bad .pstat__v { color: var(--err-ink); }
.pstat__l {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--ink-2);
}
.pstat__l i { font-style: normal; text-transform: none; letter-spacing: 0; color: var(--ink-3); font-weight: 600; }

.pace__bars {
  display: flex; align-items: flex-end; gap: 4px;
  overflow-x: auto; -webkit-overflow-scrolling: touch; padding-bottom: 2px;
  overscroll-behavior-x: contain;
}
.pcol { flex: 1 1 0; min-width: 34px; display: flex; flex-direction: column; align-items: center; gap: 3px; }
.pcol__track {
  position: relative; width: 100%; height: 84px;
  display: flex; align-items: flex-end; justify-content: center;
  border-bottom: 1px solid var(--line-strong);
}
.pbar { position: relative; width: 60%; max-width: 26px; display: flex; flex-direction: column-reverse; }
.pseg { display: block; width: 100%; }
.pseg--seated  { background: var(--conf-ink); }
.pseg--booked  { background: var(--new-ink); }
.pseg--waiting { background: var(--seat-ink); }
/* the capacity reference line — the bar crossing it is the whole point */
.pcapline {
  position: absolute; left: 0; right: 0; bottom: 48px;
  border-top: 1px dashed var(--line-strong);
}
/* the part of an hour the room cannot actually seat */
.povr {
  position: absolute; left: 50%; transform: translateX(-50%);
  width: 60%; max-width: 26px;
  background: repeating-linear-gradient(45deg,
    var(--err-ink) 0 3px, var(--err-bg) 3px 6px);
  outline: 1px solid var(--err-ink);
}
.pcol__n { font-size: 12px; font-weight: 700; color: var(--ink); }
.pcol__l { font-size: 10px; font-weight: 700; color: var(--ink-3); white-space: nowrap; }
.pcol.is-empty .pcol__n { color: var(--ink-3); font-weight: 600; }
.pcol.is-over .pcol__n, .pcol.is-over .pcol__l { color: var(--err-ink); }

.pace__legend {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 8px;
  font-size: 11px; font-weight: 700; color: var(--ink-2);
}
.pkey { display: inline-flex; align-items: center; gap: 5px; }
.pkey::before { content: ''; width: 10px; height: 10px; border-radius: 2px; background: var(--ink-3); }
.pkey--seated::before  { background: var(--conf-ink); }
.pkey--booked::before  { background: var(--new-ink); }
.pkey--waiting::before { background: var(--seat-ink); }
.pkey--cap::before { height: 0; border-top: 1px dashed var(--line-strong); border-radius: 0; }
.pace__note { margin-left: auto; font-weight: 600; color: var(--ink-3); }

/* week strip: covers under the booking count */
.wcol__cov { width: 100%; font-size: 11px; font-weight: 700; color: var(--ink-3); }
.wcol.is-sel .wcol__h .wcol__cov { color: rgba(255,255,255,.75); }
/* the header now carries a second line (covers), so let it wrap */
.wcol__h { flex-wrap: wrap; }

/* ==========================================================================
   FEATURE A — edit-booking dialog. Reuses .field / .field-row / .modal__hint
   from the New/Complete booking forms; no new component vocabulary needed.
   ========================================================================== */
.act--edit { color: var(--ink-2); }

/* ==========================================================================
   FEATURE B — opening-hours admin.
   ========================================================================== */
.modal__panel--wide { width: min(760px, 100%); }

.hdays { display: flex; flex-direction: column; gap: 8px; margin: 10px 0; }
.hday {
  display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap;
  border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 10px; background: var(--surface);
}
.hday__label { flex: 0 0 96px; font-size: 14px; font-weight: 700; color: var(--ink); padding-top: 8px; }
.hday__windows { display: flex; flex-direction: column; gap: 6px; flex: 1 1 260px; min-width: 220px; }
.hempty { font-size: 13px; color: var(--ink-3); font-weight: 600; padding: 8px 0; }
.hwrow { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.hwrow__t {
  font-family: inherit; font-size: 14px; font-weight: 600; min-height: 44px;
  border: 1.5px solid var(--line-strong); border-radius: 2px; padding: 6px 8px; background: var(--surface); color: var(--ink);
}
.hwrow__to { font-size: 13px; font-weight: 700; color: var(--ink-3); }
.hclosures { border-top: 1px solid var(--line); padding-top: 14px; margin-top: 14px; }
.hclosures__h { font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-3); margin-bottom: 8px; }
.hclose { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.hclose__date {
  font-family: inherit; font-size: 14px; font-weight: 600; min-height: 44px; flex: 0 0 auto;
  border: 1.5px solid var(--line-strong); border-radius: 2px; padding: 6px 8px; background: var(--surface); color: var(--ink);
}
.hclose__label {
  font-family: inherit; font-size: 14px; font-weight: 600; min-height: 44px; flex: 1 1 160px;
  border: 1.5px solid var(--line-strong); border-radius: 2px; padding: 6px 8px; background: var(--surface); color: var(--ink);
}

/* ==========================================================================
   FEATURE C — floor plan legend (a deliberately fake schematic).
   ========================================================================== */
.flegend { margin: 10px 0; overflow-x: auto; }
.flegend__svg { width: 100%; height: auto; display: block; }
.flegend__room { fill: var(--surface-2); stroke: var(--line-strong); stroke-width: 2; }
.flegend__door { fill: var(--surface); stroke: var(--line-strong); stroke-width: 1.5; }
.flegend__entrance { font-size: 12px; font-weight: 700; fill: var(--ink-3); text-transform: uppercase; letter-spacing: .06em; }
.flegend__box { fill: var(--new-bg); stroke: var(--new-line); stroke-width: 2; }
.flegend__name { font-size: 18px; font-weight: 800; fill: var(--new-ink); }
.flegend__seats { font-size: 11px; font-weight: 700; fill: var(--ink-3); }

/* ==========================================================================
   FEATURE — waitress order pad (menu admin + per-reservation order entry).
   Menu admin reuses the .trow/.tlist vocabulary (Tables-settings style);
   the pad itself is a new, deliberately big-target, iPad-first component.
   ========================================================================== */
.act--orders { color: var(--conf-ink); }

/* small badge in a grid block's top-right corner when it has an open order */
.tblock__orderbadge {
  position: absolute; top: 3px; right: 3px; z-index: 2;
  display: inline-flex; align-items: center; gap: 2px;
  background: var(--ink); color: #fff; border-radius: 999px;
  font-size: 10.5px; font-weight: 800; line-height: 1;
  padding: 3px 6px; min-height: 18px; cursor: pointer;
}
.tblock__orderbadge svg { width: 11px; height: 11px; }
.tblock__orderbadge:hover { background: var(--conf-ink); }

/* ---- Menu admin list ---- */
.mlist__h {
  font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .05em;
  color: var(--ink-3); margin: 16px 0 6px;
}
.mlist__h:first-child { margin-top: 4px; }
.mlist { display: flex; flex-direction: column; gap: 6px; }
.mrow {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 8px 10px; background: var(--surface);
}
.mrow.is-off { opacity: .6; background: var(--surface-2); }
.mrow__name { flex: 1 1 200px; font-weight: 600; font-size: 14px; }
.mrow__price { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--ink-2); }
.mrow__price input { width: 76px; min-height: 40px; border: 1px solid var(--line-strong); border-radius: 2px; padding: 0 8px; font-family: inherit; font-size: 14px; }
.mrow__toggle { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 700; color: var(--ink-2); cursor: pointer; }
.mrow__toggle input { width: 20px; height: 20px; }

/* Guest note banner (Feature: Guest notes) — LOUD, matches the kitchen
   ticket's treatment so the same allergy/VIP note reads the same everywhere. */
.opad__guestnote {
  background: var(--err-bg); color: var(--err-ink); border: 1.5px solid var(--err-line);
  border-radius: var(--radius-sm); padding: 10px 14px; font-size: 15px; font-weight: 700;
  margin-bottom: 12px; line-height: 1.4;
}

/* ---- Order pad: category tabs ---- */
.orderpad .modal__panel--wide { width: min(880px, 100%); }
.opad__tabs { display: flex; gap: 6px; overflow-x: auto; padding: 2px 0 10px; scrollbar-width: thin; }
.opadtab {
  appearance: none; cursor: pointer; font-family: inherit; font-weight: 700; font-size: 13px;
  flex: none; white-space: nowrap; border: 1px solid var(--line-strong); background: var(--surface);
  color: var(--ink-2); border-radius: 999px; min-height: 44px; padding: 0 16px;
}
.opadtab.is-on { background: var(--ink); color: #fff; border-color: var(--ink); }

/* ---- Order pad: item grid — big tap targets, standing-at-the-table use ---- */
.opad__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px; margin-bottom: 14px; }
.opaditem {
  appearance: none; cursor: pointer; font-family: inherit; text-align: left;
  border: 1.5px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--surface);
  min-height: 64px; padding: 10px 12px; position: relative;
  display: flex; flex-direction: column; justify-content: center; gap: 3px;
}
.opaditem:hover { border-color: var(--ink); }
.opaditem:active { transform: translateY(1px); }
.opaditem.has-qty { border-color: var(--conf-ink); background: var(--conf-bg); }
.opaditem__n { font-size: 13.5px; font-weight: 700; color: var(--ink); line-height: 1.2; }
.opaditem__p { font-size: 12px; color: var(--ink-3); font-weight: 600; }
.opaditem__qty {
  position: absolute; top: -8px; right: -8px; min-width: 24px; height: 24px; padding: 0 6px;
  border-radius: 999px; background: var(--conf-ink); color: #fff; font-size: 12px; font-weight: 800;
  display: flex; align-items: center; justify-content: center;
}

/* ---- Order pad: running cart ---- */
.opad__carth { font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-3); margin: 6px 0; }
.opad__cartempty { color: var(--ink-3); font-size: 13.5px; padding: 12px 0; }
.opad__cart { display: flex; flex-direction: column; gap: 8px; }
.opadline { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 10px; background: var(--surface); }
.opadline__top { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.opadline__n { font-weight: 700; font-size: 14px; }
.opadline__sub { font-size: 12px; color: var(--ink-3); font-weight: 600; white-space: nowrap; }
.opadline__ctrl { display: flex; align-items: center; gap: 10px; margin-top: 8px; flex-wrap: wrap; }
.opadqty { display: flex; align-items: center; gap: 8px; flex: none; }
.qtybtn {
  appearance: none; cursor: pointer; font-family: inherit; font-size: 20px; font-weight: 700; line-height: 1;
  width: 44px; height: 44px; border: 1.5px solid var(--line-strong); border-radius: 2px; background: var(--surface); color: var(--ink);
}
.qtybtn:hover { background: var(--surface-2); }
.qtybtn:active { transform: translateY(1px); }
.opadqty__n { min-width: 24px; text-align: center; font-weight: 800; font-size: 15px; }
.opadnote {
  flex: 1 1 180px; min-height: 40px; border: 1px solid var(--line-strong); border-radius: 2px;
  padding: 0 10px; font-family: inherit; font-size: 13.5px;
}
.opad__total {
  display: flex; justify-content: flex-end; gap: 8px; font-size: 16px; font-weight: 700;
  border-top: 1px solid var(--line-strong); margin-top: 14px; padding-top: 12px;
}
.opad__total b { font-size: 19px; }

@media (max-width: 640px) {
  .opad__grid { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); }
}

/* ==========================================================================
   ORDER-TAKING STAGE 2/3 — walk-in table order trigger, kitchen "ready"
   badge, ADDED tag, and the order pad's status banner + Mark-served action.
   ========================================================================== */

/* "+ Order" trigger in a table column header (Stage 2: walk-in order). Small,
   ghost-style so it doesn't compete with the table name/seat count. */
.tcolhead__order {
  appearance: none; cursor: pointer; font-family: inherit; font-weight: 700; font-size: 10px;
  display: inline-flex; align-items: center; gap: 2px; white-space: nowrap;
  border: 1px solid var(--line-strong); border-radius: 999px; background: var(--surface);
  color: var(--ink-2); padding: 2px 7px; min-height: 20px;
}
.tcolhead__order svg { width: 10px; height: 10px; }
.tcolhead__order:hover { border-color: var(--ink); color: var(--ink); }

/* Grid-block badge when the kitchen has marked the order READY (Stage 3) —
   distinct from the plain item-count badge so it reads across the room. */
.tblock__orderbadge--ready {
  background: var(--seat-ink); color: #fff; padding: 3px 7px; letter-spacing: .03em;
}
.tblock__orderbadge--ready:hover { background: var(--seat-ink); filter: brightness(1.1); }

/* Order pad: kitchen-lifecycle status banner. */
.opad__status {
  border-radius: var(--radius-sm); padding: 8px 12px; font-size: 13px; font-weight: 700;
  margin-bottom: 12px; border: 1px solid var(--line);
}
.opad__status--open { background: var(--new-bg); color: var(--new-ink); border-color: var(--new-line); }
.opad__status--ready { background: var(--seat-bg); color: var(--seat-ink); border-color: var(--seat-line); }

/* A line added to an order the kitchen already fired on. */
.opadline__added {
  display: inline-block; background: var(--seat-ink); color: #fff; font-size: 10px; font-weight: 800;
  letter-spacing: .04em; border-radius: 3px; padding: 1px 5px; vertical-align: middle; margin-left: 4px;
}

/* ==========================================================================
   DAY REPORT — revenue/covers rollup. iPad-first: big tabular-nums stats,
   a tap-through week strip, two top-dish lists, a per-reservation table.
   Reuses .btable/.btable-wrap for the reservation lines (same vocabulary as
   the List view) so it reads as one app, not a bolted-on report page.
   ========================================================================== */
.dreport { display: flex; flex-direction: column; gap: var(--s2); padding-bottom: var(--s4); }
.dreport__head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s2);
  flex-wrap: wrap;
}
.dreport__title { font-size: 20px; font-weight: 800; color: var(--ink); margin: 0; }
.dreport__sub { font-size: 13px; font-weight: 600; color: var(--ink-2); margin: 2px 0 0; }
.dreport__linesh {
  font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink-3); margin: var(--s1) 0 0;
}
.dreport__foot { font-size: 12px; color: var(--ink-3); font-weight: 600; margin: 0; line-height: 1.5; }

/* 7-day roll-up strip */
.rweek {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 6px;
}
.rweek__card {
  appearance: none; cursor: pointer; font-family: inherit; text-align: center;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface);
  min-height: 64px; padding: 8px 4px; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 2px;
}
.rweek__card:hover { border-color: var(--line-strong); }
.rweek__card.is-today { border-color: var(--ink); }
.rweek__card.is-sel { background: var(--ink); border-color: var(--ink); }
.rweek__card.is-sel .rweek__dow, .rweek__card.is-sel .rweek__num, .rweek__card.is-sel .rweek__v { color: #fff; }
.rweek__dow { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-3); }
.rweek__num { font-size: 14px; font-weight: 700; color: var(--ink); }
.rweek__v {
  font-size: 12.5px; font-weight: 800; color: var(--ink);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* stat tiles */
.rstats { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 8px; }
.rstat {
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface);
  padding: 10px 12px; display: flex; flex-direction: column; gap: 2px; min-width: 0;
}
.rstat__v {
  font-size: 22px; font-weight: 800; color: var(--ink); line-height: 1.15;
  font-variant-numeric: tabular-nums;
}
.rstat__l { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-2); }
.rstat__s { font-size: 11.5px; font-weight: 600; color: var(--ink-3); }

/* top-dish lists, two columns on wide screens */
.rtop2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s2); }
.rtop2__col {
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface);
  padding: 10px 12px; min-width: 0;
}
.rtop2__col h3 {
  font-size: 12px; font-weight: 800; text-transform: uppercase; letter-spacing: .05em;
  color: var(--ink-3); margin: 0 0 8px;
}
.rtop { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.rtop__row {
  display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  font-size: 13.5px; padding: 4px 0; border-bottom: 1px solid var(--line);
}
.rtop__row:last-child { border-bottom: 0; }
.rtop__n { font-weight: 600; color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rtop__v { font-weight: 800; color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* per-reservation table — reuses .btable, adds numeric alignment for CHF */
.rtable .c-num { text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; white-space: nowrap; }
.rtable__items { font-size: 13px; color: var(--ink-2); }
.rempty { font-size: 13.5px; color: var(--ink-3); font-weight: 600; padding: 8px 0; }

@media (max-width: 820px) {
  .rweek { grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; }
  .rweek__v { font-size: 11px; }
  .rtop2 { grid-template-columns: 1fr; }
}
@media (max-width: 480px) {
  .rweek { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ==========================================================================
   FLOOR MAP v1 — Setup mode (Tables > Layout tab) + Floor view (Grid/Floor
   toggle). .fmap is a fixed-size snap-grid canvas; .fitem is one draggable
   (Setup) or read-only (Floor) shape on it. Geometry (left/top/size/rotate)
   is applied via CSSOM in positionFmapItems() — this file only ever sets
   the FMAP_W/FMAP_H the JS constants must match (880x520).
   ========================================================================== */
.ftabs { margin-bottom: 10px; }

.ftray {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-bottom: 10px;
}
.ftray__label { font-size: 12px; font-weight: 700; color: var(--ink-3); text-transform: uppercase; letter-spacing: .05em; }

.fmapscroll {
  overflow: auto; -webkit-overflow-scrolling: touch;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
  overscroll-behavior: contain; max-height: 68vh;
}
/* MUST match FMAP_W/FMAP_H in app.js — no inline style (CSP), so the
   intrinsic canvas size is fixed here instead of computed. */
.fmap {
  position: relative; width: 880px; height: 520px;
  background-color: var(--surface-2);
  background-image:
    linear-gradient(to right, var(--line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--line) 1px, transparent 1px);
  background-size: 20px 20px;
}
.fmap--floor { background-color: var(--surface); }

.fitem {
  position: absolute; touch-action: none; user-select: none;
}
.ftable { cursor: grab; }
.fitem.is-dragging { z-index: 30; cursor: grabbing; }
.fitem.is-dragging .fitem__shape { box-shadow: 0 10px 24px rgba(0,0,0,.28); }

.fitem__shape {
  width: 100%; height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; text-align: center; line-height: 1.15;
  border: 2px solid var(--new-line); background: var(--new-bg);
  border-radius: 6px; color: var(--new-ink);
  padding: 4px; overflow: hidden;
}
.ftable--round .fitem__shape { border-radius: 999px; }
.fitem.is-pending .fitem__shape { border-style: dashed; opacity: .75; }
.fitem__n { font-size: 12.5px; font-weight: 800; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.fitem__s { font-size: 11px; font-weight: 700; display: inline-flex; align-items: center; gap: 2px; opacity: .85; }
.fitem__s svg { width: 12px; height: 12px; }
.fitem__t { font-size: 10.5px; font-weight: 700; opacity: .9; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }

/* Setup-mode rotate / round-square handles — sit BELOW the shape, outside
   the rotated inner box, so they stay upright and tappable at any angle. */
.fitem__handles {
  position: absolute; left: 50%; top: 100%; transform: translateX(-50%);
  display: flex; gap: 4px; margin-top: 4px; z-index: 5;
}
.fhandle {
  appearance: none; font-family: inherit; cursor: pointer;
  width: 32px; height: 32px; min-width: 32px; min-height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line-strong); border-radius: 999px;
  background: var(--surface); color: var(--ink-2); font-size: 14px; font-weight: 800;
  box-shadow: 0 1px 4px rgba(0,0,0,.12);
}
.fhandle:hover { background: var(--surface-2); color: var(--ink); }
.fhandle svg { width: 16px; height: 16px; }
.fhandle--rm {
  position: absolute; top: -10px; right: -10px; left: auto; transform: none;
  margin: 0; width: 26px; height: 26px; min-width: 26px; min-height: 26px;
  background: var(--err-bg); border-color: var(--err-line); color: var(--err-ink);
}
.fhandle--rm svg { width: 13px; height: 13px; }

/* landmarks — grey, non-bookable, labels only */
.flandmark .fitem__shape {
  border: 1.5px dashed var(--line-strong); background: var(--surface-2);
  color: var(--ink-3); border-radius: 4px; font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .03em;
}
.flandmark .fitem__shape span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Floor view — table states (mirrors the grid's new/arrived/seated palette) */
.fitem.ftable[type="button"] { appearance: none; padding: 0; font-family: inherit; }
.fitem.is-state-free .fitem__shape { border-color: var(--line-strong); background: var(--surface-2); color: var(--ink-2); }
.fitem.is-state-reserved-soon .fitem__shape { border-color: var(--new-line); background: var(--new-bg); color: var(--new-ink); }
.fitem.is-state-waiting .fitem__shape { border-color: var(--arr-ink); background: var(--arr-fill); color: #fff; }
.fitem.is-state-seated .fitem__shape { border-color: var(--conf-ink); background: var(--conf-ink); color: #fff; }
.fitem.ftable:hover .fitem__shape { filter: brightness(1.03); }
.fitem.ftable:active { transform: translateY(1px); }

.fboard { display: flex; flex-direction: column; gap: 10px; }
.flegendkey {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  font-size: 12.5px; font-weight: 700; color: var(--ink-2);
}
.flegendkey__i {
  display: inline-block; width: 12px; height: 12px; border-radius: 3px;
  margin-right: 4px; vertical-align: -1px; border: 1.5px solid var(--line-strong);
}
.flegendkey__i.is-state-free { background: var(--surface-2); border-color: var(--line-strong); }
.flegendkey__i.is-state-reserved-soon { background: var(--new-bg); border-color: var(--new-line); }
.flegendkey__i.is-state-waiting { background: var(--arr-fill); border-color: var(--arr-ink); }
.flegendkey__i.is-state-seated { background: var(--conf-ink); border-color: var(--conf-ink); }

/* fallback strip — tables that haven't been placed on the map yet */
.fstrip { border-top: 1px solid var(--line); padding-top: 10px; }
.fstrip__h { font-size: 12px; font-weight: 700; color: var(--ink-3); text-transform: uppercase; letter-spacing: .04em; margin-bottom: 6px; }
.fstrip__row { display: flex; flex-wrap: wrap; gap: 8px; }
.fstrip__chip {
  appearance: none; font-family: inherit; cursor: pointer; text-align: left;
  display: flex; flex-direction: column; gap: 2px; min-width: 120px;
  border: 1.5px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--surface-2); padding: 8px 10px; min-height: 44px;
}
.fstrip__chip.is-state-reserved-soon { border-color: var(--new-line); background: var(--new-bg); }
.fstrip__chip.is-state-waiting { border-color: var(--arr-ink); background: var(--arr-fill); color: #fff; }
.fstrip__chip.is-state-seated { border-color: var(--conf-ink); background: var(--conf-ink); color: #fff; }
.fstrip__n { font-size: 13px; font-weight: 800; }
.fstrip__meta { font-size: 11.5px; font-weight: 600; opacity: .85; }

/* order badge reused from the grid (.tblock__orderbadge) — anchor it to the
   Floor-view shape's corner instead of the grid block's. */
.fitem .tblock__orderbadge { position: absolute; top: -8px; right: -8px; z-index: 4; }
/* Guest note marker (Feature: Guest notes) — opposite corner from the order
   badge so the two never collide. */
.fitem__note { position: absolute; top: -8px; left: -8px; font-size: 14px; line-height: 1; z-index: 4; }

@media (max-width: 900px) {
  .fmapscroll { max-height: 52vh; }
}
