@font-face{font-family:Nunito;src:url('assets/nunito.ttf') format('truetype');font-weight:200 1000;font-display:swap}
:root{
 --sea:#95c7d1;--ink:#37544f;--paper:#f5edda;--cream:#f5edda;
 --chrome-bg:#203942;--name-color:#426c64;--name-halo:#fffdf1;
 font-family:Nunito,'Trebuchet MS',system-ui,sans-serif;color:var(--ink);background:#203942;
}
*{box-sizing:border-box}
html,body{width:100%;height:100%;margin:0;overflow:hidden}
[hidden]{display:none!important}
#main{height:100dvh;position:relative;overflow:hidden;background:var(--chrome-bg)}
#map{position:absolute;inset:0;width:1920px!important;height:1080px!important;background:var(--sea);font-family:inherit;isolation:isolate}
.leaflet-container{background:var(--sea);font-family:inherit;cursor:default!important}
.tv-stage{position:absolute;left:50%;top:50%;width:1920px;height:1080px;transform:translate(-50%,-50%) scale(var(--tv-scale,1));transform-origin:center;overflow:hidden;background:var(--sea);isolation:isolate}
/* Required resources are assembled behind this gate; no earlier map flashes. */
.scene-loading #main{visibility:hidden}
#scene-loading{position:fixed;inset:0;display:grid;place-content:center;justify-items:center;background:#203942;color:#e5eee3;z-index:1000;font-size:14px;letter-spacing:.15px}
#scene-loading svg{width:96px;height:60px}
#scene-loading p{margin:14px 24px;text-align:center;max-width:440px;line-height:1.6}
#retry-scene{font:inherit;color:#203942;background:#e5eee3;border:0;border-radius:16px;padding:11px 18px;cursor:pointer}
#retry-scene:focus-visible{outline:2px solid #ffd5a0;outline-offset:4px}
/* This is the complete rendering stack, not a cascade of old UI themes. */
.atmosphere-canvas,.moonlight-canvas,.harbor-canvas,.traffic-canvas,.holiday-canvas,.ground-light-canvas,.tv-terrain-canvas{position:absolute;pointer-events:none!important}
:is(.leaflet-background-pane,.leaflet-base-pane,.leaflet-landcover-pane,.leaflet-roads-pane,.leaflet-local-pane,.leaflet-harbor-pane,.leaflet-industrialGround-pane,.leaflet-seasonGround-pane,.leaflet-holidayGround-pane){filter:brightness(var(--map-brightness,1)) saturate(var(--map-saturation,1));transition:filter 2s ease}
.ground-light-canvas{opacity:var(--night,0);transition:opacity 2s}
.tv-terrain-canvas{opacity:calc((1 - var(--night,0)*.3)*(1 - var(--season-snow-cover,0)*.14));filter:grayscale(var(--season-relief-neutral,0))}
.tv-horizon{position:absolute;left:0;top:0;width:1920px;height:290px;background:linear-gradient(var(--horizon-color,#e6ebdc) 0%,transparent 100%);pointer-events:none}
/* A little dimensional shading; lights belong to the fixtures, not the hull. */
.boat-marker,.aircraft-marker,.tv-name-marker{background:none!important;border:0!important;pointer-events:none!important}
.boat-marker svg{overflow:visible;display:block;width:100%;height:100%;filter:drop-shadow(0 1.3px .8px #263f3a25)}
.boat-body,.aircraft-body{filter:brightness(calc(1 - var(--night,0)*.48)) saturate(calc(1 - var(--night,0)*.16))}
.boat-marker.is-stale svg{opacity:.48;filter:grayscale(.4)}
.boat-bob{transform-origin:var(--boat-origin-x,40px) var(--boat-origin-y,46px);animation:boat-rest 5.8s ease-in-out infinite;animation-delay:calc(-1 * var(--boat-delay,0s))}
.is-moving .boat-bob{animation-name:boat-sail;animation-duration:calc(var(--bob-speed,3.1s) * var(--speed-factor,1))}
.boat-flag{animation:flag-wave var(--flag-speed,3.2s) ease-in-out infinite;transform-box:fill-box;transform-origin:left center}
.boat-water .wake{opacity:0}
.is-moving .wake{opacity:.5;animation:wake var(--wake-speed,3s) ease-in-out infinite}
.wake-bubble{animation:bubble 3.4s ease-in-out infinite;transform-box:fill-box;transform-origin:center}
.bubble-2{animation-delay:-1.7s}
.moor-ripple{opacity:0;transform-origin:var(--boat-origin-x,40px) var(--boat-origin-y,46px);animation:ripple 6s ease-out infinite;animation-delay:calc(-1 * var(--boat-delay,0s))}
.ripple-1{animation-delay:calc(-2s - var(--boat-delay,0s))}.ripple-2{animation-delay:calc(-4s - var(--boat-delay,0s))}
.vessel-lights,.aircraft-nav-lights{opacity:var(--night,0);transition:opacity 2s}
.boat-light-pool{display:none}.boat-window-warmth{opacity:.24}
.boat-reflection{opacity:calc(var(--night,0)*.14);transform-origin:var(--boat-origin-x,40px) var(--boat-origin-y,53px);animation:water-lantern 6s ease-in-out infinite}
.local-workboat .moor-ripple{display:none}
.tv-cluster-member{display:none!important}
.aircraft-marker svg{display:block;width:32px;height:32px;margin:6px;overflow:visible;filter:drop-shadow(0 1px 1px #244b4720)}
.aircraft-float{transform-origin:32px 32px;animation:aircraft-sway 7s ease-in-out infinite}
.aircraft-beacon{animation:soft-beacon 3s ease-in-out infinite}
/* Name placement also reserves the three user-requested passive info fields. */
.tv-name-card{width:100%;height:100%;padding:4px 6px;color:var(--name-color);overflow:hidden;text-shadow:0 0 3px var(--name-halo),0 1px 2px var(--name-halo),1px 0 2px var(--name-halo),-1px 0 2px var(--name-halo)}
.tv-name-card.names-changed{animation:name-reveal .24s ease-out}
.tv-name-card strong{display:block;font:800 18px/24px Nunito,sans-serif;white-space:pre-line;overflow-wrap:anywhere}
.tv-name-card.local-fleet-card{padding:2px 5px}.tv-name-card.local-fleet-card strong{font:800 13px/18px Nunito,sans-serif;white-space:pre-line}
.tv-panorama-status,.screen-reader-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
.holiday-badge,.tv-season-status,.traffic-note,.leaflet-control-container{display:none!important}
.ais-update :is(.boat-marker,.tv-name-marker){transition:transform 1.6s cubic-bezier(.25,.65,.3,1)}
@keyframes name-reveal{from{opacity:.35;transform:translateY(1px)}to{opacity:1;transform:translateY(0)}}
@keyframes boat-rest{0%,100%{transform:translateY(calc(var(--bob-amplitude,2px)*.04)) rotate(-.28deg)}50%{transform:translateY(calc(var(--bob-amplitude,2px)*-.09)) rotate(.28deg)}}
@keyframes boat-sail{0%,100%{transform:translateY(calc(var(--bob-amplitude,2px)*.08)) rotate(-.45deg)}50%{transform:translateY(calc(var(--bob-amplitude,2px)*-.18)) rotate(.45deg)}}
@keyframes flag-wave{0%,100%{transform:skewY(-4deg)}50%{transform:skewY(4deg)}}
@keyframes wake{0%,100%{opacity:.35}50%{opacity:.6}}
@keyframes bubble{0%,100%{opacity:.18;transform:scale(.88)}50%{opacity:.38;transform:scale(1.05)}}
@keyframes ripple{0%{opacity:0;transform:scale(.95)}18%{opacity:.2}100%{opacity:0;transform:scale(1.15)}}
@keyframes water-lantern{0%,100%{transform:translateX(-.35px) scaleX(.94)}50%{transform:translateX(.35px) scaleX(1.04)}}
@keyframes aircraft-sway{0%,100%{transform:translateY(.2px) rotate(-.3deg)}50%{transform:translateY(-.2px) rotate(.3deg)}}
@keyframes soft-beacon{0%,70%,100%{opacity:.28}82%{opacity:.85}}
.app-paused *,.app-paused *::before,.app-paused *::after{animation-play-state:paused!important}
.reduced-motion *,.reduced-motion *::before,.reduced-motion *::after{animation:none!important;transition:none!important}
.is-stale :is(.boat-bob,.wake,.moor-ripple,.boat-flag,.boat-reflection){animation:none!important}
.is-stale :is(.wake,.moor-ripple){opacity:0!important}
@media(prefers-reduced-motion:reduce){body:not(.full-motion) *,body:not(.full-motion) *::before,body:not(.full-motion) *::after{animation:none!important;transition:none!important}}
