/* Working slice — Today / Floor / booking-detail. Aligned to the accepted
   Phase-3A-1 visual language: current recedes, exceptions surface by word+shape
   (not colour alone), ONE CTA colour, freshness shown honestly. Master-detail
   queue. Brand: plum / terracotta / cream. */
:root{
  --plum:#432940; --plum-2:#5b3a56; --terra:#a5401f; --terra-2:#8f3721;
  --cream:#f7f0e2; --paper:#fffdf8; --card:#ffffff; --bg:#f7f0e2;
  --ink:#2b1f2d; --ink-2:#665767; --line:#e7dcc9; --line-2:#efe7d6;
  --hot:#8f4a3c; --warn:#7a520c; --ok:#366a4f; --offline:#5f6b78;
  --aging:#9a6a12; --stale:#8f4a3c; --unknown:#6f6675; --safety:#9e1f2b; --safety-bg:#fbeceb;
  --shadow:0 1px 0 rgba(67,41,64,.04),0 10px 26px -18px rgba(67,41,64,.30);
  --serif:Georgia,"Iowan Old Style","Palatino Linotype",serif;
  --r:14px; --tap:44px;
}
@media (prefers-color-scheme: dark){:root{
  --plum:#ead9e6; --plum-2:#c7a9c1; --terra:#e0714f; --terra-2:#efa184;
  --cream:#1f181f; --paper:#181218; --card:#241c26; --bg:#1f181f;
  --ink:#f2e9ef; --ink-2:#b7a6b4; --line:#372d3a; --line-2:#312836;
  --hot:#e88b78; --warn:#e2b25f; --ok:#6fbf90; --offline:#9aa6b2;
  --aging:#e2b25f; --stale:#e88b78; --unknown:#b9acb8; --safety:#f28b8b; --safety-bg:#3a1d20;
  --shadow:0 1px 0 rgba(0,0,0,.25),0 12px 30px -18px rgba(0,0,0,.75);
}}
:root[data-theme="dark"]{
  --plum:#ead9e6; --plum-2:#c7a9c1; --terra:#e0714f; --terra-2:#efa184;
  --cream:#1f181f; --paper:#181218; --card:#241c26; --bg:#1f181f;
  --ink:#f2e9ef; --ink-2:#b7a6b4; --line:#372d3a; --line-2:#312836;
  --hot:#e88b78; --warn:#e2b25f; --ok:#6fbf90; --offline:#9aa6b2;
  --aging:#e2b25f; --stale:#e88b78; --unknown:#b9acb8; --safety:#f28b8b; --safety-bg:#3a1d20;
}
:root[data-theme="light"]{
  --plum:#432940; --plum-2:#5b3a56; --terra:#a5401f; --terra-2:#8f3721;
  --cream:#f7f0e2; --paper:#fffdf8; --card:#ffffff; --bg:#f7f0e2;
  --ink:#2b1f2d; --ink-2:#665767; --line:#e7dcc9; --line-2:#efe7d6;
  --hot:#8f4a3c; --warn:#7a520c; --ok:#366a4f; --offline:#5f6b78;
  --aging:#9a6a12; --stale:#8f4a3c; --unknown:#6f6675; --safety:#9e1f2b; --safety-bg:#fbeceb;
}

*{box-sizing:border-box}
html,body{margin:0}
body{font:15px/1.5 system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif; color:var(--ink); background:var(--cream); -webkit-font-smoothing:antialiased}
.concept{max-width:1220px; margin:0 auto; padding:clamp(12px,2vw,22px) clamp(14px,3vw,26px) 40px; line-height:1.5}

/* topbar */
.topbar{display:flex; align-items:center; gap:18px; flex-wrap:wrap; margin-bottom:16px}
.brand{display:flex; align-items:baseline; gap:12px; margin-right:auto}
.wordmark{font-family:var(--serif); font-size:23px; font-weight:700; color:var(--plum)}
.venue{font-size:13px; color:var(--ink-2); border-left:1px solid var(--line); padding-left:12px}
.views{display:flex; gap:2px; background:var(--card); border:1px solid var(--line); border-radius:12px; padding:4px; max-width:100%; min-width:0; overflow-x:auto; -webkit-overflow-scrolling:touch; scrollbar-width:thin}   /* 0295 R5: the 6-button nav SCROLL-CONTAINS so it never causes page overflow at 360/390 */
.view{font:inherit; font-size:14px; font-weight:600; color:var(--ink-2); background:none; border:0; padding:9px 15px; min-height:var(--tap); border-radius:9px; cursor:pointer; flex:0 0 auto; white-space:nowrap}
.view.is-active{background:var(--plum); color:var(--paper)}
.view:not(.is-active):not(:disabled):hover{color:var(--plum); background:color-mix(in srgb,var(--plum) 8%,transparent)}
.view:disabled{opacity:.45; cursor:not-allowed}
.conn{display:flex; align-items:center; gap:9px; background:var(--card); border:1px solid var(--line); border-radius:999px; padding:8px 15px 8px 13px; min-height:var(--tap); cursor:default; font:inherit; text-align:left}
.conn-dot{width:9px; height:9px; border-radius:50%; background:var(--ok); box-shadow:0 0 0 4px color-mix(in srgb,var(--ok) 22%,transparent)}
.conn.f-connecting .conn-dot{background:var(--warn); animation:pulse 1.2s ease-in-out infinite}
.conn.f-stale .conn-dot{background:var(--offline); box-shadow:0 0 0 4px color-mix(in srgb,var(--offline) 22%,transparent)}
.conn-text{display:flex; flex-direction:column; line-height:1.2}
.conn-text strong{font-size:13.5px; color:var(--ink)}
.conn-sub{font-size:11.5px; color:var(--ink-2)}
@keyframes pulse{50%{opacity:.4}}
@media (prefers-reduced-motion:reduce){.conn-dot{animation:none}}

/* summary */
.summary{display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin-bottom:16px}
.stat{background:var(--card); border:1px solid var(--line); border-radius:var(--r); padding:13px 16px; box-shadow:var(--shadow)}
.stat-label{display:block; font-size:11.5px; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-2); margin-bottom:3px}
.stat-value{display:block; font-family:var(--serif); font-size:26px; font-weight:700; color:var(--plum); font-variant-numeric:tabular-nums; line-height:1.1}
.stat-of{font-size:16px; color:var(--ink-2)}
.stat-sub{display:block; font-size:12.5px; color:var(--ink-2); margin-top:3px}
/* Degraded stat = the number is withheld, not zero. Dotted edge + the em-dash value say so without colour alone. */
.stat.is-degraded{border-style:dotted; border-color:var(--unknown)}
.stat.is-degraded .stat-value{color:var(--unknown)}

/* board = queue + detail aside */
.board{display:grid; grid-template-columns:1.55fr 1fr; gap:18px; align-items:start}
.queue{background:var(--card); border:1px solid var(--line); border-radius:var(--r); box-shadow:var(--shadow); overflow:hidden}
.queue-head{padding:16px 18px 12px; border-bottom:1px solid var(--line-2)}
.queue-head.bare{border:0; padding:0 0 8px}
.queue-head h2{margin:0 0 4px; font-family:var(--serif); font-size:17px; color:var(--plum); font-weight:700}
.queue-hint{margin:0; font-size:12.5px; color:var(--ink-2)}
.qGroup{display:flex; align-items:baseline; justify-content:space-between; gap:10px; padding:13px 18px 4px; font-size:11px; font-weight:700; letter-spacing:.05em; text-transform:uppercase; color:var(--ink-2)}
.qGroup.gHot{color:var(--stale)}
.qGroup.gWarn{color:var(--aging)}
.qCount{font-weight:600; letter-spacing:0; text-transform:none; font-variant-numeric:tabular-nums}
.qQuiet{padding:6px 18px; font-size:12.5px; font-style:italic; color:var(--ink-2)}
.row{display:grid; grid-template-columns:66px 1fr auto; gap:12px; align-items:center; padding:12px 18px; border-top:1px solid var(--line-2); cursor:pointer; position:relative; min-height:var(--tap)}
.row:hover{background:color-mix(in srgb,var(--plum) 4%,transparent)}
.row.is-sel{background:color-mix(in srgb,var(--plum) 7%,transparent)}
.row.is-sel::before{content:""; position:absolute; left:0; top:0; bottom:0; width:3px; background:var(--terra)}
.r-time{font-family:var(--serif); font-size:17px; font-weight:700; color:var(--ink); font-variant-numeric:tabular-nums}
.r-main{min-width:0}
.r-name{font-size:14.5px; font-weight:600; color:var(--ink)}
.r-meta{font-size:12.5px; color:var(--ink-2); margin-top:3px; display:flex; gap:10px; flex-wrap:wrap; font-variant-numeric:tabular-nums}
.r-right{display:flex; flex-direction:column; align-items:flex-end; gap:5px}
.qHistory{border-top:1px solid var(--line-2)}
.qHistory summary{cursor:pointer; font-size:12.5px; color:var(--ink-2); padding:10px 18px; min-height:var(--tap); display:flex; align-items:center}
.qHistory .row{opacity:.6}

/* chips */
.chip{font-size:12px; font-weight:600; padding:4px 10px; border-radius:999px; white-space:nowrap; border:1px solid transparent}
.chip-confirmed{background:color-mix(in srgb,var(--ok) 15%,transparent); color:var(--ok); border-color:color-mix(in srgb,var(--ok) 30%,transparent)}
.chip-await{background:color-mix(in srgb,var(--warn) 15%,transparent); color:var(--warn); border-color:color-mix(in srgb,var(--warn) 32%,transparent)}
.chip-seated{background:var(--plum); color:var(--paper)}
.chip-noshow{background:color-mix(in srgb,var(--stale) 12%,transparent); color:var(--stale); border-color:color-mix(in srgb,var(--stale) 34%,transparent)}
.chip-done{background:transparent; color:var(--ink-2); border-color:var(--line)}

/* detail */
.detail{background:var(--card); border:1px solid var(--line); border-radius:var(--r); box-shadow:var(--shadow); padding:18px; position:sticky; top:14px}
.d-close{display:none}
.d-eyebrow{font-size:11px; text-transform:uppercase; letter-spacing:.07em; color:var(--ink-2); margin:0}
.d-name{font-family:var(--serif); font-size:22px; font-weight:700; color:var(--plum); margin:3px 0 1px; text-wrap:balance}
.d-sub{font-size:13px; color:var(--ink-2); margin:0 0 14px}
.d-badges{display:flex; gap:8px; flex-wrap:wrap; margin-bottom:14px}
.d-grid{display:grid; grid-template-columns:1fr 1fr; gap:1px; background:var(--line-2); border:1px solid var(--line-2); border-radius:11px; overflow:hidden; margin-bottom:14px}
.d-cell{background:var(--card); padding:11px 13px}
.d-cell.full{grid-column:1 / -1}
.d-k{display:block; font-size:11px; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-2)}
.d-v{display:block; font-size:14.5px; color:var(--ink); margin-top:3px}
.d-v .sub{display:block; font-size:11.5px; color:var(--ink-2); margin-top:2px}
.d-actions{display:flex; gap:8px; flex-wrap:wrap}
.d-actions .primary{order:-1}
.codeTag{font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:13px; background:var(--bg); border:1px solid var(--line); border-radius:6px; padding:1px 7px}
.muted{color:var(--ink-2)}
.row.is-busy{opacity:.72}

/* payment rails — four independent, no inference */
.rails{display:flex; flex-direction:column; gap:8px; margin-top:4px}
.rail{display:grid; grid-template-columns:auto 1fr; gap:2px 10px; align-items:baseline; padding:8px 10px; border-radius:9px; border:1px solid var(--line); background:var(--bg)}
.rail-k{font-size:12.5px; font-weight:600; color:var(--ink)}
.rail-s{font-size:12.5px; font-weight:600; text-align:right; font-variant-numeric:tabular-nums}
.rail-n{grid-column:1 / -1; font-size:11.5px; color:var(--ink-2); line-height:1.35}
.rail-ok .rail-s{color:var(--ok)}
.rail-warn{border-color:color-mix(in srgb,var(--warn) 40%,var(--line))}
.rail-warn .rail-s{color:var(--warn)}
.rail-muted .rail-s{color:var(--ink-2)}

.d-recon{margin:0 0 12px; padding:10px 12px; border:1px solid var(--stale); border-radius:11px; background:color-mix(in srgb,var(--stale) 9%,var(--card)); color:var(--stale); font-size:13px; line-height:1.4; display:flex; flex-direction:column; gap:8px; align-items:flex-start}
.d-recon .btn{color:var(--plum)}
.d-foot{margin:12px 0 0; font-size:11.5px; color:var(--ink-2); line-height:1.45}
.d-foot code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:11px; background:var(--bg); border:1px solid var(--line); border-radius:4px; padding:0 4px}
.btn:disabled{opacity:.5; cursor:not-allowed}
.btn:disabled:hover{border-color:var(--line); background:var(--card)}

/* buttons */
.btn{font:inherit; font-size:14px; font-weight:600; padding:0 16px; min-height:var(--tap); border-radius:10px; border:1px solid var(--line); background:var(--card); color:var(--plum); cursor:pointer; display:inline-flex; align-items:center; justify-content:center}
.btn:hover{border-color:var(--plum-2); background:color-mix(in srgb,var(--plum) 5%,transparent)}
.btn.primary{border-color:var(--plum); background:color-mix(in srgb,var(--plum) 9%,transparent)}
.btn-cta{background:var(--terra); border-color:var(--terra); color:#fff}
.btn-cta:hover{background:var(--terra-2); border-color:var(--terra-2)}
/* dark theme: --terra is a light salmon, so white CTA text fails AA — use dark ink instead */
@media (prefers-color-scheme:dark){ .btn-cta{ color:#2b1f2d } }
:root[data-theme="dark"] .btn-cta{ color:#2b1f2d }
:root[data-theme="light"] .btn-cta{ color:#fff }
.btn-proposed{ border-style:dashed }
.propTag{ font-size:10px; font-weight:600; margin-left:5px; opacity:.85 }

/* footer */
.foot{margin-top:16px; display:flex; align-items:flex-start; gap:16px; flex-wrap:wrap}
.foot-note{font-size:12px; color:var(--ink-2); margin:0; max-width:62ch; flex:1 1 320px}
.foot-note em{color:var(--terra-2); font-style:normal; font-weight:600}
/* Help + honest Install links (0290 parity-lift) — footer utilities, /app only */
.foot-links{display:flex; gap:16px; flex-wrap:wrap; align-items:center}
.foot-link{background:none; border:0; padding:6px 2px; font:inherit; font-size:12px; font-weight:600; color:var(--ink-2); text-decoration:underline; cursor:pointer}
.foot-link:hover{color:var(--plum)}
.foot-link:focus-visible{outline:2px solid var(--plum); outline-offset:2px; border-radius:4px}
/* settings.css styles .modal .body ul but not ol — give the handbook's numbered steps the same indent */
#sliceModal .body ol{margin:10px 0 10px 18px}
/* Account & security shown-unavailable rows (0280 Amber 6b) */
.acctList{list-style:none; margin:14px 0 0; padding:0; display:flex; flex-direction:column; border:1px solid var(--line); border-radius:10px; overflow:hidden}
.acctRow{display:flex; align-items:center; justify-content:space-between; gap:10px; padding:11px 13px; border-top:1px solid var(--line-2); font-size:13.5px}
.acctRow:first-child{border-top:0}
.acctTag{font-size:12px; font-weight:700; color:var(--ink-2)}
/* 0334 L3(2): inline error for the native credential sub-flows (change email/password, 2FA enrol). Pinned to the
   AA-readable red (like the warn button label) so it stays legible on the white modal body in both themes. */
#sliceModal .acctErr{color:#b6492f; font-size:12.5px; font-weight:600; margin-top:10px}
/* The .modalBack info-modal button keeps a white background in BOTH themes (its dark repaint is #setMount-scoped),
   but --red goes light in dark mode → the warn (Red money) label falls to ~2.4:1 on white. Pin it to a red that is
   AA-readable (~5:1) on the white button in either theme — a money control must stay legible. */
#sliceModal .modalActs .aBtn.warn{ color:#b6492f; border-color:#e6c4bc }

/* floor */
/* 0145 Floor fix: NO hard-coded ratio. The canvas is a fixed-pixel "world" (>=560px wide, height from the
   room's own authoritative ratio) that JS scales to fit — mirroring the production renderer. A hard 3/2 here
   squashed every room to the same shape regardless of how the owner designed it. */
.floorCanvas{position:relative; width:100%; background:var(--card); border:1px solid var(--line); border-radius:var(--r); overflow:hidden; box-shadow:var(--shadow); background-image:radial-gradient(color-mix(in srgb,var(--line) 60%,transparent) 1px,transparent 1px); background-size:24px 24px}
/* 0145 Floor fix: stored pos is the tile's TOP-LEFT (dash.js tPos + left/top styling). The old
   translate(-50%,-50%) consumed it as a CENTRE, shifting every table up-left by half its size — the direct
   cause of the overlapping/misplaced tables. Shape aspect now mirrors production tileAspect(). */
.fTile{position:absolute; aspect-ratio:1; min-width:52px; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px; padding:4px; border-radius:12px; border:1.5px solid var(--line); background:var(--bg); color:var(--ink); font:inherit; text-align:center; cursor:default}
.fTile.round{border-radius:50%}
/* Floor component (0146). The controller builds this DOM itself, so pilot.html and index.html carry only
   #floorMount and cannot drift apart again.
   - The HEAD (rooms + zoom) sits ABOVE the plan, so neither can be pushed below the fold by a tall room.
   - The RAIL is furniture: a FIXED 280px column, mounted only when real slack remains. It was flex:1, and
     took 698px of a 1280px viewport while the plan was squeezed to 450px with 44.9px tables.
   - The STAGE clips at Fit (nothing scrolls by default, per the founder rule) and scrolls only when the
     operator has deliberately zoomed in. */
.fp{display:flex; flex-direction:column; gap:10px; margin:8px 0 12px}
/* Landscape phone: ~265px of chrome sat above a 390px-tall viewport, leaving the plan 30px tiles. The
   "Floor · Room view" heading duplicates the active nav item, and it is not one of the controls the
   contract requires visible (selector, counts, freshness, Fit) — so it yields its height to the plan. */
@media (max-height:560px){
  .floorView .queue-head.bare{display:none}
  .fp{gap:6px; margin-top:2px}
  /* On a short landscape screen the topbar was the biggest single cost: at 844x390 the reachability chip
     overflowed to a second row and took ~55px off the plan — a quarter of the height the room had left.
     Compacting the wordmark and the gaps puts brand, nav and chip back on ONE row. This is furniture giving
     way to the plan, the same rule the rail already follows. */
  .topbar{gap:10px; margin-bottom:8px}
  .wordmark{font-size:19px}
  .venue{font-size:12px}
  .views .view{padding:6px 12px; font-size:13px}
  .conn{padding:5px 10px}
}
.fp-head{display:flex; flex-wrap:wrap; align-items:center; gap:10px 16px; justify-content:space-between}
.fp-rooms{display:inline-flex; gap:6px; flex-wrap:wrap; align-items:center}
.roomOne{font-size:13px}
.fp-zoom{display:inline-flex; gap:6px; align-items:center; flex-wrap:wrap}
.zBtn{font:inherit; font-size:12.5px; line-height:1; min-width:32px; min-height:32px; padding:0 9px; border-radius:8px; border:1px solid var(--line); background:var(--card); color:var(--ink); cursor:pointer}
.zBtn:disabled{opacity:.45; cursor:default}
.zLbl{font-size:12px; color:var(--ink-2); font-variant-numeric:tabular-nums; min-width:42px; text-align:center}
.zNote{font-size:12px; color:var(--ink-2)}
.fp-counts{margin:0; font-size:12.5px; color:var(--ink-2); display:flex; flex-wrap:wrap; gap:4px 14px; align-items:baseline}
.cCell b{color:var(--ink); font-variant-numeric:tabular-nums}
.cCell.muted{opacity:.75}
.fp-body{display:block}
.fp-body.has-rail{display:flex; gap:20px; align-items:flex-start}
.fp-stage{position:relative; overflow:hidden}
.fp-body.has-rail .fp-stage{flex:0 0 auto}
/* 2FA verification challenge (0167). Lives in the boot-error host, so it must stay usable at phone width:
   inputs and buttons wrap rather than forcing horizontal overflow. */
#ra{max-width:32rem}
#ra input{font:inherit; font-size:16px; padding:8px 10px; min-height:44px; width:100%; max-width:11rem;
  letter-spacing:.28em; border:1px solid var(--line); border-radius:8px; background:var(--card); color:var(--ink)}
#ra label{display:flex; flex-direction:column; gap:4px; font-size:12.5px; color:var(--ink-2)}
.raBtns{display:flex; flex-wrap:wrap; gap:8px}
.raBtns .btn{min-height:44px}
.raErr{color:var(--safety); font-size:13px}
/* Founder-ruled phone hybrid (0153): when Fit renders tables below 44px the plan stays whole and to scale,
   and this list becomes the reliable touch path. Rows are 44px minimum. Built in the same render pass as the
   tiles, so it cannot show different state from the plan. */
.fp-list{margin-top:14px}
/* 0172: in the rail the list sits BESIDE the plan, inside the first viewport. It scrolls within its own
   column rather than pushing the page taller, so the plan never moves to make room for it. */
.fp-list.in-rail{margin-top:12px; max-height:min(52vh,420px); overflow-y:auto}
.fp-list.in-rail .fp-listWhy{font-size:12px}
.fp-list.in-rail .fRow{padding:6px 10px}
.fp-listWhy{margin:0 0 8px; font-size:12.5px; color:var(--ink-2)}
.fp-rows{display:flex; flex-direction:column; gap:6px}
.fRow{display:flex; align-items:center; gap:10px; width:100%; min-height:44px; padding:6px 12px; text-align:left;
  font:inherit; color:var(--ink); background:var(--card); border:1px solid var(--line); border-left-width:4px; border-radius:10px}
button.fRow{cursor:pointer}
button.fRow:hover{box-shadow:0 2px 8px rgba(67,41,64,.14)}
.fRow-t{font-weight:600; min-width:64px}
.fRow-s{flex:1 1 auto; font-size:13px; color:var(--ink-2)}
.fRow-go{color:var(--ink-2)}
.fRow.st-seated{border-left-color:var(--ok)}
.fRow.st-soon,.fRow.st-arrived{border-left-color:var(--warn)}
.fRow.st-pending,.fRow.st-holdlater{border-left-color:var(--warn); border-left-style:dashed}
.fRow.st-noshow{border-left-color:var(--stale)}
.fRow.st-unknown{border-left-color:var(--unknown); border-left-style:dotted}
/* Not railed: the legend still belongs on the page — it sits under the plan, wrapping horizontally. */
.fp-rail{display:block; margin-top:12px}
.fp-body.has-rail .fp-rail{display:flex; flex:0 0 280px; max-width:280px; margin-top:0; flex-direction:column; gap:14px; padding-top:2px}
.fp-body.has-rail .floorLegend{display:flex; flex-direction:column; align-items:flex-start; gap:9px; margin:0}
/* room picker (0145: one room at a time, never mixed) */
.roomPick{display:inline-flex; gap:6px; flex-wrap:wrap; margin-right:6px}
.roomBtn{font:inherit; font-size:12.5px; padding:3px 10px; border-radius:99px; border:1px solid var(--line); background:var(--card); color:var(--ink2); cursor:pointer; min-height:32px}
.roomBtn.is-on{background:var(--ink); color:var(--card); border-color:var(--ink)}
.fTile.rect{aspect-ratio:2}            /* production tileAspect: rect = 2:1 in pixels */
.fTile.rect.r90{aspect-ratio:0.5}      /* rotated 90deg = 1:2 */
.fName{font-family:var(--serif); font-weight:700; font-size:12px}
.fLbl{font-size:10px; line-height:1.15; color:var(--ink-2); max-width:96%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.fLbl.free{opacity:.6}
.fTile.st-free{opacity:.85}
.fTile.st-seated{background:color-mix(in srgb,var(--ok) 16%,var(--card)); border-color:var(--ok); cursor:pointer}
.fTile.st-soon,.fTile.st-arrived{background:color-mix(in srgb,var(--warn) 16%,var(--card)); border-color:var(--warn); cursor:pointer}
.fTile.st-noshow{background:color-mix(in srgb,var(--stale) 14%,var(--card)); border-color:var(--stale); cursor:pointer}
.fTile.st-pending{background:repeating-linear-gradient(45deg, color-mix(in srgb,var(--warn) 13%,var(--card)), color-mix(in srgb,var(--warn) 13%,var(--card)) 6px, color-mix(in srgb,var(--warn) 24%,var(--card)) 6px, color-mix(in srgb,var(--warn) 24%,var(--card)) 12px); border-color:var(--warn); border-style:dashed; cursor:pointer}
.fTile.st-holdlater{background:var(--card); border-color:var(--warn); border-style:dashed; cursor:pointer}
.fTile.st-holdlater .fLbl{color:var(--warn)}
.fTile.st-off{background:repeating-linear-gradient(45deg,var(--card),var(--card) 5px,var(--bg) 5px,var(--bg) 10px); opacity:.7}
/* Unknown = we don't know. Carried by the "? unknown" wording and the dotted edge, not by colour alone. */
.fTile.st-unknown{background:color-mix(in srgb,var(--unknown) 12%,var(--card)); border-color:var(--unknown); border-style:dotted; border-width:2px; cursor:pointer}
.fTile.st-unknown .fLbl{color:var(--unknown); font-style:italic}
.fTile[data-code]:hover{box-shadow:0 3px 10px rgba(67,41,64,.18)}
.floorLegend{display:flex; flex-wrap:wrap; gap:14px; font-size:12px; color:var(--ink-2)}
.floorLegend .lg{display:inline-flex; align-items:center; gap:6px}
.floorLegend .lg i{width:12px; height:12px; border-radius:4px; border:1.5px solid; display:inline-block}
.floorLegend .st-seated i{background:color-mix(in srgb,var(--ok) 16%,var(--card)); border-color:var(--ok)}
.floorLegend .st-soon i{background:color-mix(in srgb,var(--warn) 16%,var(--card)); border-color:var(--warn)}
.floorLegend .st-noshow i{background:color-mix(in srgb,var(--stale) 14%,var(--card)); border-color:var(--stale)}
.floorLegend .st-pending i{background:color-mix(in srgb,var(--warn) 20%,var(--card)); border-color:var(--warn); border-style:dashed}
.floorLegend .st-holdlater i{background:var(--card); border-color:var(--warn); border-style:dashed}
.floorLegend .st-unknown i{background:color-mix(in srgb,var(--unknown) 12%,var(--card)); border-color:var(--unknown); border-style:dotted}
.unkNote{color:var(--unknown)}
.floorLegend .st-free i{background:var(--card); border-color:var(--line)}

/* ---- Floor TIMELINE mode (0290 parity-lift). Grid scaffold only; state colours MIRROR .fTile.st-* (:256-266) so
   both views share ONE visual language. If those colours change, update both (grep st-seated). All vars are the
   slice :root tokens (theme-aware in both modes) — nothing from the legacy --blue/--sh scales. ---- */
/* [hidden] guards: an author-origin base `display` overrides the UA `[hidden]{display:none}` rule, so any element
   we toggle via .hidden AND give a base display needs an explicit guard (same pattern as .stSaveBar[hidden]/.hWin
   [hidden]). #fpBody (display:block/flex) and #fpZoom (display:inline-flex) are both .hidden-toggled by the Floor
   mode switch — placed AFTER .fp-body.has-rail so equal-specificity source order wins. */
.fp-body[hidden]{display:none}
.fp-zoom[hidden]{display:none}
.fp-view{display:inline-flex; gap:2px; background:var(--card); border:1px solid var(--line); border-radius:10px; padding:3px}
.fvBtn{font:inherit; font-size:13px; font-weight:700; color:var(--ink-2); background:none; border:0; padding:6px 13px; min-height:var(--tap); border-radius:8px; cursor:pointer}
.fvBtn.is-on{background:var(--plum); color:var(--paper)}
.fp-tl{margin-top:6px}
/* 0295 FR4: bounded read-only day navigation + event roster */
.tlNav{display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin:0 0 10px}
.tlNavBtn{font:inherit; font-size:16px; font-weight:800; line-height:1; color:var(--ink); background:var(--card); border:1px solid var(--line); border-radius:9px; min-width:var(--tap); min-height:var(--tap); cursor:pointer}
.tlNavBtn:disabled{opacity:.4; cursor:default}
.tlDay{display:flex; flex-direction:column; min-width:0; flex:1 1 120px}
.tlDayLbl{font-size:14px; font-weight:800; color:var(--ink); white-space:nowrap}
.tlDayRel{font-size:11.5px; font-weight:600; color:var(--ink-2)}
.tlToday{font:inherit; font-size:12.5px; font-weight:700; color:var(--plum); background:none; border:1px solid var(--line); border-radius:8px; padding:6px 12px; min-height:var(--tap); cursor:pointer}
.tlEvents{margin:0 0 10px; padding:8px 12px; background:color-mix(in srgb,var(--plum) 6%,var(--card)); border:1px solid var(--line); border-radius:10px}
.tlEvHd{font-size:11px; font-weight:800; letter-spacing:.04em; text-transform:uppercase; color:var(--ink-2); margin-bottom:4px}
.tlEv{display:flex; align-items:baseline; gap:8px; font-size:12.5px; padding:2px 0}
.tlEv b{font-weight:800; color:var(--ink)}
.tlEvT{font-variant-numeric:tabular-nums; font-weight:700; color:var(--ink-2)}
.tlEvN{margin-left:auto; font-weight:700; color:var(--plum); white-space:nowrap}
.tlEvN.muted{color:var(--ink-2); font-style:italic; font-weight:600}
.tlNotice{margin:0 0 10px; padding:9px 12px; font-size:12.5px; font-weight:600; color:var(--warn); background:color-mix(in srgb,var(--warn) 10%,var(--card)); border:1px solid var(--warn); border-radius:10px}
.tlWrap{overflow:auto; max-height:min(620px,calc(100dvh - 250px)); background:var(--card); border:1px solid var(--line); border-radius:var(--r); padding:10px}
.tlShell{position:relative; width:max-content; min-width:100%}
.tl{display:grid; position:relative}
.tlCorner{position:sticky; left:0; top:0; background:var(--card); z-index:9}
.tlHead{position:sticky; top:0; height:24px; border-left:1px dashed var(--line-2); background:var(--card); z-index:6}
.tlHead.hour{border-left:1.5px solid var(--line)}
.tlHead.band{background:color-mix(in srgb,var(--cream) 40%,var(--card))}
.tlHr{position:absolute; left:3px; top:4px; font-size:11px; font-weight:800; color:var(--ink); font-variant-numeric:tabular-nums; white-space:nowrap}
.tlLabel{position:sticky; left:0; background:var(--card); font-weight:800; font-size:12px; padding:7px 8px 0 3px; border-top:1px solid var(--line-2); z-index:5; line-height:1.2; white-space:nowrap}
.tlLabel small{display:block; color:var(--ink-2); font-weight:600; font-size:10px}
.tlLabel.tlOff{opacity:.5}
.tlCell{border-left:1px dashed var(--line-2); border-top:1px solid var(--line-2); min-height:46px}
.tlCell.hr{border-left:1.5px solid var(--line)}
.tlCell.band{background:color-mix(in srgb,var(--cream) 35%,var(--card))}
.tlCell.cellOff{background:repeating-linear-gradient(45deg,transparent,transparent 6px,var(--bg) 6px,var(--bg) 8px)}
.tlBlock{margin:3px 2px; padding:4px 8px; border-radius:8px; border:1.5px solid var(--line); background:var(--bg); color:var(--ink); font:inherit; text-align:left; overflow:hidden; cursor:pointer; z-index:2; line-height:1.2; align-self:stretch; min-width:0}
.tlBlock .nm{display:block; font-weight:800; font-size:12px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.tlBlock small{display:block; font-weight:600; font-size:10px; color:var(--ink-2); white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.tlBlock[data-code]:hover{box-shadow:0 3px 10px rgba(67,41,64,.18)}
.tlBlock.st-seated{background:color-mix(in srgb,var(--ok) 16%,var(--card)); border-color:var(--ok)}
.tlBlock.st-arrived{background:color-mix(in srgb,var(--warn) 16%,var(--card)); border-color:var(--warn)}
.tlBlock.st-noshow{background:color-mix(in srgb,var(--stale) 14%,var(--card)); border-color:var(--stale)}
.tlBlock.st-pending{background:repeating-linear-gradient(45deg, color-mix(in srgb,var(--warn) 13%,var(--card)), color-mix(in srgb,var(--warn) 13%,var(--card)) 6px, color-mix(in srgb,var(--warn) 24%,var(--card)) 6px, color-mix(in srgb,var(--warn) 24%,var(--card)) 12px); border-color:var(--warn); border-style:dashed}
.tlBlock.st-unknown{background:color-mix(in srgb,var(--unknown) 12%,var(--card)); border-color:var(--unknown); border-style:dotted; border-width:2px}
.tlBlock.st-unknown small{color:var(--unknown); font-style:italic}
.tlBlock.st-booked{background:color-mix(in srgb,var(--plum) 7%,var(--card)); border-color:var(--line)}     /* confirmed, not yet arrived — calm neutral (time-position already conveys "soon") */
.tlBlock.st-done{background:var(--card); border-color:var(--line); border-style:dashed; opacity:.7}        /* completed */
.tlBlock.tlBlkOff{opacity:.5}    /* on a DEACTIVATED table — the room tile makes no occupancy claim; mute rather than assert */
.tlNow{position:absolute; top:0; bottom:0; width:3px; background:var(--safety); opacity:.92; z-index:4; pointer-events:none; border-radius:2px}
.tlNow::before{content:"NOW"; position:absolute; top:26px; left:50%; transform:translateX(-50%); background:var(--safety); color:var(--paper); font-size:9px; font-weight:800; letter-spacing:.06em; padding:2px 6px; border-radius:999px; white-space:nowrap}   /* var(--paper) not #fff: --safety flips to light salmon in dark mode, where white text drops below AA */
.tlLegend{margin-top:10px}
.tlScope{margin:8px 0 0; font-size:12px; line-height:1.4; color:var(--ink-2)}   /* 0295 FR4: honest bounded read-only scope caption */
.tlEmpty{padding:26px; text-align:center; color:var(--ink-2); font-weight:600}
@media(max-width:760px){ .tlWrap{max-height:calc(100dvh - 300px)} }

/* toast + scrim + misc */
.toast{position:fixed; left:50%; bottom:20px; transform:translate(-50%,140%); z-index:60; display:flex; align-items:center; gap:12px; max-width:calc(100vw - 32px); background:var(--plum); color:var(--paper); padding:11px 16px; border-radius:12px; box-shadow:0 6px 24px rgba(67,41,64,.28); font-size:14px; opacity:0; transition:transform .22s ease,opacity .22s ease}
.toast.show{transform:translate(-50%,0); opacity:1}
.toast.err{background:var(--stale)}
.undoBtn{font:inherit; font-weight:700; font-size:13px; color:inherit; background:transparent; border:1px solid currentColor; border-radius:999px; padding:3px 14px; min-height:var(--tap); cursor:pointer}
.scrim{position:fixed; inset:0; background:rgba(20,12,18,.42); z-index:40}
.empty{padding:36px 8px; text-align:center; color:var(--ink-2)}
.bootError{margin:18px 0; padding:14px 16px; border:1px solid var(--stale); border-radius:var(--r); color:var(--stale); background:color-mix(in srgb,var(--stale) 8%,var(--card))}
/* 0331 C1(b): the new-owner CREATE form + verify gate reuse the #bootError takeover, but read as a NEUTRAL onboarding
   card (a positive action), not the stale/error banner. Scoped by the forms' unique title ids so the genuine
   error + boot-recovery states keep their warning styling. */
.bootError:has(#cvTitle), .bootError:has(#vgTitle){color:var(--ink); background:var(--card); border-color:var(--line)}
.cvForm h2{margin:0 0 4px; font-size:19px}
.cvSub{color:var(--ink-2); font-size:13.5px; margin:0 0 14px}
.cvForm label{display:block; font-size:13px; color:var(--ink-2); margin-bottom:12px}
.cvForm input:not([type=checkbox]){width:100%; min-height:44px; margin-top:4px; padding:9px 11px; border:1px solid var(--line); border-radius:var(--r); background:var(--card); color:var(--ink); font-size:15px; box-sizing:border-box}
.cvAgree label{display:flex; gap:8px; align-items:flex-start; font-size:12.5px; color:var(--ink-2)}
.cvAgree input{width:18px; height:18px; flex:none; margin-top:1px}
.cvErr{color:var(--safety); font-size:13px; margin:8px 0 0}
.cvBtns{display:flex; gap:8px; margin-top:4px}
.cvBtns .btn{min-height:44px}
/* "Closed to new bookings today" — the passive half of moving the emergency-close ACTION into
   Settings (Codex 0210 §1). It states the operational truth and offers a route; it never fires the
   action itself, so there is exactly one place that can close or reopen a day. */
.closedBanner{display:flex; align-items:center; gap:14px; flex-wrap:wrap; margin:0 0 16px; padding:12px 16px;
  border:1px solid var(--warn); border-left-width:4px; border-radius:var(--r); background:color-mix(in srgb,var(--warn) 9%,var(--card)); font-size:13.5px; line-height:1.5}
.closedBanner span{flex:1; min-width:220px}
.closedBanner .btn{flex:none}
*:focus-visible{outline:2.5px solid var(--terra); outline-offset:2px; border-radius:6px}

/* tablet */
@media (max-width:1024px) and (min-width:721px){ .board{grid-template-columns:1.35fr 1fr} }
/* phone — detail becomes a bottom sheet */
@media (max-width:720px){
  .summary{grid-template-columns:none; display:flex; gap:10px; overflow-x:auto; -webkit-overflow-scrolling:touch}
  .stat{flex:0 0 auto; min-width:138px}
  .board{grid-template-columns:1fr}
  .row{grid-template-columns:52px 1fr; row-gap:6px}
  .r-right{grid-column:2; flex-direction:row; align-items:center; gap:8px}
  .detail-wrap{position:fixed; inset:auto 0 0 0; z-index:50; transform:translateY(101%); transition:transform .22s ease}
  .detail-wrap.is-open{transform:translateY(0)}
  .detail{position:static; border-radius:18px 18px 0 0; max-height:82vh; overflow:auto; box-shadow:0 -12px 30px -12px rgba(20,12,18,.5)}
  .d-grid{grid-template-columns:1fr}
  .d-close{display:inline-flex; position:absolute; top:12px; right:12px; min-height:var(--tap); min-width:var(--tap); align-items:center; justify-content:center; border:1px solid var(--line); border-radius:10px; background:var(--card); color:var(--ink); font:inherit; font-size:18px; cursor:pointer}
  .fName{font-size:11px}
}
@media (prefers-reduced-motion:reduce){*{animation:none !important; transition:none !important}}

/* theme switch (0185) — dark is the product default; this is the explicit Light escape hatch.
   Sized to the 44px tap target like every other control in the topbar, and it keeps a visible text label
   because the ruling forbids relying on an icon alone. */
.themeBtn{display:inline-flex; align-items:center; gap:9px; font:inherit; font-size:13px; font-weight:600;
  color:var(--ink-2); background:var(--card); border:1px solid var(--line); border-radius:999px;
  padding:8px 15px 8px 11px; min-height:var(--tap); cursor:pointer}
.themeBtn:hover{color:var(--plum)}
.themeBtn:focus-visible{outline:2px solid var(--terra); outline-offset:2px}
.themeBtn-track{position:relative; width:34px; height:19px; border-radius:999px; background:var(--line);
  border:1px solid var(--line-2); flex:0 0 auto; transition:background .15s ease}
.themeBtn-knob{position:absolute; top:2px; left:2px; width:13px; height:13px; border-radius:50%;
  background:var(--paper); box-shadow:0 1px 2px rgba(0,0,0,.35); transition:transform .15s ease}
.themeBtn[aria-checked="true"] .themeBtn-track{background:var(--plum)}
.themeBtn[aria-checked="true"] .themeBtn-knob{transform:translateX(15px)}
@media (prefers-reduced-motion:reduce){.themeBtn-track,.themeBtn-knob{transition:none}}
/* Short landscape already fights for height — drop the label, keep the switch and its accessible name. */
@media (max-height:560px){
  .themeBtn{padding:5px 10px}
  .themeBtn-lbl{position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap}
}

/* search + add booking (Stage 1.1) */
.qSearchWrap{display:flex; align-items:center; gap:8px; margin-top:10px}
.qSearchLbl{position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap}
.qSearchInput{flex:1 1 auto; min-width:0; font:inherit; font-size:14px; color:var(--ink); background:var(--paper);
  border:1px solid var(--line); border-radius:10px; padding:10px 12px; min-height:var(--tap)}
.qSearchInput::placeholder{color:var(--ink-2)}
.qSearchInput:focus-visible{outline:2px solid var(--terra); outline-offset:1px}
.qSearchClear{font:inherit; font-size:13px; font-weight:600; color:var(--ink-2); background:none;
  border:1px solid var(--line); border-radius:10px; padding:0 12px; min-height:var(--tap); cursor:pointer}
.qSearchClear:hover{color:var(--plum)}

.addDlg{position:fixed; z-index:60; left:50%; top:50%; transform:translate(-50%,-50%); width:min(560px,calc(100vw - 28px));
  max-height:calc(100vh - 32px); overflow:auto; background:var(--card); border:1px solid var(--line);
  border-radius:16px; padding:20px; box-shadow:0 24px 60px -20px rgba(20,12,18,.55)}
.addTitle{margin:0 0 4px; font-family:var(--serif); font-size:20px; color:var(--plum)}
.addSub{margin:0 0 16px; font-size:12.5px; color:var(--ink-2)}
.addGrid{display:grid; grid-template-columns:1fr auto auto; gap:12px}
.addF{display:flex; flex-direction:column; gap:5px; font-size:12px; font-weight:600; color:var(--ink-2)}
.addF input{font:inherit; font-size:15px; font-weight:400; color:var(--ink); background:var(--paper);
  border:1px solid var(--line); border-radius:10px; padding:9px 11px; min-height:var(--tap)}
.addF input:focus-visible{outline:2px solid var(--terra); outline-offset:1px}
.addF-s input{width:92px}
.addF-w{grid-column:1 / -1}
.addOpt{font-weight:400; opacity:.75}
/* The assignment explanation. It is the product's actual reasoning, so it gets room and a word, not a colour. */
.addWhy{margin:14px 0 0; font-size:13px; line-height:1.45; padding:10px 12px; border-radius:10px;
  border:1px solid var(--line); background:var(--paper); color:var(--ink-2); min-height:42px}
.addWhy.is-ok{border-color:color-mix(in srgb,var(--ok) 40%,transparent); color:var(--ink)}
.addWhy.is-no{border-color:color-mix(in srgb,var(--stale) 45%,transparent); color:var(--stale)}
.addActs{display:flex; justify-content:flex-end; gap:10px; margin-top:16px}
@media (max-width:520px){
  .addGrid{grid-template-columns:1fr 1fr}
  .addF-s input{width:100%}
  .addDlg{top:auto; bottom:0; transform:translateX(-50%); width:100vw; border-radius:18px 18px 0 0; max-height:88vh}
}
.btn-reset{background:none; border:1px solid var(--line); color:var(--ink-2); margin-left:10px}
.btn-reset:hover{color:var(--plum); border-color:var(--plum-2)}

/* Week (Stage 1.4) */
.wk{display:flex; flex-direction:column; gap:14px}
.wk-strip{display:grid; grid-template-columns:repeat(7,1fr); gap:6px; background:var(--card);
  border:1px solid var(--line); border-radius:var(--r); padding:6px; box-shadow:var(--shadow)}
.wk-day{display:flex; flex-direction:column; align-items:center; gap:2px; font:inherit; cursor:pointer;
  background:none; border:1px solid transparent; border-radius:10px; padding:9px 4px; min-height:var(--tap); color:var(--ink-2)}
.wk-day:hover{background:color-mix(in srgb,var(--plum) 6%,transparent)}
.wk-day:focus-visible{outline:2px solid var(--terra); outline-offset:-2px}
.wk-dow{font-size:11.5px; text-transform:uppercase; letter-spacing:.05em}
.wk-dom{font-family:var(--serif); font-size:19px; font-weight:700; color:var(--ink); line-height:1.05}
.wk-n{font-size:11px; font-variant-numeric:tabular-nums}
.wk-day.is-today .wk-dom{color:var(--terra)}
.wk-day.is-on{background:var(--plum); border-color:var(--plum)}
.wk-day.is-on .wk-dow,.wk-day.is-on .wk-n{color:var(--paper); opacity:.85}
.wk-day.is-on .wk-dom{color:var(--paper)}
.wk-actions{margin-top:10px}
@media (max-width:560px){
  .wk-strip{grid-template-columns:repeat(4,1fr)}
  .wk-n{font-size:10.5px}
}

/* Guests (Stage 1.5) */
.gRow{display:grid; grid-template-columns:38px 1fr auto; gap:12px; align-items:center; width:100%; text-align:left;
  font:inherit; background:none; border:0; border-top:1px solid var(--line-2); padding:12px 18px; cursor:pointer; min-height:var(--tap)}
.gRow:hover{background:color-mix(in srgb,var(--plum) 4%,transparent)}
.gRow:focus-visible{outline:2px solid var(--terra); outline-offset:-2px}
.gAv{display:grid; place-items:center; width:38px; height:38px; border-radius:50%; background:var(--plum); color:var(--paper);
  font-size:13px; font-weight:700; letter-spacing:.02em}
.gTag{display:inline-block; font-size:11px; font-weight:700; padding:3px 8px; border-radius:999px; margin-left:6px; white-space:nowrap}
.gReg{background:color-mix(in srgb,var(--ok) 16%,transparent); color:var(--ok)}
.gRisk{background:color-mix(in srgb,var(--stale) 14%,transparent); color:var(--stale)}
.gNew{background:color-mix(in srgb,var(--warn) 16%,transparent); color:var(--warn)}
.d-sec{margin:16px 0 6px; display:block}
.gVisits{display:flex; flex-direction:column; border:1px solid var(--line); border-radius:10px; overflow:hidden}
.gVisit{display:grid; grid-template-columns:1fr auto auto; gap:10px; align-items:center; width:100%; text-align:left;
  font:inherit; font-size:13px; background:var(--paper); border:0; border-top:1px solid var(--line-2);
  padding:9px 12px; cursor:pointer; color:var(--ink); min-height:40px}
.gVisit:first-child{border-top:0}
.gVisit:hover{background:color-mix(in srgb,var(--plum) 6%,transparent)}
.gVisit:focus-visible{outline:2px solid var(--terra); outline-offset:-2px}
.gVisit-t{color:var(--ink-2); font-variant-numeric:tabular-nums}
.gVisit-s{color:var(--ink-2); font-size:12px}
.gNotes p{margin:0 0 6px}
.gBack,.gGo{margin:0 8px 12px 0; font-size:13px}
/* Guests sub-tabs + read-only Waitlist (0290 parity-lift). [hidden] guards because .gx-book/.gx-wait are block by
   default — an author display would defeat the attribute (the fp-body lesson). Colours are slice :root tokens. */
.gx-tabs{display:flex; gap:2px; background:var(--card); border:1px solid var(--line); border-radius:12px; padding:4px; margin-bottom:16px; max-width:100%; overflow-x:auto; -webkit-overflow-scrolling:touch; scrollbar-width:thin}   /* 0295 R5: the 4 Guests tabs scroll-contain (was width:fit-content → could overflow at 360) */
.gx-tab{font:inherit; font-size:14px; font-weight:600; color:var(--ink-2); background:none; border:0; padding:9px 15px; min-height:var(--tap); border-radius:9px; cursor:pointer; flex:0 0 auto; white-space:nowrap}
.gx-tab.on{background:var(--plum); color:var(--paper)}
.gx-book[hidden],.gx-wait[hidden]{display:none}
.gTagRow{display:flex; flex-wrap:wrap; gap:6px; margin:2px 0 10px}
.gTagRow .gTag{margin-left:0}
.gContact{display:flex; flex-wrap:wrap; gap:8px; margin:0 0 14px}
.d-sub.is-degraded{color:var(--unknown); font-style:italic}
.d-note{margin:0 0 12px; font-size:12px; line-height:1.4; padding:8px 11px; border-radius:9px; background:color-mix(in srgb,var(--unknown) 10%,var(--card)); border:1px solid var(--unknown); color:var(--ink-2)}
.d-v.is-unknown{color:var(--unknown); font-style:italic}   /* 0292 R3: three-valued money absence — withheld, not "nothing recorded" */
.betaLabel{margin:0 0 10px; padding:6px 12px; text-align:center; font-size:11.5px; font-weight:600; letter-spacing:.02em;
  color:var(--unknown); background:color-mix(in srgb,var(--unknown) 10%,var(--card)); border:1px solid var(--unknown); border-radius:8px}   /* 0292 R5: persistent Owner-Beta boundary */
.fbStatNote{margin:8px 0 2px; font-size:11.5px; line-height:1.4}   /* 0292 R3: review stats are of the capped window */
.wlBody{margin-top:2px}
.wlHead{display:flex; justify-content:flex-end; margin:0 0 10px}
.wlRefresh{font-size:13px; padding:6px 13px}
.wlLoad{padding:24px 8px; text-align:center}
.wlList{display:flex; flex-direction:column; border:1px solid var(--line); border-radius:10px; overflow:hidden}
.wlRow{display:grid; grid-template-columns:1fr auto auto; gap:10px; align-items:center; padding:10px 13px; border-top:1px solid var(--line-2); font-size:13.5px}
.wlRow:first-child{border-top:0}
.wlRow.wlRecent{opacity:.7}
.wlName{font-weight:600; color:var(--ink); min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.wlWhen{color:var(--ink-2); font-size:12.5px; font-variant-numeric:tabular-nums; white-space:nowrap}
.wlPill{font-size:11px; font-weight:700; padding:3px 9px; border-radius:999px; white-space:nowrap; background:color-mix(in srgb,var(--warn) 14%,transparent); color:var(--warn)}
.wlPill.wlOffered{background:color-mix(in srgb,var(--ok) 16%,transparent); color:var(--ok)}
.wlPill.wlDim{background:var(--card); border:1px solid var(--line); color:var(--ink-2)}
.wlTrunc{margin:10px 0 0; font-size:12px}
.uPill{display:inline-block; font-size:11px; font-weight:700; border-radius:999px; padding:2px 9px; background:color-mix(in srgb,var(--plum) 8%,transparent); color:var(--ink-2)}
/* Win-back filter chips + rows + Reviews (0290 parity-lift) */
.wbChips{display:flex; gap:6px; margin:0 0 14px; flex-wrap:wrap}
.wbChip{font:inherit; font-size:12.5px; font-weight:600; color:var(--ink-2); background:var(--card); border:1px solid var(--line); border-radius:999px; padding:5px 12px; min-height:var(--tap); cursor:pointer}
.wbChip.on{background:var(--plum); color:var(--paper); border-color:var(--plum)}
.wbList{display:flex; flex-direction:column; border:1px solid var(--line); border-radius:10px; overflow:hidden}
.wbRow{display:grid; grid-template-columns:1fr auto; gap:8px; align-items:center; border-top:1px solid var(--line-2)}
.wbRow:first-child{border-top:0}
.wbOpen{display:flex; align-items:center; gap:12px; min-width:0; flex:1; background:none; border:0; font:inherit; text-align:left; color:inherit; padding:10px 4px 10px 12px; cursor:pointer}
.wbOpen:hover{background:color-mix(in srgb,var(--plum) 4%,transparent)}
.wbActs{display:flex; gap:6px; padding-right:10px}
.wbAct{font-size:12.5px; padding:6px 11px}
.fbLink{margin:0 0 14px; padding:12px 14px; border:1px solid var(--line); border-radius:10px; background:var(--card)}
.fbLinkK{display:block; font-weight:700; font-size:12px; color:var(--ink-2); margin-bottom:4px}
.fbLinkA{word-break:break-all}
.fbLinkNote{margin:6px 0 0; font-size:12px}
.fbList{display:flex; flex-direction:column; gap:10px}
.fbRow{border:1px solid var(--line); border-radius:10px; padding:11px 13px}
.fbRowTop{display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-bottom:5px}
.fbName{font-weight:700; font-size:13.5px}
.fbStars{color:var(--warn); letter-spacing:1px}
.fbWhen{margin-left:auto; font-size:12px}
.fbComment{font-size:13.5px; white-space:pre-wrap; word-wrap:break-word; overflow-wrap:anywhere}
/* Reviews has FOUR stats; .aiStatRow is a 3-col grid (AI panel) so the 4th cell would orphan. 4-up desktop, 2x2 mobile. */
.aiStatRow.fbStatRow{grid-template-columns:repeat(4,1fr)}
@media(max-width:560px){ .aiStatRow.fbStatRow{grid-template-columns:repeat(2,1fr)} }

/* AI insights surface (0290 parity-lift). Analytics + answer-only chat. All colours are slice :root tokens
   (theme-aware). [hidden] guard because .aiView has a base display:grid (the fp-body lesson). */
.aiView{display:grid; grid-template-columns:minmax(0,1fr) minmax(320px,420px); gap:16px; align-items:start}
.aiView[hidden]{display:none}
#aiMount{display:contents}   /* review: the grid is on .aiView but its only child is #aiMount — display:contents lets the two .aiCol be the actual grid items so the analytics|chat split renders */
@media(max-width:900px){ .aiView{grid-template-columns:1fr} }
.aiDegraded{border-color:var(--unknown); background:color-mix(in srgb,var(--unknown) 12%,var(--card)); font-size:13px; line-height:1.45}
.aiColMain.is-degraded .aiCard:not(.aiDegraded), .aiColMain.is-degraded .aiStat{border-style:dashed; border-color:var(--unknown)}
.aiHeatCell.aiHeatHot{color:var(--paper)}   /* review: contrasting number on the darker (>50%) fills — legible in both themes */
.aiCol{min-width:0; display:flex; flex-direction:column; gap:14px}
.aiCard{background:var(--card); border:1px solid var(--line); border-radius:var(--r); padding:14px 16px; box-shadow:var(--shadow)}
.aiCard h3{margin:0 0 10px; font-family:var(--serif); font-size:15px; color:var(--plum); font-weight:700}
.aiSummary p{margin:0; font-size:14px; line-height:1.5}
.aiFoot{margin:2px 2px 0; font-size:12px}
.aiStatRow{display:grid; grid-template-columns:repeat(3,1fr); gap:12px}
.aiStat{background:var(--card); border:1px solid var(--line); border-radius:var(--r); padding:12px 14px; box-shadow:var(--shadow); text-align:center}
.aiStatV{display:block; font-family:var(--serif); font-size:24px; font-weight:700; color:var(--plum); font-variant-numeric:tabular-nums}
.aiStatK{display:block; font-size:11.5px; color:var(--ink-2); margin-top:3px}
.aiNsHead{margin-bottom:10px} .aiNsBig{font-family:var(--serif); font-size:28px; font-weight:700; color:var(--plum); font-variant-numeric:tabular-nums}
.aiNsBars{display:flex; flex-direction:column; gap:8px}
.aiNsBar{display:grid; grid-template-columns:64px 1fr 40px; gap:8px; align-items:center; font-size:12px}
.aiNsLbl{color:var(--ink-2)}
.aiNsTrack{height:10px; background:var(--bg); border-radius:999px; overflow:hidden}
.aiNsFill{display:block; height:100%; background:var(--terra); border-radius:999px}
.aiNsVal{text-align:right; font-variant-numeric:tabular-nums; color:var(--ink-2)}
.aiChan{display:flex; flex-direction:column; gap:8px}
.aiChanRow{display:grid; grid-template-columns:120px 1fr 40px; gap:8px; align-items:center; font-size:12.5px}
.aiChanK{color:var(--ink); overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.aiChanTrack{height:10px; background:var(--bg); border-radius:999px; overflow:hidden}
.aiChanFill{display:block; height:100%; background:var(--plum); border-radius:999px}
.aiChanVal{text-align:right; font-variant-numeric:tabular-nums; color:var(--ink-2)}
.aiHeat{display:grid; gap:2px; font-size:10px}
.aiHeatHr{text-align:center; color:var(--ink-2); font-variant-numeric:tabular-nums}
.aiHeatDay{color:var(--ink-2); font-weight:700; padding-right:4px; display:flex; align-items:center}
.aiHeatCell{aspect-ratio:1; min-height:18px; border-radius:3px; display:flex; align-items:center; justify-content:center; color:var(--ink); font-variant-numeric:tabular-nums; font-size:9px}
.aiRecs{margin:0; padding:0; list-style:none; display:flex; flex-direction:column; gap:10px}
.aiRecs li{display:flex; gap:9px; font-size:13.5px; line-height:1.45}
.aiRecIc{flex:none}
.aiChat{display:flex; flex-direction:column; position:sticky; top:12px}
.aiLog{display:flex; flex-direction:column; gap:8px; max-height:min(460px,52vh); overflow-y:auto; padding:4px 2px; margin-bottom:10px}
.msg{max-width:88%; padding:8px 12px; border-radius:12px; font-size:13.5px; line-height:1.45; word-wrap:break-word; overflow-wrap:anywhere}
.msg.me{align-self:flex-end; background:var(--plum); color:var(--paper); border-bottom-right-radius:4px}
.msg.ai{align-self:flex-start; background:var(--bg); color:var(--ink); border-bottom-left-radius:4px}
.msg.note{align-self:flex-start; background:transparent; border:1px dashed var(--line); color:var(--ink-2); font-size:12.5px}
.msg.err{align-self:flex-start; background:var(--safety-bg); border:1px solid var(--safety); color:var(--safety); font-weight:600}
.aiDots i{display:inline-block; width:6px; height:6px; margin:0 1px; border-radius:50%; background:var(--ink-2); animation:aiBlink 1.2s infinite}
.aiDots i:nth-child(2){animation-delay:.2s} .aiDots i:nth-child(3){animation-delay:.4s}
@keyframes aiBlink{0%,60%,100%{opacity:.25} 30%{opacity:1}}
@media (prefers-reduced-motion:reduce){.aiDots i{animation:none}}
.aiChips{display:flex; flex-wrap:wrap; gap:6px; margin-bottom:10px}
.aiChip{font:inherit; font-size:12px; color:var(--plum); background:color-mix(in srgb,var(--plum) 8%,transparent); border:1px solid var(--line); border-radius:999px; padding:6px 11px; cursor:pointer}
.aiForm{display:flex; gap:8px}
.aiInput{flex:1; min-width:0; font:inherit; font-size:14px; color:var(--ink); background:var(--paper); border:1px solid var(--line); border-radius:10px; padding:10px 12px; min-height:var(--tap)}
.aiInput:focus-visible{outline:2px solid var(--terra); outline-offset:1px}
.aiSend{font:inherit; font-size:13px; font-weight:700; color:var(--paper); background:var(--plum); border:0; border-radius:10px; padding:0 16px; min-height:var(--tap); cursor:pointer}
.d-edit{float:right; margin:-4px 0 0 10px; font-size:13px}
.addF select{font:inherit; font-size:15px; color:var(--ink); background:var(--paper); border:1px solid var(--line);
  border-radius:10px; padding:9px 11px; min-height:var(--tap)}
.addF select:focus-visible{outline:2px solid var(--terra); outline-offset:1px}

/* Action centre (Stage 1.6) */
.bellWrap{position:relative}
.bellBtn{display:inline-flex; align-items:center; gap:8px; font:inherit; font-size:13px; font-weight:600;
  color:var(--ink-2); background:var(--card); border:1px solid var(--line); border-radius:999px;
  padding:8px 15px; min-height:var(--tap); cursor:pointer}
.bellBtn:hover{color:var(--plum)}
.bellBtn:focus-visible{outline:2px solid var(--terra); outline-offset:2px}
/* 0330 area-2: owner pause/resume status light (Live / Paused / Suspended) — colour + dot follow the status. */
.statusPill{display:inline-flex; align-items:center; gap:7px; font:inherit; font-size:12.5px; font-weight:700; letter-spacing:.01em;
  border:1px solid var(--line); border-radius:999px; padding:5px 12px; background:var(--card); color:var(--ink-2); cursor:pointer; white-space:nowrap}
.statusPill:hover{border-color:var(--ink-2)}
.statusPill:focus-visible{outline:2px solid var(--terra); outline-offset:2px}
.statusPill .spDot{width:8px; height:8px; border-radius:50%; background:currentColor; flex:none}
.statusPill.sp-live{color:var(--ok)}
.statusPill.sp-paused{color:var(--warn)}
.statusPill.sp-suspended{color:var(--stale)}
.statusPill:disabled{opacity:.65; cursor:default}
/* 0330 area-3: VIP guest tag — distinct amber treatment on the neutral gTag base. */
.gTag.gVip{color:var(--warn); border-color:var(--warn)}
/* 0330 review P2: /app waitlist actions live in #gxWaitBody (Guests hub), OUTSIDE the settings.css .wlActs scope
   (#setMount,.modalBack,.pinPad). Give them their own flex row + a danger treatment for the destructive Remove. */
.wlActs{display:flex; gap:8px; flex-shrink:0}
.wlRow .wlActs{grid-column:1 / -1; margin-top:6px}
.wlBtn.warn{color:var(--stale); border-color:var(--stale)}
.bellIcon{font-size:15px; line-height:1}
.bellCount{display:inline-grid; place-items:center; min-width:20px; height:20px; padding:0 6px; border-radius:999px;
  background:var(--ink-2); color:var(--paper); font-size:11.5px; font-weight:800; font-variant-numeric:tabular-nums}
.bellCount.has-action{background:var(--stale)}
.bellPanel{position:absolute; z-index:70; right:0; top:calc(100% + 8px); width:min(400px,calc(100vw - 24px));
  max-height:min(70vh,560px); overflow:auto; background:var(--card); border:1px solid var(--line);
  border-radius:14px; padding:14px; box-shadow:0 20px 50px -18px rgba(20,12,18,.55)}
.nHead{display:flex; align-items:baseline; justify-content:space-between; gap:10px; margin-bottom:6px}
.nHead h2{margin:0; font-family:var(--serif); font-size:16px; color:var(--plum)}
.nAll{font:inherit; font-size:12px; font-weight:600; color:var(--ink-2); background:none; border:0; cursor:pointer; text-decoration:underline}
.nAll:hover{color:var(--plum)}
.nGroup{margin:12px 0 4px; font-size:11px; font-weight:800; letter-spacing:.05em; text-transform:uppercase; color:var(--ink-2)}
.nGroup-act{color:var(--stale)}
.nList{list-style:none; margin:0; padding:0; border:1px solid var(--line); border-radius:10px; overflow:hidden}
.nItem{display:grid; grid-template-columns:1fr auto; gap:8px; align-items:center; border-top:1px solid var(--line-2); background:var(--paper)}
.nItem:first-child{border-top:0}
.nItem.is-unread{background:color-mix(in srgb,var(--plum) 5%,var(--paper))}
.nOpen{display:flex; flex-direction:column; gap:2px; text-align:left; font:inherit; background:none; border:0;
  padding:10px 12px; cursor:pointer; color:var(--ink); min-height:44px}
.nOpen:focus-visible{outline:2px solid var(--terra); outline-offset:-2px}
.nTitle{font-size:13px; font-weight:700}
.nDot{display:inline-block; width:7px; height:7px; border-radius:50%; background:var(--terra); margin-left:6px; vertical-align:middle}
.nBody{font-size:12.5px; color:var(--ink-2)}
.nWhen{font-size:11.5px; color:var(--ink-2); opacity:.85}
.nAct{font:inherit; font-size:12px; font-weight:600; color:var(--plum); background:none; border:1px solid var(--line);
  border-radius:8px; padding:6px 10px; margin-right:10px; cursor:pointer; white-space:nowrap; min-height:34px}
.nAct:hover{border-color:var(--plum-2)}
.nState{font-size:11.5px; color:var(--ink-2); margin-right:12px; white-space:nowrap}
.nEmpty{margin:14px 0; font-size:13px; color:var(--ink-2)}
.nDone{margin-top:12px}
.nDone summary{font-size:12px; color:var(--ink-2); cursor:pointer; min-height:32px; display:flex; align-items:center}
.nCap{margin:10px 0 0; font-size:11.5px; line-height:1.4; color:var(--unknown); border:1px dashed var(--unknown); border-radius:9px; padding:8px 10px}
.nFoot{margin:12px 0 0; font-size:11.5px; line-height:1.45; color:var(--ink-2); opacity:.9}
@media (max-width:560px){ .bellLbl{display:none} .bellPanel{position:fixed; right:12px; left:12px; width:auto; top:auto; bottom:12px} }

/* Settings preview (Stage 1.7) */
.stNote{margin:0 0 16px; padding:12px 14px; font-size:13px; line-height:1.5; color:var(--ink-2);
  background:var(--card); border:1px dashed var(--line); border-radius:12px}
.stGrid{display:grid; grid-template-columns:repeat(auto-fit,minmax(300px,1fr)); gap:14px; align-items:start}
.stCard{background:var(--card); border:1px solid var(--line); border-radius:var(--r); padding:14px 16px; box-shadow:var(--shadow)}
.stCard h3{margin:0 0 10px; font-family:var(--serif); font-size:15px; color:var(--plum)}
.stRow{display:flex; justify-content:space-between; gap:14px; padding:7px 0; border-top:1px solid var(--line-2); font-size:13px}
.stRow:first-of-type{border-top:0}
.stK{color:var(--ink-2)}
.stV{color:var(--ink); text-align:right; font-variant-numeric:tabular-nums}
.stFoot{margin:10px 0 0; font-size:12px; line-height:1.5; color:var(--ink-2)}
/* Editable settings (HOSTED only — the demo stays read-only and asserts zero inputs) */
.stEdit{display:flex; flex-direction:column; gap:11px}
.stF{display:flex; flex-direction:column; gap:5px; font-size:13px; color:var(--ink-2)}
.stF>span{display:flex; align-items:baseline; gap:6px}
.stF em{font-style:normal; font-size:11.5px; color:var(--ink-3, var(--ink-2)); opacity:.85}
.stF input{width:100%; box-sizing:border-box; padding:9px 11px; font:inherit; font-size:14px; color:var(--ink);
  background:var(--bg); border:1px solid var(--line); border-radius:10px}
.stF input:focus-visible{outline:2px solid var(--plum); outline-offset:1px; border-color:var(--plum)}
/* The save bar only exists while something differs from the saved value, so it never invites a no-op save. */
.stSaveBar{display:flex; flex-wrap:wrap; align-items:center; gap:9px; margin-top:3px}
.stSaveBar[hidden]{display:none}
.stMsg{font-size:12.5px; color:var(--ink-2)}
.stMsg.ok{color:var(--ok, #2f7d52)}
/* An error here has to survive a glance: a settings save that failed must never read like one that worked. */
.stMsg.err{color:var(--accent-2, #B6492F); font-weight:600}
/* Hours editor */
.hEd{display:flex; flex-direction:column; gap:8px}
.hDay{display:grid; grid-template-columns:minmax(96px,auto) 1fr; align-items:center; gap:8px 12px;
  padding:7px 0; border-top:1px solid var(--line-2)}
.hDay:first-child{border-top:0}
.hChk{display:flex; align-items:center; gap:8px; font-size:13px; color:var(--ink); cursor:pointer}
.hChk input{width:16px; height:16px; accent-color:var(--plum); cursor:pointer}
.hWins{display:flex; flex-wrap:wrap; align-items:center; gap:6px}
.hWin{display:inline-flex; align-items:center; gap:6px}
.hWin[hidden]{display:none}
.hTo,.hAnd{font-size:12px; color:var(--ink-2)}
.hDay input[type=time]{padding:5px 7px; font:inherit; font-size:13px; color:var(--ink);
  background:var(--bg); border:1px solid var(--line); border-radius:8px}
.hDay input[type=time]:focus-visible{outline:2px solid var(--plum); outline-offset:1px}
.hSplit{grid-column:2; justify-self:start; padding:0; font:inherit; font-size:12px; color:var(--plum);
  background:none; border:0; text-decoration:underline; cursor:pointer}
/* A closed day dims its times but does NOT remove them — reopening should restore what was there, not
   make the owner retype hours they never actually changed. */
.hDay.is-closed .hWins,.hDay.is-closed .hSplit{opacity:.4}
.hDay.is-closed input[type=time],.hDay.is-closed .hSplit{pointer-events:none}
@media (max-width:520px){ .hDay{grid-template-columns:1fr} .hSplit{grid-column:1} }
/* Tables editor */
.tEd{display:flex; flex-direction:column; gap:6px; margin-top:10px}
.tRow{display:grid; grid-template-columns:auto minmax(58px,1fr) 64px minmax(70px,1.2fr) auto; align-items:center;
  gap:8px; padding:6px 0; border-top:1px solid var(--line-2)}
.tRow:first-child{border-top:0}
.tChk{display:flex; align-items:center}
.tChk input{width:16px; height:16px; accent-color:var(--plum); cursor:pointer}
.tRow input[type=text],.tRow input[type=number]{width:100%; box-sizing:border-box; padding:5px 7px; font:inherit;
  font-size:13px; color:var(--ink); background:var(--bg); border:1px solid var(--line); border-radius:8px}
.tRow input:focus-visible{outline:2px solid var(--plum); outline-offset:1px}
.tRoom{font-size:11.5px; color:var(--ink-2); white-space:nowrap}
/* Out of service is shown by more than colour: the row dims AND the name is struck through, so it reads the
   same to anyone who cannot distinguish the tint. */
.tRow.is-off{opacity:.55}
.tRow.is-off .tName{text-decoration:line-through}
@media (max-width:520px){ .tRow{grid-template-columns:auto 1fr 56px} .tZone{grid-column:2/4} .tRoom{display:none} }
/* Booking rules */
.rEd{display:flex; flex-direction:column; gap:12px}
.rF{display:grid; grid-template-columns:1fr auto; gap:3px 12px; align-items:baseline}
.rL{font-size:13px; color:var(--ink)}
.rI{display:inline-flex; align-items:center; gap:7px}
.rV{width:78px; padding:5px 7px; font:inherit; font-size:13px; text-align:right; color:var(--ink);
  background:var(--bg); border:1px solid var(--line); border-radius:8px; font-variant-numeric:tabular-nums}
.rV:focus-visible{outline:2px solid var(--plum); outline-offset:1px}
.rU{font-size:11.5px; color:var(--ink-2); white-space:nowrap}
.rH{grid-column:1/-1; font-size:11.5px; line-height:1.45; color:var(--ink-2)}
/* unknown ≠ empty: withhold the number, say why (Stage 1.8) */
.bellBtn.is-unknown{border-style:dashed; border-color:var(--unknown)}
.bellCount.is-unknown{background:transparent; color:var(--unknown); border:1px dashed var(--unknown); font-weight:700}
.nEmpty.is-unknown{color:var(--unknown); border:1px dashed var(--unknown); border-radius:10px; padding:10px 12px}
