/* tasks/060 + tasks/161 — Speedboat transfer BOARDING BOARD (one run).
   Split cockpit: a 64px run header over `work | 336px rail`. Boarding owns the
   left column; every run FACT lives once, in the rail. Touch-first (40px board
   controls, 44px toolbar controls). Tokens only — no naked hex, no dark mode.

   tasks/161 P2b/P3 ported the approved mockups (public/mockups/tt/variant-c2 +
   the R3 "Editorial" rail from rail-explore). The mockups' `.hos-bp2-*` /
   `.hos-rl-*` prefixes were mockup-only scratch names; they land here as
   `.hos-bp-*`. Retired with that port: the 4-cell `.hos-bp-strip`, the slim
   `.hos-bp-topbar`, and the bottom `details.hos-bp-run` dispatch slab — all
   three folded into the header or the rail. */

.hos-boarding-body { margin: 0; background: var(--canvas); color: var(--ink); }
.hos-bp { display: flex; flex-direction: column; font-size: var(--text-md); }

/* tasks/062 — responsive nav. The board rides the app shell (diveos-shell), but a
   station tablet should stay immersive: keep the sidebar off-canvas (hamburger drawer)
   up to 1279px so every iPad — portrait AND landscape — is chromeless, and pin it only
   on a true desktop (≥1280px). This mirrors the app shell's own ≤1023px treatment
   (diveos_shell.css), scoped to .hos-boarding-body and lifted one tier up. */
@media (max-width: 1279px) {
  .hos-boarding-body .hos-shell { grid-template-columns: 1fr; }
  .hos-boarding-body .hos-shell-hamburger { display: inline-flex; }
  .hos-boarding-body .hos-shell-sidebar {
    position: fixed; top: 0; left: 0; width: var(--sidebar-w);
    transform: translateX(-100%);
    transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
    z-index: 50; height: 100vh;
  }
  .hos-boarding-body .hos-shell--menu-open .hos-shell-sidebar { transform: translateX(0); }
  .hos-boarding-body .hos-shell--menu-open .hos-shell-scrim {
    display: block; position: fixed; inset: 0; z-index: 40; background: rgba(15, 23, 32, 0.45);
  }
  /* Reserve a top-left gutter for the fixed 44px hamburger — the run header pins
     to the top of the pane and would otherwise sit under it. */
  .hos-boarding-body .hos-bp-ops { padding-left: 64px; }

  /* tasks/161 P2a — the board now rides layout "arena" with `is-rail-collapsed`
     (the 68px icon rail). That state is guarded to >=1024px in diveos_shell.css,
     but THIS surface keeps the sidebar off-canvas one tier higher (to 1279px), so
     in the 1024-1279 band the collapsed rail would still shrink the DRAWER to an
     unreadable 68px of icons. Restore the full drawer for that band only. */
  .hos-boarding-body .hos-shell.is-rail-collapsed .hos-shell-sidebar {
    width: var(--sidebar-w); padding: 24px 16px 16px;
  }
  .hos-boarding-body .hos-shell.is-rail-collapsed .hos-sidebar__brand-link > div,
  .hos-boarding-body .hos-shell.is-rail-collapsed .hos-sidebar__label,
  .hos-boarding-body .hos-shell.is-rail-collapsed .hos-sidebar__badge,
  .hos-boarding-body .hos-shell.is-rail-collapsed .hos-sidebar__owner-text,
  .hos-boarding-body .hos-shell.is-rail-collapsed .hos-sidebar__owner-actions { display: block; }
  .hos-boarding-body .hos-shell.is-rail-collapsed .hos-sidebar__owner-actions { display: flex; }
  .hos-boarding-body .hos-shell.is-rail-collapsed .os-sidebar__link { justify-content: flex-start; }
  .hos-boarding-body .hos-shell.is-rail-collapsed .hos-sidebar__nav .section-label {
    height: auto; text-indent: 0; background: none; overflow: visible;
  }
}

/* The board's sticky run header is a FULL-BLEED band and must BUTT the breadcrumb
   band above it (the standing "bands butt the bar above" rule). Without this the
   gem's header-band body gap applies — `.os-page-head + :not(.os-page-tools)…`
   -> margin-top: 2rem (os_ds.css) — and drops a 32px void between the two bands.
   It bites HERE and not on a normal page because that rule carries a
   `:has(.os-page-tools)` carve-out and this surface deliberately renders no tab
   band. Doubled class for specificity, scoped to this surface only — the gem rule
   still holds everywhere else. */
.hos-shell-content .os-page-head + .hos-bp.hos-bp { margin-top: 0; }

/* A head band carrying only a breadcrumb does not need a title band's vertical
   rhythm: the gem's 32/18 padding is sized for an h1 underneath it. With no
   title, close it up. */
.hos-boarding-body .os-page-head { padding-top: var(--space-5); padding-bottom: var(--space-4); }
.hos-boarding-body .os-page-head .os-breadcrumb { margin-bottom: 0; }

/* ── THE ONE HEADER. 64px. No second bar, no stat strip. ──
   It keeps an edge-to-edge bar by using the SHELL's own bleed custom properties
   (the sanctioned break-out, diveos_shell.css:378-381), exactly as .os-page-head
   above it does — so its content still lines up on the column's 48px gutter.
   Class name kept from the retired ops header: it is still the run's ops bar. */
.hos-bp-ops {
  flex: none; height: 64px; display: flex; align-items: center; gap: var(--space-3);
  width: var(--bleed-w, auto); margin-inline: var(--bleed-mx, 0);
  padding: 0 var(--bleed-pad, 0);
  background: var(--surface); border-bottom: 1px solid var(--hairline);
  position: sticky; top: 0; z-index: 19;
}
.hos-bp-ops__back {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; flex: none; border-radius: var(--radius);
  color: var(--muted); border: 1px solid var(--hairline); background: var(--surface);
}
.hos-bp-ops__back:hover { color: var(--ink); border-color: var(--hairline-strong); text-decoration: none; }
.hos-bp-ops__id { display: flex; align-items: baseline; gap: var(--space-2); min-width: 0; flex: 0 1 auto; overflow: hidden; }
.hos-bp-ops__title {
  margin: 0; font-family: var(--font-display); font-size: var(--text-lg);
  font-weight: 600; letter-spacing: -0.01em; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.hos-bp-ops__meta {
  display: flex; align-items: center; gap: 7px; flex-wrap: nowrap;
  font-size: var(--text-xs); color: var(--muted); flex: none;
}
.hos-bp-ops__meta .sep { color: var(--hairline-strong); }
.hos-bp-ops__meta > span { white-space: nowrap; }
.hos-bp-ops__meta .dep { color: var(--ink); font-weight: 600; }
.hos-bp-ops__end { margin-left: auto; display: flex; align-items: center; gap: var(--space-3); flex: none; }
.hos-bp-ops__end form { margin: 0; }

/* run switcher — a joined pair */
.hos-bp-runswitch { display: inline-flex; flex: none; }
.hos-bp-runswitch .os-btn { border-radius: 0; }
.hos-bp-runswitch .os-btn:first-child { border-radius: var(--radius) 0 0 var(--radius); }
.hos-bp-runswitch .os-btn:last-child { border-radius: 0 var(--radius) var(--radius) 0; margin-left: -1px; }
.hos-bp-runswitch .is-off { opacity: .4; pointer-events: none; }

/* ── the split: work | run ───────────────────────────────────────────────
   336px rail, matching the Front Office Details precedent
   (reservation_details.css .hos-body → 1fr 336px + .hos-rail sticky). ── */
.hos-bp-split {
  flex: 1; display: grid; grid-template-columns: 1fr 336px;
  column-gap: var(--space-6); align-items: start;
  /* Horizontal gutters + the bottom pad come from .hos-shell-content. */
  padding: var(--space-5) 0 0;
  min-width: 0;
}
.hos-bp-work { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.hos-bp-rail {
  display: flex; flex-direction: column; gap: var(--space-4);
  position: sticky; top: calc(64px + var(--space-5)); min-width: 0;
}

/* ── work toolbar: filter · search · walk-on · print, one line ──
   Every control in this bar is 44px — the jetty-tablet touch floor, and the
   height that makes the row read as one band rather than three. */
.hos-bp-mbar { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.hos-bp-mbar .hos-bp-search { flex: 1; min-width: 180px; }
.hos-bp-mbar__acts { display: inline-flex; gap: var(--space-2); flex: none; }
.hos-bp-mbar__acts .os-btn { min-height: 44px; }
.hos-bp-mbar__acts .os-btn--icon { min-height: 44px; min-width: 44px; }

.hos-bp-seg {
  display: inline-flex; background: var(--surface-alt); border-radius: var(--radius); padding: 3px; gap: 3px;
  /* Narrow viewports scroll this control sideways rather than letting the chips
     wrap: a wrapped chip broke mid-word ("Not / boarded") and the label of a
     filter is the whole affordance. */
  max-width: 100%; overflow-x: auto; scrollbar-width: none;
}
.hos-bp-seg::-webkit-scrollbar { display: none; }
.hos-bp-seg button {
  border: none; background: transparent; min-height: 38px; padding: 0 14px; border-radius: var(--radius-sm);
  font: inherit; font-size: var(--text-sm); font-weight: 600; color: var(--muted); cursor: pointer;
  display: flex; align-items: center; gap: 6px; flex: none; white-space: nowrap;
}
.hos-bp-seg button.on { background: var(--surface); color: var(--ink); box-shadow: 0 0 0 1px var(--hairline); }
.hos-bp-seg .n { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--text-xs); color: var(--muted-2); }
.hos-bp-seg button.on .n { color: var(--accent); }
.hos-bp-search {
  display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 14px; flex: 1; min-width: 160px;
  background: var(--surface); border: 1px solid var(--hairline-strong); border-radius: var(--radius);
}
.hos-bp-search input { border: none; outline: none; background: transparent; font: inherit; font-size: var(--text-base); width: 100%; color: var(--ink); }
.hos-bp-search svg { color: var(--muted-2); flex: none; }

/* ── passenger list ── */
.hos-bp-grid { display: flex; flex-direction: column; gap: var(--space-3); }
.hos-bp-empty { text-align: center; color: var(--muted-2); font-size: var(--text-base); padding: 40px 10px; }

/* a PARTY is a grouped unit: a head band + its member rows. */
.hos-bp-party {
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--radius-lg); overflow: hidden;
}
.hos-bp-party__head {
  display: flex; align-items: center; gap: var(--space-3);
  padding: 9px var(--space-4); background: var(--surface-alt);
  border-bottom: 1px solid var(--hairline);
}
.hos-bp-party__id { min-width: 0; flex: 1; }
.hos-bp-party__name { font-size: var(--text-sm); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hos-bp-party__sub {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: var(--text-xs); color: var(--muted); margin-top: 1px;
}
.hos-bp-party__sub .mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.hos-bp-party__aboard {
  flex: none; font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--text-xs); font-weight: 600; color: var(--muted);
}
.hos-bp-party__aboard--full { color: var(--status-confirmed-fg); }
.hos-bp-party__acts { display: inline-flex; gap: var(--space-2); flex: none; align-items: center; }
.hos-bp-party__acts form { margin: 0; }

/* a ROW is one human. A SOLO passenger is this and nothing else — no wrapper. */
.hos-bp-row {
  display: flex; align-items: center; gap: 13px;
  padding: 10px var(--space-4); min-height: 60px; background: var(--surface);
}
.hos-bp-row--solo { border: 1px solid var(--hairline); border-radius: var(--radius-lg); }
.hos-bp-party .hos-bp-row + .hos-bp-row { border-top: 1px solid var(--hairline-2); }
.hos-bp-row--done { background: var(--status-confirmed-bg); }
.hos-bp-row--noshow { opacity: 0.62; }
.hos-bp-row__body { flex: 1; min-width: 0; }
.hos-bp-row__name { font-size: var(--text-md); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hos-bp-row__meta {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  font-size: var(--text-xs); color: var(--muted); margin-top: 1px;
}
.hos-bp-row__meta .mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.hos-bp-row__meta .sep,
.hos-bp-party__sub .sep { color: var(--hairline-strong); }
.hos-bp-row__end { margin-left: auto; display: inline-flex; align-items: center; gap: var(--space-2); flex: none; }
.hos-bp-row__end form { margin: 0; }

/* board control — 40px touch target */
.hos-bp-chk {
  width: 40px; height: 40px; border-radius: 9px; flex: none; margin: 0; cursor: pointer;
  border: 2px solid var(--hairline-strong); background: var(--surface);
  display: flex; align-items: center; justify-content: center; color: transparent;
}
.hos-bp-row--done .hos-bp-chk { background: var(--status-confirmed-fg); border-color: var(--status-confirmed-fg); color: var(--surface); }
.hos-bp-row--noshow .hos-bp-chk { border-style: dashed; }
.hos-bp-chk:focus-visible { outline: none; box-shadow: var(--shadow-focus); }

/* ── rail cards (R3 "Editorial") ─────────────────────────────────────────
   44px head, 8/16/16 body. NO left accent stroke: the DISPATCH tag is the
   single permission marker, so a gated card is marked once, in words. ── */
.hos-bp-card {
  border-width: 1px; border-style: solid;
  border-radius: var(--radius-lg); overflow: hidden;
}
/* The COLOURS are split out behind :not(.os-card--danger) on purpose. This file
   loads after os_ds.css, so a bare `.hos-bp-card { background; border }` ties
   `.os-card--danger` on specificity (0,1,0) and wins on source order — the gem's
   danger modifier rendered as a plain white card, silently. Excluding the
   modifier here leaves the gem the SOLE owner of what "danger" looks like,
   rather than re-declaring its tokens locally and having to chase them. */
.hos-bp-card:not(.os-card--danger) {
  background: var(--surface); border-color: var(--hairline);
}
.hos-bp-card__head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  height: 44px; flex: none; padding: 0 var(--space-4);
}
.hos-bp-card__head-left  { display: inline-flex; align-items: center; gap: 7px; min-width: 0; }
.hos-bp-card__head-left svg { color: var(--muted-2); flex: none; }
.hos-bp-card__head-right { display: inline-flex; align-items: center; gap: 6px; flex: none; }
.hos-bp-card__body { padding: var(--space-2) var(--space-4) var(--space-4); }
.hos-bp-card__foot { display: flex; flex-wrap: wrap; gap: var(--space-2); padding: 0 var(--space-4) var(--space-4); }
.hos-bp-card__foot form { margin: 0; }
.hos-bp-card__foot > * { flex: 1 1 auto; }
/* the single permission marker */
.hos-bp-dtag {
  font-size: var(--text-2xs); font-weight: 700; letter-spacing: var(--ls-wider);
  text-transform: uppercase; color: var(--accent-strong);
  background: var(--accent-softer); border-radius: var(--radius-pill); padding: 2px 7px;
}
/* danger foot — the CARD is now the gem's `.os-card--danger` (os-ds v1.26.0),
   which owns the cancelled-hue border + wash and the tighter body top-padding,
   and `.os-card__note` owns the blast-radius line. Both were contributed UP
   after this board hand-rolled them; the local rules they replaced are gone.
   What stays local is the ACTION LAYOUT: stacked full-width in a 336px rail,
   side-by-side once the rail goes two-up. That is a rail-context decision, not
   a card one, so the gem deliberately does not ship it. */
.hos-bp-danger__acts { display: flex; flex-direction: column; gap: var(--space-2); }
.hos-bp-danger__acts form { margin: 0; }
.hos-bp-danger__acts .os-btn { width: 100%; }

/* the ONE gauge on the page — boarding. Seats are a LINE OF TEXT, never a
   second bar (two bars asked two different questions and read as one). */
.hos-bp-gauge__row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); }
.hos-bp-gauge__num {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--text-3xl); font-weight: 600; letter-spacing: -0.02em; line-height: 1.1;
}
.hos-bp-gauge__of  { font-size: var(--text-md); color: var(--muted); font-weight: 500; }
.hos-bp-gauge__lbl { font-size: var(--text-xs); color: var(--muted); }
.hos-bp-gauge__bar { margin-top: 10px; }
.hos-bp-bar { height: 8px; border-radius: var(--radius-pill); background: var(--surface-alt); overflow: hidden; }
.hos-bp-bar__fill { display: block; height: 100%; border-radius: var(--radius-pill); background: var(--accent); }
.hos-bp-bar__fill--ok { background: var(--status-confirmed-fg); }
.hos-bp-seats {
  margin-top: var(--space-3); padding-top: var(--space-3);
  border-top: 1px solid var(--hairline-2);
  font-size: var(--text-xs); color: var(--muted);
  display: flex; align-items: center; gap: 6px;
}
.hos-bp-seats svg { flex: none; }
.hos-bp-seats b { color: var(--ink); font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* VESSEL & CREW — one card, one question ("who is sailing this, on what").
   The boat leads as a SUBJECT (sans, display face — a name is identity, not
   telemetry); crew sit under a hairline as compact people rows. */
.hos-bp-subj { min-width: 0; }
.hos-bp-subj__name {
  font-family: var(--font-display); font-size: var(--text-lg); font-weight: 600;
  line-height: 1.25; color: var(--ink);
}
.hos-bp-subj__meta { font-size: var(--text-xs); color: var(--muted); margin-top: 3px; }
.hos-bp-crew {
  margin-top: var(--space-4); padding-top: var(--space-1);
  border-top: 1px solid var(--hairline);
}
.hos-bp-crew__lbl { display: block; margin: var(--space-3) 0 var(--space-1); }
.hos-bp-crew__list { display: flex; flex-direction: column; gap: var(--space-2); }
.hos-bp-crew__person { display: flex; align-items: center; gap: var(--space-3); }
.hos-bp-crew__person > span:last-child { min-width: 0; }
.hos-bp-crew__name { display: block; font-size: var(--text-sm); font-weight: 600; color: var(--ink); }
.hos-bp-crew__role { display: block; font-size: var(--text-xs); color: var(--muted); margin-top: 1px; }

/* ROUTE & TIMING — three unrelated labelled facts, so key/value earns its keep.
   A narrow fixed label column puts the value 96px from its label, always. */
.hos-bp-kv { display: flex; flex-direction: column; }
.hos-bp-kv__row {
  display: grid; grid-template-columns: 96px 1fr; gap: var(--space-3);
  align-items: baseline; min-height: 34px; padding: 6px 0;
}
.hos-bp-kv__row + .hos-bp-kv__row { border-top: 1px solid var(--hairline-2); }
.hos-bp-kv__k { font-size: var(--text-xs); color: var(--muted); font-weight: 500; }
.hos-bp-kv__v { font-size: var(--text-sm); color: var(--ink); font-weight: 500; min-width: 0; }
.hos-bp-kv__v--mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-weight: 600; }

/* ── 1023px: the rail must not squeeze the list. It MOVES BELOW the list —
      not behind a toggle: at a jetty the boarding gauge and the boat/crew facts
      must stay readable without a tap, and scrolling is cheaper than a panel. ── */
@media (max-width: 1023px) {
  /* Below 1023px the shell takes the sidebar off-canvas and collapses the grid to
     one column, but `.hos-shell.is-rail-collapsed { …: 68px 1fr }` is unscoped and
     outweighs it — leaving a phantom 68px column. The off-canvas rule wins here. */
  .hos-shell.is-rail-collapsed { grid-template-columns: 1fr; }

  /* the header keeps its 64px: the date and "run 4 of 4" drop out. */
  .hos-bp-ops__meta .opt { display: none; }
  .hos-bp-split { grid-template-columns: 1fr; row-gap: var(--space-5); }
  .hos-bp-work { order: 1; }
  /* two-up the rail cards so the run block does not become a long tail */
  .hos-bp-rail {
    order: 2; position: static;
    display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); align-items: start;
  }
  /* The danger card is the gem's `.os-card--danger` since v1.26.0 — these two
     rules must follow it, or the two-up rail silently loses its full-width
     danger row and its side-by-side actions. */
  /* SCOPED under .hos-bp-rail: a bare `.os-card--danger` here is a local redefinition of
     a selector the gem owns, and it applied to EVERY danger card app-wide in this viewport
     range, not just the rail's. The comment above already calls this "a rail-context
     decision, not a card one" — the selector now says so too. That is what
     config/ds_shadow_allowlist.json asks for ("scope it to the page that needs it")
     instead of allowlisting a shadow. */
  .hos-bp-rail .os-card--danger { grid-column: 1 / -1; }
  .hos-bp-rail .os-card--danger .hos-bp-danger__acts { flex-direction: row; }
}
@media (max-width: 719px) {
  .hos-bp-rail { grid-template-columns: 1fr; }
  /* ONE compact line, never a stack. Wrapping produced a 115px three-row header
     (nav / id-meta / status) that pushed the manifest — the only thing this
     screen is for — below the fold. What survives is what a phone needs: back,
     the route, the departure time, the status and the one primary action. The
     run switcher and the id/date/position meta are desktop affordances; the
     breadcrumb and the rail already carry that information. */
  .hos-bp-ops { height: 56px; flex-wrap: nowrap; gap: var(--space-2); }
  .hos-bp-runswitch { display: none; }
  /* The breadcrumb directly above collapses to a "< Airport Transfers" back
     link on a phone, so the arrow button is the same journey twice. */
  .hos-bp-ops__back { display: none; }
  .hos-bp-ops__title { font-size: var(--text-base); }
  .hos-bp-ops__meta { flex: 0 1 auto; min-width: 0; }
  .hos-bp-ops__meta > span:not(.dep) { display: none; }
  /* "departs 15:30" -> "15:30": at 390 the word costs more than the whole run
     title has to spend. The time keeps its mono/ink emphasis, so it still reads
     as the departure and not as a second id. */
  .hos-bp-ops__meta .dep .lbl { display: none; }
  .hos-bp-ops__end { gap: var(--space-2); }
}
@media (max-width: 560px) {
  /* Last thing to give at phone width is the primary action's LABEL, not the run
     title or the status pill: the icon keeps a 44px target, the button keeps its
     aria-label, and the confirm dialog still spells the action out. Dropping the
     pill instead would delete a run fact this screen states exactly once. */
  .hos-bp-ops__end .os-btn--primary .lbl { display: none; }
  .hos-bp-ops__end .os-btn--primary { min-width: 44px; justify-content: center; padding-inline: var(--space-3); }
}

/* The gem collapses a breadcrumb to a single "< Parent" back link below 640px —
   `.os-breadcrumb__sep, .os-breadcrumb__crumb:not(--parent) { display: none }`.
   `.os-page-head .os-breadcrumb__crumb { display: inline-flex }`
   (hos_guest_surfaces.css) ties it on specificity and wins on source order, so
   the trail stayed expanded with its separators hidden — three crumbs run
   together with nothing between them. Re-assert the collapse for THIS surface
   only: the app-wide rule cannot simply be restored, because `page_breadcrumb`
   renders a single crumb that carries no --parent marker and would vanish. */
@media (max-width: 640px) {
  .hos-boarding-body .os-page-head .os-breadcrumb__crumb:not(.os-breadcrumb__crumb--parent) { display: none; }
}

/* utilities (keep token-styles out of the ERB) */
.hos-bp .mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.hos-bp-check { display: flex; align-items: center; gap: 8px; font-size: var(--text-sm); color: var(--muted); }
.hos-bp-muted { color: var(--muted); font-size: var(--text-sm); }

/* ── VESSEL & CREW EDITOR (the rail's one drawer) ────────────────────────
   Ported from public/mockups/tt/r3-edit.html. The chassis is the canonical
   HotelOS drawer (.hos-odrawer + the gem's .os-side-panel), so only the
   deckhand sub-group needs classes of its own: it is the one part of the
   drawer that commits PER ROW while the boat and the captain save together in
   the single POST /transfers/assign. That split is why it is set apart by a
   rule and labelled "saved as you go" rather than silently mixed in. ── */
.hos-vc__sub { padding-top: var(--space-3); border-top: 1px solid var(--hairline); }
.hos-vc__subhead {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-2); margin-bottom: var(--space-2);
}
.hos-vc__sublabel {
  font-size: var(--text-2xs); font-weight: 700; letter-spacing: var(--ls-wider);
  text-transform: uppercase; color: var(--muted);
}
.hos-vc__ledger { font-size: var(--text-xs); color: var(--muted); }
.hos-vc__crew { display: flex; flex-direction: column; gap: var(--space-1); }
.hos-vc__crewrow { display: flex; align-items: center; gap: var(--space-2); }
.hos-vc__crewrow .os-profile-row { flex: 1; min-width: 0; }
.hos-vc__crewrow form { margin: 0; }
.hos-vc__add { margin-top: var(--space-3); display: flex; gap: var(--space-2); align-items: flex-end; }
.hos-vc__add .os-field { flex: 1; margin: 0; }
.hos-vc__hint { font-size: var(--text-xs); color: var(--muted); margin: var(--space-2) 0 0; line-height: 1.5; }
.hos-vc__empty {
  padding: var(--space-4); text-align: center; border: 1px dashed var(--hairline-strong);
  border-radius: var(--radius-md); color: var(--muted); font-size: var(--text-sm);
}
/* the boatless rail's single call to action fills the card foot */
.hos-bp-card__foot .hos-vc-trigger { width: 100%; justify-content: center; }

/* The refused-assignment violation list inside the Vessel & crew drawer (the desktop
   twin of the phone's blocked state). A plain <ul> in a callout keeps the browser
   bullets and a 40px indent; these are three short refusal reasons, not prose. */
.hos-vc__violations { margin: var(--space-1) 0 0; padding-left: var(--space-4); font-size: var(--text-xs); line-height: 1.5; }
