/* Longitude — Marine design, translated from web/design-ref/marine.dc.html.
   Palette, radii, shadows, spacing and type lifted verbatim from the approved canvas. */

:root {
  --paper: #eff2f5;
  --ink: #16202b;
  --amber: #f0a93b;
  --amber-dark: #e2991f;
  /* Text-only amber, distinct from --amber-dark's button-hover use: the
     shared token read as ink-on-amber-dark (fine) and amber-text-on-cream
     (2.14:1, an audit finding) — two different contrast requirements from
     one variable, so the chip gets its own. */
  --warn-text: #8a5a0a;
  --link: #1d5f8a;
  --link-dark: #123f5c;
  /* --muted/--faint darkened 2026-08-25 (audit finding): #6b7d8f and #8496a5
     read 4.24:1 / 3.05:1 against white, both under WCAG AA's 4.5:1 for the
     small secondary text they're used for across every view. */
  --muted: #526577;
  --faint: #5a6f80;
  --ghosttext: #2d4256;
  --slate: #4c6072;
  --line: #e4e9ee;
  --line2: #eaeef2;
  --ctl-border: #dce3e9;
  --hair: #e8edf1;
  --good: #1c7a5e;
  --bad: #b4482f;
  --serif: 'Playfair Display', Georgia, serif;
  --sans: 'Public Sans', system-ui, sans-serif;
}

html, body { margin: 0; padding: 0; background: var(--paper); }
* { box-sizing: border-box; }
body {
  min-height: 100vh;
  color: var(--ink);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
}
a { color: var(--link); text-decoration: none; }
button { font-family: var(--sans); }
button:focus-visible, select:focus-visible, input:focus-visible, a:focus-visible,
[role="button"]:focus-visible {
  outline: 2px solid var(--amber);
  outline-offset: 1px;
}

.wrap { max-width: 1680px; margin: 0 auto; padding-left: 28px; padding-right: 28px; }
.min0 { min-width: 0; }
.boot { padding: 90px 28px; text-align: center; color: var(--faint); font-size: 15px; }

/* ---------- shared controls (verbatim from the design's <style>) ---------- */
.navlink {
  font-size: 14.5px; font-weight: 500; color: var(--muted);
  cursor: pointer; padding: 7px 11px; border-radius: 9px;
  border: 0; background: transparent;
}
.navlink.active { color: var(--ink); background: var(--paper); }

.ctl {
  font-family: var(--sans); font-size: 14px; font-weight: 500; color: var(--ink);
  background: #fff; border: 1px solid var(--ctl-border); border-radius: 11px;
  padding: 9px 12px; cursor: pointer; appearance: none;
}

.prim {
  font-family: var(--sans); font-size: 14.5px; font-weight: 650; color: var(--ink);
  background: var(--amber); border: 0; border-radius: 11px; padding: 11px 18px; cursor: pointer;
}
.ghost {
  font-family: var(--sans); font-size: 14.5px; font-weight: 550; color: var(--ghosttext);
  background: #fff; border: 1px solid var(--ctl-border); border-radius: 11px;
  padding: 11px 18px; cursor: pointer;
}
.prim.sm, .ghost.sm { padding: 9px 15px; font-size: 14px; }
a.prim, a.ghost { display: inline-flex; align-items: center; }
a.prim, a.prim:hover { color: var(--ink); }
a.ghost, a.ghost:hover { color: var(--ghosttext); }

.chipx {
  font-family: var(--sans); font-size: 13.5px; font-weight: 600; color: var(--ink);
  background: #fdeccc; border: 1px solid #f3d69a; border-radius: 999px; padding: 6px 11px;
  cursor: pointer; display: inline-flex; align-items: center; gap: 7px;
}
.chipx .x { opacity: .5; font-weight: 500; }
input[type=range] { accent-color: var(--amber); }

.sailing {
  background: #fff; border: 1px solid var(--line); border-radius: 18px;
  box-shadow: 0 1px 2px rgba(22,32,43,.05);
  transition: box-shadow .16s, border-color .16s, transform .16s;
}

.kicker {
  font-size: 11.5px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--faint);
}
.kicker.pb { padding-bottom: 9px; }
.hr { height: 1px; background: var(--hair); margin: 14px 0; }
.hr2 { height: 1px; background: var(--line2); }

/* ---------- header ---------- */
.site-head { background: #fff; border-bottom: 1px solid var(--line); }
.head-inner { display: flex; align-items: center; gap: 22px; padding-top: 13px; padding-bottom: 13px; flex-wrap: wrap; }
.brand { display: flex; align-items: center; gap: 11px; }
.brandmark { width: 30px; height: 30px; flex: none; color: var(--ink); }
.brandname { font-family: var(--serif); font-weight: 500; font-size: 22px; letter-spacing: -.005em; }
.brandname em { font-style: italic; font-weight: 400; }
.navwrap { display: flex; min-width: 0; position: relative; }
.nav { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; }
.navhint { display: none; }
.navmore { appearance: none; -webkit-appearance: none; cursor: pointer; }
.navmore.active { color: var(--ink); background: var(--paper); }
.navmore-mobile { display: none; }
.head-right { margin-left: auto; display: flex; align-items: center; gap: 12px; flex: none; }
.regionbar { border-top: 1px solid var(--line); padding: 8px 0; }
.regionbar .tabstrip { max-width: 100%; }

/* Strips never widen the page: they scroll horizontally inside their own box
   at every viewport width (scrollbars hidden; wheel, drag, and Tab-focus all
   still reach off-screen tabs). */
.tabstrip {
  display: flex; border-radius: 11px; padding: 3px;
  max-width: 100%; overflow-x: auto;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.tabstrip::-webkit-scrollbar { display: none; }
.tabstrip.light { background: var(--paper); }
.tabstrip.grey { background: #e5eaef; }
.tab {
  border: 0; cursor: pointer; font-family: var(--sans); font-size: 13.5px; font-weight: 600;
  padding: 7px 14px; border-radius: 9px; background: transparent; color: var(--muted); white-space: nowrap;
}
.tab.active { background: #fff; color: var(--ink); box-shadow: 0 1px 3px rgba(22,32,43,.12); }
.tabstrip.cabins .tab { padding: 7px 13px; }
select.tabmore { appearance: none; -webkit-appearance: none; }

/* ---------- search: hero + map panel ---------- */
.hero { padding-top: 22px; }
.hero-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; padding-bottom: 16px; }
.headline { margin: 0; font-family: var(--serif); font-size: 32px; font-weight: 600; letter-spacing: -.015em; line-height: 1.1; }
.subhead { font-size: 14.5px; color: var(--muted); padding-top: 5px; }
/* Cold-start value proposition — see the `pitch` comment in app.js. Sits
   between the subhead and the stats row; disappears once a port is picked. */
.pitch {
  margin: 10px 0 0; max-width: 62ch; font-size: 14px; line-height: 1.6;
  color: var(--slate); text-wrap: pretty;
}
.pitch strong { color: var(--ink); font-weight: 650; }
/* Desktop shows the pitch outright, so its reveal control is mobile-only —
   mirrors how .mtoggle works for the map/filter collapses. */
.pitchtoggle { display: none; }
/* Mobile-only region picker; desktop keeps the tabstrip. */
.regionpick { display: none; }
.stats { display: flex; align-items: center; gap: 26px; }
.stat-v { font-family: var(--serif); font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums; }
.stat-l { font-size: 12px; color: var(--faint); letter-spacing: .02em; }

.mappanel { background: var(--ink); border-radius: 22px; padding: 14px; position: relative; }
.mapbox { position: relative; height: 420px; border-radius: 14px; overflow: hidden; }
/* #mappanel-aux wraps depcard/mapsearch/maplegend/port-tooltip so app.js can
   patch them in place without ever touching .mapbox's <cruise-map> (keeps its
   expensive connectedCallback from refiring on every filter tweak — see
   patchSearch() in app.js). display:contents makes the wrapper invisible to
   layout, so .depcard/.mapsearch keep resolving position:absolute against
   .mappanel (not this wrapper) and the mobile flex `order` rules below still
   apply to them directly, exactly as if the wrapper weren't there. */
#mappanel-aux { display: contents; }
/* Without this, a slow/uncertain drag starting over a port label can get
   claimed by the browser's native text-selection (or, on iOS, the
   long-press callout) instead of reaching d3-zoom's own pointer handling —
   observed live 2026-08-24: a drag selected a port name instead of panning.
   That's a second, independent way a drag can get interrupted, on top of
   the touchcancel issue fixed earlier tonight. */
cruise-map {
  display: block; position: absolute; inset: 0;
  -webkit-user-select: none; user-select: none;
  -webkit-touch-callout: none; -webkit-user-drag: none;
}

.depcard {
  position: absolute; left: 28px; top: 28px; width: 302px;
  background: rgba(255,255,255,.96); backdrop-filter: blur(6px);
  border-radius: 16px; padding: 16px 17px; box-shadow: 0 18px 44px -20px rgba(0,0,0,.55);
}
.deprow { display: flex; align-items: center; gap: 10px; padding-top: 7px; }
.depswatch { width: 11px; height: 11px; border-radius: 3px; background: var(--amber); flex: none; }
.depname { font-family: var(--serif); font-size: 22px; font-weight: 600; line-height: 1.1; }
.deprow .navlink { margin-left: auto; padding: 4px 8px; font-size: 13px; }
.dephint { font-size: 14px; line-height: 1.5; color: var(--muted); padding-top: 6px; }
.stophead { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.stophead .navlink { padding: 3px 7px; font-size: 12.5px; }
.stopchips { display: flex; flex-wrap: wrap; gap: 6px; padding-top: 8px; }
.stopchips .dephint { padding-top: 0; }

.maplegend {
  position: absolute; right: 28px; bottom: 28px; display: flex; flex-wrap: wrap; gap: 8px 18px;
  background: rgba(22,32,43,.72); backdrop-filter: blur(6px); border-radius: 12px; padding: 9px 13px;
}
.lg { display: flex; align-items: center; gap: 7px; font-size: 12px; font-weight: 500; color: #cfd9e2; }
.lg-dep { width: 9px; height: 9px; border: 1.5px solid rgba(233,239,245,.6); border-radius: 50%; }
.lg-from { width: 9px; height: 9px; background: var(--amber); border-radius: 2px; }
.lg-call { width: 9px; height: 9px; border: 1.6px solid var(--amber); border-radius: 50%; }
.lg-route { width: 20px; border-top: 2px dashed var(--amber); }

/* Map v2: port search overlay (top-right of the map panel, mirrors .depcard). */
.mapsearch { position: absolute; right: 28px; top: 28px; width: 230px; z-index: 3; }
.mapsearch .ctl {
  width: 100%; background: rgba(255,255,255,.96); backdrop-filter: blur(6px); border: 0;
  border-radius: 12px; padding: 11px 14px; box-shadow: 0 18px 44px -20px rgba(0,0,0,.55);
  cursor: text;
}
.mapsearch .ctl::placeholder { color: var(--faint); }
.portsearch-list {
  margin-top: 6px; background: rgba(255,255,255,.98); backdrop-filter: blur(6px);
  border-radius: 12px; overflow: hidden auto; max-height: 264px;
  box-shadow: 0 18px 44px -20px rgba(0,0,0,.55);
}
.portsearch-item {
  display: flex; align-items: baseline; gap: 8px; width: 100%; text-align: left;
  font-family: var(--sans); font-size: 13.5px; font-weight: 600; color: var(--ink);
  background: transparent; border: 0; padding: 9px 13px; cursor: pointer;
}
.portsearch-item .ps-place { font-weight: 500; color: var(--muted); font-size: 12px; }
.portsearch-item:hover, .portsearch-item.active { background: var(--paper); }
.portsearch-empty { padding: 10px 13px; font-size: 13px; color: var(--muted); }

/* ---------- mobile collapse (map guide + filter panel) ----------
   Toggle buttons exist in the markup at every width but are display:none
   above 720px, where both panels cost nothing (the depcard is a map
   overlay, the filter bar is two compact rows). Below 720px they became
   the whole first screen — see the .mtoggle rules in the mobile block. */
.mtoggle { display: none; }
.mbody { display: block; }

/* ---------- search: filters ---------- */
.filters-wrap { padding-top: 18px; }
.filters {
  background: #fff; border: 1px solid var(--line); border-radius: 18px; padding: 13px 16px;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.filters .navlink { font-size: 13.5px; }
.filters-right { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.pricectl {
  display: flex; align-items: center; gap: 10px; background: #fff;
  border: 1px solid var(--ctl-border); border-radius: 11px; padding: 8px 13px;
}
.pricectl > span { font-size: 13.5px; font-weight: 500; color: var(--muted); white-space: nowrap; }
.pricerow { display: flex; align-items: center; gap: 6px; }
.pricecur { font-size: 13.5px; color: var(--faint); }
.pricerow input[type="number"] {
  width: 58px; border: 1px solid var(--ctl-border); border-radius: 7px;
  padding: 3px 6px; font-size: 13.5px; font-variant-numeric: tabular-nums;
  font-family: var(--sans); color: var(--ink);
}
.pricerow input[type="number"]::-webkit-inner-spin-button,
.pricerow input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.pricerow input[type="range"] { width: 112px; }

.resulthead { padding-top: 20px; display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.rescount { font-size: 15px; color: var(--muted); }
.rescount b { font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.cabins { display: flex; align-items: center; gap: 9px; }
.cabins-label { font-size: 13px; color: var(--faint); }
.cabins.guests { margin-left: auto; }

/* Solo (1-guest) price tag — SOLO-CONTRACT.md: a small neutral/muted chip,
   distinct from the A-F grade chip colors (.gradechip/.gradedot above), since
   it's a confidence signal on the fare source, not a value judgment on the
   fare itself. Never shown in 2-guest mode. */
.estchip {
  display: inline-block; margin-left: 7px; font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .03em; padding: 2px 7px;
  border-radius: 999px; background: #eef1f4; color: #6b7d8f;
  vertical-align: middle; cursor: help;
}
.estchip-fallback { background: var(--paper); color: var(--faint); }

/* Taxes-unquoted flag — the line didn't publish a tax split at search time,
   so the displayed total is cruise-fare-only even in "with taxes" mode; the
   real total is unknown until you check the line's own site. Amber (not the
   neutral .estchip gray) because this one genuinely needs the reader's
   attention before they compare it against a fare that DOES include taxes. */
.taxflag {
  display: inline-block; font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .03em; padding: 2px 7px; border-radius: 999px;
  background: #fdf1de; color: var(--warn-text); cursor: help;
}

/* Per-person / total-for-2 caption under a headline price — quiet by design
   (plain small text, not a chip) since it repeats on every result row; a
   loud badge that often would read as noise. Never shown in solo mode
   (priceModeTagHtml() returns '' there — soloTagHtml's chip covers it). */
.pricemodetag { display: block; font-size: 11px; font-weight: 400; color: var(--faint); margin-top: 2px; }

/* ---------- search: result rows ---------- */
.results { padding-top: 14px; padding-bottom: 64px; display: flex; flex-direction: column; gap: 12px; list-style: none; margin: 0; }
.loadmore {
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 10px 16px;
  color: var(--muted); font-size: 13.5px; padding: 8px 0 2px;
}
.srow {
  display: grid;
  grid-template-columns: 52px minmax(0,1.5fr) minmax(0,1fr) minmax(0,.65fr) minmax(0,.8fr) minmax(0,.95fr) minmax(0,.85fr) 22px;
  gap: 14px 16px; align-items: center; padding: 17px 20px; cursor: pointer;
}
.codechip {
  width: 44px; height: 44px; border-radius: 13px; display: grid; place-items: center;
  background: var(--paper); color: var(--ghosttext); font-weight: 750; font-size: 14px; letter-spacing: .03em;
}
.srow-meta { display: none; } /* mobile-only summary line; grid placement skips it on desktop */
.sname { font-family: var(--serif); font-size: 20px; font-weight: 600; line-height: 1.2; letter-spacing: -.01em; text-wrap: pretty; }
.sdates { font-size: 13.5px; color: var(--muted); padding-top: 3px; font-variant-numeric: tabular-nums; }
.sline { font-size: 13px; color: var(--faint); }
.shipname { font-size: 14.5px; font-weight: 600; color: var(--link); }
.shipmeta { font-size: 13px; color: var(--faint); font-variant-numeric: tabular-nums; }
.cellbig { font-size: 16px; font-weight: 650; }
.cellsub { font-size: 13px; color: var(--faint); }
.cellsub.pretty { text-wrap: pretty; }
.turn { font-size: 14.5px; font-weight: 550; }
.cell-price { text-align: right; }
.pernight { font-family: var(--serif); font-size: 26px; font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; }
.pn-sub { font-size: 12px; color: var(--faint); }
.total { font-size: 13.5px; font-weight: 550; padding-top: 3px; font-variant-numeric: tabular-nums; }
.gradechip { display: inline-flex; align-items: center; gap: 7px; border-radius: 999px; padding: 5px 11px 5px 8px; max-width: 100%; }
.gradedot {
  width: 19px; height: 19px; border-radius: 50%; display: grid; place-items: center;
  color: #fff; font-size: 11.5px; font-weight: 750; flex: none;
}
.gradelabel { font-size: 12.5px; font-weight: 600; min-width: 0; }
.dropline { font-size: 12.5px; font-weight: 600; padding-top: 5px; }
.dropline.down { color: var(--good); }
.dropline.up { color: var(--bad); }
.chev { text-align: right; font-size: 12px; color: #a9b8c5; }

/* ---------- search: expanded detail ---------- */
.sdetail {
  border-top: 1px solid var(--line2); background: #f8fafb; border-radius: 0 0 18px 18px; padding: 20px;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); gap: 26px;
  cursor: default;
}
.minimap { height: 222px; background: var(--ink); border-radius: 14px; overflow: hidden; position: relative; }
.minimap.routes { height: 186px; }
.routetext { font-size: 13.5px; line-height: 1.55; color: var(--muted); padding-top: 10px; text-wrap: pretty; }
.daylist, .farelist { display: flex; flex-direction: column; gap: 1px; }
.dayrow {
  display: grid; grid-template-columns: 1fr auto; gap: 12px; align-items: baseline;
  background: #fff; border-radius: 9px; padding: 9px 12px;
}
.dayname { font-size: 14px; font-weight: 600; }
.daykind { font-size: 12.5px; color: var(--faint); }
.farerow {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  background: #fff; border-radius: 9px; padding: 10px 12px;
}
.farecabin { font-size: 14px; font-weight: 600; display: inline-flex; align-items: center; gap: 7px; }
.gletter {
  width: 19px; height: 19px; border-radius: 50%; display: inline-grid; place-items: center;
  color: #fff; font-size: 11.5px; font-weight: 750;
}
.fareright { text-align: right; }
.farepp { font-size: 14.5px; font-weight: 650; font-variant-numeric: tabular-nums; }
.faresub { font-size: 12px; color: var(--faint); font-variant-numeric: tabular-nums; }
.upgradetag {
  display: inline-block; font-size: 11px; font-weight: 600;
  color: var(--amber); background: rgba(240,169,59,.12);
  padding: 1px 6px; border-radius: 4px;
}
.farestale { color: var(--muted); }
.movesignal {
  font-size: 13.5px; line-height: 1.55; color: var(--muted);
  background: var(--paper); border-radius: 10px; padding: 10px 13px;
}
.movesignal strong { color: var(--ink); }
.farenote { font-size: 13.5px; line-height: 1.55; color: var(--muted); padding-top: 12px; }
.sisterwrap { padding-top: 12px; }
.sisterstrip {
  display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.sisterstrip::-webkit-scrollbar { display: none; }
.sisterchip {
  display: inline-flex; flex-direction: column; align-items: center; gap: 2px;
  background: #fff; border: 1px solid var(--line2); border-radius: 10px;
  padding: 7px 12px; cursor: pointer; flex: none; text-align: center; font-family: var(--sans);
  transition: border-color .12s, transform .12s, box-shadow .12s;
}
.sisterchip:hover { border-color: var(--amber); transform: translateY(-1px); box-shadow: 0 3px 8px rgba(22,32,43,.06); }
.sisterchip.cheapest { border-color: var(--good); background: #f6fcf8; }
.sdate { font-size: 12px; font-weight: 600; color: var(--muted); }
.sfare { font-size: 13.5px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.sbadge { font-size: 10px; font-weight: 700; text-transform: uppercase; color: var(--good); letter-spacing: .02em; }
.sistermore { align-self: center; font-size: 12px; color: var(--faint); font-weight: 600; padding: 0 4px; }
.detailbtns { display: flex; flex-wrap: wrap; gap: 9px; padding-top: 10px; }
.agentpitch {
  margin-top: 14px; padding: 12px 14px; border-radius: 12px;
  background: #fdf6e8; border: 1px solid #f3e2b3;
}
.agentpitch-h { font-size: 14px; font-weight: 700; color: var(--ink); }
.agentpitch-b { font-size: 13px; color: var(--slate); padding-top: 3px; line-height: 1.4; }
.agentcta { flex: 1 1 auto; }
.directlink {
  display: block; margin-top: 10px; font-size: 12.5px; color: var(--faint);
  text-decoration: underline; text-underline-offset: 2px;
}
.directlink:hover { color: var(--muted); }

/* ---------- active filter chips ---------- */
.active-filters-wrap { padding-top: 14px; }
.active-filters { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; font-size: 13.5px; }
.af-label { font-size: 12px; font-weight: 700; color: var(--faint); text-transform: uppercase; letter-spacing: .03em; margin-right: 4px; }
.chipx {
  display: inline-flex; align-items: center; gap: 6px;
  background: #fff; border: 1px solid var(--ctl-border); border-radius: 999px;
  padding: 5px 11px; font-size: 12.5px; font-weight: 600; color: var(--ink);
  cursor: pointer; font-family: var(--sans); transition: background .12s, border-color .12s;
}
.chipx:hover { background: #f0f4f8; border-color: var(--ghosttext); }
.chipx .x { color: var(--faint); font-size: 11px; font-weight: 700; margin-left: 2px; }
.chipx:hover .x { color: var(--bad); }

/* ---------- map port hover tooltip ---------- */
.port-tooltip {
  position: absolute; left: 28px; bottom: 28px; max-width: 320px;
  background: rgba(22,32,43,.92); backdrop-filter: blur(8px);
  border-radius: 14px; padding: 12px 16px; color: #fff;
  box-shadow: 0 16px 36px -12px rgba(0,0,0,.6); z-index: 4;
  pointer-events: none; transition: opacity .15s ease;
}
.pt-title { font-family: var(--serif); font-size: 17px; font-weight: 600; line-height: 1.2; color: #fff; }
.pt-place { font-family: var(--sans); font-size: 12px; font-weight: 500; color: #cfd9e2; margin-left: 4px; }
.pt-meta { font-size: 12.5px; color: #a9b8c5; margin-top: 4px; line-height: 1.4; }
.pt-from { color: var(--amber); font-weight: 600; }

/* ---------- empty / error cards ---------- */
.emptycard { background: #fff; border: 1px solid var(--line); border-radius: 18px; padding: 34px 26px; max-width: 52ch; }
.emptytitle { font-family: var(--serif); font-size: 26px; font-weight: 600; line-height: 1.2; }
.emptybody { font-size: 15px; line-height: 1.55; color: var(--muted); padding-top: 8px; }
.emptycard .prim { margin-top: 16px; }
.errwrap { padding-top: 48px; padding-bottom: 64px; }

/* ---------- generic view scaffolding (deals / routes / ships / watchlist) ---------- */
.view { padding-top: 26px; padding-bottom: 64px; }
.view-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; padding-bottom: 18px; }

/* ---------- deals ---------- */
.dealcontrols {
  display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap;
  padding: 13px 14px; margin-bottom: 16px; background: #fff;
  border: 1px solid var(--line); border-radius: 13px;
}
.dealctl { display: flex; flex-direction: column; gap: 5px; min-width: 150px; }
.dealctl > span { font-size: 11.5px; font-weight: 700; color: var(--faint); text-transform: uppercase; letter-spacing: .06em; }
.dealctl.dealsort { min-width: 220px; }
.dealcount { margin-left: auto; padding: 9px 2px; font-size: 13px; color: var(--muted); }
.dealgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 330px), 1fr)); gap: 14px; list-style: none; padding: 0; margin: 0; }
.dealcard { padding: 18px 19px; display: flex; flex-direction: column; gap: 12px; }
.dealtop { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.dealline { font-size: 12.5px; font-weight: 600; color: var(--faint); }
.dealname { font-family: var(--serif); font-size: 21px; font-weight: 600; line-height: 1.18; letter-spacing: -.01em; padding-top: 2px; text-wrap: pretty; }
.dealpct { flex: none; background: #e4f4ec; color: #155c47; border-radius: 999px; padding: 6px 11px; font-size: 13px; font-weight: 700; }
.dealprice { display: flex; align-items: baseline; gap: 10px; }
.dealnow { font-family: var(--serif); font-size: 28px; font-weight: 600; line-height: 1; font-variant-numeric: tabular-nums; }
.dealwas { font-size: 14.5px; color: #a9b8c5; text-decoration: line-through; font-variant-numeric: tabular-nums; }
.dealpn { font-size: 12.5px; color: var(--faint); margin-left: auto; }
.dealmeta { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 13.5px; color: var(--slate); }
.dealroute { font-size: 13.5px; line-height: 1.5; color: var(--muted); text-wrap: pretty; }
.dealbtns { display: flex; align-items: center; gap: 9px; padding-top: 2px; }
.dealmore { display: flex; justify-content: center; padding-top: 18px; }

/* ---------- routes ---------- */
.routelist { display: flex; flex-direction: column; gap: 12px; list-style: none; padding: 0; margin: 0; }
.routegroup {
  display: grid; grid-template-columns: minmax(0,.9fr) minmax(0,1.6fr) minmax(0,.6fr);
  gap: 22px; align-items: stretch; padding: 16px;
}
.routemid { min-width: 0; display: flex; flex-direction: column; gap: 9px; }
.routeport { font-family: var(--serif); font-size: 24px; font-weight: 600; letter-spacing: -.012em; line-height: 1.12; }
.routemeta { font-size: 13.5px; color: var(--faint); }
.callchips { display: flex; flex-wrap: wrap; gap: 6px; }
.callchip { font-size: 13px; font-weight: 550; color: var(--ghosttext); background: var(--paper); border-radius: 999px; padding: 5px 10px; }
.routelines { font-size: 13.5px; color: var(--muted); }
.routeside { display: flex; flex-direction: column; justify-content: space-between; align-items: flex-end; text-align: right; gap: 10px; }
.fromlabel { font-size: 12.5px; color: var(--faint); }
.fromfare { font-family: var(--serif); font-size: 28px; font-weight: 600; line-height: 1.05; font-variant-numeric: tabular-nums; }

/* ---------- ships ---------- */
.shipcontrols { display: flex; gap: 9px; flex-wrap: wrap; }
.shipcontrols .ctl { min-width: 160px; }
.shipgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 360px), 1fr)); gap: 14px; margin-top: 16px; list-style: none; padding: 0; }
.shipcard { padding: 18px 19px; display: flex; flex-direction: column; gap: 13px; }
.shiptop { display: flex; align-items: flex-start; gap: 13px; }
.shipchip {
  width: 46px; height: 46px; border-radius: 14px; flex: none; display: grid; place-items: center;
  background: var(--ink); color: var(--amber); font-weight: 750; font-size: 14px; letter-spacing: .03em;
}
.shiptitle { font-family: var(--serif); font-size: 21px; font-weight: 600; line-height: 1.15; letter-spacing: -.01em; }
.shipline { font-size: 13.5px; color: var(--faint); }
.shipfrom { margin-left: auto; text-align: right; flex: none; }
.shipfrom .l { font-size: 12.5px; color: var(--faint); }
.shipfrom .v { font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums; }
.shipstats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--line2); border-radius: 11px; overflow: hidden; }
.shipstat { background: #f8fafb; padding: 10px 12px; }
.shipstat .v { font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; }
.shipstat .l { font-size: 12px; color: var(--faint); }
.shipstat .refit { font-size: 12.5px; font-weight: 600; color: var(--faint); }
.itins { display: flex; flex-direction: column; gap: 7px; }
.itin { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.itin .n { font-size: 14px; font-weight: 600; min-width: 0; }
.itin .m { font-size: 13px; color: var(--faint); white-space: nowrap; }
.itin-more { font-size: 13px; color: var(--faint); }
/* "Featured on board" chips — positive claims from the line's own ship page. */
.shipfeats { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.shipfeats .l { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--faint); margin-right: 2px; }
.featchip { font-size: 12px; font-weight: 600; padding: 3px 9px; border-radius: 999px; background: #eef4f8; color: #33566e; white-space: nowrap; }
.featchip.more { background: none; color: var(--faint); font-weight: 500; }
.shipcard .ghost { align-self: flex-start; }

/* ---------- watchlist ---------- */
.wlgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 560px), 1fr)); gap: 14px; align-items: start; }
.wlrows { display: flex; flex-direction: column; gap: 12px; list-style: none; padding: 0; margin: 0; }
.wlrow {
  display: grid; grid-template-columns: 52px minmax(0,1.5fr) minmax(0,.8fr) minmax(0,1fr) minmax(0,1fr);
  gap: 14px 16px; align-items: center; padding: 17px 20px;
}
.wlname { font-family: var(--serif); font-size: 19px; font-weight: 600; line-height: 1.2; }
.wlmeta { font-size: 13px; color: var(--faint); }
.wlnights { font-size: 15px; font-weight: 650; }
.wlcabin { font-size: 12.5px; color: var(--faint); }
.wlnow { font-size: 19px; font-weight: 700; font-variant-numeric: tabular-nums; }
.wlchange { font-size: 12.5px; font-weight: 600; text-wrap: pretty; }
.wlchange.down { color: var(--good); }
.wlchange.up { color: var(--bad); }
.wlchange.flat, .wlchange.gone { color: var(--faint); }
.wlbtns { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; min-width: 0; }
.wlbtns .prim, .wlbtns .ghost { padding: 9px 14px; font-size: 13.5px; }
.alertcard { padding: 18px 19px; display: flex; flex-direction: column; gap: 13px; }
.alertfoot { font-size: 13.5px; line-height: 1.55; color: var(--muted); }
.alertcard .prim { align-self: flex-start; }

/* ---------- account control (header) ---------- */
.head-account { display: flex; align-items: center; gap: 8px; flex: none; }
.account-email { font-size: 13.5px; font-weight: 600; color: var(--ghosttext); white-space: nowrap; }
.navlink.acct-del { color: #a3372f; }
.navlink.acct-del:hover { color: #fff; background: #a3372f; }
.fullpending {
  position: fixed; left: 14px; bottom: 14px; z-index: 60;
  background: var(--ink); color: var(--paper);
  font-size: 12.5px; font-weight: 600; letter-spacing: .2px;
  padding: 8px 13px; border-radius: 999px; box-shadow: 0 2px 10px rgba(0,0,0,.18);
  opacity: .92; pointer-events: none;
}
@media (max-width: 720px) { .fullpending { left: 10px; bottom: 10px; font-size: 12px; } }

/* ---------- sign-in modal (renders into #overlay, outside #app) ---------- */
#overlay:empty { display: none; }
#overlay { position: fixed; inset: 0; bottom: auto; height: 100dvh; z-index: 50; display: grid; place-items: center; padding: 20px; }
.modal-back { position: absolute; inset: 0; background: rgba(22,32,43,.45); }
.modal {
  position: relative; width: min(420px, 100%); background: #fff; border-radius: 16px;
  padding: 22px 22px 20px; box-shadow: 0 24px 60px -24px rgba(0,0,0,.5);
  font-family: var(--sans);
  /* Never taller than the viewport: the booking form outgrew small screens
     and its submit button became unreachable (reported live 2026-08-24) —
     the modal itself scrolls instead. */
  max-height: 100%; overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}
.modal:has(.cmprow) { width: min(720px, 100%); }
.modal-title { font-family: var(--serif); font-size: 24px; font-weight: 600; letter-spacing: -.012em; }
.modal-body { font-size: 14.5px; line-height: 1.55; color: var(--muted); padding-top: 8px; }
.modal input.ctl { width: 100%; cursor: text; }
.modal select.ctl, .modal textarea.ctl { width: 100%; }
.modal textarea.ctl { resize: vertical; min-height: 64px; font-family: var(--sans); }
/* Visible field labels (2026-08-25 audit finding): the booking/sign-in
   fields relied on aria-label + placeholder only, no persistent visible
   label. A label now owns the top margin between stacked fields; the input
   itself sits flush under it. */
.modal-field { margin-top: 14px; }
.modal-field label {
  display: block; margin-bottom: 6px; font-size: 11px; font-weight: 650;
  letter-spacing: .04em; text-transform: uppercase; color: var(--muted);
}
.modal-field .req { color: var(--bad); margin-left: 2px; }
.modal-field input.ctl, .modal-field select.ctl, .modal-field textarea.ctl { margin-top: 0; }
.modal-err { font-size: 13.5px; font-weight: 600; color: var(--bad); padding-top: 8px; }
.modal-btns { display: flex; flex-wrap: wrap; gap: 9px; padding-top: 14px; }
.modal .prim[disabled] { opacity: .6; cursor: default; }
/* Read-only sailing summary pinned to a booking-agent lead — same idea as
   .depswatch/.deprow's quiet confirmation chrome elsewhere, not an input. */
.modal-sailing {
  margin-top: 14px; padding: 10px 12px; background: var(--paper); border-radius: 10px;
  font-size: 13px; line-height: 1.5; color: var(--muted);
}

/* ---------- toasts ---------- */
#toasts {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 22px; z-index: 60;
  display: flex; flex-direction: column; align-items: center; gap: 8px; pointer-events: none;
}
.toast {
  background: var(--ink); color: #eef3f8; font-size: 13.5px; font-weight: 550;
  border-radius: 11px; padding: 10px 16px; max-width: min(92vw, 480px); text-align: center;
  box-shadow: 0 10px 30px -12px rgba(0,0,0,.5);
}

/* ---------- watchlist sign-in note ---------- */
.linklike {
  border: 0; background: none; padding: 0; color: var(--link);
  font-family: var(--sans); font-size: inherit; font-weight: 600; cursor: pointer;
}
.wl-signin-note { font-size: 13.5px; color: var(--muted); padding-top: 6px; }

/* ---------- footer ---------- */
.site-foot { border-top: 1px solid var(--line); }
.footinner {
  display: flex; flex-wrap: wrap; gap: 8px 24px; justify-content: space-between;
  padding-top: 18px; padding-bottom: 40px; font-size: 13px; color: var(--faint); line-height: 1.5;
}
.freshness { font-variant-numeric: tabular-nums; }
.freshwarn { color: var(--bad); font-weight: 600; }
/* flex-wrap (2026-08-27 audit, HIGH): without it the 9-link row forced a
   709px min-width — every page horizontally overflowed on phones, rendering
   ~0.53x zoomed-out, and the fixed consent banner landed OUTSIDE the visible
   viewport, hiding the CPRA notice from all mobile visitors. */
.footlinks { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.footlinks .navlink { font-size: 13px; padding: 4px 8px; }
.buildver { font-size: 11px; opacity: .7; }

/* ---------- crossings (repositioning finder) ---------- */
.xinggrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr)); gap: 14px; list-style: none; padding: 0; margin: 0; }
.xingcard { padding: 17px 18px; display: flex; flex-direction: column; gap: 12px; }
.xingtop { display: flex; align-items: flex-start; gap: 12px; }
.xingroute { font-family: var(--serif); font-size: 18px; font-weight: 600; line-height: 1.2; text-wrap: pretty; }
.xingmeta { font-size: 13px; color: var(--faint); padding-top: 3px; }
.xingnums { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--line2); border-radius: 11px; overflow: hidden; }
.xingnums .xn { background: #f8fafb; padding: 9px 12px; }
.xingnums .v { font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; }
.xingnums .l { font-size: 11.5px; color: var(--faint); }
.xingkick { padding: 26px 0 12px; }

/* ---------- fare-history sparkline (expanded row) ---------- */
.sparkwrap { padding-top: 14px; }
.sparkrow { display: flex; align-items: center; gap: 12px; }
.spark { display: block; }
.sparklegend { display: flex; flex-direction: column; font-size: 12.5px; color: var(--faint); font-variant-numeric: tabular-nums; }
.sparknow { font-weight: 700; }

/* ---------- deals: month heat strip ---------- */
.heatwrap { padding-bottom: 18px; }
.heatstrip { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 4px; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.heatstrip::-webkit-scrollbar { display: none; }
.heatcell {
  flex: none; display: flex; flex-direction: column; align-items: center; gap: 2px;
  border: 1px solid var(--line2); border-radius: 10px; padding: 8px 12px;
  cursor: pointer; font-family: var(--sans); transition: border-color .12s, transform .12s;
}
.heatcell:hover { border-color: var(--good); transform: translateY(-1px); }
.heatcell .hm { font-size: 12px; font-weight: 600; color: var(--ghosttext); }
.heatcell .hv { font-size: 13.5px; font-weight: 700; font-variant-numeric: tabular-nums; }

/* ---------- inversions ---------- */
.invgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr)); gap: 14px; list-style: none; padding: 0; margin: 0; }
.invcard { padding: 17px 18px; display: flex; flex-direction: column; gap: 11px; }
.invtop { display: flex; align-items: flex-start; gap: 12px; }
.invname { font-family: var(--serif); font-size: 17.5px; font-weight: 600; line-height: 1.2; text-wrap: pretty; }
.invmeta { font-size: 13px; color: var(--faint); padding-top: 3px; }
.invpair { display: flex; align-items: center; gap: 12px; background: #f8fafb; border-radius: 11px; padding: 10px 14px; }
.invside .l { font-size: 12px; color: var(--faint); }
.invside .v { font-size: 18px; font-weight: 700; font-variant-numeric: tabular-nums; }
.invside .v.good { color: var(--good); }
.invlt { font-size: 18px; font-weight: 700; color: var(--faint); }
.invsave { font-size: 13px; font-weight: 600; color: var(--good); }

/* ---------- compare tray + modal ---------- */
.cmptray {
  /* below #overlay (z 50): the modal backdrop must cover the tray */
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 16px; z-index: 45;
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px; max-width: min(94vw, 780px);
  background: #fff; border: 1px solid var(--line); border-radius: 14px;
  box-shadow: 0 6px 24px rgba(22,32,43,.14); padding: 10px 12px;
}
.cmpchips { display: contents; }
.cmp-mobile-summary { display: none; }
.cmphint { font-size: 12.5px; color: var(--faint); }
.cmpscroll { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 4px -4px 0; padding: 0 4px; }
.cmprow { display: flex; gap: 12px; }
.cmpcol {
  flex: 1 0 200px; min-width: 200px; display: flex; flex-direction: column; gap: 7px;
  background: var(--paper); border-radius: 12px; padding: 13px 14px;
}
.cmpname { font-family: var(--serif); font-size: 16.5px; font-weight: 600; line-height: 1.2; }
.cmpmeta { font-size: 12.5px; color: var(--muted); line-height: 1.4; }
.cmpstat { font-size: 13px; font-weight: 600; }
.cmpfare { display: flex; justify-content: space-between; align-items: baseline; font-size: 13.5px; }
.cmpfare .l { color: var(--faint); }
.cmpfare .v { font-weight: 700; font-variant-numeric: tabular-nums; }
.cmpgrade {
  display: inline-grid; place-items: center; width: 16px; height: 16px; border-radius: 50%;
  color: #fff; font-size: 10px; font-weight: 750; vertical-align: 2px;
}
.cmpcol .ghost.sm { margin-top: auto; }

/* ---------- legal pages ---------- */
.legal { max-width: 68ch; font-size: 15px; line-height: 1.65; color: var(--ghosttext); }
.legal h2 { font-family: var(--serif); font-size: 19px; color: var(--ink); margin: 26px 0 6px; }
.legal p { margin: 10px 0; }
.legal em { color: var(--faint); }

/* ---------- hover-capable pointers only (no sticky hovers on touch) ---------- */
@media (hover: hover) {
  a:hover { color: var(--link-dark); }
  .navlink:hover { color: var(--ink); background: #e5eaef; }
  .ctl:hover { border-color: #a9b8c5; }
  .prim:hover { background: var(--amber-dark); }
  .ghost:hover { background: #f4f7f9; }
  .chipx:hover { background: #fbe2b3; }
  .linklike:hover { color: var(--link-dark); }
  .sailing:hover {
    border-color: #cdd8e1;
    box-shadow: 0 10px 26px -14px rgba(22,32,43,.28);
    transform: translateY(-1px);
  }
}

/* ---------- tablet: the 8-column row grid gets tight ---------- */
@media (max-width: 1024px) {
  .srow { gap: 14px 10px; }
  .pernight { font-size: 22px; }
}

/* ---------- mobile ---------- */
@media (max-width: 720px) {
  /* page scaffolding */
  .wrap { padding-left: 16px; padding-right: 16px; }
  .headline { font-size: 24px; }
  .hero { padding-top: 14px; }
  .view { padding-top: 18px; padding-bottom: 48px; }
  .hero-head { padding-bottom: 12px; gap: 12px 14px; }
  .stats { gap: 18px; flex-wrap: wrap; }
  .results { padding-bottom: 48px; }

  /* Header: brand/account on row one; four explicit navigation controls on
     row two. Routes, Ships and specialist views live in a real More picker,
     so no destination is hidden behind an undiscoverable horizontal scroll. */
  .head-inner { gap: 10px 12px; min-width: 0; }
  .brand { flex: none; order: 1; }
  /* Phones: the wordmark ate a third of the bar — the anchor icon alone
     identifies the site and every freed pixel goes to the nav (reported
     live 2026-08-24). */
  .brandname { display: none; }
  /* Signed-in account block (email + Sign out + Delete account) had no
     mobile treatment at all: three nowrap navlinks with no shrink room
     forced the whole header row wider than the viewport (2026-09-06,
     reported live while signed in). min-width:0 lets the flex item actually
     shrink instead of protecting its content's natural width; flex-wrap
     lets it drop to a second line instead of pushing the page wide. */
  .head-right { order: 2; margin-left: auto; min-width: 0; max-width: 100%; }
  .head-account { flex-wrap: wrap; justify-content: flex-end; row-gap: 4px; min-width: 0; }
  .account-email { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
  .navwrap { order: 3; flex: 1 0 100%; min-width: 0; max-width: 100%; }
  .nav {
    width: 100%; min-width: 0; max-width: 100%; flex-wrap: nowrap;
    justify-content: space-between; overflow: visible;
  }
  .navhint { display: none !important; }
  .nav-routes, .nav-ships, .navmore-desktop { display: none; }
  .navmore-mobile { display: inline-flex; }
  .navlink { flex: none; white-space: nowrap; }
  .tab { flex: none; }
  .view-head { min-width: 0; }

  .dealcontrols { align-items: stretch; padding: 12px; }
  .dealctl { flex: 1 1 calc(50% - 5px); min-width: 0; }
  .dealctl.dealsort { flex-basis: 100%; min-width: 0; }
  .dealcount { flex-basis: 100%; margin-left: 0; padding: 3px 1px 0; }

  /* map panel: "Sailing from" card above the map, in normal flow */
  .mappanel { display: flex; flex-direction: column; padding: 10px; }
  .depcard {
    position: static; order: 0; width: 100%; margin-bottom: 10px;
    background: #fff; backdrop-filter: none; box-shadow: none; border: 1px solid var(--hair);
  }
  .mapbox { order: 2; height: 300px; }
  .maplegend { position: static; order: 3; margin-top: 10px; padding: 8px 11px; gap: 6px 12px; }
  .mapsearch { position: static; order: 1; width: 100%; margin-bottom: 10px; }
  .mapsearch .ctl { box-shadow: none; border: 1px solid var(--hair); background: #fff; }
  .portsearch-list { box-shadow: none; border: 1px solid var(--hair); }

  /* Region bar: swap the scrolling tabstrip for one native picker. The
     tabstrip showed five tabs with the rest off-screen behind a horizontal
     scroll most people never discover; the picker names the current region
     and reaches all of them in one tap, in ~half the height. */
  .regionbar .tabstrip { display: none; }
  .regionbar { padding: 6px 0; }
  /* Explicit chevron. `.ctl` sets appearance:none sitewide without replacing
     the native arrow — fine for the filter pills, where the pill shape and
     "Any month" copy already read as a control, but this one REPLACED
     visible tabs, so without an affordance a visitor can't tell regions are
     still switchable at all. Scoped here rather than changing every select
     on the site, which is a wider design call. */
  .regionpick {
    display: block; width: 100%; min-height: 40px; padding: 8px 34px 8px 12px;
    font-size: 14.5px; font-weight: 600; color: var(--ink);
    background: #fff; border: 1px solid var(--ctl-border); border-radius: 11px;
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%236b7d8f' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 13px center;
  }

  /* Pitch: hidden until asked for (Sean — it doesn't need to be shown), then
     tap-to-dismiss. Same copy, tighter setting when it is open. */
  .pitch { display: none; font-size: 13.5px; line-height: 1.5; margin-top: 8px; }
  .pitch.m-open { display: block; }
  .pitchtoggle {
    display: inline-block; margin-top: 6px; padding: 0;
    background: none; border: 0; font: inherit; font-size: 13.5px;
    color: var(--link); text-decoration: underline; text-underline-offset: 2px;
    cursor: pointer;
  }

  /* Collapsed map panel drops its dark card entirely: with only a toggle and
     a search box inside, the heavy frame was pure weight above the results. */
  .mappanel.m-mapclosed {
    background: none; border: 0; box-shadow: none; padding: 0; margin-bottom: 4px;
  }
  .mappanel.m-mapclosed .mapsearch { margin-bottom: 0; }

  /* Whole-map collapse. Visual order at this width: [Show map] toggle,
     port search, then (when open) the map, depcard and legend. The port
     search deliberately stays OUTSIDE the collapse — a departure can be
     chosen by typing without ever opening the map. */
  .mtoggle-map { order: -1; margin-bottom: 10px; }
  .mappanel.m-mapclosed .mapbox,
  .mappanel.m-mapclosed .depcard,
  .mappanel.m-mapclosed .maplegend { display: none; }
  .mappanel.m-mapclosed { padding-bottom: 10px; }
  .mtoggle-map .mtoggle-lead { font-weight: 600; }
  .mtoggle-map .mtoggle-sum {
    margin-left: 8px; min-width: 0; overflow: hidden; text-overflow: ellipsis;
    white-space: nowrap; font-weight: 400; font-size: 13px; color: var(--muted);
  }

  /* Collapse toggles: real, tappable controls only at this width. 44px min
     height is the Apple/Google tap-target floor. */
  .mtoggle {
    display: flex; align-items: center; gap: 8px; width: 100%;
    min-height: 44px; padding: 11px 14px; margin: 0;
    background: #fff; border: 1px solid var(--hair); border-radius: 12px;
    font: inherit; font-size: 14.5px; font-weight: 600; color: var(--ink);
    text-align: left; cursor: pointer;
  }
  .mtoggle .mchev { margin-left: auto; color: var(--faint); font-size: 12px; }
  .mtoggle .mcount {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 20px; height: 20px; padding: 0 6px; border-radius: 10px;
    background: var(--amber); color: var(--ink); font-size: 12px; font-weight: 700;
  }
  .mtoggle-filters { margin-bottom: 10px; }
  /* Collapsed by default on mobile; .m-open (driven by state.mGuide /
     state.mFilters) is what reveals them. */
  .mbody, .filters { display: none; }
  .mbody.m-open { display: block; }
  .filters.m-open { display: flex; }
  .depcard .mtoggle { margin-top: 10px; background: transparent; border-color: var(--hair); }
  .depcard .mbody.m-open { margin-top: 8px; }

  /* filter bar: selects two-up, slider + sort full-width */
  .filters { padding: 12px; }
  .filters > select.ctl { flex: 1 1 calc(50% - 5px); min-width: 0; }
  .pricectl { flex-basis: 100%; }
  .pricerow { flex: 1; min-width: 0; }
  .pricerow input[type="range"] { flex: 1; width: auto; min-width: 0; }
  .filters-right { margin-left: 0; flex-basis: 100%; }
  .filters-right .ctl { width: 100%; }

  /* cabin tabs scroll instead of wrapping (scroll containment is on .tabstrip) */
  /* Compact the result header so actual sailings clear the fold. It was
     four stacked full-width rows (count, "Fares for", "Guests", "Show") —
     roughly 280px of chrome between the filters and the first fare, which
     is what kept results off a phone's first screen even after the map and
     filters collapsed (Sean, 2026-08-24). The controls all stay visible and
     tappable; only their prose labels go, since the tab text ("Interior",
     "2 guests", "Per person") already says what each one is. Guests and
     price-mode share a row. */
  .resulthead { gap: 8px 12px; padding-top: 14px; }
  .resulthead .cabins { min-width: 0; max-width: 100%; }
  .resulthead .cabins-label { display: none; }
  .resulthead .rescount { flex-basis: 100%; }
  .resulthead > .cabins:not(.guests):not(.pricemode) { flex-basis: 100%; }
  .resulthead .cabins.guests, .resulthead .cabins.pricemode { flex: 1 1 auto; min-width: 0; }
  /* Tight enough that guests + price-mode share one row instead of taking a
     full-width row each — that pairing alone was ~46px of pure chrome. */
  .resulthead .cabins.guests .tab, .resulthead .cabins.pricemode .tab {
    font-size: 12.5px; padding: 6px 9px;
  }
  .resulthead .cabins.guests .tabstrip, .resulthead .cabins.pricemode .tabstrip { padding: 2px; }

  /* result rows -> stacked cards:
     row 1 chip + name/dates/line · row 2 meta line · row 3 price left, grade right */
  .srow { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 10px 12px; padding: 14px 16px; min-height: 44px; }
  .cell-ship, .cell-n, .cell-turn, .chev { display: none; }
  .cell-main { flex: 1 1 calc(100% - 56px); }
  .srow-meta { display: block; flex-basis: 100%; font-size: 13px; line-height: 1.5; color: var(--muted); text-wrap: pretty; }
  .cell-price { flex: 1 1 auto; text-align: left; }
  .cell-price .pernight { font-size: 24px; }
  .cell-grade { margin-left: auto; flex: none; max-width: 55%; display: flex; flex-direction: column; align-items: flex-end; align-self: center; }
  .sname { font-size: 18px; }
  .sdetail { padding: 14px; gap: 18px; }

  /* watchlist rows: same stacked treatment */
  .wlrow { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 10px 12px; padding: 14px 16px; }
  .wl-main { flex: 1 1 calc(100% - 56px); }
  .wl-mid { flex: 1 1 auto; }
  .wl-price { margin-left: auto; text-align: right; }
  .wlbtns { flex-basis: 100%; justify-content: flex-end; }

  /* routes: stack map / info / fare vertically, fare left-aligned */
  .routegroup { grid-template-columns: 1fr; gap: 14px; }
  .minimap.routes { height: 180px; }
  .routeside { flex-direction: column; justify-content: flex-start; align-items: flex-start; text-align: left; gap: 10px; }

  /* A pinned comparison should be a compact action, not a floating row of
     itinerary names. Hide it while filters are open (app.js) and reserve
     footer space when it is visible so it never covers the last control. */
  .cmptray {
    left: 10px; right: 10px; bottom: 10px; transform: none; max-width: none;
    flex-wrap: nowrap; padding: 8px 10px;
  }
  .cmpchips, .cmptray .cmphint { display: none; }
  .cmp-mobile-summary { display: inline; font-size: 13px; font-weight: 650; color: var(--muted); }
  .cmptray .prim { margin-left: auto; }
  .cmptray > .navlink { min-height: 36px; }
  body.has-cmptray .site-foot { padding-bottom: 78px; }
}

/* ---------- touch affordances ---------- */
@media (pointer: coarse) {
  .navlink, button.tab { display: inline-flex; align-items: center; }
  .navlink, .tab { min-height: 40px; }
}
@media (hover: none) {
  .maplegend .lg-hoveronly { display: none; } /* no hover on touch — the entry would lie */
}

/* ---------- motion preferences ---------- */
@media (prefers-reduced-motion: reduce) {
  .sailing { transition: none; }
  .sailing:hover { transform: none; }
}

/* ---------- consent banner (2026-08-26) ---------- */
/* z-index 40: BELOW the modal overlay (50) and toasts (60) — at 900 the
   banner covered watch/error toasts and the booking modal's buttons on short
   viewports for the visitor's whole first session (2026-08-27 audit). */
#consentbar{position:fixed;left:0;right:0;bottom:0;z-index:40}
#consentbar .consent-inner{max-width:1100px;margin:0 auto 14px;background:#1e2d3d;color:#e4e8ec;border:1px solid rgba(255,255,255,.14);border-radius:12px;padding:14px 18px;display:flex;flex-wrap:wrap;gap:12px;align-items:center;box-shadow:0 12px 40px rgba(0,0,0,.35)}
#consentbar p{margin:0;flex:1 1 420px;font-size:13.5px;line-height:1.55}
#consentbar .linklike{background:none;border:none;padding:0;color:#8fc1e3;text-decoration:underline;cursor:pointer;font:inherit}
#consentbar .consent-btns{display:flex;gap:8px;flex-wrap:wrap}
#consentbar button.consent-accept{background:#d4a843;color:#16202b;border:none;border-radius:8px;padding:9px 18px;font-weight:600;cursor:pointer;font-size:13.5px}
#consentbar button.consent-decline{background:transparent;color:#cdd6df;border:1px solid rgba(255,255,255,.3);border-radius:8px;padding:9px 14px;cursor:pointer;font-size:13px}
@media (max-width:640px){#consentbar .consent-inner{margin:0;border-radius:12px 12px 0 0}}

/* Weekly newsletter capture (2026-09-01) */
.newsbox { background: #fff; border: 1px solid var(--line); border-radius: 12px; padding: 16px 18px; margin: 18px 0 6px; max-width: 560px; }
.newsbox-h { font-family: var(--serif); font-size: 18px; font-weight: 600; color: var(--ink); margin-bottom: 4px; }
.newsbox-b { font-size: 13.5px; color: var(--muted); margin-bottom: 10px; }
.newsbox-row { display: flex; gap: 8px; flex-wrap: wrap; }
.newsbox-row .ctl { flex: 1 1 220px; min-width: 0; }
.newsbox-err { margin-top: 8px; font-size: 13px; color: #a3372f; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

/* Dates and budget stay visible while advanced mobile filters collapse. */
.search-basic{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:10px}
.search-basic .ctl{min-width:180px}.search-basic .pricectl{flex:1}
.watch-options{display:grid;gap:14px;margin:20px 0}.watch-options label{display:flex;gap:10px;align-items:center}
.watch-options input{width:18px;height:18px}
@media(max-width:720px){.search-basic{display:grid;grid-template-columns:1fr;gap:10px}.search-basic .ctl{width:100%;min-width:0}.search-basic .pricectl{display:block}.search-basic .pricerow{margin-top:8px}.search-basic .pricerow input[type=range]{width:100%}}

/* Booking actions stay reachable while only the form body scrolls. */
.modal-booking { display: flex; flex-direction: column; overflow: hidden; min-height: 0; }
.modal-booking .modal-title, .modal-actions { flex: 0 0 auto; }
.modal-scroll { min-height: 0; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; padding: 0 3px 12px; }
.modal-actions { border-top: 1px solid var(--line); }
.modal-actions .prim { flex: 1; min-height: 44px; }
.booking-estimate { margin-top: 14px; padding: 12px; border: 1px solid var(--line); border-radius: 10px; font-size: 13px; line-height: 1.5; }
.booking-estimate p { margin: 8px 0 0; color: var(--muted); }
.booking-price span { display: block; color: var(--muted); }
.booking-price strong { display: block; font-size: 24px; color: var(--ink); }
.booking-estimate details, .modal-sailing details { margin-top: 8px; }
.booking-estimate summary, .modal-sailing summary { cursor: pointer; color: var(--link); }
@media (max-width: 720px) {
  #overlay { padding: max(8px, env(safe-area-inset-top)) max(10px, env(safe-area-inset-right)) max(12px, env(safe-area-inset-bottom)) max(10px, env(safe-area-inset-left)); }
  .modal-booking { padding: 16px 14px 12px; }
  .modal .ctl { font-size: 16px; } /* Prevent iOS focus zoom. */
  .modal-booking .modal-title { font-size: 21px; padding-bottom: 8px; }
}

.booking-total { padding-top: 10px; font-size: 12px; line-height: 1.5; color: var(--muted); }
.booking-total strong { color: var(--ink); }
.modal-actions .modal-btns { padding-top: 8px; }

/* Static route preview: vertical swipes continue scrolling the booking form. */
.booking-map { height: 190px; margin-top: 10px; border-radius: 9px; pointer-events: none; }
.booking-map-note { margin: 6px 0 10px; font-size: 11px; line-height: 1.4; }

/* A real month grid with exact-cabin, selected-occupancy party totals. */
.modal:has(.fare-calendar) { width: min(720px, 100%); }
.fare-calendar { font-size: 14px; line-height: 1.5; }
.calendar-controls { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.calendar-controls label { display: grid; gap: 4px; flex: 1; min-width: 120px; font-size: 12px; }
.calendar-controls .ctl { width: 100%; min-width: 0; }
.calendar-grid { display: grid; grid-template-columns: repeat(7, minmax(0,1fr)); gap: 4px; }
.calendar-weekday { text-align: center; color: var(--muted); font-size: 11px; }
.calendar-day { min-width: 0; min-height: 64px; padding: 7px 2px; border: 1px solid var(--line); border-radius: 7px; font: inherit; background: var(--paper); text-align: center; }
.calendar-day span, .calendar-day strong { display: block; }
.calendar-day strong { font-size: 11px; overflow-wrap: anywhere; }
.calendar-day.available { color: var(--link); background: #eef7fb; cursor: pointer; }
.calendar-day.selected { border: 2px solid var(--amber-dark); }
.calendar-day.needs-quote { color: var(--muted); }
.calendar-open { margin: 10px 0; }
@media(max-width:720px) {
  .calendar-controls { gap: 6px; }
  .calendar-controls label { min-width: 85px; }
  .calendar-day { min-height: 62px; }
  .calendar-day strong { font-size: 10px; }
}

.modal .ctl { font-size: 16px; }
@media(max-width:720px) {
  .calendar-controls { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); }
  .calendar-controls label:first-child { grid-column: 1 / -1; }
}
