/* Portolan mirror demos — shared design system.
   Follows the Portolan design rules (portolan-sdi.org/DESIGN.md, portolan-ops/brand):
   cream paper, one blue accent, Hanken Grotesk for prose and JetBrains Mono for numbers,
   labels and code, square corners, 1px ink rules instead of shadows, light mode only.
   Co-branded: CARTO is named as the publisher of the mirrors in header and footer. */

/* ---------------------------------------------------------------- fonts */
@font-face { font-family: "Hanken Grotesk"; font-weight: 400; font-display: swap; src: url("./brand/fonts/hanken-grotesk-400.woff2") format("woff2"); }
@font-face { font-family: "Hanken Grotesk"; font-weight: 500; font-display: swap; src: url("./brand/fonts/hanken-grotesk-500.woff2") format("woff2"); }
@font-face { font-family: "Hanken Grotesk"; font-weight: 600; font-display: swap; src: url("./brand/fonts/hanken-grotesk-600.woff2") format("woff2"); }
@font-face { font-family: "Hanken Grotesk"; font-weight: 700; font-display: swap; src: url("./brand/fonts/hanken-grotesk-700.woff2") format("woff2"); }
@font-face { font-family: "Hanken Grotesk"; font-weight: 800; font-display: swap; src: url("./brand/fonts/hanken-grotesk-800.woff2") format("woff2"); }
@font-face { font-family: "JetBrains Mono"; font-weight: 400; font-display: swap; src: url("./brand/fonts/jetbrains-mono-400.woff2") format("woff2"); }
@font-face { font-family: "JetBrains Mono"; font-weight: 500; font-display: swap; src: url("./brand/fonts/jetbrains-mono-500.woff2") format("woff2"); }
@font-face { font-family: "JetBrains Mono"; font-weight: 600; font-display: swap; src: url("./brand/fonts/jetbrains-mono-600.woff2") format("woff2"); }

/* --------------------------------------------------------------- tokens */
:root {
  --p-primary: #4163cc; --p-primary-ink: #2d4aa8; --p-on-primary: #fff;
  --p-bg: #fcfcfa; --p-bg-soft: #f5f5f1; --p-paper: #fff;
  --p-ink: #16170f; --p-ink-2: #3d3f33; --p-ink-3: #74766a;
  --p-line: #16170f; --p-line-soft: #d6d5ca;
  --p-success: #2f7d63; --p-warn: #b06e2a; --p-warn-ink: #8a5418; --p-danger: #a3271f;
  --p-sans: "Hanken Grotesk", ui-sans-serif, system-ui, sans-serif;
  --p-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --p-pad-x: clamp(20px, 5vw, 64px);
  --p-pad-y: clamp(40px, 6vw, 80px);
  --p-measure: 62ch;
  --p-max: 1400px;
  /* Quantitative palette for maps and charts: one hue, five steps, plus the accent. */
  --q1: #dbe3f7; --q2: #b3c3ea; --q3: #86a0dd; --q4: #5a7dd0; --q5: #2d4aa8;
  /* Back-compat aliases used by earlier pages. */
  --ink: var(--p-ink); --ink-2: var(--p-ink-2); --line: var(--p-line-soft); --paper: var(--p-paper); --accent: var(--p-primary); --wash: var(--p-bg-soft);
}

/* ----------------------------------------------------------------- base */
*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
html { background: var(--p-bg); color: var(--p-ink); font: 400 15px/1.6 var(--p-sans); -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }
body { margin: 0; min-height: 100vh; display: flex; flex-direction: column; }
a { color: var(--p-primary); text-decoration: none; }
a:hover { color: var(--p-primary-ink); text-decoration: underline; text-underline-offset: 2px; }
h1, h2, h3, h4 { margin: 0; font-weight: 700; letter-spacing: -0.015em; line-height: 1.2; text-wrap: balance; }
h1 { font-size: clamp(30px, 4vw + 8px, 46px); font-weight: 800; letter-spacing: -0.03em; line-height: 1.05; }
h2 { font-size: clamp(22px, 2vw + 15px, 26px); letter-spacing: -0.02em; }
h3 { font-size: 20px; }
p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }
code, pre, kbd, .mono, .num, .kicker, .eyebrow, .badge, .kpi b, .kpi dd, .stats dd, table td.num, .timing { font-family: var(--p-mono); }
code { font-size: 0.92em; background: var(--p-bg-soft); padding: 0 4px; }
pre { margin: 0; font-size: 12px; line-height: 1.55; overflow: auto; background: var(--p-bg-soft); padding: 12px 14px; border-inline-start: 2px solid var(--p-line); }
pre code { background: none; padding: 0; }
hr { border: 0; border-top: 1px solid var(--p-line); margin: 0; }
img, svg, canvas, video { max-width: 100%; }
button, input, select { font: inherit; color: inherit; }
:focus-visible { outline: 2px solid var(--p-primary); outline-offset: 2px; }
::selection { background: var(--p-primary); color: var(--p-on-primary); }

/* Machine register: kickers, labels, statuses. */
.kicker, .eyebrow { font: 400 11px/1.4 var(--p-mono); letter-spacing: 0.04em; text-transform: uppercase; color: var(--p-ink-3); }
.kicker b, .eyebrow b { font-weight: 600; color: var(--p-ink); }
.lede, .lead { font-size: clamp(16px, 0.4vw + 14.5px, 18px); line-height: 1.6; color: var(--p-ink-2); max-width: var(--p-measure); }
.small, .meta, .attrib, .caption { font-size: 13px; line-height: 1.5; color: var(--p-ink-2); }
.attrib { color: var(--p-ink-3); margin-top: 10px; }
.timing { font-size: 12px; color: var(--p-ink-2); }
.timing b, .timing strong { color: var(--p-ink); font-weight: 600; }
.status, #status { font: 400 12px/1.4 var(--p-mono); color: var(--p-ink-3); letter-spacing: 0.02em; }
.status b { color: var(--p-ink); font-weight: 600; }

/* ---------------------------------------------------------------- shell */
section[id] { scroll-margin-top: 72px; } /* anchor targets clear the sticky top bar */
.shell-top { position: sticky; top: 0; z-index: 30; background: var(--p-bg); border-bottom: 1px solid var(--p-line); }
.shell-top .row { max-width: var(--p-max); margin: 0 auto; padding: 0 var(--p-pad-x); height: 56px; display: flex; align-items: center; gap: 24px; }
.shell-brand { display: flex; align-items: center; gap: 10px; color: var(--p-ink); text-decoration: none; }
.shell-brand:hover { text-decoration: none; color: var(--p-ink); }
.shell-brand svg { height: 22px; width: auto; display: block; color: var(--p-primary); }
.shell-brand .word { font-weight: 700; font-size: 17px; letter-spacing: -0.02em; white-space: nowrap; }
.shell-brand .word span { font-weight: 400; color: var(--p-ink-3); }
.shell-status { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font: 400 11px/1.3 var(--p-mono); letter-spacing: 0.02em; color: var(--p-ink-3); transition: opacity 0.6s; }
.shell-status:empty { display: none; }
.shell-status::before { content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--p-primary); margin-inline-end: 8px; vertical-align: 1px; animation: shell-pulse 1.2s ease-in-out infinite; }
.shell-status.done { opacity: 0; }
@keyframes shell-pulse { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
.shell-nav { display: flex; gap: 20px; margin-inline-start: auto; }
.shell-nav a { font: 500 12px/1 var(--p-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--p-ink-2); padding: 6px 0; border-bottom: 2px solid transparent; }
.shell-nav a:hover, .shell-nav a[aria-current] { color: var(--p-ink); text-decoration: none; border-bottom-color: var(--p-primary); }
.shell-pub { display: flex; align-items: center; gap: 10px; color: var(--p-ink-3); font: 400 11px/1 var(--p-mono); letter-spacing: 0.04em; text-transform: uppercase; }
.shell-pub svg, .shell-pub img { height: 18px; width: auto; display: block; }
/* "Index": the small-screen menu control (a word, never a hamburger — Portolan rule). */
.shell-index { display: none; margin-inline-start: auto; border: 1px solid var(--p-line); background: var(--p-paper); padding: 6px 10px; font: 500 11px/1 var(--p-mono); letter-spacing: 0.08em; text-transform: uppercase; cursor: pointer; }
.shell-menu { border-top: 1px solid var(--p-line); background: var(--p-bg); padding: 8px var(--p-pad-x) 12px; display: grid; gap: 2px; }
.shell-menu a { display: block; padding: 8px 0; border-bottom: 1px solid var(--p-line-soft); color: var(--p-ink); font-size: 14px; }
.shell-menu a[aria-current] { color: var(--p-primary-ink); font-weight: 600; }
.shell-menu a:last-child { border-bottom: 0; }
@media (max-width: 860px) { .shell-index { display: inline-block; } .shell-pub { margin-inline-start: 0; } }
@media (min-width: 861px) { .shell-menu { display: none !important; } }
/* Progress rule while DuckDB boots and the first queries run. */
.shell-progress { position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: linear-gradient(90deg, var(--p-primary) 0 40%, transparent 40% 100%); background-size: 250% 100%; animation: shell-progress 1.6s linear infinite; }
.shell-progress.done { animation: none; background: var(--p-primary); opacity: 0; transition: opacity 0.5s; }
@keyframes shell-progress { from { background-position: 100% 0; } to { background-position: -150% 0; } }
.shell-foot { border-top: 1px solid var(--p-line); margin-top: auto; }
.shell-pager { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; padding-top: 22px; padding-bottom: 22px; border-bottom: 1px solid var(--p-line-soft); }
.shell-pager a { display: block; color: var(--p-ink); }
.shell-pager a:hover { text-decoration: none; color: var(--p-primary-ink); }
.shell-pager a b { display: block; font-size: 16px; line-height: 1.3; letter-spacing: -0.01em; margin-top: 4px; }
.shell-pager .next { text-align: end; }
@media (max-width: 600px) { .shell-pager { grid-template-columns: 1fr; } .shell-pager .next { text-align: start; } }
.shell-foot .row { max-width: var(--p-max); margin: 0 auto; padding: 28px var(--p-pad-x) 36px; display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: 32px; font-size: 13px; color: var(--p-ink-2); line-height: 1.55; }
.shell-foot .brands { display: flex; align-items: center; gap: 18px; justify-content: flex-end; }
.shell-foot .brands svg, .shell-foot .brands img { height: 20px; width: auto; color: var(--p-ink); }
@media (max-width: 860px) { .shell-nav { display: none; } .shell-pub span { display: none; } .shell-pub { margin-inline-start: auto; } .shell-foot .row { grid-template-columns: 1fr; } .shell-foot .brands { justify-content: flex-start; } }

/* --------------------------------------------------------------- layout */
.wrap { max-width: var(--p-max); margin: 0 auto; padding-inline: var(--p-pad-x); }
main.page { flex: 1; }

/* Hero: kicker, h1, lead, then a ruled KPI strip. */
.hero, header.top { max-width: var(--p-max); margin: 0 auto; padding: clamp(36px, 5vw, 64px) var(--p-pad-x) 0; }
.hero .kicker { margin-bottom: 14px; }
.hero h1, header.top h1 { max-width: 24ch; }
.hero .lede, header.top .lede { margin-top: 18px; }
.hero .lede + .lede { margin-top: 12px; }
.kpis, .stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 0; margin: 32px 0 0; padding: 0; border-top: 1px solid var(--p-line); border-bottom: 1px solid var(--p-line); }
.kpis > *, .stats > * { padding: 14px 16px 16px 0; border-inline-end: 1px solid var(--p-line-soft); border-bottom: 1px solid var(--p-line-soft); margin: 0; margin-bottom: -1px; }
.kpis > * + *, .stats > * + * { padding-inline-start: 16px; }
.kpis > *:last-child, .stats > *:last-child { border-inline-end: 0; }
.kpi .lbl, .kpi dt, .stats dt, .kpi .label { font: 400 11px/1.4 var(--p-mono); letter-spacing: 0.04em; text-transform: uppercase; color: var(--p-ink-3); }
.kpi b, .kpi dd, .stats dd, .kpi .n { display: block; margin: 4px 0 0; font: 500 clamp(22px, 1.6vw + 12px, 30px)/1.1 var(--p-mono); letter-spacing: -0.02em; color: var(--p-ink); font-variant-numeric: tabular-nums; }
.kpi .sub, .kpi small { display: block; margin-top: 4px; font-size: 12px; color: var(--p-ink-2); font-family: var(--p-sans); }
@media (max-width: 720px) {
  .kpis, .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kpis > *, .stats > * { padding: 12px 12px 12px 0; border-inline-end: 0; border-bottom: 1px solid var(--p-line-soft); }
  .kpis > * + *, .stats > * + * { padding-inline-start: 0; }
  .kpis > *:nth-child(odd), .stats > *:nth-child(odd) { border-inline-end: 1px solid var(--p-line-soft); }
  .kpis > *:nth-child(even), .stats > *:nth-child(even) { padding-inline-start: 12px; }
  .kpis > *:nth-last-child(-n+2):nth-child(odd), .kpis > *:last-child, .stats > *:nth-last-child(-n+2):nth-child(odd), .stats > *:last-child { border-bottom: 0; }
}

/* Panels: one question each. Head with number + badges + h2; a two-column body
   (text 60ch | figure), or a single column when there is no figure. */
.panel, section.q { max-width: var(--p-max); margin: 0 auto; padding: var(--p-pad-y) var(--p-pad-x); border-top: 1px solid var(--p-line); }
.panel:first-of-type, section.q:first-of-type { border-top: 0; }
.panel-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px 16px; margin-bottom: 8px; }
.panel-head .kicker { flex-basis: 100%; }
.panel-head h2 { max-width: 30ch; }
.panel-grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 32px 48px; margin-top: 20px; align-items: start; }
.panel-grid.wide { grid-template-columns: 1fr; }
.panel-grid > * { min-width: 0; }
.panel-text, .reading { max-width: var(--p-measure); min-width: 0; }
.panel-text .kpi dd, .panel-text .kpi b { font-size: clamp(18px, 0.8vw + 10px, 22px); }
.panel-text > p:first-child, .reading > p:first-child { margin-top: 0; }
.panel-figure { min-width: 0; position: sticky; top: 72px; }
.figure-note, .caption { margin-top: 8px; }
@media (max-width: 960px) { .panel-grid { grid-template-columns: 1fr; } .panel-figure { position: static; } }

/* Badges: live / precomputed / not comparable. */
.badge { display: inline-block; font: 500 11px/1 var(--p-mono); letter-spacing: 0.04em; text-transform: uppercase; padding: 5px 8px; border: 1px solid currentColor; color: var(--p-ink-2); vertical-align: middle; }
.badge.live, .live { color: var(--p-success); }
.badge.precomputed, .badge.pre, .precomputed { color: var(--p-warn-ink); }
.badge.na, .badge.unanswerable, .badge.danger { color: var(--p-danger); }
.badge.ok { color: var(--p-success); }

/* SQL blocks: a collapsible mono block with a ruled summary. */
details.sql, details.code { margin: 14px 0; border: 1px solid var(--p-line-soft); background: var(--p-paper); }
details.sql > summary, details.code > summary { cursor: pointer; padding: 9px 12px; font: 500 12px/1.4 var(--p-mono); letter-spacing: 0.02em; color: var(--p-ink-2); list-style: none; display: flex; gap: 8px; align-items: center; }
details.sql > summary::before, details.code > summary::before { content: "▸"; color: var(--p-primary); }
details[open].sql > summary::before, details[open].code > summary::before { content: "▾"; }
details.sql > summary:hover, details.code > summary:hover { color: var(--p-ink); background: var(--p-bg-soft); }
details.sql pre, details.code pre { border: 0; border-top: 1px solid var(--p-line-soft); max-height: 420px; }

/* Figures: maps, charts and tables sit in a ruled frame. */
.figure, .map-frame, .mapwrap { position: relative; border: 1px solid var(--p-line); background: var(--p-paper); min-width: 0; }
.map-frame, .mapwrap { aspect-ratio: 16 / 10; }
/* The map canvas: any direct child div that is not chrome (legend, chips, controls, caption) fills the frame. */
.map-frame > div:not(.legend):not(.chips):not(.controls):not(.caption):not(.figure-note), .mapwrap > div[id]:not(.legend) { position: absolute; inset: 0; }
@media (max-width: 600px) { .map-frame, .mapwrap { aspect-ratio: 1 / 1; } }
/* Stacked children of a figure column (map, KPIs, table) breathe; KPI strips inside a figure are smaller than the hero's. */
.panel-figure > * + * { margin-top: 12px; }
.panel-figure .kpis, .panel-figure .stats { margin: 0; }
.panel-figure .kpi dd, .panel-figure .kpi b { font-size: clamp(20px, 1vw + 10px, 24px); }
.hero .status, .hero #status { margin: 14px 0 0; }
.controls { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 10px; }
.controls select, .controls input { width: auto; padding: 6px 10px; font: 500 12px/1.3 var(--p-mono); }
td.pre, td.precomputed { color: var(--p-warn-ink); }
td.live { color: var(--p-success); }
.dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; vertical-align: -1px; margin-inline-end: 6px; background: var(--p-primary); }
/* Loading placeholders. A map div is empty until MapLibre mounts and `.map-loading` (set by createMap) until its
   style and first tiles are in; both show a quiet centred label over faint paper. Empty KPI strips and tables get a
   shimmer band only while `body.is-loading` (the shell clears it when #status says ready). */
.map-frame > div:not(.legend):not(.chips):not(.controls):not(.caption):not(.figure-note):empty, .mapwrap > div[id]:not(.legend):empty { position: absolute; inset: 0; }
.map-frame > div:not(.legend):not(.chips):not(.controls):not(.caption):not(.figure-note):empty::after, .mapwrap > div[id]:not(.legend):empty::after, .map-loading::after {
  content: "loading map…"; position: absolute; inset: 0; z-index: 3; display: grid; place-items: center; pointer-events: none;
  font: 400 11px/1 var(--p-mono); letter-spacing: 0.06em; text-transform: uppercase; color: var(--p-ink-3);
  background: rgba(252, 252, 250, 0.55); animation: shell-pulse 1.6s ease-in-out infinite; }
.is-loading .kpis:empty, .is-loading .stats:empty, .is-loading .table-wrap:empty, .is-loading .table-wrap > table:empty { display: block; min-height: 44px; border-radius: 2px;
  background: linear-gradient(90deg, var(--p-bg-soft) 0 30%, var(--p-paper) 50%, var(--p-bg-soft) 70% 100%); background-size: 300% 100%; animation: shimmer 1.8s linear infinite; }
@keyframes shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }
.legend { position: absolute; left: 12px; bottom: 44px; max-width: min(440px, calc(100% - 24px)); background: rgba(252, 252, 250, 0.96); border: 1px solid var(--p-line); padding: 8px 12px; font-size: 12px; line-height: 1.45; color: var(--p-ink-2); }
.legend b { color: var(--p-ink); }
.legend:empty, .legend.is-hidden { display: none; }
/* The legend's show/hide button (site/lib/portolan.js positions it): a bordered − in the legend's top-right corner while
   shown; a bordered □ at the legend's bottom-left anchor while hidden. */
.legend.has-toggle { padding-inline-end: 30px; }
.legend-toggle { position: absolute; left: 12px; bottom: 44px; z-index: 2; margin: 0; padding: 0; width: 20px; height: 20px; font: 500 13px/18px var(--p-mono); text-align: center; color: var(--p-ink-2); background: rgba(252, 252, 250, 0.96); border: 1px solid var(--p-line); cursor: pointer; }
.legend-toggle:hover { color: var(--p-ink); background: var(--p-bg-soft); border-color: var(--p-ink-3); }
.legend-toggle[hidden] { display: none; }
.swatch { display: inline-block; width: 12px; height: 12px; border: 1px solid var(--p-line); vertical-align: -2px; margin-inline-end: 6px; }
.chart { width: 100%; display: block; }
.chart text { font-family: var(--p-mono); font-size: 11px; fill: var(--p-ink-2); }
.chart-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 8px; font: 400 11px/1.4 var(--p-mono); color: var(--p-ink-2); }
.table-wrap:empty { display: none; }

/* Tables: mono numbers, right-aligned, sticky head, scroll inside the frame. */
.table-wrap, .result table, .data { max-width: 100%; overflow: auto; max-height: 520px; border: 1px solid var(--p-line-soft); }
table { width: 100%; border-collapse: collapse; font-size: 13px; line-height: 1.4; background: var(--p-paper); }
thead th, table > tr:first-child > th, table > tbody:first-child > tr:first-child > th { position: sticky; top: 0; background: var(--p-bg-soft); text-align: start; font: 500 11px/1.4 var(--p-mono); letter-spacing: 0.04em; text-transform: uppercase; color: var(--p-ink-2); padding: 8px 10px; border-bottom: 1px solid var(--p-line); white-space: nowrap; }
tbody td, tbody th { padding: 7px 10px; border-bottom: 1px solid var(--p-line-soft); vertical-align: top; }
tbody th { text-align: start; font-weight: 600; }
tr.total td { font-weight: 600; border-top: 1px solid var(--p-line); }
blockquote { margin: 0 0 1em; padding: 4px 0 4px 14px; border-inline-start: 2px solid var(--p-primary); color: var(--p-ink); font-size: 16px; line-height: 1.5; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover td { background: var(--p-bg-soft); }
td.num, th.num, .num { text-align: end; font-variant-numeric: tabular-nums; white-space: nowrap; }
tfoot td { font-weight: 600; border-top: 1px solid var(--p-line); padding: 8px 10px; }
tfoot td.num { font-family: var(--p-mono); }
tr.group th { background: var(--p-bg-soft); font: 500 11px/1.4 var(--p-mono); letter-spacing: 0.04em; text-transform: uppercase; color: var(--p-ink-2); padding: 8px 10px; border-top: 1px solid var(--p-line); }
td.thumb { width: 64px; min-width: 64px; padding: 4px 8px; }
td.thumb img { width: 56px; height: 38px; max-width: none; object-fit: cover; border: 1px solid var(--p-line-soft); display: block; }
.chips.scroll { max-height: 160px; overflow: auto; }
.who { font: 500 10.5px/1.3 var(--p-mono); letter-spacing: 0.04em; text-transform: uppercase; color: var(--p-ink-2); border: 1px solid var(--p-line-soft); padding: 2px 6px; white-space: nowrap; }

/* Controls: chips, buttons, inputs — square, ruled, mono labels. */
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chips button, .btn, button.chip { border: 1px solid var(--p-line-soft); background: var(--p-paper); padding: 5px 10px; font: 500 11px/1.3 var(--p-mono); letter-spacing: 0.04em; text-transform: uppercase; color: var(--p-ink-2); cursor: pointer; }
.chips button:hover, .btn:hover, button.chip:hover { border-color: var(--p-ink); color: var(--p-ink); }
.chips button.on, .btn.on, button.chip.on, .btn.primary { background: var(--p-primary); border-color: var(--p-primary); color: var(--p-on-primary); }
.chips.small button { font-size: 10px; padding: 3px 7px; letter-spacing: 0.02em; text-transform: none; }
input[type="search"], input[type="text"], select { width: 100%; padding: 10px 12px; border: 1px solid var(--p-line); background: var(--p-paper); font-size: 14px; }
input[type="search"]:focus { outline: 2px solid var(--p-primary); outline-offset: -1px; }

/* Cards: ruled, square, no shadow. */
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 0; border-top: 1px solid var(--p-line); border-inline-start: 1px solid var(--p-line); }
.card { display: flex; flex-direction: column; gap: 8px; padding: 20px 20px 22px; color: inherit; text-decoration: none; border-inline-end: 1px solid var(--p-line); border-bottom: 1px solid var(--p-line); background: var(--p-paper); }
.card:hover { text-decoration: none; background: var(--p-bg-soft); color: inherit; }
.card.wip { opacity: 0.55; pointer-events: none; }
.card .kicker { color: var(--p-primary-ink); }
.card h3 { font-size: 19px; line-height: 1.25; }
.card p { font-size: 13.5px; line-height: 1.5; color: var(--p-ink-2); flex: 1; }
.card .cats { display: flex; flex-wrap: wrap; gap: 4px; }
.card .cats span { font: 400 10.5px/1.3 var(--p-mono); padding: 2px 6px; background: var(--p-bg-soft); color: var(--p-ink-2); }

/* Section band (the one permitted colour field): white text on Portolan blue. */
.band { background: var(--p-primary); color: var(--p-on-primary); }
.band a { color: var(--p-on-primary); text-decoration: underline; }
.band .kicker { color: rgba(255, 255, 255, 0.8); }

/* --------------------------------------------------------- the explorer */
.explorer { max-width: var(--p-max); margin: 0 auto; padding: 0 var(--p-pad-x) var(--p-pad-y); display: grid; grid-template-columns: 440px minmax(0, 1fr); gap: 0; border-top: 1px solid var(--p-line); }
.explorer .panel-side { display: flex; flex-direction: column; border-inline-end: 1px solid var(--p-line); min-height: 0; max-height: 82vh; }
.explorer .search { padding: 16px 16px 8px 0; }
.explorer .chips { padding: 6px 16px 6px 0; }
.explorer .status { padding: 8px 16px 8px 0; }
.results { list-style: none; margin: 0; padding: 0 16px 16px 0; overflow: auto; flex: 1; border-top: 1px solid var(--p-line-soft); }
.results li { display: grid; grid-template-columns: 88px minmax(0, 1fr); gap: 12px; padding: 10px 8px 10px 0; cursor: pointer; border-bottom: 1px solid var(--p-line-soft); }
.results li:hover { background: var(--p-bg-soft); }
.results li.on { background: var(--p-bg-soft); box-shadow: inset 3px 0 0 var(--p-primary); padding-inline-start: 8px; }
.results img, .results .nothumb { width: 88px; height: 58px; object-fit: cover; border: 1px solid var(--p-line-soft); background: var(--p-bg-soft); }
.results .title { font-weight: 600; font-size: 13.5px; line-height: 1.3; }
.results .meta { font-size: 11.5px; margin-top: 3px; }
.results .cat { font-weight: 600; color: var(--p-ink); }
.results .actions { font: 400 11px/1.4 var(--p-mono); margin-top: 3px; }
.explorer .mapwrap { aspect-ratio: auto; min-height: 560px; border: 0; border-bottom: 1px solid var(--p-line); }
@media (max-width: 960px) { .explorer { grid-template-columns: 1fr; } .explorer .panel-side { max-height: none; border-inline-end: 0; border-bottom: 1px solid var(--p-line); } .explorer .mapwrap { min-height: 60vh; } }

/* Demos strip on the explorer page. */
.demos { max-width: var(--p-max); margin: 0 auto; padding: var(--p-pad-y) var(--p-pad-x); }
.demos h2 { margin-bottom: 18px; }
.demos .kicker { margin-bottom: 10px; }

/* MapLibre chrome on the Portolan palette. */
.maplibregl-ctrl-group { border-radius: 0 !important; box-shadow: none !important; border: 1px solid var(--p-line) !important; }
.maplibregl-ctrl-group button + button { border-top: 1px solid var(--p-line-soft) !important; }
.maplibregl-ctrl-attrib { font-family: var(--p-sans) !important; font-size: 11px !important; }
.maplibregl-popup-content { border-radius: 0 !important; box-shadow: none !important; border: 1px solid var(--p-line); font: 13px/1.45 var(--p-sans); }
.maplibregl-ctrl-scale { border-radius: 0 !important; font-family: var(--p-mono) !important; font-size: 10px !important; }
