/* bb-sheet.css - the ONE sheet skin (variant A)
 *
 * Single source of truth for every bb-sheet surface. No page may declare its
 * own sheet CSS: all sizes, colours, radii, blur, typography and the grab
 * handle come from the tokens below. Per marker type only a .bbs--<type> skin
 * class may vary the thumb gradient + accent; nothing structural.
 *
 * Everything is namespaced .bbs* so it can never cascade into a page's generic
 * .hero / .card / .chip (CSS Cascade Scoping Rule). Theme via [data-theme];
 * the sheet is its own DOM so no :not(:has()) dark-guards are needed. Safe-area
 * is respected on notch devices.
 */

:root {
  --bbs-radius: 24px;
  /* "rd-glass look" (captain 2026-07-12): the translucent Liquid-Glass recipe
     from the routes rd-glass panel, adopted for every sheet - navy 0.66 with a
     heavier blur+saturate so the map reads softly through the glass. */
  --bbs-bg: rgba(9, 28, 53, 0.66);
  --bbs-fg: #ffffff;
  --bbs-fg-dim: rgba(255, 255, 255, 0.72);
  --bbs-fg-body: rgba(255, 255, 255, 0.86);
  --bbs-border: rgba(255, 255, 255, 0.12);
  --bbs-hairline: rgba(255, 255, 255, 0.12);
  --bbs-grab: rgba(255, 255, 255, 0.34);
  --bbs-shadow: 0 18px 48px rgba(0, 0, 0, 0.46), inset 0 1px 0 rgba(255, 255, 255, 0.08);
  --bbs-blur: blur(22px) saturate(180%);

  --bbs-accent: #69FEFF;                    /* cyan info accent */

  /* SATURATED ACTION accent, a separate role from --bbs-accent above.
     --bbs-accent is the "navigating" hue (eyebrow text, progress fill, links)
     and flips per theme; the tokens below paint the FILLED discs and the
     primary CTA, which stay one colour in both themes. They were hardcoded
     #3366FF until 2026-08-06, so a white-label tenant could not reach them:
     the live Mokumboot sheet measured 2226 px of Captain blue on the Luister
     pill in both themes while every other token was already warm.
     Every use site keeps the literal as its var() fallback, so a stylesheet
     that fails to load leaves the Captain build exactly as it was.
     --bbs-on-accent is the ink ON the filled disc. Do NOT assume white: the
     Colour Rule allows white only below 25% lightness, and a tenant whose
     action colour is light (Sloepdelen green, 2,26:1 against white) needs dark
     ink here. The glow carries the whole box-shadow rather than just a colour,
     so a tenant can also set it to `none`; the two sizes exist because the
     40px transport disc and the 28px Luister disc were authored with
     different shadow geometry. */
  --bbs-accent-strong: #3366FF;
  --bbs-on-accent: #ffffff;
  --bbs-accent-tint: rgba(51, 102, 255, 0.22);   /* open-state fill */
  --bbs-accent-glow: 0 4px 12px rgba(51, 102, 255, 0.42);
  --bbs-accent-glow-sm: 0 3px 10px rgba(51, 102, 255, 0.4);
  /* Photo-tile gradient behind a highlight thumb + its number badge. Always a
     DARK gradient in every tenant, because white numerals sit on it. */
  --bbs-thumb-grad: linear-gradient(135deg, #274B8F, #3366FF);

  --bbs-chip-bg: rgba(255, 255, 255, 0.10);
  --bbs-chip-fg: var(--bbs-fg);
  --bbs-chip-cyan-bg: rgba(105, 254, 255, 0.14);
  --bbs-chip-cyan-fg: #69FEFF;
  --bbs-chip-warn-bg: #FFF4D6;
  --bbs-chip-warn-fg: #5C3A00;

  --bbs-ctrl-bg: rgba(255, 255, 255, 0.10);
  --bbs-ctrl-border: rgba(255, 255, 255, 0.16);

  --bbs-ease: cubic-bezier(.25, .8, .3, 1);
  --bbs-dur: 380ms;

  --bbs-dock-w: 420px;
  /* Docked-panel top offset so the panel head clears the fixed top nav. Every
     map page has the ~64px .bb-header (and the app-shell overlays its own nav on
     the embedded page), so default to clearing it; pages can override. */
  --bbs-dock-top: calc(env(safe-area-inset-top, 0px) + 90px);
  --bbs-safe-bottom: env(safe-area-inset-bottom, 0px);
  /* Sticky-header fill (filter chips): a near-opaque match of the sheet's
     COMPOSITED interior tone (a medium slate, not another navy tint - stacking
     navy over the glass just darkens it), so pinned chips read as one surface and
     the list rows scrolling under are fully hidden. */
  --bbs-sticky: rgb(44, 69, 96);

  --bbs-font: 'Libre Franklin', -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', sans-serif;
}

/* Light theme: a genuine LIGHT liquid-glass (captain 2026-07-12: "de bar is niet
 * light mode / de tekst is niet leesbaar"). Frosted off-white, opaque ENOUGH that
 * the bright map can't wash out the text (dark-glass-in-light left white body text
 * at ~3:1 contrast over the light map - unreadable). Navy text throughout, blue
 * accent. Keeps the liquid-glass feel via the blur + a hint of translucency. */
:root[data-theme="light"] {
  --bbs-bg: rgba(240, 244, 250, 0.90);
  --bbs-sticky: rgb(228, 235, 244);
  --bbs-fg: #091C35;
  --bbs-fg-dim: rgba(9, 28, 53, 0.62);
  --bbs-fg-body: rgba(9, 28, 53, 0.90);
  --bbs-border: rgba(9, 28, 53, 0.10);
  --bbs-hairline: rgba(9, 28, 53, 0.10);
  --bbs-grab: rgba(9, 28, 53, 0.26);
  --bbs-shadow: 0 18px 48px rgba(9, 28, 53, 0.18), inset 0 1px 0 rgba(255, 255, 255, 0.5);
  --bbs-accent: #3366FF;
  --bbs-chip-bg: rgba(9, 28, 53, 0.06);
  --bbs-chip-fg: #091C35;
  --bbs-chip-cyan-bg: rgba(51, 102, 255, 0.12);
  --bbs-chip-cyan-fg: #3366FF;
  --bbs-ctrl-bg: rgba(9, 28, 53, 0.06);
  --bbs-ctrl-border: rgba(9, 28, 53, 0.12);
}
:root[data-theme="light"] .bbs-bar { background: rgba(9, 28, 53, 0.12); }
:root[data-theme="light"] .bbs-pbtn--stop { background: rgba(9, 28, 53, 0.08); }

/* ── Shell ────────────────────────────────────────────────────────────────── */
.bbs {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 96;
  display: flex;
  flex-direction: column;
  height: 30vh;
  box-sizing: border-box;
  border-radius: var(--bbs-radius) var(--bbs-radius) 0 0;
  background: var(--bbs-bg);
  -webkit-backdrop-filter: var(--bbs-blur);
  backdrop-filter: var(--bbs-blur);
  border: 1px solid var(--bbs-border);
  border-bottom: none;
  box-shadow: var(--bbs-shadow);
  color: var(--bbs-fg);
  font-family: var(--bbs-font);
  overflow: hidden;
  transform: translateY(110%);
  visibility: hidden;
  transition: transform var(--bbs-dur) var(--bbs-ease),
              height 300ms var(--bbs-ease),
              visibility 0s linear var(--bbs-dur);
  /* Safe-area padding so the body never tucks under the home indicator. */
  padding-bottom: var(--bbs-safe-bottom);
}
.bbs[hidden] { display: none; }
.bbs.bbs--open {
  transform: translateY(0);
  visibility: visible;
  transition: transform var(--bbs-dur) var(--bbs-ease),
              height 300ms var(--bbs-ease);
}
.bbs.bbs--dragging,
.bbs.bbs--noanim { transition: none; }

/* Grab handle */
.bbs-grab {
  flex: 0 0 auto;
  height: 22px;
  display: flex; align-items: center; justify-content: center;
  cursor: grab;
  touch-action: none;
}
.bbs-grab::before {
  content: "";
  width: 44px; height: 5px;
  border-radius: 999px;
  background: var(--bbs-grab);
}
.bbs.bbs--dragging .bbs-grab { cursor: grabbing; }

/* ── Head ─────────────────────────────────────────────────────────────────── */
.bbs-head {
  flex: 0 0 auto;
  display: flex; align-items: flex-start; gap: 12px;
  padding: 6px 16px 12px;
  cursor: grab;
  touch-action: none;
}
.bbs.bbs--dragging .bbs-head { cursor: grabbing; }
/* Visueel 30px (de navy-glas-badge-familie), maar het TIKDOEL wordt hieronder
   opgerekt naar 44px via een transparante ::after - hetzelfde recept als de
   back/route-chips in shared-prototype.css. Audit 2026-07-28 mat hier 28x28
   effectief met elementFromPoint, ruim onder de 44pt uit Apple's HIG, op de
   twee drukst gebruikte knoppen van de app (elke bottom-sheet heeft ze). */
.bbs-back, .bbs-close {
  flex: 0 0 auto;
  position: relative;
  width: 30px; height: 30px;
  border-radius: 999px;
  background: var(--bbs-ctrl-bg);
  border: 1px solid var(--bbs-ctrl-border);
  color: var(--bbs-fg);
  font-size: 15px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  padding: 0;
}
/* Het tikdoel-verlengstuk: onzichtbaar, gecentreerd, rekt 30px op naar 44px.
   Geen achtergrond en geen eigen z-index, dus puur hitbox - het uiterlijk van
   de knop verandert niet. pointer-events:none op de ::after zou de hele truc
   opheffen, dus die staat er bewust NIET. */
.bbs-back::after, .bbs-close::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  width: 44px; height: 44px;
  transform: translate(-50%, -50%);
}
.bbs-back { margin-top: 2px; }
.bbs-close { margin-left: auto; color: var(--bbs-fg-dim); }
.bbs-back:active, .bbs-close:active { transform: scale(0.94); }
/* Subtle stack-depth affordance: a faint layered edge behind the back button +
   a small muted count, shown only 2+ layers deep (captain 2026-07-13). */
.bbs-back--stacked { position: relative; box-shadow: -3px 3px 0 -1px var(--bbs-ctrl-border), -6px 6px 0 -2px var(--bbs-ctrl-border); }
.bbs-back-depth {
  position: absolute; top: -4px; right: -4px;
  min-width: 15px; height: 15px; padding: 0 3px; box-sizing: border-box;
  border-radius: 8px; background: var(--bbs-chip-bg); color: var(--bbs-fg-dim);
  font: 700 9.5px/15px var(--bbs-font); text-align: center;
  box-shadow: 0 0 0 2px var(--bbs-bg);
}
/* Peek mini-player thumbnail + audio progress-ring (captain-approved 4.1). Only
   shows on peek; once the sheet expands the body photo takes over. */
.bbs-pthumb { position: relative; width: 48px; height: 48px; flex: 0 0 auto; margin-top: 2px; }
.bbs-pthumb-img { position: absolute; inset: 5px; width: 38px; height: 38px; border-radius: 50%; object-fit: cover; }
.bbs-pthumb-ring { position: absolute; inset: 0; width: 48px; height: 48px; transform: rotate(-90deg); overflow: visible; }
.bbs-pthumb-track { fill: none; stroke: var(--bbs-hairline); stroke-width: 3; }
.bbs-pthumb-prog { fill: none; stroke: var(--bbs-accent, #3366FF); stroke-width: 3; stroke-linecap: round; transition: stroke-dashoffset 0.25s linear; }
.bbs:not(.bbs--peek) .bbs-pthumb { display: none; }

.bbs-thumb {
  flex: 0 0 auto;
  width: 58px; height: 58px;
  border-radius: 14px;
  display: flex; align-items: center; justify-content: center;
  font-size: 26px; line-height: 1;
  background: var(--bbs-thumb-grad, linear-gradient(135deg, #274B8F, #3366FF));
  border: 1px solid var(--bbs-hairline);
  color: #fff;
  overflow: hidden;
}
.bbs-thumb img { width: 100%; height: 100%; object-fit: cover; }
/* Stop-list foto-thumb (captain 2026-07-13): kleine highlight-foto in de rij
   met het stopnummer als hoek-badge eroverheen. Zonder foto rendert de rij de
   klassieke nummer-tegel (geen extra class). Badge = klein verzadigd schijfje
   (Colour Rule: saturated alleen voor badges), leesbaar op elke foto door de
   witte hairline + schaduw. min-width vangt 2-cijferige nummers. */
.bbs-thumb--img { position: relative; }
.bbs-thumb--img img { position: absolute; inset: 0; }
.bbs-thumb-badge {
  position: absolute; top: 3px; left: 3px; z-index: 1;
  min-width: 18px; height: 18px; padding: 0 4px;
  border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; line-height: 1; color: #fff;
  background: var(--bbs-thumb-grad, linear-gradient(135deg, #274B8F, #3366FF));
  border: 1px solid rgba(255, 255, 255, 0.55);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}
.bbs-list-item .bbs-thumb-badge { font-size: 10px; min-width: 17px; height: 17px; }

.bbs-headtext { min-width: 0; flex: 1 1 auto; }
.bbs-title {
  font-size: 17px; font-weight: 600;
  letter-spacing: -0.018em; line-height: 1.2;
  color: var(--bbs-fg);
  text-wrap: balance;
}
.bbs-sub {
  font-size: 10.5px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--bbs-accent);
  margin-top: 3px;
}
.bbs-meta {
  display: flex; gap: 6px; flex-wrap: wrap;
  margin-top: 7px;
}
.bbs-chip {
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.2px;
  padding: 4px 10px; border-radius: 999px;   /* pill, matching the app's chip language */
  background: var(--bbs-chip-bg); color: var(--bbs-chip-fg);
  /* nowrap houdt de pill-vorm, maar zonder vangnet loopt een lange chip
     de sheet uit (toilet-openingstijden: 874 px in een 375 px viewport,
     captain 2026-07-27). De bron kort de tekst nu in; dit is de vangrail
     voor elke volgende chip die dat vergeet. */
  white-space: nowrap;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis;
}
.bbs-chip--cyan { background: var(--bbs-chip-cyan-bg); color: var(--bbs-chip-cyan-fg); }
.bbs-chip--warn { background: var(--bbs-chip-warn-bg); color: var(--bbs-chip-warn-fg); }

/* ── Controls row (audio transport - stays visible at peek) ─────────────────── */
.bbs-controls {
  flex: 0 0 auto;
  padding: 0 16px 10px;
}
.bbs-controls[hidden] { display: none; }
.bbs-player {
  display: flex; align-items: center; gap: 12px;
  /* Ankerpunt voor de volume-popover (.bbs-vol), die absoluut boven de rij hangt. */
  position: relative;
}
.bbs-pbtn {
  flex: 0 0 auto;
  width: 40px; height: 40px;
  border-radius: 999px;
  border: 0;
  background: var(--bbs-accent-strong, #3366FF);
  color: var(--bbs-on-accent, #fff);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  box-shadow: var(--bbs-accent-glow, 0 4px 12px rgba(51, 102, 255, 0.42));
  transition: transform 180ms var(--bbs-ease);
}
.bbs-pbtn:active { transform: scale(0.94); }
.bbs-pbtn:disabled { opacity: 0.5; cursor: default; box-shadow: none; }
.bbs-pbtn--stop { width: 34px; height: 34px; background: rgba(255,255,255,0.12); color: var(--bbs-fg); box-shadow: none; }
.bbs-pbtn--stop[hidden] { display: none; }
/* Play/pause icon morph driven by .is-playing on the button. */
.bbs-pbtn .bbs-ic-pause { display: none; }
.bbs-pbtn.is-playing .bbs-ic-play { display: none; }
.bbs-pbtn.is-playing .bbs-ic-pause { display: inline; }
.bbs-bar {
  flex: 1 1 auto;
  height: 4px; border-radius: 2px;
  background: rgba(255, 255, 255, 0.15);
  overflow: hidden;
}
.bbs-bar-fill {
  display: block; height: 100%; width: 0;
  background: var(--bbs-accent);
  border-radius: 2px;
}
.bbs-time {
  flex: 0 0 auto;
  font-size: 10.5px; color: var(--bbs-fg-dim);
  font-variant-numeric: tabular-nums;
}
.bbs-controls.is-disabled { opacity: 0.5; pointer-events: none; }
/* Mute is een GLOBALE instelling, geen transport-knop: als de rij ooit
   uitgeschakeld wordt (geen clip bij het huidige hoogtepunt) moet hij
   bruikbaar blijven - in de oude topbalk was hij dat ook altijd. */
.bbs-controls.is-disabled .bbs-mute,
.bbs-player.is-disabled .bbs-mute { opacity: 1; pointer-events: auto; }
/* Mute hoort bij de speler (P3, captain 2026-07-26): #ltMuteBtn wordt door
   lt-sheet.js uit de live-tour chrome hierheen verplaatst en staat links van
   play. 28px rond, stil van kleur - de blauwe disc blijft de play-knop. */
.bbs-player .bbs-mute {
  flex: 0 0 auto;
  width: 28px; height: 28px; padding: 0; margin: 0;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.10);
  color: var(--bbs-fg);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  box-shadow: none;
}
:root[data-theme="light"] .bbs-player .bbs-mute {
  border-color: rgba(9, 28, 53, 0.12);
  background: rgba(9, 28, 53, 0.06);
}
.bbs-player .bbs-mute:active { transform: scale(0.92); }
.bbs-player .bbs-mute .lt-mute-on,
.bbs-player .bbs-mute .lt-mute-off { font-size: 14px; line-height: 1; display: block; }
.bbs-player .bbs-mute .lt-mute-on[hidden],
.bbs-player .bbs-mute .lt-mute-off[hidden] { display: none; }

/* ── Volume-popover (variant B, captain 2026-07-27) ────────────────────────
   Een tik op de speaker-knop opent deze verticale slider boven de speler-rij
   (Control Center-stijl): percentage boven, witte fill-track, mute-toggle
   onder. Donker glaspaneel in BEIDE thema's - het zweeft over de kaart en de
   sheet heen, dus een lichte variant zou op een lichte kaart verdwijnen.
   Wit op #091C35-glas voldoet aan de contrastregel. */
.bbs-vol {
  /* Portal-kind van document.body (zie ensureVolPopover): de sheet knipt met
     overflow:hidden + transform alles weg wat erbovenuit steekt. left/bottom
     worden per opening gezet door placeVolPopover(). */
  position: fixed;
  left: 16px;
  bottom: 96px;
  /* Boven de sheet (96) en de kaart-chrome, maar onder de paneel/modal-laag
     (1085+) - een openstaande popover mag nooit over een dialoog vallen. */
  z-index: 400;
  width: 58px;
  box-sizing: border-box;
  padding: 9px 8px 8px;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  border-radius: 18px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(9, 28, 53, 0.88);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  backdrop-filter: blur(18px) saturate(140%);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.42);
}
.bbs-vol[hidden] { display: none; }
.bbs-vol-val {
  font-size: 11px; font-weight: 700; line-height: 1;
  color: #fff; font-variant-numeric: tabular-nums;
}
.bbs-vol.is-muted .bbs-vol-val { opacity: 0.55; }
.bbs-vol-track {
  position: relative;
  width: 34px; height: 132px;
  border-radius: 17px;
  background: rgba(255, 255, 255, 0.16);
  overflow: hidden;
  cursor: pointer;
  /* Zonder dit pakt iOS het verticale sleepgebaar als page-scroll en springt
     de slider terug. */
  touch-action: none;
}
/* Hairline op de 100%-stand (de track loopt tot 200%), zodat de captain de
   neutrale stand blind terugvindt. */
.bbs-vol-track::after {
  content: ''; position: absolute; left: 6px; right: 6px; bottom: 50%;
  height: 1px; pointer-events: none;
  /* difference-blend: donker op de witte fill (volume > 100%), licht op de
     lege track (volume < 100%). Een vaste kleur is in een van beide standen
     onzichtbaar. */
  background: #fff; mix-blend-mode: difference;
}
.bbs-vol-fill {
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 100%;
  background: #fff;
  border-radius: 17px 17px 0 0;
}
.bbs-vol-track:focus-visible { outline: 2px solid var(--bbs-accent); outline-offset: 2px; }
.bbs-vol-mute {
  width: 30px; height: 30px; padding: 0; margin: 0;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.10);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.bbs-vol-mute[aria-pressed="true"] { background: rgba(255, 80, 60, 0.22); border-color: rgba(255, 80, 60, 0.5); }
.bbs-vol-mute:active { transform: scale(0.92); }
.bbs-vol-mute .lt-mute-on,
.bbs-vol-mute .lt-mute-off { font-size: 14px; line-height: 1; display: block; }
.bbs-vol-mute .lt-mute-on[hidden],
.bbs-vol-mute .lt-mute-off[hidden] { display: none; }

/* On-demand "Luister"/"Listen" pill in a TAPPED highlight's detail body
   (captain 2026-07-15). Blue play/pause disc (matches the mini-player button)
   + accent progress bar; navy-glass in dark, navy-tint in light. */
.bbs-hl-audio {
  display: flex; align-items: center; gap: 10px;
  width: 100%; box-sizing: border-box;
  margin: 2px 0 10px; padding: 9px 12px;
  border: 0; border-radius: 12px; cursor: pointer;
  background: rgba(255, 255, 255, 0.08); color: var(--bbs-fg);
  font: 600 0.85rem/1.2 inherit; text-align: left;
  position: relative; overflow: hidden;
}
:root[data-theme="light"] .bbs-hl-audio { background: rgba(9, 28, 53, 0.06); }
.bbs-hl-audio .bbs-hl-audio-ico {
  flex: 0 0 auto; display: inline-grid; place-items: center;
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--bbs-accent-strong, #3366FF); color: var(--bbs-on-accent, #fff);
  box-shadow: var(--bbs-accent-glow-sm, 0 3px 10px rgba(51, 102, 255, 0.4));
}
.bbs-hl-audio .bbs-hl-audio-ico::before { content: "\25B6"; font-size: 0.7rem; margin-left: 1px; }
.bbs-hl-audio.is-playing .bbs-hl-audio-ico::before { content: "\23F8"; margin-left: 0; }
.bbs-hl-audio .bbs-hl-audio-txt { flex: 1 1 auto; }
.bbs-hl-audio .bbs-hl-audio-bar {
  position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: rgba(255, 255, 255, 0.14);
}
:root[data-theme="light"] .bbs-hl-audio .bbs-hl-audio-bar { background: rgba(9, 28, 53, 0.12); }
.bbs-hl-audio .bbs-hl-audio-fill {
  display: block; height: 100%; width: 0;
  background: var(--bbs-accent); transition: width 0.15s linear;
}

/* Rij rond de pill: speaker-knop links, pill vult de rest. Deze sheet heeft
   bewust geen transport-rij, dus zonder deze knop is volume/mute hier
   onbereikbaar (captain 2026-07-28). De pill hield zijn eigen marge, dus die
   verhuist naar de rij. */
.bbs-hl-audio-row {
  display: flex; align-items: center; gap: 8px;
  margin: 2px 0 10px;
}
.bbs-hl-audio-row .bbs-hl-audio { margin: 0; }
.bbs-hl-vol {
  flex: 0 0 auto; display: inline-grid; place-items: center;
  width: 38px; height: 38px; padding: 0;
  border: 0; border-radius: 12px; cursor: pointer;
  background: rgba(255, 255, 255, 0.08); color: var(--bbs-fg);
  font-size: 1rem; line-height: 1;
}
:root[data-theme="light"] .bbs-hl-vol { background: rgba(9, 28, 53, 0.06); }
.bbs-hl-vol[aria-expanded="true"] { background: var(--bbs-accent-tint, rgba(51, 102, 255, 0.22)); }
.bbs-hl-vol:active { transform: scale(0.94); }

/* ── Body (revealed at half+; scrolls) ─────────────────────────────────────── */
.bbs-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 8px 16px 18px;
  font-size: 14px; line-height: 1.55;
  color: var(--bbs-fg-body);
  opacity: 0;
  transition: opacity 220ms var(--bbs-ease);
}
.bbs-body::-webkit-scrollbar { width: 0; height: 0; }
/* Mobile: the bottom tab-nav (page's own, or the app-shell's over the iframe)
   floats over the edge-to-edge sheet, so the LAST body content (actions, final
   lines) was hidden behind it. Reserve clearance so nothing tucks under the nav
   (audit 2026-07-12). Desktop dock has no bottom nav. */
.bbs:not(.bbs--desktop) .bbs-body { padding-bottom: calc(20px + var(--bbs-safe-bottom) + 84px); }

/* Inside the /app shell the floating bottom tab bar (.bb-mobile-nav) overlaps the
   bottom of the iframe, so at partial snaps the Routes filter chips + top stop-rows
   rendered BEHIND it (audit 2026-07-12). The sheet still starts from the screen
   bottom (glass runs seamlessly behind the floating nav - no detached gap), but a
   padding-bottom equal to the nav reserve pushes the CONTENT box up so it ends
   ABOVE the nav; .bbs is overflow:hidden + border-box so the body clips exactly at
   the nav top and nothing renders behind the bar (captain 2026-07-12). The shell
   measures its own nav and hands the reserve down as --bbs-shell-nav-h. Scoped to
   html.bb-embed per the CSS Cascade Scoping Rule - standalone pages keep their own
   84px body pad (below), since the var is unset (0) there. */
html.bb-embed .bbs:not(.bbs--desktop) { padding-bottom: var(--bbs-shell-nav-h, 0px); }
html.bb-embed .bbs:not(.bbs--desktop) .bbs-body { padding-bottom: calc(20px + var(--bbs-safe-bottom)); }
.bbs.bbs--half .bbs-body,
.bbs.bbs--full .bbs-body,
.bbs.bbs--fit .bbs-body,
.bbs.bbs--desktop .bbs-body { opacity: 1; }

/* Content-fit open: a detail opens at its natural height (body visible) instead
   of a fixed snap, so short content never leaves an empty void and the detail is
   readable without a drag-up. Capped at the full-snap height (then the body
   scrolls). Dragging converts back to the fixed snap model (see onDown). */
.bbs.bbs--fit {
  height: auto;
  /* fitOpen() always sets --bbs-fit-max in px; the fallback covers the frame
     before that runs. It keeps the historical 84vh when no page-level top
     reserve is declared, and honours the reserve when there is one (see
     topReservePx in src/shared/bb-sheet.js). */
  max-height: var(--bbs-fit-max, calc(100vh - max(16vh, var(--bbs-top-reserve, 0px))));
}
.bbs-body p + p { margin-top: 10px; }
.bbs-body img { max-width: 100%; }

/* ── Content scaling (captain 2026-07-12: "tekst en plaatje schalen niet goed") ─
   The reused Google-InfoWindow markup (.gmaps-popup) was capped at 312px, so on a
   wide sheet (tablet bottom-sheet, desktop dock) the content sat in a tiny left
   column with a big empty void and a small image. Let it FILL the sheet, cap the
   text column at a readable width centred, and make images responsive + larger. */
.bbs-body > .bbs-maps-body,
.bbs-body > .bbs-hl-body,
.bbs-body > .bbs-boat,
.bbs-body > .gmaps-popup { max-width: 680px; margin-inline: auto; }
.bbs .gmaps-popup { max-width: 100% !important; min-width: 0 !important; width: 100%; box-sizing: border-box; }
/* The reused .gmaps-popup body repeats the title (.pp-head) that the sheet head
   already shows - hide it so the title isn't duplicated (audit 2026-07-12). The
   rich eyebrow (.pp-sub) + detail stay. */
.bbs .gmaps-popup .pp-head { display: none; }
.bbs .gmaps-popup .pp-sub { margin-top: 0; }
/* The SWEETS booking link (.pp-link) rendered as a sharp, unpadded text link -
   make it a clean rounded button inside the sheet (audit 2026-07-12). */
.bbs .gmaps-popup .pp-link {
  display: inline-flex; align-items: center; gap: 6px;
  margin-top: 14px; padding: 10px 16px;
  border-radius: 12px;
  background: var(--bbs-chip-cyan-bg); color: var(--bbs-chip-cyan-fg);
  font-weight: 600; font-size: 13px; text-decoration: none;
}
.bbs .gmaps-popup img,
.bbs .bbs-hl-img,
.bbs .bbs-photo {
  width: 100% !important; max-width: 100% !important; height: auto !important;
  aspect-ratio: 20 / 9; object-fit: cover; border-radius: 12px; margin-bottom: 12px;
}

/* ── Generic body helpers (shared by every map surface via bb-sheet-maps) ───── */
.bbs-maps-body { display: block; }
.bbs-photo {
  width: 100%; aspect-ratio: 20 / 9;
  object-fit: cover; border-radius: 12px;
  margin: 0 0 12px; display: block;
  background: rgba(127, 127, 127, 0.18);
}
.bbs-note {
  background: var(--bbs-chip-warn-bg); color: var(--bbs-chip-warn-fg);
  border: 1px solid rgba(180, 83, 9, 0.35);
  border-radius: 12px; padding: 10px 12px;
  font-size: 13px; line-height: 1.45; margin: 0 0 10px;
}
.bbs-rows { display: flex; flex-direction: column; gap: 2px; margin: 4px 0 2px; }
.bbs-row {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 7px 0; border-bottom: 1px solid var(--bbs-hairline);
  font-size: 13.5px;
}
.bbs-row:last-child { border-bottom: none; }
.bbs-row .k { color: var(--bbs-fg-dim); }
.bbs-row .v { color: var(--bbs-fg); font-weight: 600; text-align: right; }
.bbs-links { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; }
.bbs-links a { color: var(--bbs-accent); font-size: 13px; font-weight: 600; text-decoration: none; }
.bbs-act-row { display: flex; gap: 10px; margin-top: 14px; flex-wrap: wrap; }
.bbs-act {
  flex: 1 1 auto; min-width: 120px;
  border: none; border-radius: 12px; padding: 11px 14px;
  font-size: 13.5px; font-weight: 600; cursor: pointer;
  font-family: var(--bbs-font);
}
.bbs-act--primary { background: var(--bbs-accent-strong, #3366FF); color: var(--bbs-on-accent, #fff); }
.bbs-act--ghost { background: var(--bbs-chip-bg); color: var(--bbs-fg); }
.bbs-act--on { background: var(--bbs-chip-cyan-bg); color: var(--bbs-chip-cyan-fg); }
.bbs-act:active { transform: scale(0.98); }

/* ── Boat stat card (vaarverkeer / live-tour vessel detail) ─────────────────── */
.bbs-boat-photo {
  margin: 2px 0 10px;
  border-radius: 12px;
  overflow: hidden;
  background: var(--bbs-chip-bg);
}
.bbs-boat-photo img {
  display: block; width: 100%;
  aspect-ratio: 20 / 9; object-fit: cover;
}
/* Operator lockup (captain-approved 2026-07-13, variant A): a readable logo +
   name that replaces the old 'Rederij' stat cell. Sits between the photo and the
   stat grid. operatorColor is applied inline to the eyebrow + dot. */
/* Operator logo chip. Lives in the sheet HEAD (left of the vessel title) on the
   operator's brand colour, so light AND dark wordmarks read (captain 2026-07-13).
   The old body "Rederij" lockup card was folded into the head - the rederij name
   is now the head subtitle - so the body is just photo + stats, a much smaller
   panel. Wide wordmarks (e.g. "Flagship Amsterdam") keep their aspect: fixed 44px
   tall, width follows up to a cap; the mono-initials fallback stays square. */
.bbs-op-logo {
  height: 44px; width: auto; min-width: 44px; max-width: 104px; flex: 0 0 auto;
  border-radius: 11px; background: #fff; overflow: hidden; margin-top: 1px;
  display: grid; place-items: center; box-sizing: border-box;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18), inset 0 0 0 1px rgba(9, 28, 53, 0.06);
}
.bbs-op-logo img { height: 100%; width: auto; max-width: 92px; object-fit: contain; padding: 6px 8px; box-sizing: border-box; }
.bbs-op-logo--mono { width: 44px; box-shadow: none; }
.bbs-op-mono { color: #fff; font-weight: 800; font-size: 16px; letter-spacing: 0.5px; }
.bbs-boat-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 6px;
  margin-top: 4px;
}
/* Finish-moment completion card (captain 2026-07-17). Reuses .bbs-boat-* chips
   for the stat tiles; only the wrapper + the check circle need styling. Theme-
   aware via the sheet tokens. */
.lt-finish { display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 2px 0; }
.lt-finish-check {
  width: 48px; height: 48px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 24px; font-weight: 800; line-height: 1;
  background: var(--bbs-chip-bg); color: var(--bbs-accent-strong, #3366FF);
}
.lt-finish .bbs-boat-grid { margin-top: 0; width: 100%; }
/* Vessel detail packs length + beam into one "Afmeting" cell, so the three core
   stats (afmeting / snelheid / koers) sit on ONE compact row instead of a tall
   2x2 (captain 2026-07-13). Destination, when present, spans the full width. */
.bbs-boat-grid--3 { grid-template-columns: repeat(3, 1fr); }
.bbs-boat-cell--wide { grid-column: 1 / -1; }
.bbs-boat-cell {
  background: var(--bbs-chip-bg);
  border-radius: 11px;
  padding: 7px 10px;
}
.bbs-boat-k {
  font-size: 9.5px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--bbs-fg-dim);
}
.bbs-boat-v {
  font-size: 14px; font-weight: 600;
  color: var(--bbs-fg);
  font-variant-numeric: tabular-nums;
  margin-top: 1px;
}
.bbs-boat-age {
  margin-top: 10px;
  font-size: 11.5px; color: var(--bbs-fg-dim);
}
.bbs-boat-age[hidden] { display: none; }
.bbs-boat-mmsi {
  margin-top: 6px;
  font-size: 11px; color: var(--bbs-fg-dim);
  font-variant-numeric: tabular-nums; letter-spacing: 0.02em;
}
.bbs-boat-lost {
  margin-top: 8px;
  background: var(--bbs-chip-warn-bg); color: var(--bbs-chip-warn-fg);
  border: 1px solid rgba(180, 83, 9, 0.35);
  border-radius: 12px; padding: 9px 11px;
  font-size: 12.5px; font-weight: 600;
}

/* ── List template (cluster) ───────────────────────────────────────────────── */
.bbs-list-item {
  display: flex; align-items: center; gap: 12px;
  padding: 10px; border-radius: 12px;
  cursor: pointer;
}
.bbs-list-item:hover { background: var(--bbs-chip-bg); }
.bbs-list-item .bbs-thumb { width: 42px; height: 42px; font-size: 19px; border-radius: 10px; }
.bbs-list-item .bbs-li-title { font-size: 13.5px; font-weight: 600; color: var(--bbs-fg); }
.bbs-li-sub { font-size: 11px; color: var(--bbs-fg-dim); }
.bbs-li-go { margin-left: auto; color: var(--bbs-fg-dim); }

/* ── Type skins (thumb gradient + accent only) ─────────────────────────────── */
.bbs--stop   .bbs-thumb, .bbs--player .bbs-thumb { background: var(--bbs-thumb-grad, linear-gradient(135deg, #274B8F, #3366FF)); }
.bbs--boot   .bbs-thumb { background: linear-gradient(135deg, #0D2440, #14538A); }
.bbs--strem  .bbs-thumb { background: linear-gradient(135deg, #8a5a10, #B45309); }
.bbs--opstap .bbs-thumb { background: linear-gradient(135deg, #0F5132, #1B7A4E); }
.bbs--toilet .bbs-thumb { background: linear-gradient(135deg, #3a4350, #4B5563); }
.bbs--regels .bbs-thumb { background: linear-gradient(135deg, #3E2A6E, #5E35B1); }
.bbs--dine   .bbs-thumb { background: linear-gradient(135deg, #7d0a1e, #C8102E); }
.bbs--cluster .bbs-thumb { background: linear-gradient(135deg, #1D3566, #274B8F); }

/* ── Desktop: right-docked 420px CONTENT-FIT floating card ─────────────────────
   Suggestion 1 (captain-approved 2026-07-12): the panel used to be full-height,
   leaving a big empty void under short content. It now grows to its content
   height (capped at the available height, then the body scrolls) as a floating
   rounded card - no void. */
@media (min-width: 960px) {
  .bbs.bbs--desktop {
    left: auto; right: 16px; top: var(--bbs-dock-top); bottom: auto;
    width: var(--bbs-dock-w);
    height: auto;
    max-height: calc(100% - var(--bbs-dock-top) - 20px);
    border-radius: 20px;
    border: 1px solid var(--bbs-border);
    transform: translateX(calc(100% + 24px));
    transition: transform var(--bbs-dur) var(--bbs-ease), visibility 0s linear var(--bbs-dur);
    padding-bottom: 12px;
    box-shadow: 0 18px 48px rgba(0, 0, 0, 0.40);
  }
  .bbs.bbs--desktop.bbs--open {
    transform: translateX(0);
    transition: transform var(--bbs-dur) var(--bbs-ease);
  }
  /* No drag on desktop; the panel scrolls. Hide the grab handle, show a plain
     head, and let the body always show. */
  .bbs.bbs--desktop .bbs-grab { display: none; }
  .bbs.bbs--desktop .bbs-head { cursor: default; }
}

@media (prefers-reduced-motion: reduce) {
  .bbs, .bbs.bbs--open, .bbs.bbs--desktop { transition: none; }
  .bbs-body { transition: none; }
}
