/* Shared "Hear it in action" moment cards — used by the homepage AND the
   marinas page so the two can never drift. Each card replays a REAL captured
   moment exactly the way the app does: real MapLibre chart, the app's actual
   vessels3d sprites on feathered identity discs, radio-ring on-air signature,
   spotlight dimming, karaoke captions, and the bar's transmission timeline.
   Colors are self-contained (no dependence on each page's CSS variables);
   keyframes carry an m- prefix so they can't collide with page-local ones. */

.caro-wrap { position: relative; }
.caro { display: flex; gap: 18px; overflow-x: auto; scroll-snap-type: x mandatory;
  padding: 8px 4px 22px; -webkit-overflow-scrolling: touch; }
.caro::-webkit-scrollbar { height: 8px; }
.caro::-webkit-scrollbar-thumb { background: #E3DAC4; border-radius: 4px; }
.mcard { flex: 0 0 300px; scroll-snap-align: center; border-radius: 26px; overflow: hidden;
  border: 8px solid #0B2545; background: #0D1B2E; box-shadow: 0 18px 44px #0B254526;
  display: flex; flex-direction: column; height: 560px; position: relative; }
.mcard .m-live { position: absolute; top: 12px; left: 12px; z-index: 5; background: #0A0F14D9;
  color: #E6EDF3; font-size: 9px; font-weight: 900; letter-spacing: 1.2px; border-radius: 999px; padding: 5px 10px; }
.mcard .m-live i { color: #E63946; font-style: normal; animation: mlive-blink 1.4s infinite; }
@keyframes mlive-blink { 50% { opacity: 0.35; } }
.mcard .m-head { position: absolute; top: 34px; left: 14px; right: 14px; z-index: 5; text-align: center; }
.mcard .m-headline { display: inline-block; background: #13294AF2; color: #F2F7FD;
  font-size: 13px; font-weight: 800; line-height: 1.3; border-radius: 12px; padding: 8px 12px; }
.mcard .m-port { margin-top: 6px; color: #FFD60A; font-size: 9.5px; font-weight: 900; letter-spacing: 1.6px; }
.m-chart { flex: 1; position: relative; background: #0A1420; }
/* The REAL chart: the same dark MapLibre style the app renders moments
   on, framed on the actual scene coordinates. No painted landmasses. */
.m-map { position: absolute; inset: 0; }
.m-chart .maplibregl-ctrl-attrib { display: none; }
/* The app's replay rendering, layer for layer (HarborMap.tsx): each party
   is its ACTUAL vessels3d sprite sitting on two flat feathered identity
   discs in its speaker color (0.12 soft / 0.28 core — the halved inks,
   2026-09-07). No filled badge circle — that was never the app. Pucks are
   map MARKERS at the real positions. */
.puck { text-align: center; width: 110px; transition: opacity 0.3s; }
.puck .p-spot { position: relative; width: 60px; height: 60px; margin: 0 auto; }
.puck .p-spot i { position: absolute; border-radius: 50%; pointer-events: none; }
.puck .p-d1 { inset: 0; background: var(--pc); opacity: 0.12; }
.puck .p-d2 { inset: 15px; background: var(--pc); opacity: 0.28; }
.puck img.p-ship { position: absolute; left: 50%; top: 50%; height: 46px; z-index: 2;
  transform: translate(-50%, -50%) rotate(var(--rot, 0deg)); }
/* Approximate fix ("last seen"): sprite and discs run dimmer, the app's
   approx treatment for boats without a live AIS fix. */
.puck.approx img.p-ship { opacity: 0.55; }
.puck.approx .p-d1 { opacity: 0.08; }
.puck.approx .p-d2 { opacity: 0.2; }
/* Shore stations, same as the app: the station sprite on a soft yellow
   presence puck; broadcast rings are yellow and a notch stronger than
   ship rings, and the tower grows while transmitting. */
.puck.tower .p-d1 { background: #FFC400; opacity: 0.16; }
.puck.tower .p-d2 { display: none; }
.puck.tower img.p-ship { height: 40px; transition: height 0.3s; }
.puck.tower.speaking img.p-ship { height: 49px; }
/* On-air signature (replay-active-ring / station-ring): two expanding
   HOLLOW radio rings, half a period apart on a 2.4s cycle, in the
   speaker's own color, fading as they grow — not a dome. */
.puck .p-r { inset: 12px; border: 1.5px solid var(--pc); opacity: 0; }
.puck.tower .p-r { border-color: #FFD60A; border-width: 2px; --rmax: 0.55; }
.puck.speaking .p-r.r1 { animation: mradiowave 2.4s linear infinite; }
.puck.speaking .p-r.r2 { animation: mradiowave 2.4s linear infinite -1.2s; }
@keyframes mradiowave { 0% { transform: scale(1); opacity: var(--rmax, 0.45); }
  100% { transform: scale(2.9); opacity: 0; } }
/* Names wear the SPEAKER COLOR, same as the app's replay labels — the
   name is what ties a party to its caption. */
.puck .p-name { margin-top: 2px; font-size: 9px; font-weight: 900; letter-spacing: 0.8px;
  color: var(--pc, #E9F0F8); text-shadow: 0 1px 6px #000; line-height: 1.25; transition: opacity 0.3s; }
/* Spotlight by subtraction: while someone talks, everyone ELSE dims a
   notch — pucks to 80%, labels to 75% ink. */
.m-chart.spotlight .puck:not(.speaking) { opacity: 0.8; }
.m-chart.spotlight .puck:not(.speaking) .p-name { opacity: 0.75; }
/* Approximate scene zone, exactly the app's treatment: where the speakers
   SAID they were, drawn as a soft searching sonar pulse — deliberately
   vague, never a boat dot pretending to be a fix. */
.zone { text-align: center; width: 160px; pointer-events: none; }
.zone .z-ring { position: relative; width: 92px; height: 92px; margin: 0 auto; }
.zone .z-ring i { position: absolute; inset: 0; border-radius: 50%; }
.zone .z-fill { background: #FFD60A; opacity: 0.1; }
.zone .z-pulse { border: 1.5px solid #FFD60A; opacity: 0; animation: msonar 3.6s ease-out infinite; }
.zone .z-pulse.p2 { animation-delay: -1.8s; }
@keyframes msonar { 0% { transform: scale(0.3); opacity: 0.5; } 100% { transform: scale(1.05); opacity: 0; } }
.zone .z-lbl { margin-top: 2px; font-size: 9px; font-weight: 900; letter-spacing: 0.8px;
  color: #FFD60A; text-shadow: 0 1px 6px #000; }
.m-caps { position: absolute; left: 0; right: 0; bottom: 80px; padding: 0 13px; z-index: 4;
  pointer-events: none; }
.m-cap-prev { color: #93A3B8; font-size: 11.5px; line-height: 1.3; margin-bottom: 4px;
  text-shadow: 0 1px 5px #000; display: -webkit-box; -webkit-line-clamp: 2;
  -webkit-box-orient: vertical; overflow: hidden; }
.m-cap-now { color: #F5F8FC; font-size: 14.5px; font-weight: 800; line-height: 1.3;
  text-shadow: 0 1px 6px #000; min-height: 56px; display: -webkit-box; -webkit-line-clamp: 5;
  -webkit-box-orient: vertical; overflow: hidden; }
.m-bar { height: 74px; background: #FFD60A; padding: 8px 11px; flex: none; z-index: 4;
  display: flex; align-items: center; gap: 9px; }
/* The app bar's dotted timeline: every transmission is a blob in its
   speaker's map color, with a playhead riding the tape. */
.mb-track { position: relative; height: 6px; border-radius: 3px; background: #14100026;
  margin: 4px 0; }
.mb-track i { position: absolute; top: 0; bottom: 0; border-radius: 3px; min-width: 2px; }
.mb-ph { position: absolute; top: -2px; bottom: -2px; width: 2px; border-radius: 1px;
  background: #141000; margin-left: -1px; transition: left 0.25s linear; }
.mb-play { flex: none; width: 40px; height: 40px; border-radius: 50%; border: none;
  background: #141000; color: #FFD60A; font-size: 15px; font-weight: 900; cursor: pointer;
  display: flex; align-items: center; justify-content: center; }
.mb-play:active { transform: scale(0.94); }
.mb-info { flex: 1; min-width: 0; }
.mb-title { font-size: 10px; font-weight: 900; color: #141000; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.mb-chap { width: fit-content; margin-top: 3px; background: #141000; color: #FFD60A;
  font-size: 8px; font-weight: 900; letter-spacing: 0.5px; border-radius: 999px; padding: 3px 9px;
  white-space: nowrap; }
.mb-time { flex: none; font-size: 10.5px; font-weight: 900; color: #141000;
  font-variant-numeric: tabular-nums; }
.caro-hint { text-align: center; color: #5B6B7E; font-size: 13px; font-weight: 700; margin-top: 2px; }
@media (max-width: 760px) {
  .mcard { flex-basis: min(300px, calc(100vw - 70px)); }
}
