/* dt-poc — SC14 maritime Digital Twin demonstrator.
   Colour, type, spacing and motion come from the SeaCras brand kit: sc-tokens.css is
   generated by docs/brand-kit/tools/sync-tokens.mjs and loaded before this file. Nothing
   here re-declares a --sc-* token; local aliases below name the few product decisions
   this application makes on top of the system. */

:root {
  /* Headings sit on the accessible deep blue, not the raw brand blue: brand blue on
     white is 3.10:1 and only clears AA at display sizes. The deep blue itself fails on
     the dark surfaces (2.5:1), so the dark blocks below flip this alias to the accent. */
  --heading: var(--sc-blue-deep);
  /* The header gradient is a brand moment and stays dark navy in BOTH themes, so text on
     it is always white. Never --sc-on-accent here: that token flips to near-black in the
     dark theme (it is meant for the then-light accent fills) and would sit at 1.6:1 on
     the gradient. */
  --on-brand: var(--sc-white);
  --stat-numeral: var(--sc-stat-numeral-on-light);
  --radius-sm: var(--sc-radius-sm);
  --radius-md: var(--sc-radius-md);
  --radius-lg: var(--sc-radius-lg);
  --shadow: var(--sc-shadow-1);
  --topbar-h: 56px;
}

* { box-sizing: border-box; }

/* The operations view is an application screen, not a document: it fills the viewport
   exactly and its own panels scroll. Every other page scrolls normally. */
body.ops-page {
  height: 100vh;
  overflow: hidden;
}

body {
  margin: 0;
  background: var(--sc-surface);
  color: var(--sc-text);
  font-family: var(--sc-font-body);
  font-size: var(--sc-text-body);
  line-height: 1.55;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

a { color: var(--sc-link); }
:focus-visible { outline: 2px solid var(--sc-focus); outline-offset: 2px; border-radius: 3px; }
.muted { color: var(--sc-text-muted); }
.tabular { font-variant-numeric: tabular-nums; }
.center { text-align: center; }

/* ------------------------------------------------------------------ chrome */

.topbar {
  display: flex;
  align-items: center;
  gap: 16px;
  min-height: var(--topbar-h);
  padding: 6px 18px;
  background: var(--sc-gradient-brand-deep);
  color: var(--on-brand);
  flex: none;
  flex-wrap: wrap;
}
/* The default focus colour is picked against the page surface and vanishes on the
   gradient (1.06:1 in light); everything focusable in the header gets the white ring. */
.topbar :focus-visible { outline-color: var(--on-brand); }
.brand { display: flex; align-items: center; gap: 8px; color: #fff; text-decoration: none; }
.brand-mark { width: 26px; height: 26px; color: #fff; flex: none; }
.brand-text { font-weight: 600; letter-spacing: .12em; text-transform: uppercase; font-size: var(--sc-text-sm); }
.brand-sep { width: 1px; height: 18px; background: rgba(255, 255, 255, .55); }
.brand-product { font-size: var(--sc-text-sm); color: var(--on-brand); }

.mainnav { display: flex; gap: 2px; flex-wrap: wrap; }
.mainnav a {
  color: var(--on-brand);
  text-decoration: none;
  padding: 5px 10px;
  border-radius: var(--sc-radius-pill);
  font-size: var(--sc-text-sm);
  white-space: nowrap;
}
.mainnav a:hover { background: rgba(255, 255, 255, .16); color: var(--on-brand); }
.mainnav a.is-active {
  background: rgba(255, 255, 255, .24);
  color: var(--on-brand);
  font-weight: 600;
}

.topbar-right {
  margin-left: auto; display: flex; align-items: center; gap: 12px;
  font-size: var(--sc-text-sm); white-space: nowrap;
}
.topbar-right a, .port-name, .user { color: var(--on-brand); }
.port-name { border-left: 1px solid rgba(255, 255, 255, .55); padding-left: 12px; }
.port-control { border-left: 1px solid rgba(255, 255, 255, .55); padding-left: 12px; }
.port-select {
  max-width: 240px; background: rgba(255, 255, 255, .12); color: var(--on-brand);
  border: 1px solid rgba(255, 255, 255, .45); border-radius: var(--radius-sm, 6px);
  padding: 4px 8px; font: inherit; font-weight: 600;
}
.port-select option, .port-select optgroup { color: var(--text, #111); background: var(--surface, #fff); }
.inline-form { display: inline; }
.linkish {
  background: none; border: 0; color: var(--on-brand);
  cursor: pointer; font: inherit; text-decoration: underline; padding: 0;
}

.footer {
  flex: none;
  border-top: 1px solid var(--sc-border);
  padding: 12px 18px;
  font-size: var(--sc-text-sm);
  color: var(--sc-text-muted);
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  background: var(--sc-surface-sunken);
}
.footer-note { margin-left: auto; }

main { flex: 1 1 auto; min-height: 0; }
.page { max-width: 1180px; margin: 0 auto; padding: 26px 20px 40px; width: 100%; }
.page.centered { max-width: 460px; }

.page-head { margin-bottom: 22px; }
.page-head h1 { font-size: var(--sc-text-h2); font-weight: 600; color: var(--heading); margin: 0 0 6px; }
.page-head p { margin: 0; max-width: var(--sc-measure); }
.page-head .notice-inline { margin-top: 8px; font-size: var(--sc-text-sm); }

/* ------------------------------------------------------------------ operations */

.ops { display: flex; min-height: 0; }
.ops-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 380px;
  grid-template-rows: minmax(0, 1fr);
  flex: 1;
  width: 100%;
  min-height: 520px;
}
@media (max-width: 1120px) {
  .ops-grid { grid-template-columns: minmax(0, 1fr) 330px; }
}
@media (max-width: 980px) {
  .ops-grid { grid-template-columns: 1fr; grid-template-rows: auto auto; min-height: 0; }
  .mapwrap { height: 62vh; }
}

.mapwrap { position: relative; min-width: 0; min-height: 0; background: var(--sc-surface-sunken); }
/* Scoped past `.maplibregl-map`, which the library applies to this same element. */
.mapwrap > .map { position: absolute; inset: 0; width: 100%; height: 100%; }

.map-overlay {
  position: absolute;
  z-index: 2;
  background: var(--sc-surface);
  border: 1px solid var(--sc-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow);
  padding: 10px 12px;
  font-size: var(--sc-text-sm);
  max-width: 260px;
}
.map-layers { overflow-y: auto; }
.map-legend { top: 12px; right: 12px; width: 210px; }

.panel-label {
  font-size: var(--sc-text-xs); letter-spacing: var(--sc-section-label-tracking); text-transform: uppercase;
  color: var(--sc-text-muted); font-weight: 600; margin-bottom: 6px;
}

.layer-toggles { display: flex; flex-direction: column; gap: 2px; }
.layer-toggle {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 6px; border-radius: var(--radius-sm); cursor: pointer;
}
.layer-toggle:hover { background: var(--sc-surface-sunken); }
.layer-toggle input { margin: 0; flex: none; }
.layer-toggle .lt-name { flex: 1; min-width: 0; }
.badge-fidelity {
  font-size: var(--sc-text-xs); padding: 1px 6px; border-radius: 200px;
  background: var(--sc-surface-sunken); color: var(--sc-text-muted); white-space: nowrap;
}
.badge-fidelity.is-interim { background: var(--sc-status-info-bg); color: var(--sc-status-info-text); }
.badge-fidelity.is-synthetic { background: var(--sc-status-moderate-bg); color: var(--sc-status-moderate-text); }

.legend-title { font-weight: 600; margin-bottom: 6px; }
.legend-ramp { height: 10px; border-radius: var(--sc-radius-pill); margin-bottom: 4px; border: 1px solid var(--sc-border-strong); }
.legend-scale {
  display: flex; justify-content: space-between;
  font-size: var(--sc-text-xs); color: var(--sc-text-muted); font-variant-numeric: tabular-nums;
}
.legend-attr { font-size: var(--sc-text-xs); color: var(--sc-text-muted); margin-top: 6px; line-height: 1.35; }

.timebar {
  position: absolute; left: 12px; right: 12px; bottom: 12px; z-index: 2;
  background: var(--sc-surface);
  border: 1px solid var(--sc-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow);
  padding: 8px 12px 10px;
}
.timebar-head { display: flex; align-items: baseline; gap: 10px; }
.timebar-label { font-size: var(--sc-text-xs); letter-spacing: var(--sc-section-label-tracking); text-transform: uppercase; color: var(--sc-text-muted); font-weight: 600; }
.time-readout { margin-left: auto; font-weight: 600; font-variant-numeric: tabular-nums; }
.timebar-controls { display: flex; align-items: center; gap: 10px; }
.timebar-controls input[type=range] { flex: 1; accent-color: var(--sc-accent-solid); }
.btn-icon {
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  border: 1px solid var(--sc-border-strong); background: var(--sc-surface);
  color: var(--sc-text); cursor: pointer; font-size: var(--sc-text-xs); line-height: 1;
}
.btn-icon:hover { background: var(--sc-surface-sunken); }

/* The strip encodes worst status per timestep, so trouble is visible before scrubbing.
   Same inset ring as .dot and .key-swatch: the good and moderate fills are light by
   design and sit under 2:1 against the white timebar on their own. */
.timeline-strip { display: flex; gap: 1px; height: 8px; margin: 6px 0 8px; }
.timeline-strip span {
  flex: 1; border-radius: 1px; background: var(--map-status-no_data);
  box-shadow: inset 0 0 0 1px var(--sc-border-strong);
}
.timeline-strip span.s-green { background: var(--map-status-green); }
.timeline-strip span.s-amber { background: var(--map-status-amber); }
.timeline-strip span.s-red { background: var(--map-status-red); }
.timeline-strip span.is-current { outline: 2px solid var(--sc-text); outline-offset: 1px; }

.sidepanel {
  border-left: 1px solid var(--sc-border);
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
  padding: 16px;
  background: var(--sc-surface);
  display: flex; flex-direction: column; gap: 16px;
}
.scenario-headline {
  font-size: var(--sc-text-sm); font-weight: 600; color: var(--heading); margin: 8px 0 0;
}
.scenario-desc { font-size: var(--sc-text-sm); color: var(--sc-text-muted); margin: 4px 0 0; }

/* Scrollable overlay panels get an edge so a cut-off row reads as "more below". */
.map-layers { scrollbar-width: thin; overscroll-behavior: contain; }
.map-layers::after {
  content: ""; position: sticky; bottom: -10px; display: block; height: 12px;
  margin: 0 -12px -10px;
  background: linear-gradient(to top, var(--sc-surface), transparent);
}

input[type=checkbox], input[type=radio] { accent-color: var(--sc-accent-solid); }

.select, input[type=text], input[type=password], input:not([type]), textarea, .num {
  width: 100%; padding: 7px 9px;
  border: 1px solid var(--sc-input-border); border-radius: var(--radius-sm);
  background: var(--sc-input-background); color: var(--sc-text); font: inherit;
}
.num { width: 90px; font-variant-numeric: tabular-nums; }

.status-headline {
  border: 1px solid var(--sc-border); border-radius: var(--radius-md);
  padding: 12px; background: var(--sc-surface-sunken);
}
.headline-status { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: var(--sc-text-body); }
.dot {
  width: 12px; height: 12px; border-radius: 50%; flex: none;
  background: var(--map-asset-neutral);
  box-shadow: inset 0 0 0 1px var(--sc-border-strong);
}
.dot.s-green { background: var(--map-status-green); }
.dot.s-amber { background: var(--map-status-amber); }
.dot.s-red { background: var(--map-status-red); }
.headline-text { margin: 6px 0 0; font-size: var(--sc-text-sm); color: var(--sc-text-muted); }

.alerts { display: flex; flex-direction: column; gap: 8px; }
.alert-card {
  border: 1px solid var(--sc-border); border-left-width: 3px;
  border-radius: var(--radius-sm); padding: 9px 11px; font-size: var(--sc-text-sm);
  background: var(--sc-surface);
}
.alert-card.s-red { border-left-color: var(--sc-status-alert-fill); background: var(--sc-status-alert-bg); }
.alert-card.s-amber { border-left-color: var(--sc-status-moderate-fill); background: var(--sc-status-moderate-bg); }
.alert-head { display: flex; gap: 8px; align-items: baseline; }
.alert-asset { font-weight: 600; }
.alert-value { margin-left: auto; font-variant-numeric: tabular-nums; white-space: nowrap; }
.alert-rule { color: var(--sc-text-muted); }
.alert-guidance { margin-top: 5px; font-size: var(--sc-text-sm); }
.empty { color: var(--sc-text-muted); font-size: var(--sc-text-sm); font-style: italic; }

.asset-list { display: flex; flex-direction: column; gap: 1px; }
.asset-row {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 8px; border-radius: var(--radius-sm); cursor: pointer; font-size: var(--sc-text-sm);
}
.asset-row {
  transition: background-color var(--sc-duration-fast) var(--sc-ease-standard);
}
.asset-row:hover, .asset-row.is-selected { background: var(--sc-surface-hover); }
.asset-row .asset-title { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.asset-row .asset-kindline { font-size: var(--sc-text-xs); color: var(--sc-text-muted); }

.vessel-list { display: flex; flex-direction: column; gap: 6px; font-size: var(--sc-text-sm); }
.vessel-row { display: flex; gap: 8px; align-items: baseline; padding: 5px 0; border-bottom: 1px solid var(--sc-border); }
.vessel-row:last-child { border-bottom: 0; }
.vessel-name { font-weight: 600; }
.vessel-phase {
  margin-left: auto; font-size: var(--sc-text-xs); padding: 1px 8px; border-radius: 200px;
  background: var(--sc-surface-sunken); color: var(--sc-text-muted); white-space: nowrap;
}
.vessel-phase.p-alongside { background: var(--sc-status-good-bg); color: var(--sc-status-good-text); }
.vessel-phase.p-inbound { background: var(--sc-surface-sunken); color: var(--sc-link); }

.notice {
  font-size: var(--sc-text-sm); border: 1px solid var(--sc-border);
  background: var(--sc-status-moderate-bg); color: var(--sc-status-moderate-text);
  border-radius: var(--radius-sm); padding: 10px 12px;
}
.notice a { color: inherit; }
.notice-block { margin-bottom: 18px; font-size: var(--sc-text-sm); }

/* ------------------------------------------------------------------ badges */

.badge {
  display: inline-block; font-size: var(--sc-text-xs); font-weight: 600;
  padding: 2px 10px; border-radius: var(--sc-radius-pill); white-space: nowrap;
  box-shadow: inset 0 0 0 1px var(--sc-border-strong);
}
.badge-sm { font-size: var(--sc-text-xs); padding: 1px 8px; }
.badge-green { background: var(--sc-status-good-bg); color: var(--sc-status-good-text); }
.badge-amber { background: var(--sc-status-moderate-bg); color: var(--sc-status-moderate-text); }
.badge-red { background: var(--sc-status-alert-bg); color: var(--sc-status-alert-text); }
.badge-no_data { background: var(--sc-status-neutral-bg); color: var(--sc-status-neutral-text); }
.badge-synthetic { background: var(--sc-status-moderate-bg); color: var(--sc-status-moderate-text); }

.fidelity { font-size: var(--sc-text-xs); padding: 2px 9px; border-radius: 200px; background: var(--sc-surface-sunken); color: var(--sc-text-muted); }
.fidelity-pipeline { background: var(--sc-status-good-bg); color: var(--sc-status-good-text); }
.fidelity-precomputed { background: var(--sc-surface-sunken); color: var(--sc-link); }
.fidelity-authored { background: var(--sc-status-neutral-bg); color: var(--sc-status-neutral-text); }

/* ------------------------------------------------------------------ tables */

.table { width: 100%; border-collapse: collapse; font-size: var(--sc-text-sm); }
.table th {
  text-align: left; font-size: var(--sc-text-xs); letter-spacing: var(--sc-section-label-tracking); text-transform: uppercase;
  color: var(--sc-text-muted); font-weight: 600;
  padding: 8px 12px 8px 0; border-bottom: 2px solid var(--sc-border);
}
.table td { padding: 11px 12px 11px 0; border-bottom: 1px solid var(--sc-border); vertical-align: top; }
.table-compact td { padding: 6px 8px 6px 0; font-size: var(--sc-text-sm); }
.row-degraded { background: var(--sc-status-moderate-bg); }
.asset-name { font-weight: 600; }
.asset-meta { font-size: var(--sc-text-xs); color: var(--sc-text-muted); }
.guidance { font-size: var(--sc-text-sm); color: var(--sc-text-muted); margin-top: 4px; max-width: 52ch; }
.attribution { font-size: var(--sc-text-xs); color: var(--sc-text-muted); margin-top: 4px; font-style: italic; }
.breach-list { margin: 0; padding-left: 0; list-style: none; display: flex; flex-direction: column; gap: 8px; }
.check-list { margin: 6px 0 0; padding-left: 0; list-style: none; font-size: var(--sc-text-xs); }
.check-list li { display: flex; gap: 8px; padding: 2px 0; }
.chk-name { min-width: 130px; color: var(--sc-text-muted); }
.chk-ok .chk-name::before { content: "\2713 "; color: var(--sc-status-good-text); }
.chk-fail .chk-name::before { content: "\2717 "; color: var(--sc-status-alert-text); }
.chk-advisory .chk-name::before { content: "\26A0 "; color: var(--sc-status-moderate-text); }
.chk-detail { color: var(--sc-text); }
.degraded-flag { color: var(--sc-status-moderate-text); margin-left: 4px; }

.toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 18px; }
.toolbar .select { width: auto; min-width: 240px; }
.toolbar label { font-size: var(--sc-text-sm); color: var(--sc-text-muted); }

.compare-summary {
  display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
  border: 1px solid var(--sc-border); border-radius: var(--radius-md);
  padding: 14px 18px; margin-bottom: 18px; background: var(--sc-surface-sunken);
}
.compare-kind { font-size: var(--sc-text-xs); letter-spacing: var(--sc-section-label-tracking); text-transform: uppercase; color: var(--sc-text-muted); font-weight: 600; }
.compare-name { font-weight: 600; margin-bottom: 4px; }
.compare-arrow { font-size: var(--sc-text-lg); color: var(--sc-text-muted); }
.compare-verdict { margin-left: auto; text-align: right; }
.compare-verdict strong { font-size: var(--sc-text-h2); font-weight: 600; color: var(--heading); display: block; font-variant-numeric: tabular-nums; }
.compare-verdict span { font-size: var(--sc-text-sm); color: var(--sc-text-muted); }

.narrative {
  border-left: 3px solid var(--sc-accent);
  background: var(--sc-surface-sunken);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  padding: 12px 16px; margin-bottom: 20px;
}
.narrative-headline { font-weight: 600; color: var(--heading); }
.narrative p { margin: 6px 0 0; max-width: var(--sc-measure); font-size: var(--sc-text-sm); }
.narrative-decision { border-top: 1px solid var(--sc-border); padding-top: 8px; }

/* ------------------------------------------------------------------ forms */

.stack { display: flex; flex-direction: column; gap: 8px; }
.stack label { font-size: var(--sc-text-sm); font-weight: 500; margin-top: 4px; }
.card {
  border: 1px solid var(--sc-border); border-radius: var(--radius-md);
  padding: 18px; background: var(--sc-surface);
}
.two-col { display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr); gap: 20px; align-items: start; }
@media (max-width: 860px) { .two-col { grid-template-columns: 1fr; } }

.btn-primary {
  background: var(--sc-accent-solid); color: var(--sc-on-accent-solid); border: 0;
  padding: 9px 18px; border-radius: var(--radius-sm);
  font: inherit; font-weight: 500; cursor: pointer; align-self: flex-start;
  transition: background-color var(--sc-duration-fast) var(--sc-ease-standard);
}
.btn-primary:hover { background: var(--sc-accent-solid-hover); }
.btn-primary:active { background: var(--sc-accent-solid-pressed); }
.form-actions { display: flex; align-items: center; gap: 14px; margin-top: 16px; }

.form-error {
  background: var(--sc-status-alert-bg); color: var(--sc-status-alert-text);
  border-radius: var(--radius-sm); padding: 9px 12px; font-size: var(--sc-text-sm); margin-bottom: 12px;
}
.form-ok {
  background: var(--sc-status-good-bg); color: var(--sc-status-good-text);
  border-radius: var(--radius-sm); padding: 9px 12px; font-size: var(--sc-text-sm); margin-bottom: 14px;
}
.login-card {
  border: 1px solid var(--sc-border); border-radius: var(--radius-lg);
  padding: 26px; box-shadow: var(--shadow); background: var(--sc-surface);
}
.login-card h1 { margin: 0 0 4px; font-size: var(--sc-text-lg); color: var(--heading); }
.demo-hint { font-size: var(--sc-text-sm); color: var(--sc-text-muted); margin: 14px 0 0; }

.scores { border: 1px solid var(--sc-border); border-radius: var(--radius-md); padding: 12px 14px; margin: 10px 0; }
.scores legend { font-size: var(--sc-text-xs); color: var(--sc-text-muted); padding: 0 6px; }
.score-row { display: flex; align-items: center; gap: 14px; padding: 7px 0; border-bottom: 1px solid var(--sc-border); }
.score-row:last-child { border-bottom: 0; }
.score-label { flex: 1; font-size: var(--sc-text-sm); }
.score-label em { display: block; font-size: var(--sc-text-xs); color: var(--sc-text-muted); font-style: normal; }
.score-inputs { display: flex; gap: 4px; }
.score-inputs label { display: flex; flex-direction: column; align-items: center; cursor: pointer; font-size: var(--sc-text-xs); }
.score-inputs input { margin: 0 0 2px; }

.stat-callout { margin: 6px 0 12px; }
.stat-callout strong {
  display: block; line-height: 1;
  font-family: var(--sc-font-display);
  font-size: var(--sc-stat-numeral-size);
  font-weight: 600;
  color: var(--stat-numeral);
  font-variant-numeric: tabular-nums;
}
.stat-callout span {
  font-size: var(--sc-text-sm); color: var(--sc-text-muted);
  display: block; max-width: 18ch;
}

/* MapLibre control tinting so its chrome sits inside the design rather than beside it. */
.maplibregl-ctrl-group { border-radius: var(--radius-sm) !important; box-shadow: var(--shadow) !important; }
.maplibregl-popup-content {
  border-radius: var(--radius-md); padding: 10px 12px; font-size: var(--sc-text-sm);
  font-family: inherit; color: var(--sc-neutral-900); box-shadow: var(--shadow);
}
.popup-title { font-weight: 600; margin-bottom: 2px; }
.popup-meta { font-size: var(--sc-text-xs); color: var(--sc-neutral-600); }
.popup-list { margin: 6px 0 0; padding-left: 0; list-style: none; font-size: var(--sc-text-sm); }
.popup-list li { display: flex; gap: 6px; padding: 1px 0; }

.map-fallback {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 6px; text-align: center;
  padding: 30px; color: var(--sc-text-muted); background: var(--sc-surface-sunken);
}
.map-fallback p { max-width: 42ch; font-size: var(--sc-text-sm); margin: 0; }

/* Colour theme control. Three states: System (default), Light, Dark. */
.theme-control select {
  font: inherit;
  font-size: var(--sc-text-xs);
  color: var(--on-brand);
  background: rgba(255, 255, 255, .16);
  border: 1px solid rgba(255, 255, 255, .55);
  border-radius: var(--radius-sm);
  padding: 3px 6px;
  width: auto;
}
.theme-control select option { color: var(--sc-text); background: var(--sc-surface); }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Status key. Colour alone never conveys state: every swatch is labelled, and each
   carries a 1px outline because several of the status fills are deliberately light and
   do not clear 3:1 against the surface on their own. */
.map-layers { top: 12px; left: 12px; max-height: calc(100% - 150px); }
.status-key { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 12px; }
.map-layers .panel-label + .status-key { margin-bottom: 2px; }
.status-key li { display: flex; align-items: center; gap: 6px; font-size: var(--sc-text-xs); }
.key-swatch {
  width: 12px; height: 12px; border-radius: 3px; flex: none;
  background: var(--map-asset-neutral);
  box-shadow: inset 0 0 0 1px var(--sc-border-strong);
}
.key-swatch.s-green { background: var(--map-status-green); }
.key-swatch.s-amber { background: var(--map-status-amber); }
.key-swatch.s-red { background: var(--map-status-red); }

/* MapLibre ships its own focus ring in an off-brand blue. */
.maplibregl-ctrl button:focus-visible { box-shadow: 0 0 0 2px var(--sc-focus) !important; }

/* Map palette.
   MapLibre paint properties take literal colour strings and cannot read a CSS variable,
   so operations.js reads these at runtime with getComputedStyle. Declaring them here
   rather than in the script keeps every colour decision in the stylesheet, keeps the kit
   tokens as the single source, and makes the map follow the theme for free. */
:root {
  --map-sea: var(--sc-blue-tints-20);
  --map-land: var(--sc-neutral-50);
  --map-coast: var(--sc-border-strong);
  --map-aoi-fill: var(--sc-map-aoi-fill);
  --map-aoi-casing: var(--sc-map-aoi-casing);
  --map-aoi-stroke: var(--sc-map-aoi-stroke);
  --map-asset-neutral: var(--sc-neutral-600);
  --map-track: var(--sc-blue-dark-ink);
  --map-vessel: var(--sc-blue-dark-ink);
  --map-vessel-inbound: var(--sc-neutral-0);

  --map-status-red: var(--sc-status-alert-fill);
  --map-status-amber: var(--sc-status-moderate-fill);
  --map-status-green: var(--sc-status-good-fill);
  --map-status-no_data: var(--sc-status-neutral-fill);

  /* Earth-observation layers are categorical identity, deliberately not status colours. */
  --map-eo-marpol_slick: var(--sc-viz-cat-6);
  --map-eo-runoff_plume: var(--sc-viz-cat-2);
  --map-eo-shoreline_change: var(--sc-viz-cat-7);
  --map-eo-default: var(--sc-accent);

  /* Legend ramps, mirroring dtpipe/render.py. */
  --ramp-seq: var(--sc-viz-seq-1), var(--sc-viz-seq-2), var(--sc-viz-seq-3),
              var(--sc-viz-seq-4), var(--sc-viz-seq-5), var(--sc-viz-seq-6), var(--sc-viz-seq-7);
  --ramp-div: var(--sc-viz-div-1), var(--sc-viz-div-2), var(--sc-viz-div-3),
              var(--sc-viz-div-4), var(--sc-viz-div-5), var(--sc-viz-div-6), var(--sc-viz-div-7);
  --ramp-status: var(--sc-status-good-fill), var(--sc-status-moderate-fill),
                 var(--sc-status-poor-fill), var(--sc-status-alert-fill);
  --ramp-wind: #FFF4D6, #F5D99A, var(--sc-viz-cat-4), var(--sc-viz-cat-5), #B43014, #6E1214;
  --ramp-wave: #EEE9F5, #BFAED9, var(--sc-viz-cat-6), #4F3778, #2C1C4B;
  --ramp-current: #DFF5F7, #8FDDE6, var(--sc-viz-cat-3), var(--sc-viz-cat-7), #063E45;

  --map-sea-satellite: #0A1426;
  --map-hill-shadow: rgba(8, 24, 40, 0.55);
  --map-hill-highlight: rgba(255, 255, 255, 0.28);
  --map-hill-accent: rgba(8, 24, 40, 0.35);
  --map-contour: #FFFFFF;
  --map-contour-casing: #0B2238;
  --map-vector: #FFFFFF;
  --map-vector-casing: #0B2238;
  --map-particle: rgba(255, 255, 255, 0.62);
  --map-vessel-hull: #FFFFFF;
  --map-vessel-inbound-fill: var(--sc-viz-cat-4);
  --map-vessel-casing: #0B2238;
  --map-vessel-trail: #FFFFFF;
  --map-sky: #8EBFE6;
  --map-horizon: #D9E7F2;
  --map-label-bg: rgba(11, 34, 56, 0.78);
}

/* The map ground follows the theme. The sea and land values come from the fixed brand
   ramp rather than the semantic tokens, so unlike everything else they do not flip on
   their own — a light map inside dark chrome glares badly, so they are set explicitly.
   Same three-state cascade as tokens.css: media query for "system", attribute for an
   explicit choice, so the toggle wins in both directions. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    /* App-local aliases that are anchored to LIGHT-surface colours and fail on the dark
       surfaces: deep-blue headings sit at 2.5:1 there, the map's neutral asset outline
       at 2.0:1 against the dark sea, and the dark alert *chip* fill at 2.3:1 as a mark.
       Each flips to the token designed for a dark ground. */
    --heading: var(--sc-accent);
    --stat-numeral: var(--sc-accent);
    --map-asset-neutral: var(--sc-neutral-400);
    --map-status-red: var(--sc-status-alert-text);

    --map-sea: var(--sc-blue-dark-ink);
    --map-land: var(--sc-neutral-900);
    --map-coast: var(--sc-neutral-600);
    --map-aoi-casing: var(--sc-neutral-950);
    --map-aoi-stroke: var(--sc-blue-tints-60);
    --map-track: var(--sc-blue-tints-40);
    --map-vessel: var(--sc-blue-tints-40);
    --map-vessel-inbound: var(--sc-neutral-950);
    --map-sky: #0E2238;
    --map-horizon: #1C3550;
  }
}
:root[data-theme="dark"] {
  --heading: var(--sc-accent);
  --stat-numeral: var(--sc-accent);
  --map-asset-neutral: var(--sc-neutral-400);
  --map-status-red: var(--sc-status-alert-text);

  --map-sea: var(--sc-blue-dark-ink);
  --map-land: var(--sc-neutral-900);
  --map-coast: var(--sc-neutral-600);
  --map-aoi-casing: var(--sc-neutral-950);
  --map-aoi-stroke: var(--sc-blue-tints-60);
  --map-track: var(--sc-blue-tints-40);
  --map-vessel: var(--sc-blue-tints-40);
  --map-vessel-inbound: var(--sc-neutral-950);
}

.compare-note { margin: -6px 0 18px; font-size: var(--sc-text-sm); max-width: var(--sc-measure); }
.toolbar { flex-wrap: wrap; }

.badge-tier-interim { background: var(--sc-status-info-bg); color: var(--sc-status-info-text); }
.badge-tier-synthetic { background: var(--sc-status-moderate-bg); color: var(--sc-status-moderate-text); }

/* Wave divider under the header. Masked rather than <img> so it takes the page surface
   colour and therefore follows the theme; 14px tall so it reads as an edge, not a band. */
.wave-divider {
  height: 14px;
  flex: none;
  order: 0;
  /* It is pulled up over the header, so it must not swallow clicks on the nav. */
  pointer-events: none;
  background: var(--sc-surface);
  -webkit-mask: url("/static/wave-divider-white.svg") no-repeat center / 100% 100%;
  mask: url("/static/wave-divider-white.svg") no-repeat center / 100% 100%;
  margin-top: -14px;
  position: relative;
  z-index: 1;
}
body.ops-page .wave-divider { display: none; }

/* The one red accent in the product: the current position on the timeline. Brand red is
   sanctioned only as a "here, now" marker — round, under 8px, one per view, and always
   with a non-colour partner, which here is the time readout beside it. */
.timeline-strip span.is-current {
  outline: none;
  position: relative;
}
.timeline-strip span.is-current::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 7px;
  height: 7px;
  margin: -3.5px 0 0 -3.5px;
  border-radius: 50%;
  background: var(--sc-red);
  box-shadow: 0 0 0 1.5px var(--sc-surface);
}

/* Header at narrower widths: drop the decorative parts first, keep navigation last. */
@media (max-width: 1400px) {
  .brand-product, .brand-sep { display: none; }
}
@media (max-width: 1180px) {
  .port-name { display: none; }
  .port-select { max-width: 150px; }
  .topbar { gap: 12px; }
  .mainnav a { padding: 5px 8px; }
}
@media (max-width: 900px) {
  .topbar-right .user { display: none; }
}

.layer-toggle .lt-note { font-weight: 400; color: var(--sc-text-muted); font-size: var(--sc-text-xs); }
.legend-dir { display: flex; align-items: center; gap: 6px; margin-top: 6px; font-size: var(--sc-text-xs); }
.legend-dir[hidden] { display: none; }
.legend-arrow { display: inline-block; font-weight: 700; font-size: 14px; line-height: 1; }

.swipe { margin-top: 10px; }
.swipe[hidden] { display: none; }
.swipe input[type=range] { width: 100%; accent-color: var(--sc-accent-solid); }
.swipe-scale { display: flex; justify-content: space-between; font-size: var(--sc-text-xs); color: var(--sc-text-muted); }

.btn-chip {
  flex: none; height: 30px; padding: 0 12px; border-radius: var(--sc-radius-pill);
  border: 1px solid var(--sc-border-strong); background: var(--sc-surface); color: var(--sc-text);
  font-size: var(--sc-text-xs); font-weight: 600; cursor: pointer;
}
.btn-chip:hover { background: var(--sc-surface-sunken); }
.btn-chip.is-on { background: var(--sc-accent-solid); border-color: var(--sc-accent-solid); color: var(--sc-on-accent-solid); }
.btn-chip[hidden] { display: none; }

.map-label {
  font-size: 11px; font-weight: 600; line-height: 1.2; white-space: nowrap; color: #FFFFFF;
  pointer-events: none; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
}
.asset-label { pointer-events: auto; cursor: pointer; text-shadow: none; }
.asset-label .al-text {
  position: relative; display: inline-block; padding: 2px 8px;
  border-radius: var(--sc-radius-pill); background: var(--map-label-bg);
  border: 1.5px solid rgba(255, 255, 255, 0.4);
}
.asset-label.s-green .al-text { border-color: var(--map-status-green); }
.asset-label.s-amber .al-text { border-color: var(--map-status-amber); }
.asset-label.s-red .al-text { border-color: var(--map-status-red); }
.asset-label.is-pulsing .al-text::after {
  content: ""; position: absolute; inset: -5px; border-radius: var(--sc-radius-pill);
  border: 2px solid var(--map-status-red); animation: dt-pulse 1.6s ease-out infinite;
}
@keyframes dt-pulse {
  from { transform: scale(0.9); opacity: 0.95; }
  to { transform: scale(1.45); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .asset-label.is-pulsing .al-text::after { animation: none; opacity: 0.9; }
}
.contour-label { font-size: 10px; padding: 0 4px; border-radius: 3px; background: rgba(11, 34, 56, 0.6); text-shadow: none; }
.vessel-label { display: flex; align-items: center; gap: 5px; }
.vessel-label .vl-phase {
  font-size: 10px; font-weight: 600; padding: 0 6px; border-radius: var(--sc-radius-pill);
  background: rgba(11, 34, 56, 0.7); text-transform: capitalize; text-shadow: none;
}

.popup-list li { display: block; }
.popup-list .pl-row { display: flex; gap: 6px; }
.spark { display: block; width: 100%; height: 46px; margin: 2px 0 6px; overflow: visible; }
.spark-line { fill: none; stroke: var(--sc-accent); stroke-width: 1.6; vector-effect: non-scaling-stroke; }
.spark-amber, .spark-red { stroke-width: 1.2; stroke-dasharray: 4 3; vector-effect: non-scaling-stroke; }
.spark-amber { stroke: var(--map-status-amber); }
.spark-red { stroke: var(--map-status-red); }
.spark-cursor { stroke: var(--sc-text-muted); stroke-width: 1; vector-effect: non-scaling-stroke; }
.spark-dot { fill: var(--sc-accent); }

.kiosk-hud {
  position: absolute; top: 16px; left: 16px; right: 16px; z-index: 6;
  display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 2fr) auto;
  gap: 12px; align-items: stretch; pointer-events: none;
}
.kiosk-hud[hidden] { display: none; }
.kiosk-tile {
  background: rgba(10, 24, 42, 0.84); color: #FFFFFF; border-radius: 14px; padding: 12px 16px;
  border: 1px solid rgba(255, 255, 255, 0.12);
}
.kiosk-label { font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; color: rgba(255, 255, 255, 0.72); font-weight: 600; }
.kiosk-big { display: flex; align-items: center; gap: 10px; font-size: 28px; font-weight: 700; margin-top: 4px; }
.kiosk-big .dot { width: 18px; height: 18px; }
.kiosk-value { font-size: 18px; font-weight: 600; margin-top: 4px; }
.kiosk-alert-value { font-variant-numeric: tabular-nums; color: rgba(255, 255, 255, 0.8); }
.kiosk-exit { pointer-events: auto; align-self: start; }
body.kiosk .topbar, body.kiosk .wave-divider, body.kiosk .footer,
body.kiosk .sidepanel, body.kiosk .map-layers { display: none !important; }
body.kiosk .ops-grid { grid-template-columns: minmax(0, 1fr) !important; }
body.kiosk .map-legend { top: 172px; }

.split { margin: 18px 0 22px; }
.split[hidden] { display: none; }
.split-toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.split-toolbar .select { width: auto; min-width: 220px; }
.split-note { font-size: var(--sc-text-sm); }
.split-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.split-pane { border: 1px solid var(--sc-border); border-radius: var(--sc-radius-md); overflow: hidden; background: var(--sc-surface-sunken); }
.split-head { display: flex; align-items: baseline; gap: 10px; padding: 8px 12px; border-bottom: 1px solid var(--sc-border); font-size: var(--sc-text-sm); }
.split-map { height: 420px; position: relative; }
.split-legend { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 10px; font-size: var(--sc-text-sm); }
.split-legend-title { font-weight: 600; }
.split-legend-key { display: inline-flex; flex-direction: column; gap: 2px; width: 200px; }
.split-legend-ramp { height: 10px; border-radius: var(--sc-radius-pill); border: 1px solid var(--sc-border-strong); }
.split-legend-scale { display: flex; justify-content: space-between; font-size: var(--sc-text-xs); color: var(--sc-text-muted); }
.split-legend-attr { font-size: var(--sc-text-xs); }
@media (max-width: 900px) {
  .split-grid { grid-template-columns: 1fr; }
  .split-map { height: 320px; }
}

:root {
  --wq-excellent: rgb(91, 64, 228);
  --wq-very-good: rgb(89, 175, 104);
  --wq-good: rgb(196, 190, 81);
  --wq-poor: rgb(216, 126, 69);
}
.map-legend [hidden] { display: none; }
.layer-toggle-product { flex-wrap: wrap; row-gap: 3px; }
.layer-toggle .lt-product-dates { flex: 1 0 100%; display: flex; align-items: center; gap: 8px; padding-left: 21px; min-width: 0; }
.layer-toggle .lt-dates { flex: 1 1 auto; min-width: 0; font-weight: 400; color: var(--sc-text-muted); font-size: var(--sc-text-xs); line-height: 1.3; }
.layer-toggle .product-date {
  flex: none; max-width: 112px; padding: 1px 4px; border-radius: var(--radius-sm);
  border: 1px solid var(--sc-border-strong); background: var(--sc-surface); color: var(--sc-text);
  font: inherit; font-size: var(--sc-text-xs);
}
.legend-product + .legend-product { margin-top: 10px; }
#legend-title:not([hidden]) ~ .legend-products .legend-product:first-child {
  margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--sc-border);
}
.legend-product-date { font-size: var(--sc-text-xs); color: var(--sc-text-muted); margin: -4px 0 6px; }
.legend-classes { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 3px; }
.legend-classes li { display: flex; align-items: center; gap: 6px; font-size: var(--sc-text-xs); }
.legend-swatch { width: 12px; height: 12px; border-radius: 3px; flex: none; box-shadow: inset 0 0 0 1px var(--sc-border-strong); }
.legend-swatch.wq-excellent { background: var(--wq-excellent); }
.legend-swatch.wq-very-good { background: var(--wq-very-good); }
.legend-swatch.wq-good { background: var(--wq-good); }
.legend-swatch.wq-poor { background: var(--wq-poor); }
.legend-class-label { flex: 1; }
.legend-class-pct { font-variant-numeric: tabular-nums; color: var(--sc-text-muted); }
.split-legend-classes { list-style: none; margin: 0; padding: 0; display: inline-flex; gap: 10px; flex-wrap: wrap; }
.split-legend-classes li { display: inline-flex; align-items: center; gap: 5px; font-size: var(--sc-text-xs); }
