/* Front-office board — the Cards view.
 *
 * Ported from Design/Front-office/HotelOS Arrivals - Final.html, the `framed`
 * card style only (`.hc`, `.hc__foot`, `.pay*`). The prototype's OTHER card
 * styles (boarding-pass `renderBP`, status-panel `renderSP`), its Tweaks panel
 * and its `data-cardstyle` switcher are designer scaffolding, not product —
 * they are deliberately NOT ported. We ship one card.
 *
 * What was rejected from the prototype and why:
 *   * its four competing page widths (1280/1300/1060/1200) and zero media
 *     queries — the grid lives in `.hos-shell-content` (already --page-wide) and
 *     gutters come from --gutter. No hardcoded width below.
 *   * its 24 raw font sizes incl. half-pixels (8.5/10.5/12.5/13.5/14.5) — every
 *     size here is a var(--text-*) step (hallmark OffScaleType flags any bare
 *     px font-size). The snap is recorded per-rule below.
 *   * its raw hex — every colour here is a var(--token).
 *
 * What was KEPT (the portable mechanisms, retokenised):
 *   * the --tone / --tone-bg / --tone-line triad — one custom-property set per
 *     card drives chip + spine + node colour, so a state change is one var.
 *   * the --spine accent bar (`.hc__bar`).
 *
 * Reading order is the design critique's: status/blocker → identity → stay
 * essentials → one number (Balance) → action.
 */

/* ── grid ────────────────────────────────────────────────────────────
   Prototype `.grid` was `max-width:1280px;margin:0 auto;padding:24px 32px 70px`
   — all four dropped: the page column is `.hos-shell-content`'s job. minmax(300px)
   from the prototype is kept; gap is the shell's --gutter. */
.hos-board {
  display: grid;
  /* auto-FILL (not auto-fit): a card keeps ~one-track width regardless of how many
     are in the list. auto-fit collapses empty tracks so a lone/partial-row card
     absorbed the whole row via 1fr and ballooned to full width (#293). auto-fill
     keeps the empty tracks, so a single card stays card-sized with blank space to
     its right (the standard card-grid behaviour, reporter's expectation) while a
     FULL row still fills the width via 1fr. Gutter pinned to 24px (--space-6): the
     os-ds gem overrides --gutter to a responsive clamp(16px,4cqi,64px) that resolved
     to 64px here — DESIGN.md's intended gutter is --space-6. */
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--space-6);
  align-items: stretch;
}

/* The positioning context for the card's sibling overlays — task 2's action and
   the sign-slips checkbox. Both must sit OUTSIDE the card's <a> (a form or
   checkbox nested in a link is invalid and double-fires the drawer nav), so the
   wrapper, not the card, is what they anchor to. */
.hos-cardwrap {
  position: relative;
  display: flex;
}

.hos-cardwrap > .hos-card { flex: 1; }

.hos-cardwrap__pick {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 18px;
  height: 18px;
  accent-color: var(--accent);
  cursor: pointer;
  z-index: 1;
}

/* ── tone triad ──────────────────────────────────────────────────────
   Prototype `.t-ok/.t-crit/.t-warn/.t-slate/.t-brand` → the semantic families.
   `.t-gold` is NOT ported: DESIGN.md retired gold — VIP rides the accent.
   Set on any ancestor (card) or on the element itself (chip); everything below
   reads --tone/--tone-bg/--tone-line, so a state change is one class. */
.hos-tone--ok     { --tone: var(--success); --tone-bg: var(--success-bg); --tone-line: var(--success-border); }
.hos-tone--warn   { --tone: var(--warning); --tone-bg: var(--warning-bg); --tone-line: var(--warning-border); }
.hos-tone--crit   { --tone: var(--danger);  --tone-bg: var(--danger-bg);  --tone-line: var(--danger-border); }
.hos-tone--accent { --tone: var(--accent);  --tone-bg: var(--accent-soft); --tone-line: var(--accent-border); }

/* Prototype `.chip` — the blocker chip. Colour comes wholly from the triad, so
   the tone class is the only thing that varies (no inline colour). */
.hos-fo-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  padding: 0 10px;
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);       /* ← 12px */
  font-weight: var(--fw-semibold);
  line-height: 1;
  white-space: nowrap;
  color: var(--tone);
  background: var(--tone-bg);
  border: 1px solid var(--tone-line);
}

/* ── chassis ─────────────────────────────────────────────────────────
   Prototype `.hc` carried its own background/border/radius/shadow. Here the
   chassis IS `.os-card` (its ring is the border — DESIGN.md: don't add one);
   `.hos-card` only adds the flex column + the spine's positioning context. */
.hos-card {
  --spine: var(--hairline-strong);
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  text-decoration: none;
}
/* Better hover for the front-office board cards (over the generic
   .hos-card--interactive lift): the hairline ring turns accent + a stronger
   lift/shadow, so a selectable card reads clearly interactive in the brand
   colour. Scoped to .hos-card so the global card component is untouched. */
.hos-card.hos-card--interactive:hover {
  box-shadow: 0 0 0 1px var(--accent-border), var(--shadow-lg);
  transform: translateY(-4px);
}

/* Prototype `.hc__bar` — the stub variant (`.hc--spine-stub`, height:34px) the
   shipped framed cards use. The `.vfin` mockup drops the stub to `top:46px` so
   it sits beside the NAME row (the identity), not the eyebrow above it. */
.hos-card__spine {
  position: absolute;
  left: 0;
  top: 44px;
  width: 3px;
  height: 34px;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: var(--spine);
}

/* Source `.hc__in{padding:18px 22px}`. Section rhythm follows the `.vfin` card's
   explicit margins (eyerow 10 · chiprow 14 · dates/journey 20 in `hc--nolines`)
   rather than a uniform gap, so no `gap` here — each section sets its own top. */
.hos-card__in {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  padding: 14px 16px;   /* QA: tightened from 18px 22px — less header top/left, shorter card */
}

/* Sign-slips mode overlays a selection checkbox on the card's top-right
   (_cardgrid.html.erb — it must be a sibling of the card's <a>, not a child).
   Whatever row happens to be first — the blocker chiprow, or the head when a
   card has no blockers — reserves the strip so the checkbox never lands on the
   pax mark. Scoped to :first-child so only the row actually under it pays. */
.hos-cardwrap--slips .hos-card__in > :first-child { padding-right: 22px; }

/* ── chiprow — status + blockers, below identity ─────────────────────
   Prototype `.hc__chiprow` + `.chiprow`. The status chip leads; blocker
   chips (fo_blockers) follow it on the same row (tasks/041 order revised —
   the mockup reads identity-first, blockers alongside status). */
.hos-card__chiprow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  min-height: 24px;
  margin-top: 9px;   /* QA: tightened from 14px */
}

/* ── head: identity ──────────────────────────────────────────────────
   Prototype `.hc__head` / `.hc__idcol` / `.hc__namerow` / `.hc__name` (17px)
   / `.hc__ref` (11px) / `.hc__pax` (12.5px). */
/* Source `.vfin .hc__head{align-items:center}` — the name is middle-aligned
   against the source-mark tile, not top-aligned. */
.hos-card__head {
  display: flex;
  align-items: center;
  gap: 11px;
}

.hos-card__idcol {
  flex: 1;
  min-width: 0;
}

.hos-card__namerow {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px 10px;
}

.hos-card__name {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  min-width: 0;
  font-size: var(--text-md);       /* ← 17px */
  font-weight: var(--fw-bold);
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--ink);
}

.hos-card__name-txt {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── eyebrow — context line + pax ────────────────────────────────────
   Prototype `.hc__eyerow`: one mono UPPERCASE context line
   (ref · channel · booked) that truncates, with the pax mark (`.hc__nrr`)
   pinned right. Replaces the old ref-under-name + pax-in-namerow layout. */
.hos-card__eyerow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 7px;   /* QA: tightened from 10px */
}

.hos-card__ref {
  flex: 1;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: var(--text-xs);       /* ← 11px */
  /* mixed-case (was uppercase) — adopts the os-card ref treatment during the
     HotelOS DS promotion; keeps mono + muted, drops the shouty caps. */
  color: var(--muted-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Prototype `.hc__nrr` — the pax mark(s), pinned to the eyebrow's right. */
.hos-card__nrr {
  display: flex;
  align-items: center;
  gap: 10px;   /* source `.hc__nrr{gap:10px}` */
  flex: none;
}

/* ── dates: the arrive → nights → depart strip ───────────────────────
   Prototype `.e2` (framed dates, stacked ends + nights connector). Its
   `border-bottom` belongs to the `.hc--nolines` variant the shipped cards turn
   OFF, so it is not ported. */
.hos-card__dates {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 20px;   /* source `hc--nolines .hc__sec{margin-top:20px}` */
}

.hos-card__end {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.hos-card__end--r {
  align-items: flex-end;
  text-align: right;
}

.hos-card__endhead {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 2px;
}

/* Prototype `.e2ic` — 22px tinted tile. */
.hos-card__endic {
  width: 22px;
  height: 22px;
  border-radius: var(--radius-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

.hos-card__endic--arr { background: var(--accent-soft); color: var(--accent-strong); }
.hos-card__endic--dep { background: var(--surface-alt); color: var(--muted); }

/* Prototype `.e2k` — 9px eyebrow. DESIGN.md's eyebrow floor is 10px. */
.hos-card__endk {
  font-size: var(--text-2xs);      /* ← 9px */
  font-weight: var(--fw-bold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted-2);
}

.hos-card__endd {
  font-family: var(--font-mono);
  font-size: var(--text-sm);       /* ← 15px */
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.hos-card__endd--arr   { color: var(--accent-strong); }
.hos-card__endd--empty { color: var(--muted-2); }

.hos-card__endt {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);      /* ← 10.5px */
  color: var(--muted-2);
}

/* Prototype `.e2conn` / `.e2line` / `.e2circ` — the nights connector.
   The circle's raw #F1F5F9 → --surface-alt (the slate-100 the theme points it
   at, i.e. the same colour, now named). */
.hos-card__conn {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 40px;
}

.hos-card__connline {
  flex: 1;
  height: 1px;
  background: var(--hairline);
}

.hos-card__nights {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--surface-alt);
  flex: none;
  line-height: 1;
}

.hos-card__nights-n {
  font-family: var(--font-mono);
  font-size: var(--text-md);       /* ← 16px */
  font-weight: var(--fw-semibold);
  color: var(--ink);
  line-height: 1;
}

.hos-card__nights-l {
  margin-top: 3px;
  font-size: var(--text-2xs);      /* ← 8px */
  font-weight: var(--fw-bold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  /* --slate-600 (not --muted-2 = slate-500) so this 10px caption clears WCAG AA
     4.5:1 on the --surface-alt circle (slate-500 was 4.34, just under). */
  color: var(--slate-600);
  font-style: normal;    /* the label is an <em>; kill the browser default italic */
}

/* ── journey: flight → boat → room ───────────────────────────────────
   Prototype `.hc__logi` / `.vjourney` / `.vstep`. */
.hos-card__logi {
  /* Source `hc--nolines .hc__logi{margin-top:20px}` — a fixed 20px break above the
     journey. NO `margin-top:auto`: the footer is a separate flex child and
     `.hos-card__in` is `flex:1`, so feet are ALREADY bottom-pinned by the structure —
     an auto-margin here did nothing for alignment, it only floated the journey down
     and made the dates→journey gap vary per card. Slack falls below the journey. */
  padding-top: 20px;
}

.hos-card__step {
  display: flex;
  gap: 12px;
  position: relative;
  padding-bottom: 14px;
}

.hos-card__step:last-child { padding-bottom: 0; }

.hos-card__step::before {
  content: "";
  position: absolute;
  left: 15px;
  top: 30px;
  bottom: -2px;
  width: 2px;
  background: var(--hairline);
}

.hos-card__step:last-child::before { display: none; }

.hos-card__node {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  border: 1.5px solid var(--hairline);
  color: var(--muted-2);
  z-index: 1;
  flex: none;
}

/* The step's tone drives node + value together — the prototype's
   `.vstep--done/--now/--warn/--crit`, retokenised onto the triad. Pair with a
   `.fo-tone--*` on the same element. */
.hos-card__step--tone .hos-card__node {
  background: var(--tone-bg);
  border-color: var(--tone-line);
  color: var(--tone);
}

.hos-card__step--tone .hos-card__stepv { color: var(--tone); }

/* The live "now" node — the mockup's `.vstep--now`: the CURRENT journey stage
   (fo_journey_now) filled in accent, leaving the rest neutral. A distinct rule
   from `--tone` above (accent isn't part of the semantic tone triad); it only
   tints the node, so the step's value text stays its normal weight/colour. */
.hos-card__step--now .hos-card__node {
  background: var(--accent-soft);
  border-color: var(--accent-border);
  color: var(--accent-strong);
}

.hos-card__stepbody { padding-top: 6px; min-width: 0; }

.hos-card__stepl {
  font-size: var(--text-2xs);      /* ← 9.5px */
  font-weight: var(--fw-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-2);
}

.hos-card__stepv {
  margin-top: 2px;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  font-size: var(--text-xs);       /* ← 12.5px */
  font-weight: var(--fw-medium);
  color: var(--text-secondary);
}

.hos-card__stepv--muted { color: var(--muted-2); }

.hos-card__stepv-mono {
  font-family: var(--font-mono);
  font-weight: var(--fw-semibold);
  color: var(--ink);
}

/* The "· unassigned" / "Not assigned" room hint — an open loop for the desk, so
   it is amber, matching fo_blockers' amber-not-rose rule (tasks/041). */
.hos-card__stepv-flag {
  font-weight: var(--fw-semibold);
  color: var(--status-briefing-fg);
}

/* Prototype `.vroom__b` — the meal plan under the room. */
.hos-card__stepsub {
  flex-basis: 100%;
  font-size: var(--text-xs);       /* ← 11px */
  font-weight: var(--fw-medium);
  color: var(--muted);
  margin-top: 2px;
}

/* ── foot: the one number + the one action ───────────────────────────
   Prototype `.rc__foot` — its raw #FCFCFD tint → --surface-alt. Layout matches
   the mockup: the pay column (label → amount+paid → bar) fills the left, and the
   action is vertically CENTRED on the right. The card's whole body is one <a>, so
   the action is an absolutely-positioned SIBLING overlaying the foot's right (a
   <form> nested in an <a> is invalid and double-fires the drawer nav).
   The action overlays the right strip across the pay column's full height now (it
   is centred, not pinned to the bottom), so the WHOLE pay column dodges it via
   --act-gap. A fixed height keeps the pay column centred and the action's centre
   deterministic across billed / settled / not-priced cards. */
.hos-card__foot {
  --act-gap: 120px;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 18px;   /* source `.rc__foot{padding:14px 18px}` */
  border-top: 1px solid var(--hairline-2);
  background: var(--surface-alt);
  min-height: 74px;
}

/* No action for this stay (terminal lifecycle, or a viewer without front-desk
   rights) → nothing to dodge, so the pay column spans the foot too. */
.hos-card__foot--noact { --act-gap: 0px; }

/* ── pay ─────────────────────────────────────────────────────────────
   Prototype `.rc__fin`. The balance is the headline; the paid figure sits inline
   to its right; the bar below carries paid-vs-total. The total is implied by the
   bar — the paid figure is just "$X paid", never "paid of $Y". The whole column
   clears the centred action via --act-gap. */
.hos-pay {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  /* Shrink-wrap to content so the balance/paid row AND the bar under it end at the
     paid figure — not stretched full-width under the action button. max-width caps
     it clear of the action strip even for a long balance. */
  flex: 0 1 auto;
  max-width: calc(100% - var(--act-gap));
}

/* Source `.rc__frow` — the balance amount with the paid figure inline to its
   right, baseline-aligned, on ONE row (no wrap: individual and grouped cards
   render the identical single-line structure). --act-gap on .hos-pay reserves the
   action strip, and the amounts are tabular mono, so the row fits the track. */
.hos-pay__row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}

.hos-pay__k {
  font-size: var(--text-2xs);      /* ← 10px */
  font-weight: var(--fw-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-2);
  white-space: nowrap;
}

.hos-pay__k--ok { color: var(--success); }

.hos-pay__bal {
  font-family: var(--font-mono);
  font-size: var(--text-lg);       /* ← 18px */
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--danger);
}

/* Prototype `.rc__fp` — the paid figure, inline after the balance. */
.hos-pay__paid {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);      /* ← 11px */
  color: var(--muted);
}

/* The bar carries paid-vs-total. It clears the action via the column's own
   --act-gap margin (above), so no per-element margin here. */
.hos-pay__bar {
  height: 6px;
  margin-top: 4px;
  border-radius: var(--radius-pill);
  background: var(--hairline-strong);
  overflow: hidden;
}

.hos-pay__fill {
  display: block;
  height: 100%;
  background: var(--accent);
  border-radius: var(--radius-pill);
}

.hos-pay__fill--ok { background: var(--success); }

/* Prototype `.pay--np` — "not yet priced". Its 13px italic is the one place the
   prototype leans on italics; kept, snapped to the scale. */
.hos-pay--np {
  flex-direction: row;             /* .hos-pay is a column; this one is a single line */
  align-items: center;
  gap: 7px;
  font-size: var(--text-sm);       /* ← 13px */
  font-style: italic;
  color: var(--muted);
  padding: 4px 0;
}

/* Task 2's state-aware action — a sibling of the card's <a>, overlaying the
   foot's reserved right strip and vertically CENTRED in it (the mockup's
   `.rc__btn`). Positioned against _cardgrid's relative wrapper, whose height is
   the whole card; the foot is flush at the bottom with a fixed 74px min-height,
   so centring the 32px button in it means bottom:(74−32)/2 = 21px. */
.hos-card__act {
  position: absolute;
  right: 18px;
  bottom: 21px;
  margin: 0;
  z-index: 1;
}

/* ── List view — the editorial stripe list ────────────────────────────
 * Replicates Design/Front-office/HotelOS Arrivals - Final.html `#hos-list`
 * (`.rows`/`.row`/`.row__*`) faithfully: a 7-column CSS-grid row, NOT a
 * table. Columns: stripe · time+flight · name+source · room+meal · status ·
 * balance · action. Shares the card's tone triad (--tone/--tone-bg/
 * --tone-line) + .hos-fo-chip; blockers render through fo_blockers(g), the same
 * derivation as the card/worklist.
 *
 * NOTE: boat-unassigned stays AMBER here (--warning) to match the card +
 * drawer convention (tasks/041: unassigned boat is a warning, not a
 * cancellation), NOT the mockup's red — flagged for the human to flip. */
.hos-fo-rows {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  margin-top: var(--space-5);
}
.hos-fo-row {
  position: relative;
  display: grid;
  grid-template-columns: 84px minmax(0, 1.25fr) minmax(0, 1.4fr) 178px 124px 148px;
  align-items: center;
  gap: 16px;
  padding: 0 18px 0 22px;
  min-height: 74px;
  border-bottom: 1px solid var(--hairline-2);
  cursor: pointer;
  transition: background var(--transition-base);
}
.hos-fo-row:last-child { border-bottom: none; }
.hos-fo-row:hover { background: var(--state-hover); }
.hos-fo-row:focus-visible { outline: none; background: var(--state-hover); box-shadow: inset 0 0 0 2px var(--focus-ring-color); }

/* stripe — reads --tone off the row (hos-tone--warn/--crit); hairline default */
.hos-fo-row__stripe { position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--tone, var(--hairline-strong)); }

.hos-fo-row__time { min-width: 0; }
.hos-fo-row__t {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.hos-fo-row__t--warn { color: var(--warning); }
.hos-fo-row__d { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--muted-2); margin-top: 2px; }

.hos-fo-row__name { min-width: 0; }
.hos-fo-row__n {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: var(--text-sm);
  font-weight: var(--fw-bold);
  letter-spacing: -0.01em;
  color: var(--ink);
}
.hos-fo-row__n > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hos-fo-row__plus { color: var(--muted-2); font-weight: var(--fw-semibold); flex: none; }
.hos-fo-row__r { font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--muted-2); margin-top: 2px; white-space: nowrap; }

.hos-fo-row__room { display: flex; align-items: flex-start; gap: 8px; min-width: 0; }
.hos-fo-row__room-txt { min-width: 0; }
.hos-fo-row__room-ic { color: var(--muted-2); flex: none; margin-top: 1px; display: inline-flex; }
.hos-fo-row__a { font-size: var(--text-sm); font-weight: var(--fw-medium); color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hos-fo-row__b { font-size: var(--text-xs); color: var(--muted); margin-top: 2px; }

.hos-fo-row__status { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; min-width: 0; }
.hos-fo-row__more {
  font-size: var(--text-2xs);
  font-weight: var(--fw-semibold);
  color: var(--muted);
  background: var(--surface-alt);
  border-radius: var(--radius-pill);
  padding: 2px 7px;
  flex: none;
}

.hos-fo-row__bal { text-align: right; }
.hos-fo-row__k {
  font-size: var(--text-2xs);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.hos-fo-row__v {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  margin-top: 2px;
  color: var(--ink);
}
.hos-fo-row__v--due { color: var(--danger); font-weight: var(--fw-bold); }
.hos-fo-row__v--settled { color: var(--success); }

.hos-fo-row__act { display: flex; justify-content: flex-end; }
.hos-fo-row__act-btn { white-space: nowrap; }

/* Narrow panes: let the row wrap gracefully rather than clip (container query
   on the content pane, matching the board's other views). */
@container (max-width: 900px) {
  .hos-fo-row { grid-template-columns: 76px minmax(0,1.4fr) 150px 120px; row-gap: 4px; }
  .hos-fo-row__room, .hos-fo-row__act { display: none; }
}

/* ── Rooms Map — the spatial board, grouped by room type ──────────────
 * Ported from Design/Front-office/HotelOS Arrivals - Final.html `#rooms-map`
 * (`.rmap`/`.rzone`/`.rmt`) + the `.rlegend`/`.rchip` legend above it.
 *
 * What was KEPT (the portable mechanism): the prototype's --rc / --rc-bg pair,
 * one custom-property set per tile driving badge + tint + spine together, so a
 * status change is one class. Same shape as the card's --tone triad above.
 *
 * What was CHANGED and why:
 *   * the prototype sets --rc INLINE (style="--rc:var(--st-vacant);..."). Here
 *     it is a `.fo-rst--<status>` class — Room::STATUSES is a closed set, so a
 *     class per status is exhaustive, and no view sets a token-governed prop
 *     inline (DESIGN.md / hallmark InlineStyle).
 *   * `.rmt__s` reads "Ready". Our label is the app's — "Vacant" — via
 *     FrontOfficeHelper::ROOM_STATUS, whose naming source is Room::STATUSES.
 *     The word rides a tinted `.hos-rmt__badge` (prototype `.rbadge`) so the
 *     tile states its status on EVERY status, not only the free ones; the
 *     prototype's redundant `.rmt__dot` is dropped (the badge carries --rc).
 *   * its `padding:8px 32px 70px` / `padding:16px 32px 4px` page insets — the
 *     column is `.hos-shell-content`'s job, as with `.hos-board` above.
 *   * its raw font sizes (10/10.5/11/11.5/12/12.5/13/14) → var(--text-*) steps
 *     off the GEM's scale (os_ds.css: 2xs 10 / xs 12 / sm 14 / md 16), NOT
 *     arena_ds.css's competing, overridden block. Snap recorded per rule.
 */

/* Status → the --rc/--rc-bg pair. Set on any ancestor or the element itself;
   everything below reads the pair, so a status change is one class. One rule
   per Room::STATUSES member — the lint test pins the tokens' existence. */
.hos-rst--vacant   { --rc: var(--st-vacant);   --rc-bg: var(--st-vacant-bg); }
.hos-rst--occupied { --rc: var(--st-occupied); --rc-bg: var(--st-occupied-bg); }
.hos-rst--reserved { --rc: var(--st-reserved); --rc-bg: var(--st-reserved-bg); }
.hos-rst--dueout   { --rc: var(--st-dueout);   --rc-bg: var(--st-dueout-bg); }
.hos-rst--dirty    { --rc: var(--st-dirty);    --rc-bg: var(--st-dirty-bg); }
.hos-rst--blocked  { --rc: var(--st-blocked);  --rc-bg: var(--st-blocked-bg); }

/* Prototype `.rlegend` / `.rchip` — the status summary above the map. Not a
   filter control here (the fbar owns filtering), so it is a static <div>. */
.hos-rlegend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.hos-rchip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 30px;
  padding: 0 12px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius-md);
  background: var(--surface);
  font-size: var(--text-sm);        /* ← 12px (.rmodebar .rchip); the gem's
                                        nearest body step — the legend is read
                                        at a glance, not skimmed as meta */
  font-weight: var(--fw-medium);
  color: var(--text-secondary);
  white-space: nowrap;
}

/* Prototype `.rchip__dot` is a 8px circle; squared to 3px radius to echo the
   status swatch the board already used. Colour is wholly --rc. */
.hos-rchip__dot {
  width: 9px;
  height: 9px;
  border-radius: var(--radius-sm);
  background: var(--rc, var(--hairline-strong));
  flex: none;
}

.hos-rchip__n {
  font-family: var(--font-mono);
  font-size: var(--text-sm);        /* ← 13px */
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

/* Prototype `.rmap` — the zone stack. */
.hos-rmap {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/* Prototype `.rzone__h` / `.rzone__t` / `.rzone__n` — the type header. */
.hos-rzone__h {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 10px;
}

.hos-rzone__t {
  font-size: var(--text-xs);        /* ← 12px */
  font-weight: var(--fw-bold);
  letter-spacing: -0.01em;
  color: var(--text-secondary);
}

.hos-rzone__n {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);       /* ← 10.5px */
  font-variant-numeric: tabular-nums;
  color: var(--muted-2);
}

/* Prototype `.rzone__grid` — minmax(134px) kept, widened to 150px: our tile
   carries the status WORD (a badge) where the prototype carried a dot. */
.hos-rzone__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 8px;
}

/* Prototype `.rmt` — the tile. Its `border:1px solid transparent` + hover
   border-color:var(--rc) is kept: the tint IS the chassis, so this is NOT an
   .os-card (a card ring would fight the tint). */
.hos-rmt {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-height: 64px;
  padding: 10px 12px;
  border: 1px solid transparent;
  border-radius: var(--radius-lg);
  background: var(--rc-bg, var(--surface-alt));
  text-decoration: none;
}

/* Only the openable tiles (a stay to open in the drawer) are interactive — a
   vacant tile is a <div> and must not claim a pointer it has no action for. */
a.hos-rmt { cursor: pointer; }
a.hos-rmt:hover { border-color: var(--rc, var(--hairline-strong)); }

.hos-rmt__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.hos-rmt__no {
  font-family: var(--font-mono);
  font-size: var(--text-sm);        /* ← 14px, exact */
  font-weight: var(--fw-semibold);
  letter-spacing: -0.01em;
  color: var(--ink);
}

/* Prototype `.rbadge` — the status word, tinted from the pair. The prototype
   put this on its `.rcard` only and left `.rmt` with a bare dot; we carry it on
   the tile so every status is NAMED, not just colour-coded (colour alone is not
   an accessible status channel). */
.hos-rmt__badge {
  display: inline-flex;
  align-items: center;
  height: 18px;
  padding: 0 7px;
  border-radius: var(--radius-pill);
  font-size: var(--text-2xs);       /* ← 11px */
  font-weight: var(--fw-bold);
  line-height: 1;
  white-space: nowrap;
  color: var(--rc);
  background: var(--surface);
  flex: none;
}

/* Prototype `.rmt__m` — the tile's one line: guest, block reason, or the
   housekeeping/ready note. */
.hos-rmt__m {
  display: flex;
  align-items: center;
  gap: 5px;
  min-width: 0;
  font-size: var(--text-xs);        /* ← 11.5px */
  font-weight: var(--fw-semibold);
  color: var(--rc, var(--ink));
}

.hos-rmt__m-txt {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hos-rmt__m svg { flex: none; }

/* Prototype `.rmt__sub` — the dates line under the guest. */
.hos-rmt__sub {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);       /* ← 10px, exact */
  font-variant-numeric: tabular-nums;
  color: var(--muted-2);
  margin-top: -2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Rooms Worklist — the desk's queue, grouped BY status ─────────────
 * Ported from Design/Front-office/HotelOS Arrivals - Final.html `#rooms-work`
 * (`.rwork`/`.rwsec`/`.rwrow`). Same board, same --rc/--rc-bg status pair as the
 * Map above — a status change is one `.fo-rst--<status>` class. The rows are
 * grouped into four action sections (Needs attention · Turnover & arrivals · In
 * house · Ready); the grouping runs off @rooms_for_worklist (PRE-status), so a
 * status filter never collapses it (§4a).
 *
 * Changed from the prototype: its page insets (`padding:8px 32px 70px`) are
 * `.hos-shell-content`'s job; its raw sizes (11/11.5/12.5/14) snap to the GEM's
 * var(--text-*) steps (2xs 10 / xs 12 / sm 14); its box-shadow rgba → --shadow-sm.
 */
.hos-rwork {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/* Prototype `.rwsec__h` / `.rwsec__t` / `.rwsec__n` — the section header. */
.hos-rwsec__h {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 9px;
}

.hos-rwsec__t {
  font-size: var(--text-xs);          /* ← 11px */
  font-weight: var(--fw-bold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.hos-rwsec__n {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);         /* ← 11px */
  font-variant-numeric: tabular-nums;
  color: var(--muted-2);
}

/* Prototype `.rwrows` — the section's row list, one hairline-ringed panel. */
.hos-rwrows {
  border: 1px solid var(--hairline);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--surface);
  box-shadow: var(--shadow-sm);
}

.hos-rwrows--empty {
  padding: 14px 18px;
  font-size: var(--text-sm);
  color: var(--muted-2);
}

/* Prototype `.rwrow` — one room. The `::before` spine carries --rc (set by the
   `.fo-rst--<status>` class), same mechanism as the Map tile. */
.hos-rwrow {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 16px 12px 18px;
  border-bottom: 1px solid var(--hairline-2);
}

.hos-rwrow:last-child { border-bottom: none; }

.hos-rwrow::before {
  content: "";
  position: absolute;
  left: 0;
  top: 11px;
  bottom: 11px;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--rc, var(--hairline-strong));
}

.hos-rwrow__no {
  font-family: var(--font-mono);
  font-size: var(--text-sm);          /* ← 14px, exact */
  font-weight: var(--fw-semibold);
  color: var(--ink);
  width: 56px;
  flex: none;
}

.hos-rwrow__ty {
  font-size: var(--text-xs);          /* ← 11.5px */
  color: var(--muted);
  width: 120px;
  flex: none;
}

.hos-rwrow__task {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-sm);          /* ← 12.5px */
  font-weight: var(--fw-medium);
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hos-rwrow__task b { color: var(--ink); font-weight: var(--fw-semibold); }
.hos-rwrow__task svg { flex: none; color: var(--muted-2); }

.hos-rwrow__act {
  flex: none;
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}

/* The action <form>s (button_to) must sit inline in the row, no block margin. */
.hos-rwrow__act form { margin: 0; }

/* ── Stay rack — the tape chart (Task 7) ───────────────────────────────
 * Ported from Design/Front-office/HotelOS Arrivals - Final.html `#view-stay`
 * (`.rack`/`.rrow`/`.rhead-*`/`.rroom-*`/`.rtrack`/`.rbar`). A RESTYLE only —
 * `fo_rack_geom` (bar left/width/clip) and `fo_bar_tone` (lifecycle → tone
 * key) are unchanged in front_office_helper.rb; this just moves how colour
 * and typography reach the DOM off inline var(--token) styles and onto these
 * classes (hallmark InlineStyle). Per-instance pixel geometry (bar
 * left/width, column width/left, row/head height, the rack's total width)
 * stays inline in `_stay.html.erb` — it's computed per render from
 * FrontOfficeHelper::RACK and the stay/room data, not a fixed enum, so a
 * class can't express it (DESIGN.md: one-off layout may stay inline).
 *
 * The room status dot reuses the Rooms Map's `--rc` mechanism verbatim
 * (`.fo-rst--*`, above) — one source of truth for the six Room::STATUSES
 * colours, not a second copy for the rack.
 *
 * What the mockup does NOT have that the app's rack already did (kept,
 * because parity means preserved, not just what the mockup shows): the
 * blocked-room hatch band, weekend + today column shading, the clipped-bar
 * chevron, the Unassigned row, and the 5-tone legend.
 */
.hos-rack {
  overflow: auto;
  max-height: calc(100vh - 320px);
}

.hos-rack__title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--fw-semibold);
  color: var(--ink);
}

.hos-rack__meta {
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* ── status filter chips (#119): one per Room::STATUS + All, with live counts ── */
.hos-rack__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.hos-rack__chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: transparent;
  text-decoration: none;
  font-size: var(--text-xs);
  font-weight: var(--fw-medium);
  color: var(--muted);
}
.hos-rack__chip--on {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--ink);
}
.hos-rack__chipdot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--rc, var(--muted-2));
}
.hos-rack__chipn {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: var(--fw-semibold);
  color: var(--muted-2);
}
.hos-rack__chip--on .hos-rack__chipn { color: var(--accent); }

/* ── per-day inventory + occupancy footer (#119) ── */
.hos-rack__foot {
  display: flex;
  align-items: center;
  background: var(--slate-50);
  border-top: 1px solid var(--hairline-2);
}
.hos-rack__foot--top { border-top: 2px solid var(--hairline); }
.hos-rack__footlbl {
  position: sticky;
  left: 0;
  z-index: 2;
  flex: none;
  background: var(--slate-50);
  border-right: 1px solid var(--hairline);
  display: flex;
  align-items: center;
  padding: 0 14px;
}
.hos-rack__footcell {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  border-right: 1px solid var(--hairline-2);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
/* col_class applies the gridcol background modifier only (not the positioned base);
   override its .5 opacity so the footer figure stays legible on the today column. */
.hos-rack__footcell.hos-rack__gridcol--today {
  opacity: 1;
  color: var(--accent);
  font-weight: var(--fw-bold);
}
.hos-rack__footunit {
  font-size: var(--text-2xs);
  color: var(--muted-2);
  margin-left: 1px;
}

/* rate-plan filter: bars on non-selected plans dim back but stay in place (#119 D-119a) */
.hos-rack__bar--dim {
  opacity: .28;
  filter: grayscale(0.5);
}

/* hover column highlight (#120) + drag-to-book selection (#121): single moved overlays,
   click-through (pointer-events:none) so they never block a bar link or a fresh drag. */
.hos-rack__colhi {
  position: absolute;
  top: 0;
  height: 100%;
  z-index: 1;
  background: var(--accent-soft);
  opacity: .5;
  pointer-events: none;
}
.hos-rack__dragsel {
  position: absolute;
  z-index: 2;
  background: var(--accent-soft);
  border: 1.5px solid var(--accent);
  border-radius: 4px;
  pointer-events: none;
}

/* ── header row: sticky "Room" label + the day columns ── */
.hos-rack__head {
  display: flex;
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--slate-50);
  border-bottom: 1px solid var(--hairline);
}

.hos-rack__headlbl {
  position: sticky;
  left: 0;
  z-index: 4;
  flex: none;
  background: var(--slate-50);
  border-right: 1px solid var(--hairline);
  display: flex;
  align-items: center;
  padding: 0 14px;
}

.hos-rack__daycol {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  border-right: 1px solid var(--hairline-2);
}

.hos-rack__daycol--today { background: var(--accent-soft); }
.hos-rack__daycol--weekend { background: var(--slate-100); }

.hos-rack__dayw {
  font-size: var(--text-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.hos-rack__dayw--today { color: var(--accent); }

.hos-rack__dayd {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: var(--fw-medium);
  color: var(--slate-700);
}
.hos-rack__dayd--today { font-weight: var(--fw-bold); color: var(--accent); }

/* ── the Unassigned row — an open loop for the desk, pinned above every
   room row so a roomless booking is never silently dropped from the rack. ── */
.hos-rack__unrow {
  display: flex;
  border-bottom: 2px solid var(--hairline);
  background: var(--status-briefing-bg);
}

.hos-rack__unlbl {
  position: sticky;
  left: 0;
  z-index: 2;
  flex: none;
  background: var(--status-briefing-bg);
  border-right: 1px solid var(--hairline);
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 14px;
}

.hos-rack__untxt {
  font-size: var(--text-sm);
  font-weight: var(--fw-bold);
  color: var(--status-briefing-fg);
}

/* ── room rows ── */
.hos-rack__row {
  display: flex;
  border-bottom: 1px solid var(--hairline-2);
}
.hos-rack__row:last-child { border-bottom: none; }

.hos-rack__roomlbl {
  position: sticky;
  left: 0;
  z-index: 2;
  flex: none;
  background: var(--surface);
  border-right: 1px solid var(--hairline);
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 0 14px;
}

/* Reads --rc off the SAME `.fo-rst--*` class the Rooms Map sets (above) —
   one status→colour mapping for both views. */
.hos-rack__roomsq {
  width: 8px;
  height: 8px;
  border-radius: 2px;
  flex: none;
  background: var(--rc, var(--hairline-strong));
}

.hos-rack__roomtxt { min-width: 0; }

.hos-rack__roomno {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: var(--fw-semibold);
  color: var(--ink);
  line-height: 1.1;
}

.hos-rack__roomty {
  font-size: var(--text-2xs);
  color: var(--muted-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── the day track — background grid + the absolutely-positioned bars ── */
.hos-rack__track {
  position: relative;
  flex: none;
}

.hos-rack__gridcol {
  position: absolute;
  top: 0;
  height: 100%;
  border-right: 1px solid var(--hairline-2);
}
.hos-rack__gridcol--today { background: var(--accent-soft); opacity: .5; }
.hos-rack__gridcol--weekend { background: var(--slate-100); }

/* The blocked-room hatch band — a room out of service is never a bookable
   track, so no bar renders under it. */
.hos-rack__blocked {
  position: absolute;
  inset: 6px 3px;
  border-radius: var(--radius-sm);
  background: repeating-linear-gradient(45deg, var(--slate-100), var(--slate-100) 6px, var(--slate-50) 6px, var(--slate-50) 12px);
  display: flex;
  align-items: center;
  gap: 6px;
  padding-left: 10px;
  color: var(--muted-2);
  font-size: var(--text-xs);
}

/* ── the stay bar ── */
.hos-rack__bar {
  position: absolute;
  top: 6px;
  height: calc(100% - 12px);
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 0 8px;
  overflow: hidden;
  text-decoration: none;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-xs);
}

/* A bar clipped at a window edge loses the rounded corner on that side — it
   visually continues off-screen, so squaring the edge is the "there's more"
   cue (paired with the chevron on the right, below). */
.hos-rack__bar--clipl { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.hos-rack__bar--clipr { border-top-right-radius: 0; border-bottom-right-radius: 0; }

.hos-rack__bar--inhouse    { background: var(--status-in-water-bg); color: var(--status-in-water-fg); border-left: 3px solid var(--status-in-water-fg); }
.hos-rack__bar--arriving   { background: var(--accent-soft); color: var(--accent-strong); border-left: 3px solid var(--accent); }
.hos-rack__bar--departing  { background: var(--status-returning-bg); color: var(--status-returning-fg); border-left: 3px solid var(--status-returning-fg); }
.hos-rack__bar--confirmed  { background: var(--status-confirmed-bg); color: var(--status-confirmed-fg); border-left: 3px solid var(--status-confirmed-fg); }
.hos-rack__bar--unassigned {
  background: var(--status-briefing-bg);
  color: var(--status-briefing-fg);
  border: 1px dashed var(--status-briefing-fg);
}
/* The left spine reads as "this bar starts here" — hidden when clipped-left
   (the booking actually started before the visible window). Declared AFTER
   the tone rules above so it wins the cascade at equal specificity. */
.hos-rack__bar--nospine { border-left: none; }

.hos-rack__barlabel {
  font-size: var(--text-xs);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── legend ── */
.hos-rack__legend {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  font-size: var(--text-xs);
  color: var(--text-muted);
}

.hos-rack__legend-i {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.hos-rack__legend-sw {
  width: 12px;
  height: 12px;
  border-radius: 3px;
}

.hos-rack__legend-sw--inhouse    { background: var(--status-in-water-fg); }
.hos-rack__legend-sw--arriving   { background: var(--accent); }
.hos-rack__legend-sw--departing  { background: var(--status-returning-fg); }
.hos-rack__legend-sw--confirmed  { background: var(--status-confirmed-fg); }
.hos-rack__legend-sw--unassigned { background: var(--status-briefing-fg); }

/* ── Board chrome — the control strip + filters drawer (Task 8) ─────────
 * Ported from Design/Front-office/HotelOS Arrivals - Final.html `.cstrip`
 * (`.fotabs`/`.cbar`/`.vtoggle`/`.fbar__*`) and its `#fdrawer` filters drawer
 * (`.fgrp`/`.fseg`/`.fdrawer__*`). This REPLACES the ~38 inline token-styles
 * `index.html.erb` carried (hallmark InlineStyle debt) with classes.
 *
 * Mockup tokens → theme tokens: --brand→--accent, --brand-soft→--accent-soft,
 * --brand-strong→--accent-strong, --line→--hairline, --line-2→--hairline-2 /
 * --slate-100 (segment tracks, matching the existing view toggle),
 * --line-strong→--hairline-strong, --ink-2→--text-secondary. Every raw font
 * px snaps to a var(--text-*) step off the gem's scale (os_ds.css: 2xs 10 /
 * xs 12 / sm 14 / md 16 / lg 18). Every colour is a var(--token); no hex.
 *
 * The tab strip itself is `.page-tab`/`.page-tab-count` (os-ds gem) — reused
 * verbatim, not re-cut. The filters drawer reuses the `.hos-odrawer` chassis
 * (scrim/panel/`data-open`) so there is ONE slide-in mechanism, not two; it
 * only opts a narrower panel and adds the filter-specific inner layout below.
 */
/* No flex gap between the tools band and the content: the top spacing is the
   single DS body-gap MARGIN the `.os-page-tools + content` rule applies. A flex
   gap here doubled it (16px gap + 32px margin = 48px). Page-top = the top margin. */
.hos-chrome { display: flex; flex-direction: column; }

/* Tab scaffolding retired 2026-07-19 — the index control strip is now the DS
   toolbar (os-ds `.os-page-tools`) directly: tabs are a pure `.page-tabs` group
   (the gem's `.os-page-tools > .page-tabs` rule stretches them flush to the band
   bottom), a `.os-spacer` pushes the control cluster right. The old `.hos-cstrip`
   (space-between) + `.hos-tabs` (negative-margin flush hack) are gone. */

/* `.hos-cstrip__lead` — the lens-context lead (Rooms / Stay heads + view toggle),
   NOT tabs. Kept: it's genuine FO lens UI, not tab scaffolding. */
.hos-cstrip__lead { display: flex; align-items: center; gap: 14px; min-width: 0; flex-wrap: wrap; }

/* `.cbar` — search + Filters + divider + view toggle (the FO control cluster). */
.hos-cbar { display: flex; align-items: center; gap: 8px; flex: none; flex-wrap: wrap; justify-content: flex-end; min-width: 0; }
.hos-cbar__div { width: 1px; height: 22px; background: var(--hairline); flex: none; }

/* Prototype `.pghead` context head for the Rooms / Stay lenses (no tabs). */
.hos-ctxhead { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.hos-ctxhead__t {
  font-family: var(--font-display);
  font-size: var(--text-lg);          /* ← 18px */
  font-weight: var(--fw-semibold);
  color: var(--ink);
}
.hos-ctxhead__sub { font-size: var(--text-xs); color: var(--text-muted); }

/* ── search (Task 9's `data-hos-fo-search` mechanism — markup unchanged, restyled).
   The collapsed→expanded width/padding/border toggle is written by the script
   at runtime as inline style; the initial state is the `--open` modifier so the
   ERB carries NO inline style. */
.hos-fo-search { position: relative; display: flex; align-items: center; flex: none; }
.hos-fo-search__btn {
  width: 34px; height: 34px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--hairline); border-radius: var(--radius-md);
  background: var(--surface); color: var(--muted-2); cursor: pointer;
}
.hos-fo-search__btn:hover { border-color: var(--hairline-strong); color: var(--text-secondary); }
.hos-fo-search__input {
  width: 0; padding: 0; border: 0; margin-left: 0;
  height: 34px; border-radius: var(--radius-md);
  background: var(--surface);
  font-family: var(--font-sans); font-size: var(--text-sm); color: var(--ink);
  outline: none;
  transition: width .2s, padding .2s;
}
.hos-fo-search__input--open {
  width: 220px; padding: 0 11px; margin-left: 6px;
  border: 1px solid var(--hairline-strong);
}
.hos-fo-search__results { position: absolute; left: 0; top: 38px; z-index: 50; }

/* Prototype `.fbar__field` + `#filtersBtn` — the Filters drawer trigger. */
.hos-filterbtn {
  display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 12px;
  border: 1px solid var(--hairline); border-radius: var(--radius-md);
  background: var(--surface); color: var(--text-secondary);
  font-family: var(--font-sans); font-size: var(--text-sm); font-weight: var(--fw-semibold);
  cursor: pointer;
}
.hos-filterbtn:hover { border-color: var(--hairline-strong); }
.hos-filterbtn svg { color: var(--muted-2); flex: none; }

/* Prototype `.cbar__n` — the active-filter count badge. */
.hos-filterbtn__n {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px; margin-left: 1px;
  border-radius: var(--radius-pill);
  background: var(--accent-soft); color: var(--accent-strong);
  font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
}

/* The view pill (Cards/List/Rooms/Stay) and the Rooms Map/Worklist sub-toggle
   both use the gem's `.os-segmented` — no local segmented family. */

/* ── the date control (strip) — kept OUT of the drawer exactly as the mockup
   keeps its datenav out of `#fdrawer`. `.hos-cal` is the list-view calendar
   `<details data-hos-cal>` (Task 9 script populates `[data-cal-grid]`); the
   rooms/stay lenses use a single date_field in the same pill. */
.hos-datepill {
  display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 12px;
  border: 1px solid var(--hairline); border-radius: var(--radius-md);
  background: var(--surface); flex: none;
}
.hos-datepill--btn { list-style: none; cursor: pointer; }
.hos-datepill--label { cursor: pointer; }
.hos-datepill__k {
  font-size: var(--text-2xs); font-weight: var(--fw-bold);
  letter-spacing: .04em; text-transform: uppercase; color: var(--muted-2);
}
.hos-datepill__v { font-size: var(--text-sm); font-weight: var(--fw-semibold); color: var(--ink); }
.hos-datepill__input {
  border: none; background: transparent; outline: none;
  font-family: var(--font-sans); font-size: var(--text-sm); font-weight: var(--fw-semibold);
  color: var(--ink); cursor: pointer; margin-left: 2px;
}

.hos-cal { position: relative; flex: none; }
.hos-cal__pop {
  position: absolute; left: 0; top: calc(100% + 6px); z-index: 40;
  display: flex; background: var(--surface);
  border: 1px solid var(--hairline); border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg); overflow: hidden;
}
.hos-cal__presets {
  display: flex; flex-direction: column; gap: 2px; padding: 10px;
  border-right: 1px solid var(--hairline-2); min-width: 140px;
}
.hos-cal__preset {
  display: block; width: 100%; text-align: left; padding: 8px 12px;
  border: none; background: transparent; cursor: pointer;
  font-family: var(--font-sans); font-size: var(--text-sm); color: var(--text-secondary);
  border-radius: var(--radius-sm);
}
.hos-cal__preset--clear { color: var(--text-muted); display: flex; align-items: center; gap: 6px; margin-top: 4px; }
.hos-cal__cal { padding: 12px 14px; width: 296px; }
.hos-cal__nav { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.hos-cal__title { font-family: var(--font-display); font-size: var(--text-md); font-weight: var(--fw-semibold); color: var(--ink); }
.hos-cal__wdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; margin-bottom: 4px; }
.hos-cal__wday { text-align: center; font-size: var(--text-2xs); font-weight: var(--fw-bold); color: var(--muted-2); }
.hos-cal__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.hos-cal__hint { margin-top: 8px; font-size: var(--text-2xs); color: var(--muted-2); text-align: right; }

/* ── filters drawer — inner layout (chassis is `.hos-odrawer`, above) ─────
   Prototype `.fdrawer__*` / `.fgrp` / `.fseg` / `.os-field-select` selects. */
.hos-fdrawer .hos-odrawer-panel { width: min(400px, 92vw); background: var(--surface); }
.hos-fdrawer__hd {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
  padding: 20px 22px 16px; border-bottom: 1px solid var(--hairline);
}
.hos-fdrawer__t { font-size: var(--text-md); font-weight: var(--fw-bold); letter-spacing: -.02em; color: var(--ink); }
.hos-fdrawer__sub { font-size: var(--text-xs); color: var(--muted); margin-top: 3px; }
.hos-fdrawer__x {
  width: 30px; height: 30px; border: 0; background: transparent; border-radius: var(--radius-sm);
  color: var(--muted); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; flex: none;
}
.hos-fdrawer__x:hover { background: var(--hairline-2); color: var(--text-secondary); }
.hos-fdrawer__form { display: flex; flex-direction: column; flex: 1; min-height: 0; margin: 0; }
.hos-fdrawer__body { flex: 1; overflow-y: auto; padding: 6px 22px 20px; }
.hos-fgrp { padding: 18px 0; border-bottom: 1px solid var(--hairline-2); }
.hos-fgrp:last-child { border-bottom: none; }
.hos-fgrp__k {
  font-size: var(--text-2xs); font-weight: var(--fw-bold);
  letter-spacing: .1em; text-transform: uppercase; color: var(--muted-2); margin-bottom: 12px;
}
.hos-fdrawer__ft { display: flex; gap: 10px; padding: 16px 22px; border-top: 1px solid var(--hairline); }
.hos-fdrawer__ft .os-btn { flex: 1; }
.hos-fdrawer__n {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; padding: 0 5px; margin-left: 7px; border-radius: var(--radius-pill);
  background: var(--surface); color: var(--accent-strong);
  font-family: var(--font-mono); font-size: var(--text-2xs); font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
}

/* Prototype `.fseg--full` — the booking segmented control, radio-backed so it
   holds its choice with NO script (Apply submits the drawer form). */
.hos-fseg { display: flex; background: var(--slate-100); border-radius: var(--radius-md); padding: 3px; gap: 2px; }
.hos-fseg__o { flex: 1; position: relative; }
.hos-fseg__o input { position: absolute; opacity: 0; width: 0; height: 0; }
.hos-fseg__lbl {
  display: flex; align-items: center; justify-content: center; height: 32px;
  border-radius: var(--radius-sm); cursor: pointer;
  font-family: var(--font-sans); font-size: var(--text-xs); font-weight: var(--fw-semibold); color: var(--muted);
}
.hos-fseg__lbl:hover { color: var(--text-secondary); }
.hos-fseg__o input:checked + .hos-fseg__lbl { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-xs); }
.hos-fseg__o input:focus-visible + .hos-fseg__lbl { box-shadow: 0 0 0 3px var(--accent-soft); }

/* Slice-3 (perf/front-office-index-bounding): the reservations "Load more" control —
   centered under the card grid / list with breathing room above. The wrapper is ALWAYS
   rendered (stable turbo_stream replace target) but holds only whitespace when the backlog
   is exhausted, so the spacing is gated on :has(a) — no stray gap on the final slice. */
.hos-fo-loadmore:has(a) { display: flex; justify-content: center; margin-top: var(--space-6); }
