/* ============================================================================
   ClickStay — Andaman Ferry Board
   The staff workspace: masthead, board strip, room rack, drawer, and the
   three secondary views. Everything here is enamel on a board.
   ========================================================================= */

*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--face-ui);
  font-size: var(--t-base);
  line-height: var(--lh-base);
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: 100%;
  overscroll-behavior: none;
}

h1, h2, h3, h4 { margin: 0; font-family: var(--face-sign); font-weight: 600; line-height: var(--lh-tight); letter-spacing: var(--track-sign); text-wrap: balance; }
p { margin: 0; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
[hidden] { display: none !important; }

:focus-visible {
  outline: 2px solid var(--rule-ink);
  outline-offset: 2px;
  border-radius: var(--r-field);
}

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

.num { font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1; }
.sign { font-family: var(--face-sign); }

/* Codes and micro-labels: stamped, tracked, uppercase. */
.code {
  font-family: var(--face-sign);
  font-size: var(--t-code);
  font-weight: 600;
  letter-spacing: var(--track-code);
  text-transform: uppercase;
}

/* ── Icons ─────────────────────────────────────────────────────────────── */
.i { width: 16px; height: 16px; flex: none; stroke-width: 1.6; }
.i--lg { width: 20px; height: 20px; }
.i--xl { width: 26px; height: 26px; stroke-width: 1.4; }

/* ── App frame ─────────────────────────────────────────────────────────── */
.app {
  display: grid;
  grid-template-rows: auto auto auto 1fr;
  height: 100dvh;
  overflow: hidden;
}

/* ── Masthead: the enamel name plate over the board ────────────────────── */
.masthead {
  display: flex; align-items: center; gap: var(--s-6);
  padding: 0 var(--s-6);
  height: 50px;
  background: var(--enamel-hull);
  color: var(--on-hull);
  border-bottom: 2px solid rgba(0,0,0,.28);
}

.brand { display: flex; align-items: baseline; gap: var(--s-3); }
.brand__mark {
  font-family: var(--face-sign); font-weight: 700; font-size: 17px;
  letter-spacing: .06em; text-transform: uppercase;
}
.brand__mark em { font-style: normal; color: var(--enamel-ticket); }

.masthead__prop { display: flex; align-items: baseline; gap: var(--s-3); min-width: 0; }
.masthead__prop b { font-family: var(--face-sign); font-weight: 600; font-size: 15px; }
.masthead__prop span { font-size: var(--t-micro); color: rgba(246,242,232,.72); white-space: nowrap; }

.masthead__sep { width: 1px; height: 22px; background: rgba(246,242,232,.22); }
.masthead__end { margin-left: auto; display: flex; align-items: center; gap: var(--s-2); }

.mbtn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  height: 32px; min-width: 32px; padding: 0 var(--s-3);
  background: rgba(246,242,232,.10);
  color: var(--on-hull);
  border: 1px solid rgba(246,242,232,.18);
  border-radius: var(--r-plate);
  transition: background 120ms linear;
}
.mbtn:hover { background: rgba(246,242,232,.20); }
.mbtn[aria-pressed="true"] { background: var(--enamel-ticket); color: var(--on-ticket); border-color: transparent; }

.lang { display: inline-flex; border: 1px solid rgba(246,242,232,.20); border-radius: var(--r-plate); overflow: hidden; }
.lang button {
  height: 32px; padding: 0 10px; background: transparent; color: rgba(246,242,232,.68);
  border: 0; font-family: var(--face-sign); font-size: var(--t-code);
  font-weight: 600; letter-spacing: var(--track-code);
}
.lang button[aria-pressed="true"] { background: var(--on-hull); color: var(--enamel-hull); }

.who { display: flex; align-items: center; gap: var(--s-3); padding-left: var(--s-3); }
.who__name { font-size: var(--t-micro); line-height: 1.2; }
.who__role { font-size: var(--t-code); color: rgba(246,242,232,.66); }

/* ── Route tabs: the destination selector on a ferry board ─────────────── */
.routes {
  display: flex; align-items: stretch; gap: 0;
  background: var(--surface-2);
  border-bottom: 1px solid var(--rule-2);
  padding-left: var(--s-3);
}
.route {
  position: relative;
  display: inline-flex; align-items: center; gap: var(--s-3);
  height: 40px; padding: 0 var(--s-6);
  background: transparent; border: 0;
  color: var(--ink-2);
  font-family: var(--face-sign); font-weight: 500; font-size: var(--t-base);
  border-right: 1px solid var(--rule);
}
.route:first-child { border-left: 1px solid var(--rule); }
.route:hover { color: var(--ink); background: var(--surface); }
.route[aria-selected="true"] { color: var(--ink); background: var(--ground); font-weight: 600; }
.route[aria-selected="true"]::after {
  content: ''; position: absolute; inset: auto 0 -1px 0; height: 3px;
  background: var(--enamel-rust);
}
.route__count {
  font-family: var(--face-sign); font-size: var(--t-code); font-weight: 600;
  padding: 1px 5px; border-radius: 2px;
  background: var(--tint-hull); color: var(--ink);
}
.routes__end { margin-left: auto; display: flex; align-items: center; gap: var(--s-3); padding: 0 var(--s-5); }

.search {
  display: flex; align-items: center; gap: var(--s-3);
  height: 30px; padding: 0 var(--s-4);
  background: var(--surface); border: 1px solid var(--rule-2);
  border-radius: var(--r-field); color: var(--ink-3); min-width: 210px;
}
.search input { flex: 1; border: 0; background: transparent; outline: none; font-size: var(--t-small); min-width: 0; }
.search input::placeholder { color: var(--ink-3); }
.search kbd {
  font-family: var(--face-sign); font-size: var(--t-code); font-weight: 600;
  padding: 1px 4px; border: 1px solid var(--rule-2); border-radius: 2px; color: var(--ink-3);
}

/* ── Board strip: the ops + compliance readout, one dense row ──────────── */
.strip {
  display: flex; align-items: stretch; gap: 0;
  background: var(--surface);
  border-bottom: 1px solid var(--rule-2);
  overflow-x: auto;
  scrollbar-width: none;
}
.strip::-webkit-scrollbar { display: none; }

/* The plates share the band rather than bunching at the left: the receptionist
   strip has seven of them and left a 500px dead span before the gauge. They
   only grow into slack, so the owner's ten still sit at their natural width. */
.stat {
  flex: 1 1 auto; min-width: max-content;
  display: flex; align-items: baseline; gap: var(--s-3);
  padding: var(--s-4) var(--s-6);
  border-right: 1px solid var(--rule);
  white-space: nowrap;
  background: none; border-top: 0; border-bottom: 0; border-left: 0;
  text-align: left;
  transition: background 120ms linear;
}
.stat:hover { background: var(--surface-2); }
.stat__n {
  font-family: var(--face-sign); font-weight: 700; font-size: var(--t-xl);
  line-height: 1; font-variant-numeric: tabular-nums;
}
.stat__l { font-size: var(--t-micro); color: var(--ink-2); }
.stat__sub { font-size: var(--t-code); color: var(--ink-3); }

/* The compliance plate is the moat, so it is loud when it needs to be. */
.stat--alert { background: var(--enamel-signal); border-right-color: rgba(0,0,0,.2); }
.stat--alert:hover { background: var(--enamel-signal); filter: brightness(1.06); }
.stat--alert .stat__n,
.stat--alert .stat__l { color: #FFF6F2; }
.stat--alert .stat__sub { color: #FFE3D8; }

.stat--clear .stat__n { color: var(--enamel-sea); }

.strip__end { flex: 0 0 auto; display: flex; align-items: center; gap: var(--s-4); padding: 0 var(--s-6); border-left: 1px solid var(--rule); }

/* Occupancy as a filled gauge bar, not a ring. */
.gauge { display: flex; align-items: center; gap: var(--s-4); }
.gauge__track { width: 96px; height: 8px; background: var(--surface-sunk); border-radius: 1px; overflow: hidden; }
.gauge__fill { height: 100%; background: var(--enamel-hull); }
.gauge__n { font-family: var(--face-sign); font-weight: 700; font-size: var(--t-lg); font-variant-numeric: tabular-nums; }

/* ── View host ─────────────────────────────────────────────────────────── */
.views { position: relative; min-height: 0; overflow: hidden; }
.view { position: absolute; inset: 0; display: none; overflow: auto; }
.view[data-active] { display: block; }
.view--rack { display: none; }
.view--rack[data-active] { display: grid; grid-template-rows: auto 1fr; overflow: hidden; }

/* ── Rack toolbar ──────────────────────────────────────────────────────── */
.rackbar {
  display: flex; align-items: center; gap: var(--s-5);
  padding: var(--s-4) var(--s-6);
  border-bottom: 1px solid var(--rule);
  background: var(--ground);
  flex-wrap: wrap;
}
.datenav { display: flex; align-items: center; gap: var(--s-2); }
.datenav__range {
  font-family: var(--face-sign); font-weight: 600; font-size: var(--t-lg);
  min-width: 168px; font-variant-numeric: tabular-nums;
}

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-3);
  height: 32px; padding: 0 var(--s-5);
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--rule-2); border-radius: var(--r-plate);
  font-family: var(--face-sign); font-weight: 500; font-size: var(--t-small);
  box-shadow: var(--lift-1);
  transition: background 120ms linear, box-shadow 120ms linear, transform 80ms linear;
}
.btn:hover { background: var(--surface-2); }
.btn:active { transform: translateY(1px); box-shadow: none; }
.btn--icon { padding: 0; width: 32px; }
.btn--primary { background: var(--enamel-hull); color: var(--on-hull); border-color: transparent; }
.btn--primary:hover { background: var(--enamel-hull); filter: brightness(1.12); }
.btn--signal { background: var(--enamel-signal); color: #FFF6F2; border-color: transparent; }
.btn--signal:hover { filter: brightness(1.07); }
.btn--ghost { background: transparent; box-shadow: none; border-color: transparent; color: var(--ink-2); }
.btn--ghost:hover { background: var(--surface-2); color: var(--ink); }
.btn--lg { height: 44px; padding: 0 var(--s-7); font-size: var(--t-form); }
.btn:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; }

/* Segmented control — the enamel selector plate. */
.seg { display: inline-flex; border: 1px solid var(--rule-2); border-radius: var(--r-plate); overflow: hidden; box-shadow: var(--lift-1); }
.seg button {
  height: 32px; padding: 0 var(--s-5); background: var(--surface); border: 0;
  border-right: 1px solid var(--rule);
  font-family: var(--face-sign); font-size: var(--t-small); font-weight: 500; color: var(--ink-2);
}
.seg button:last-child { border-right: 0; }
.seg button:hover { background: var(--surface-2); color: var(--ink); }
.seg button[aria-pressed="true"] { background: var(--enamel-hull); color: var(--on-hull); font-weight: 600; }

.rackbar__end { margin-left: auto; display: flex; align-items: center; gap: var(--s-4); }

/* Legend: the key printed at the edge of the board. */
.legend { display: flex; align-items: center; gap: var(--s-5); flex-wrap: wrap; font-size: var(--t-code); color: var(--ink-2); }
.legend__item { display: inline-flex; align-items: center; gap: var(--s-3); }
.legend__chip { width: 16px; height: 11px; border-radius: 1px; border: 1px solid rgba(0,0,0,.16); flex: none; }
.legend__chip--vacant { background: var(--ground); border-style: dashed; border-color: var(--rule-2); }
.legend__chip--hull { background: var(--enamel-hull); }
.legend__chip--ticket { background: var(--enamel-ticket); }
.legend__chip--sea { background: var(--enamel-sea); }
.legend__chip--rust { background: var(--hatch-bed); background-image: var(--hatch-rust); }
.legend__chip--ink { background: var(--hatch-bed); background-image: var(--hatch-ink); }

/* ── The rack itself ───────────────────────────────────────────────────── */
.rack { position: relative; overflow: auto; background: var(--ground); }

.rack__grid {
  display: grid;
  grid-template-columns: var(--room-col) 1fr;
  min-width: min-content;
}

/* Date scale — printed, recessed, sticky */
.scale {
  position: sticky; top: 0; z-index: 6;
  display: grid; grid-auto-flow: column;
  background: var(--surface-2);
  border-bottom: 2px solid var(--rule-2);
}
.scale__corner {
  position: sticky; left: 0; z-index: 7;
  background: var(--surface-2);
  border-right: 2px solid var(--rule-2);
  display: flex; flex-direction: column; justify-content: center;
  padding: var(--s-3) var(--s-4);
}
.scale__corner b { font-family: var(--face-sign); font-size: var(--t-micro); font-weight: 600; }
.scale__corner span { font-size: var(--t-code); color: var(--ink-3); }

.day {
  width: var(--day-w); flex: none;
  padding: var(--s-3) 0 var(--s-2);
  text-align: center;
  border-right: 1px solid var(--rule);
  position: relative;
}
.day__dow { display: block; font-size: var(--t-code); color: var(--ink-3); letter-spacing: .04em; }
.day__n { display: block; font-family: var(--face-sign); font-weight: 600; font-size: var(--t-lg); line-height: 1.15; font-variant-numeric: tabular-nums; }
.day__mon { display: block; font-size: var(--t-code); color: var(--ink-3); }
.day--weekend { background: rgba(11,60,73,.045); }
:root[data-theme="dark"] .day--weekend { background: rgba(255,255,255,.035); }
.day--weekend .day__dow { color: var(--enamel-rust); }
/* A public holiday is not a room state, so it gets none of the state pigments.
   It is printed on the scale: a neutral tint, a rule in ink, and a label with
   no fill. The amber this used to wear is the enamel the legend assigns to
   จองแล้ว, which is exactly the collision the four-channel rule exists to
   prevent — and it survived one round of fixing that rule elsewhere. */
.day--holiday {
  background: rgba(19, 26, 29, .05);
  box-shadow: inset 0 3px 0 var(--ink-2);
}
:root[data-theme="dark"] .day--holiday { background: rgba(237, 230, 214, .06); }
.day--holiday .day__n { color: var(--ink); }
/* In the flow, not floated over the cell: absolute positioning laid the label
   straight across the month line. The month gives way instead — it is already
   in the toolbar's range label. */
.day__flag {
  display: block; margin-top: 2px;
  font-size: 9px; letter-spacing: .02em;
  color: var(--ink-2); border-top: 1px dotted var(--rule-2);
  padding: 1px 2px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.day--holiday .day__mon { display: none; }
.day--today { background: var(--enamel-hull); }
.day--today .day__dow, .day--today .day__mon { color: rgba(246,242,232,.78); }
.day--today .day__n { color: var(--on-hull); }

/* Room group heading — a painted band across the board.
   It appears twice, once in each column, and the two copies must agree to the
   pixel or every lane below them drifts out of register. Hence a fixed box. */
.grouprow {
  display: flex; align-items: center; gap: var(--s-3);
  height: 18px; box-sizing: content-box;
  padding: 0 var(--s-5);
  margin-bottom: var(--lane-gap);
  background: var(--surface-2);
  border-block: 1px solid var(--rule-2);
  font-family: var(--face-sign); font-size: var(--t-code); font-weight: 600;
  letter-spacing: var(--track-code); text-transform: uppercase; color: var(--ink-2);
  white-space: nowrap; overflow: hidden;
}
.grouprow span { color: var(--ink-3); font-weight: 500; letter-spacing: 0; text-transform: none; }
.lanes > .grouprow { padding: 0; }

/* Room plate column */
.rooms { position: sticky; left: 0; z-index: 5; background: var(--ground); border-right: 2px solid var(--rule-2); }

.roomplate {
  display: flex; align-items: center; gap: var(--s-3);
  height: var(--lane-h); margin-bottom: var(--lane-gap);
  padding: 0 var(--s-4);
  background: var(--enamel-hull); color: var(--on-hull);
  border-radius: var(--r-plate);
  box-shadow: var(--lift-1);
}
.roomplate__id {
  font-family: var(--face-sign); font-weight: 700; font-size: var(--t-base);
  letter-spacing: .02em; font-variant-numeric: tabular-nums;
  min-width: 34px;
}
.roomplate__t { font-size: var(--t-code); color: rgba(246,242,232,.72); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.roomplate__t i { font-style: normal; }
/* Which word a room gets is a question about the width of its plate, so width
   alone decides it. Keying this to the tight state made label length depend on
   how TALL the window was: at 1440 wide, a 900px-tall window showed "Fan" in a
   134px plate that was half empty, while a 1400px-tall one showed the full
   "Standard Fan" in exactly the same space. */
.roomplate__t .t-short { display: none; }
@media (max-width: 1180px) {
  .roomplate__t .t-long { display: none; }
  .roomplate__t .t-short { display: inline; }
}
.roomplate__rate { margin-left: auto; font-size: var(--t-code); color: var(--enamel-ticket); font-variant-numeric: tabular-nums; }

/* Lanes */
.lanewrap { position: relative; }
.lanes { position: relative; }
.lane {
  position: relative;
  height: var(--lane-h); margin-bottom: var(--lane-gap);
}
.lane__bed {
  position: absolute; inset: 0;
  background-image: repeating-linear-gradient(
    to right,
    transparent 0 calc(var(--day-w) - 1px),
    var(--rule) calc(var(--day-w) - 1px) var(--day-w));
}
.lane:nth-child(even) .lane__bed { background-color: rgba(11,60,73,.028); }
:root[data-theme="dark"] .lane:nth-child(even) .lane__bed { background-color: rgba(255,255,255,.022); }

/* Today — a marked column, not just a rule.
   In the default view today IS the first column, so a rule on its left edge
   reads as the board's own frame. The wash is what makes it a marker. */
/* The wash is ink, not pigment. A rust tint here read as a fifth colour on a
   board whose one rule is that colour means room state, and it sat close
   enough to --tint-rust to be mistaken for ซ่อมบำรุง. The rule keeps the
   colour; the field keeps out of it. */
.todaycol {
  position: absolute; top: 0; bottom: 0;
  background: rgba(19, 26, 29, .055);
  z-index: 0; pointer-events: none;
}
:root[data-theme="dark"] .todaycol { background: rgba(237, 230, 214, .06); }

.todayline {
  position: absolute; top: 0; bottom: 0; width: 2px;
  background: var(--enamel-rust);
  z-index: 4; pointer-events: none;
}
.todayline::before {
  content: ''; position: absolute; top: 0; left: -4px;
  border-left: 5px solid transparent; border-right: 5px solid transparent;
  border-top: 6px solid var(--enamel-rust);
}

/* ── The booking bar: a ticket slid into its lane ──────────────────────── */
.bar {
  position: absolute;
  top: var(--bar-inset); bottom: var(--bar-inset);
  display: flex; align-items: center; gap: 0;
  border-radius: var(--r-plate);
  box-shadow: var(--lift-1);
  overflow: hidden;
  cursor: grab;
  user-select: none;
  touch-action: none;
  z-index: 2;
  transition: box-shadow var(--dur-snap) var(--ease-out),
              transform var(--dur-snap) var(--ease-detent);
}
.bar:hover { box-shadow: var(--lift-2); z-index: 3; }
.bar:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; z-index: 8; }

.bar--hull   { background: var(--enamel-hull);   color: var(--on-hull); }
.bar--ticket { background: var(--enamel-ticket); color: var(--on-ticket); }
.bar--sea    { background: var(--enamel-sea);    color: var(--on-sea); }

/* Rooms that cannot be sold are hatched, not filled: they share a family. */
.bar--rust-hatch, .bar--ink-hatch {
  background-color: var(--hatch-bed);
  cursor: default;
  border: 1px solid var(--rule-2);
}
.bar--rust-hatch { background-image: var(--hatch-rust); }
.bar--ink-hatch  { background-image: var(--hatch-ink); }
.bar--rust-hatch .bar__name, .bar--ink-hatch .bar__name {
  background: var(--hatch-bed); padding: 1px 6px; border-radius: 2px; color: var(--ink);
  margin-left: 4px;
}

/* Channel 2 — payment, read at the left end as a ticket stub. */
.bar__stub {
  flex: none; width: 11px; align-self: stretch;
  border-right: 1px dashed rgba(0,0,0,.30);
  background-image: radial-gradient(circle at 50% 50%, rgba(0,0,0,.28) 1px, transparent 1.2px);
  background-size: 100% 6px;
}
.bar--ticket .bar__stub { border-right-color: rgba(0,0,0,.38); }
.bar--hull .bar__stub, .bar--sea .bar__stub {
  border-right-color: rgba(246,242,232,.45);
  background-image: radial-gradient(circle at 50% 50%, rgba(246,242,232,.42) 1px, transparent 1.2px);
}
.bar__stub--deposit { background-color: rgba(255,255,255,.22); }
.bar--ticket .bar__stub--deposit { background-color: rgba(0,0,0,.14); }
.bar__stub--paid { background-color: rgba(255,255,255,.42); }
.bar--ticket .bar__stub--paid { background-color: rgba(0,0,0,.26); }
/* unpaid keeps the hollow stub — nothing filled it in yet */

.bar__name {
  flex: 1; min-width: 0;
  padding: 0 var(--s-3);
  font-size: var(--t-small); font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bar__pax { font-size: var(--t-code); opacity: .72; margin-left: 4px; }

/* Channel 4 — booking source, an agent code stamped at the right end. */
.bar__src {
  flex: none; margin-right: 3px;
  font-family: var(--face-sign); font-size: 9.5px; font-weight: 600; letter-spacing: .06em;
  padding: 1px 3px; border-radius: 1px;
  background: rgba(0,0,0,.22); color: inherit;
}
.bar--ticket .bar__src { background: rgba(0,0,0,.14); }
.bar__src--direct { background: var(--enamel-ticket); color: var(--on-ticket); }
.bar--ticket .bar__src--direct { background: rgba(19,26,29,.86); color: var(--enamel-ticket); }

/* Channel 3 — ตม.30, a rubber stamp in the corner. */
.bar__stamp { flex: none; width: 15px; height: 15px; margin-right: 3px; }
.bar__stamp circle { fill: none; }
.stamp--pending circle { stroke: currentColor; stroke-opacity: .62; stroke-dasharray: 2.4 2.2; stroke-width: 1.5; }
.stamp--sent circle { stroke: currentColor; stroke-opacity: .55; stroke-width: 1.5; }
.stamp--sent path { stroke: currentColor; stroke-opacity: .8; }
.stamp--overdue circle { stroke: var(--enamel-signal); stroke-width: 2.1; }
.stamp--overdue path { stroke: var(--enamel-signal); }
.bar--ticket .stamp--overdue circle,
.bar--ticket .stamp--overdue path { stroke: #8E1F00; }

/* Bars that started before the window: torn perforated edge, not a lie. */
.bar.is-cont-l { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.bar.is-cont-l .bar__stub { border-left: 2px dotted rgba(0,0,0,.35); width: 9px; }
.bar.is-cont-r { border-top-right-radius: 0; border-bottom-right-radius: 0;
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 10px), rgba(0,0,0,.35));
          mask-image: linear-gradient(to right, #000 calc(100% - 10px), rgba(0,0,0,.35)); }

/* Width classes — a one-night bar cannot carry four channels. */
.bar.is-xs .bar__name, .bar.is-xs .bar__src { display: none; }
.bar.is-sm .bar__src { display: none; }
.bar.is-xs .bar__stub { width: 7px; }

/* Drag: the ticket lifts off the board, then falls into its detent. */
.bar.is-dragging { cursor: grabbing; box-shadow: var(--lift-drag); z-index: 20; opacity: .96; transition: none; }
.bar.is-resizing { cursor: ew-resize; box-shadow: var(--lift-drag); z-index: 20; transition: none; }
.bar.just-landed { animation: detent var(--dur-snap) var(--ease-detent); }
@keyframes detent {
  0%   { transform: translateY(-2px) scaleY(1.06); }
  100% { transform: none; }
}

.bar__grip {
  position: absolute; top: 0; bottom: 0; width: 9px; right: 0;
  cursor: ew-resize; z-index: 3;
}
.bar__grip::after {
  content: ''; position: absolute; top: 50%; right: 3px; translate: 0 -50%;
  width: 2px; height: 12px; border-radius: 1px;
  background: currentColor; opacity: 0;
  transition: opacity 120ms linear;
}
.bar:hover .bar__grip::after { opacity: .5; }

/* A short lane steps the whole board down together, rather than letting each
   label clip on its own. */
.rack.is-tight .bar__name { font-size: var(--t-micro); }
.rack.is-tight .roomplate__id { font-size: var(--t-small); min-width: 30px; }
/* 11px is the floor for Thai on a plate: below it the upper vowel and the tone
   mark merge at counter distance on an old panel in daylight. Where the lane
   cannot hold the word at 11px, the word gets shorter — it never gets smaller. */
.rack.is-tight .roomplate__t,
.rack.is-tight .roomplate__rate { font-size: 11px; }
.rack.is-tight .bar__stamp { width: 13px; height: 13px; }
.rack.is-micro .bar__name { font-size: 10.5px; }
.rack.is-micro .bar__pax { display: none; }
.rack.no-bands .grouprow { display: none; }
/* The month already sits in the toolbar's range label, so the scale gives it
   up first when the board needs the height for a room. */
.rack.is-tight .day { padding-top: var(--s-2); }
.rack.is-tight .day__mon { display: none; }
.rack.is-tight .day__flag { display: none; }

/* Turnover: the morning a room has to be stripped and cleaned.
   In the grid it is a hairline under today's cell — anything with height reads
   as a second booking bar. The signal that matters lives on the room plate,
   which stays put while the board scrolls sideways. */
.turn {
  position: absolute; bottom: 0; height: 3px;
  background: var(--enamel-sea);
  z-index: 3; pointer-events: none;
}
.roomplate--turn { position: relative; }
.roomplate--turn::after {
  content: ''; position: absolute; top: 3px; bottom: 3px; right: 4px; width: 4px;
  border-radius: 1px; background: var(--enamel-sea);
}
.rack.is-micro .roomplate--turn::after { top: 2px; bottom: 2px; width: 3px; }

/* Ghost drawn while dragging across empty nights */
.ghost {
  position: absolute; top: var(--bar-inset); bottom: var(--bar-inset);
  border: 2px dashed var(--enamel-rust);
  background: rgba(228,87,46,.12);
  border-radius: var(--r-plate);
  z-index: 10; pointer-events: none;
  display: flex; align-items: center; padding-left: var(--s-4);
  font-family: var(--face-sign); font-size: var(--t-code); font-weight: 600;
  color: var(--enamel-rust); letter-spacing: var(--track-code);
}
.lane.is-target .lane__bed { background-color: rgba(228,87,46,.09); }

/* ── Drawer ────────────────────────────────────────────────────────────── */
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(440px, 100vw);
  background: var(--surface);
  border-left: 2px solid var(--enamel-hull);
  box-shadow: var(--lift-3);
  z-index: 60;
  display: flex; flex-direction: column;
  translate: 100% 0;
  transition: translate var(--dur-panel) var(--ease-out);
  overflow: hidden;
}
.drawer[data-open] { translate: 0 0; }
.scrim {
  position: fixed; inset: 0; background: rgba(11,26,31,.42);
  z-index: 55; opacity: 0; pointer-events: none;
  transition: opacity var(--dur-panel) linear;
}
.scrim[data-open] { opacity: 1; pointer-events: auto; }

.drawer__head {
  display: flex; align-items: flex-start; gap: var(--s-4);
  padding: var(--s-5) var(--s-6);
  background: var(--enamel-hull); color: var(--on-hull);
}
.drawer__room {
  font-family: var(--face-sign); font-weight: 700; font-size: var(--t-2xl); line-height: 1;
  background: var(--enamel-ticket); color: var(--on-ticket);
  padding: var(--s-3) var(--s-4); border-radius: var(--r-plate);
  font-variant-numeric: tabular-nums;
}
.drawer__id { font-size: var(--t-code); color: rgba(246,242,232,.7); letter-spacing: var(--track-code); }
.drawer__guest { font-family: var(--face-sign); font-weight: 600; font-size: var(--t-xl); line-height: var(--lh-tight); }
.drawer__meta { font-size: var(--t-small); color: rgba(246,242,232,.78); }
.drawer__close { margin-left: auto; }
.drawer__body { flex: 1; overflow: auto; }

.drawer__tabs { display: flex; background: var(--surface-2); border-bottom: 1px solid var(--rule-2); }
.drawer__tabs button {
  flex: 1; height: 38px; background: transparent; border: 0; border-right: 1px solid var(--rule);
  font-family: var(--face-sign); font-size: var(--t-small); font-weight: 500; color: var(--ink-2);
}
.drawer__tabs button:last-child { border-right: 0; }
.drawer__tabs button[aria-selected="true"] { background: var(--surface); color: var(--ink); font-weight: 600; box-shadow: inset 0 -3px 0 var(--enamel-rust); }

.drawer__foot {
  display: flex; gap: var(--s-4); padding: var(--s-5) var(--s-6);
  border-top: 1px solid var(--rule-2); background: var(--surface-2);
}
.drawer__foot .btn { flex: 1; }

/* ── Shared content blocks ─────────────────────────────────────────────── */
.pane { padding: var(--s-6); }
.pane > * + * { margin-top: var(--s-6); }

.block { border: 1px solid var(--rule); border-radius: var(--r-panel); background: var(--surface); overflow: hidden; }
.block__head {
  display: flex; align-items: center; gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
  background: var(--surface-2); border-bottom: 1px solid var(--rule);
}
.block__head h3 { font-size: var(--t-small); letter-spacing: var(--track-code); text-transform: uppercase; color: var(--ink-2); }
.block__head .btn { margin-left: auto; }
.block__body { padding: var(--s-5); }
.block__body > * + * { margin-top: var(--s-4); }

.rows { display: grid; gap: 0; }
.row {
  display: grid; grid-template-columns: 108px 1fr; gap: var(--s-5);
  padding: var(--s-3) 0; border-bottom: 1px solid var(--rule);
  font-size: var(--t-small);
}
.row:last-child { border-bottom: 0; }
.row dt { color: var(--ink-2); }
.row dd { margin: 0; font-weight: 500; }

.tag {
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: 2px 7px; border-radius: 2px;
  font-family: var(--face-sign); font-size: var(--t-code); font-weight: 600;
  letter-spacing: .04em;
}
.tag--hull   { background: var(--tint-hull);   color: var(--ink); }
.tag--ticket { background: var(--tint-ticket); color: var(--ink); }
.tag--sea    { background: var(--tint-sea);    color: var(--ink); }
.tag--rust   { background: var(--tint-rust);   color: var(--ink); }
.tag--signal { background: var(--enamel-signal); color: #FFF6F2; }
.tag--solid  { background: var(--enamel-hull); color: var(--on-hull); }

/* Money table */
.money { width: 100%; border-collapse: collapse; font-size: var(--t-small); }
.money th {
  text-align: left; font-family: var(--face-sign); font-size: var(--t-code);
  letter-spacing: var(--track-code); text-transform: uppercase; color: var(--ink-3);
  padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--rule-2); font-weight: 600;
}
.money td { padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--rule); vertical-align: top; }
.money .n { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.money tfoot td { border-bottom: 0; border-top: 2px solid var(--rule-2); font-weight: 600; padding-top: var(--s-4); }
.money tfoot .big { font-family: var(--face-sign); font-size: var(--t-lg); }
.money tr.due td { color: var(--enamel-signal); }

/* ── Today ─────────────────────────────────────────────────────────────────
   One board, not a grid of cards. The first build laid Today out as auto-fit
   cards full of tinted pills — precisely the arrangement the thesis refuses —
   and stranded a third of the viewport in empty ground. This is the same
   object the rack is: ruled rows under painted bands, running the full width,
   reusing the rack's own stub / stamp / code grammar instead of inventing a
   second vocabulary for the same four facts.                                */
.today { padding: var(--s-6); }
.today > * + * { margin-top: var(--s-7); }

.board {
  border: 1px solid var(--rule-2); border-radius: var(--r-panel);
  background: var(--surface); overflow: hidden; box-shadow: var(--lift-1);
}

.board__band {
  display: flex; align-items: center; gap: var(--s-4);
  padding: var(--s-4) var(--s-6);
  background: var(--enamel-hull); color: var(--on-hull);
}
.board__band h3 {
  font-family: var(--face-sign); font-weight: 600; font-size: var(--t-xl);
  letter-spacing: var(--track-sign);
}
.board__band--alert { background: var(--enamel-signal); }
.board__band--alert h3 { color: #FFF6F2; }
.board__band--clear { background: var(--enamel-sea); }
.board__n {
  margin-left: auto;
  font-family: var(--face-sign); font-weight: 700; font-size: var(--t-xl);
  font-variant-numeric: tabular-nums;
}
.board__band .btn { margin-left: var(--s-4); }

.brow {
  display: flex; align-items: center; gap: var(--s-5);
  padding: var(--s-4) var(--s-6);
  border-bottom: 1px solid var(--rule);
  width: 100%; text-align: left;
  background: transparent; border-left: 0; border-right: 0; border-top: 0;
  transition: background 110ms linear;
}
.brow:last-child { border-bottom: 0; }
button.brow:hover { background: var(--surface-2); }

.brow__plate {
  flex: none; min-width: 48px; text-align: center;
  font-family: var(--face-sign); font-weight: 700; font-size: var(--t-lg);
  font-variant-numeric: tabular-nums;
  background: var(--enamel-hull); color: var(--on-hull);
  padding: var(--s-2) var(--s-3); border-radius: var(--r-plate);
}
.brow__name {
  flex: 1 1 auto; min-width: 0;
  font-weight: 500; font-size: var(--t-form);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.brow__meta {
  flex: 0 1 auto; min-width: 0; color: var(--ink-2); font-size: var(--t-small);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.brow__end { flex: none; margin-left: auto; display: flex; align-items: center; gap: var(--s-5); }
.brow__amt {
  font-family: var(--face-sign); font-weight: 600; font-size: var(--t-form);
  font-variant-numeric: tabular-nums; min-width: 78px; text-align: right;
}
.brow__amt--due { color: var(--enamel-signal); }
.brow__nat { font-family: var(--face-sign); font-size: var(--t-code); letter-spacing: var(--track-code); color: var(--ink-3); }

/* The rack's four channels, reused verbatim so Today teaches the same board. */
.mark { display: inline-flex; align-items: center; gap: var(--s-3); font-size: var(--t-code); color: var(--ink-2); white-space: nowrap; }
.mark__stub {
  width: 10px; height: 17px; flex: none;
  border: 1px solid var(--ink-3); border-radius: 1px;
  background-image: radial-gradient(circle at 50% 50%, rgba(0,0,0,.22) 1px, transparent 1.2px);
  background-size: 100% 5px;
}
:root[data-theme="dark"] .mark__stub { background-image: radial-gradient(circle at 50% 50%, rgba(255,255,255,.28) 1px, transparent 1.2px); }
.mark__stub--deposit { background-color: color-mix(in srgb, var(--enamel-hull) 45%, transparent); }
.mark__stub--paid { background-color: var(--enamel-hull); border-color: var(--enamel-hull); }
.mark__stamp { width: 17px; height: 17px; flex: none; }
.mark__stamp circle { fill: none; stroke-width: 1.5; }
.mark--pending .mark__stamp circle { stroke: var(--ink-3); stroke-dasharray: 2.4 2.2; }
.mark--sent .mark__stamp circle, .mark--sent .mark__stamp path { stroke: var(--enamel-sea); }
.mark--overdue { color: var(--enamel-signal); font-weight: 600; }
.mark--overdue .mark__stamp circle, .mark--overdue .mark__stamp path { stroke: var(--enamel-signal); stroke-width: 2; }
.mark__code {
  font-family: var(--face-sign); font-size: 9.5px; font-weight: 600; letter-spacing: .06em;
  padding: 2px 4px; border-radius: 1px;
  background: var(--surface-2); color: var(--ink-2); border: 1px solid var(--rule);
}
.mark__code--direct { background: var(--enamel-ticket); color: var(--on-ticket); border-color: transparent; }

@media (max-width: 900px) {
  .brow { flex-wrap: wrap; gap: var(--s-3) var(--s-4); }
  .brow__meta { flex-basis: 100%; order: 5; }
  .brow__end { margin-left: 0; flex-wrap: wrap; gap: var(--s-4); }
  .brow__amt { min-width: 0; }
}

.list { display: flex; flex-direction: column; }
.listrow {
  display: flex; align-items: center; gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--rule);
  text-align: left; background: transparent; border-top: 0; border-left: 0; border-right: 0;
  width: 100%; transition: background 110ms linear;
}
.listrow:last-child { border-bottom: 0; }
.listrow:hover { background: var(--surface-2); }
.listrow__room {
  font-family: var(--face-sign); font-weight: 700; font-size: var(--t-base);
  background: var(--enamel-hull); color: var(--on-hull);
  padding: 3px var(--s-3); border-radius: var(--r-plate); min-width: 42px; text-align: center;
  font-variant-numeric: tabular-nums; flex: none;
}
.listrow__main { flex: 1; min-width: 0; }
.listrow__name, .listrow__sub { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.listrow__name { font-weight: 500; }
.listrow__sub { font-size: var(--t-code); color: var(--ink-2); }
.listrow__end { display: flex; align-items: center; gap: var(--s-3); flex: none; }
.listrow__time { font-family: var(--face-sign); font-weight: 600; font-variant-numeric: tabular-nums; color: var(--ink-2); }

.empty {
  display: flex; flex-direction: column; align-items: center; gap: var(--s-4);
  padding: var(--s-10) var(--s-6); text-align: center; color: var(--ink-2);
}
.empty svg { color: var(--ink-3); opacity: .55; }
.empty b { font-family: var(--face-sign); font-size: var(--t-lg); color: var(--ink); font-weight: 600; }
.empty p { font-size: var(--t-small); max-width: 34ch; }

/* ── Check-in flow ─────────────────────────────────────────────────────── */
.checkin { max-width: 1080px; margin: 0 auto; padding: var(--s-8) var(--s-6) var(--s-12); }
.checkin__head { display: flex; align-items: flex-end; gap: var(--s-6); margin-bottom: var(--s-7); flex-wrap: wrap; }
.checkin__head h2 { font-size: var(--t-2xl); }
.checkin__head p { color: var(--ink-2); font-size: var(--t-small); }

/* Stepper drawn as a route line: piers along a crossing. */
.steps { display: flex; align-items: center; gap: 0; margin-bottom: var(--s-8); }
.step { display: flex; align-items: center; gap: var(--s-3); }
.step__dot {
  width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center; flex: none;
  background: var(--surface); border: 2px solid var(--rule-2); color: var(--ink-3);
  font-family: var(--face-sign); font-weight: 700; font-size: var(--t-small);
  font-variant-numeric: tabular-nums;
}
.step__label { font-family: var(--face-sign); font-size: var(--t-small); color: var(--ink-3); white-space: nowrap; }
.step__link { width: 44px; height: 2px; background: var(--rule-2); margin: 0 var(--s-4); }
.step__dot .i { width: 13px; height: 13px; stroke-width: 2.4; }
.step.is-done .step__dot { background: var(--enamel-sea); border-color: var(--enamel-sea); color: var(--on-sea); }
.step.is-done .step__label { color: var(--ink-2); }
.step.is-now .step__dot { background: var(--enamel-hull); border-color: var(--enamel-hull); color: var(--on-hull); }
.step.is-now .step__label { color: var(--ink); font-weight: 600; }

.checkin__grid { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: var(--s-7); align-items: start; }

/* Passport capture bay */
.scanbay {
  position: relative; aspect-ratio: 1.42; border-radius: var(--r-panel);
  background: var(--surface-2); border: 2px dashed var(--rule-2);
  display: grid; place-items: center; overflow: hidden;
  transition: border-color 200ms linear, background 200ms linear;
}
.scanbay.is-armed { border-style: solid; border-color: var(--enamel-hull); background: var(--enamel-hull); }
.scanbay__prompt { display: flex; flex-direction: column; align-items: center; gap: var(--s-4); color: var(--ink-2); text-align: center; padding: var(--s-6); }
.scanbay__prompt b { font-family: var(--face-sign); font-size: var(--t-lg); color: var(--ink); }
.scanbay__prompt p { font-size: var(--t-small); max-width: 32ch; }

/* The synthetic passport page. Deliberately drawn, deliberately watermarked. */
.doc {
  position: absolute; inset: 0; padding: 5%;
  display: grid; grid-template-rows: auto 1fr auto; gap: 3%;
  background: #E9E3D3; color: #1B2426;
  opacity: 0; transition: opacity 260ms linear;
}
.scanbay.is-armed .doc { opacity: 1; }
.doc__top { display: flex; justify-content: space-between; align-items: flex-start; font-family: var(--face-sign); }
.doc__type { font-size: var(--t-code); letter-spacing: .14em; text-transform: uppercase; color: #5B6A6E; }
.doc__country { font-family: var(--face-sign); font-weight: 700; font-size: var(--t-lg); letter-spacing: .1em; }
.doc__mid { display: grid; grid-template-columns: 62px 1fr; gap: 4%; }
.doc__photo {
  background: #C9C3B0; border: 1px solid #A79F8B;
  display: grid; place-items: center; padding: 14% 12%;
}
.doc__photo svg { width: 100%; height: auto; opacity: .8; }
.doc__fields { display: grid; grid-template-columns: 1fr 1fr; gap: 2% 6%; align-content: start; font-size: 10.5px; }
.doc__fields dt { color: #6C7A7E; font-size: 8.5px; letter-spacing: .08em; text-transform: uppercase; }
.doc__fields dd { margin: 0 0 4px; font-family: var(--face-sign); font-weight: 600; }
.doc__mrz {
  font-family: ui-monospace, 'SFMono-Regular', Menlo, monospace;
  font-size: 10.5px; letter-spacing: .06em; line-height: 1.5;
  background: #F3EEE0; border-top: 1px solid #C3BBA6; padding: 2% 3%;
  white-space: nowrap; overflow: hidden; color: #1B2426;
}
.doc__mrz span { display: block; }
.doc__wm {
  position: absolute; inset: auto 5% 5% auto;
  font-family: var(--face-sign); font-size: var(--t-code); font-weight: 600;
  letter-spacing: var(--track-code); text-transform: uppercase;
  color: #B03A17; border: 1.5px solid #B03A17; padding: 2px 6px;
  rotate: -6deg; opacity: .85;
}

/* Scanning sweep — one authored moment, not a decoration loop. */
.sweep {
  position: absolute; left: 0; right: 0; height: 34%;
  background: linear-gradient(to bottom, transparent, rgba(242,193,78,.42), transparent);
  border-top: 1px solid rgba(242,193,78,.9);
  border-bottom: 1px solid rgba(242,193,78,.9);
  opacity: 0;
}
.scanbay.is-scanning .sweep { animation: sweep 900ms var(--ease-out) 2; opacity: 1; }
@keyframes sweep { from { top: -34%; } to { top: 100%; } }
@media (prefers-reduced-motion: reduce) { .scanbay.is-scanning .sweep { animation: none; opacity: .35; top: 33%; } }

/* Field auto-fill: each lands in sequence, like keys being punched. */
.field { display: grid; gap: var(--s-2); }
.field > label { font-size: var(--t-code); letter-spacing: var(--track-code); text-transform: uppercase; color: var(--ink-2); font-weight: 600; }
.field input, .field select, .field textarea {
  height: 40px; padding: 0 var(--s-4);
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--rule-2); border-radius: var(--r-field);
  outline: none; font-size: var(--t-form); width: 100%;
}
.field textarea { height: auto; padding: var(--s-3) var(--s-4); min-height: 74px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--rule-ink); box-shadow: 0 0 0 3px rgba(11,60,73,.14); }
.field input::placeholder { color: var(--ink-3); }
.field input[readonly] { background: var(--surface-2); }
.field.is-filled input { border-color: var(--enamel-sea); background: var(--tint-sea); }
.autofill {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-4); border-radius: var(--r-field);
  background: var(--tint-sea); color: var(--ink);
  font-size: var(--t-small);
}
.autofill svg { color: var(--enamel-sea); }
.fieldgrid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-5); }
.fieldgrid--3 { grid-template-columns: repeat(3, 1fr); }
.fieldgrid .span2 { grid-column: span 2; }

/* ตม.30 result — the stamp landing is the demo's punchline. */
.tm30 { border: 2px solid var(--rule-2); border-radius: var(--r-panel); background: var(--surface); overflow: hidden; }
.tm30.is-sent { border-color: var(--enamel-sea); }
.tm30__head { display: flex; align-items: center; gap: var(--s-4); padding: var(--s-5); background: var(--surface-2); border-bottom: 1px solid var(--rule); }
.tm30__head h3 { font-size: var(--t-lg); }
.tm30__body { padding: var(--s-5); display: grid; gap: var(--s-5); }
.tm30__stamp {
  margin-left: auto; width: 74px; height: 74px; flex: none;
  display: grid; place-items: center; position: relative;
  opacity: 0; scale: 1.6; rotate: -14deg;
}
.tm30.is-sent .tm30__stamp { animation: press 340ms var(--ease-detent) forwards; }
@keyframes press {
  0%   { opacity: 0; scale: 1.6; rotate: -14deg; }
  60%  { opacity: 1; scale: .94; rotate: -7deg; }
  100% { opacity: 1; scale: 1;   rotate: -7deg; }
}
@media (prefers-reduced-motion: reduce) {
  .tm30.is-sent .tm30__stamp { animation: none; opacity: 1; scale: 1; rotate: -7deg; }
}
.tm30__stamp svg { width: 100%; height: 100%; color: var(--enamel-sea); }

.proof { font-family: ui-monospace, 'SFMono-Regular', Menlo, monospace; font-size: var(--t-micro); line-height: 1.7; color: var(--ink-2); }
.proof b { color: var(--ink); font-weight: 600; }

/* Sync state — the connection drops on this coast, so the board says so. */
.sync { display: inline-flex; align-items: center; gap: var(--s-3); font-size: var(--t-code); color: var(--ink-2); }
/* On the hull masthead the ink colours invert, so this reads in both themes. */
.masthead .sync { color: rgba(246, 242, 232, .82); }
.sync__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--enamel-sea); flex: none; }
.sync[data-state="syncing"] .sync__dot { background: var(--enamel-ticket); animation: pulse 1.1s ease-in-out infinite; }
.sync[data-state="offline"] .sync__dot { background: var(--enamel-signal); }
@keyframes pulse { 50% { opacity: .3; } }
@media (prefers-reduced-motion: reduce) { .sync__dot { animation: none !important; } }

/* Toast — a slip of paper landing on the counter */
.toasts { position: fixed; left: 50%; bottom: var(--s-7); translate: -50% 0; z-index: 90; display: grid; gap: var(--s-3); justify-items: center; pointer-events: none; }
.toast {
  display: flex; align-items: center; gap: var(--s-4);
  padding: var(--s-4) var(--s-6);
  background: var(--enamel-hull); color: var(--on-hull);
  border-radius: var(--r-plate); box-shadow: var(--lift-3);
  font-size: var(--t-small);
  animation: slipin 260ms var(--ease-out);
}
.toast--undo { pointer-events: auto; }
.toast button { background: transparent; border: 0; color: var(--enamel-ticket); font-family: var(--face-sign); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
@keyframes slipin { from { opacity: 0; translate: 0 10px; } }

/* ── Responsive ────────────────────────────────────────────────────────────
   Three real devices: counter tablet in landscape, cheap laptop, owner's
   phone. The phone does not get a squeezed rack — it gets a different view.
*/
@media (hover: none) {
  /* Touch: nothing may depend on hover, and grips are always visible. */
  .bar__grip::after { opacity: .5; }
  .btn, .mbtn, .seg button, .route { min-height: 40px; }
  .listrow { min-height: var(--tap); }
}

@media (max-width: 1180px) {
  /* The short labels are in play at these widths, so the column can give the
     space back to the nights. */
  :root { --room-col: 106px; }
  .legend { display: none; }
}

/* A short viewport spends its height on rooms, not on chrome. Every pixel the
   masthead, tabs, strip and toolbar give back is another room on the board.
   It is not enough on a 768px panel — 28 lanes need about 460px of clear space
   and a 768px screen leaves roughly 400 — so that one scrolls, with the room
   column pinned. Below ~17px Thai loses its tone marks, and a rack you cannot
   read is worse than a rack you have to scroll. */
@media (max-height: 820px) and (min-width: 761px) {
  /* Tightening the lane gutter to a hairline buys 56px across 28 lanes — the
     difference between all 28 rooms fitting an 1180×820 iPad in landscape and
     three of them falling off it. The lane bed keeps its own rule, so the rows
     stay separated without the gutter. */
  :root { --lane-gap: 1px; }
  .masthead { height: 42px; }
  .route { height: 34px; }
  .stat { padding: var(--s-3) var(--s-5); }
  .stat__n { font-size: var(--t-lg); }
  .rackbar { padding: var(--s-3) var(--s-5); }
  .btn, .seg button { height: 30px; }
  .scale__corner { padding: var(--s-2) var(--s-4); }
}

@media (max-width: 900px) {
  .checkin__grid { grid-template-columns: 1fr; }
  .fieldgrid--3 { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 760px) {
  .masthead { height: auto; padding: var(--s-3) var(--s-4); flex-wrap: wrap; gap: var(--s-3); }
  .masthead__sep, .masthead__prop span, .who__role { display: none; }
  .routes { overflow-x: auto; scrollbar-width: none; }
  .routes::-webkit-scrollbar { display: none; }
  .routes__end { display: none; }
  .route { padding: 0 var(--s-5); }
  .rackbar { gap: var(--s-4); }
  .datenav__range { min-width: 0; font-size: var(--t-base); }
  .rackbar__end { width: 100%; }
  .fieldgrid, .fieldgrid--3 { grid-template-columns: 1fr; }
  .checkin { padding: var(--s-6) var(--s-4) var(--s-10); }
  .today { padding: var(--s-4); gap: var(--s-4); }
  .drawer { width: 100vw; border-left: 0; border-top: 2px solid var(--enamel-hull); }
  .stat { padding: var(--s-3) var(--s-5); }
}

/* The rack collapses to a stacked day board on a phone: same data, a form
   that a thumb can actually use. */
.rack__phone { display: none; }
@media (max-width: 700px) {
  .rack__grid { display: none; }
  .rack__phone { display: block; padding: var(--s-4); }
  .rack__phone > * + * { margin-top: var(--s-5); }
  .legend { display: none; }
}

@media print {
  .masthead, .routes, .rackbar, .drawer, .scrim, .toasts { display: none !important; }
  body { background: #fff; }
}
