/* The page around the map. Sober on purpose: the map is the content, and a chart reads better without
   decoration competing with it.

   /!\ Every colour is a token, defined once for light and once for dark. The family colours are NOT here:
   they are in `js/map2d.js`, because the map draws with them and a legend that disagrees with the map is
   worse than no legend. */

:root {
  --ink: #16181d;
  --ink-muted: #5b6472;
  --surface: #ffffff;
  --surface-muted: #f4f5f8;
  --line: #d8dce4;
  --accent: #1d4ed8;
  --warn-ink: #7c2d12;
  --warn-surface: #fef3c7;
  --shadow: 0 2px 12px rgb(16 24 40 / 12%);
  --radius: 8px;
  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ink: #e7e9ee;
    --ink-muted: #9aa4b2;
    --surface: #14161b;
    --surface-muted: #1c1f26;
    --line: #2c313b;
    --accent: #7ba2ff;
    --warn-ink: #fde68a;
    --warn-surface: #3f2d12;
    --shadow: 0 2px 12px rgb(0 0 0 / 50%);
  }
}

* { box-sizing: border-box; }

/* /! Any `display` we set beats the browser's own rule for `[hidden]`, which is the weakest there is:
   the file bar was `hidden` in the DOM, `display: flex` on screen, and took 46 px of the map with it.
   One line, and `hidden` means hidden everywhere on this page. */
[hidden] { display: none !important; }

body {
  margin: 0;
  /* /! A column, not a grid with its rows written out: that template said «the third child gets the
     space», and the day a fourth band appeared between the chips and the map, the space went to the
     band. Flex gives it to whoever asks, which is the map and only the map. */
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;   /* the mobile bar that appears and disappears: dvh follows it, vh does not */
  background: var(--surface);
  color: var(--ink);
  font: 15px/1.45 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

a { color: var(--accent); }
.muted { color: var(--ink-muted); font-size: 13px; margin: 0; }

/* --- header ------------------------------------------------------------------------------------------- */

/* /!\ Una barra sola per tutto quel che non è mappa: titolo, ricerca, lingua, attrezzi, chip. Ogni riga
   di intestazione è mappa in meno, e qui la mappa è il contenuto. */
.bar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 12px;
  align-items: center;
  padding: 8px 14px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}

.bar > h1 { flex: none; font-size: 16px; margin: 0; letter-spacing: -0.01em; white-space: nowrap; }

/* Gli attrezzi chiudono la riga; le chip stanno accanto alla lingua e si spezzano da sole su due righe
   quando non ci stanno. Sotto i 320 px di spazio rimasto vanno a capo tutte insieme, su una riga loro. */
.tools { display: flex; flex: none; gap: 8px; align-items: center; margin-inline-start: auto; order: 0; }


/* The source page keeps a brand with a subtitle under it, and pushes its own buttons to the far end. */
.brand { flex: 1 1 auto; }
.brand h1 { font-size: 17px; margin: 0; letter-spacing: -0.01em; }

.search { position: relative; flex: 1 1 260px; max-width: 380px; }

#search {
  width: 100%;
  padding: 7px 10px;
  font: inherit;
  color: var(--ink);
  background: var(--surface-muted);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
#search:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.results {
  position: absolute;
  z-index: 1400;             /* above the detail card, which is above the 3D stage */
  inset-inline: 0;
  margin: 4px 0 0;
  padding: 4px;
  max-height: 50vh;
  overflow-y: auto;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.results li.muted { padding: 6px 8px; }

.results button {
  display: flex;
  gap: 8px;
  align-items: center;
  width: 100%;
  padding: 6px 8px;
  font: inherit;
  text-align: left;
  color: inherit;
  background: none;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
}
.results button:hover,
.results button:focus-visible { background: var(--surface-muted); outline: none; }

.hit-name { flex: 1 1 auto; }
.hit-band { color: var(--ink-muted); font-size: 12px; font-variant-numeric: tabular-nums; white-space: nowrap; }

.ghost {
  padding: 6px 10px;
  font: inherit;
  font-size: 13px;
  color: var(--ink-muted);
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  cursor: pointer;
}
.ghost:hover { color: var(--ink); border-color: var(--ink-muted); }
/* Un ghost che e' anche un interruttore: acceso si vede che e' premuto, non solo che c'e'. */
.ghost.on { color: var(--ink); background: var(--surface-muted); border-color: var(--ink-muted); }

/* --- the family chips -------------------------------------------------------------------------------- */

/* /! Le chip vanno a capo tutte insieme e gli attrezzi restano in testa (`order`), perche' su una
   finestra normale non c'e' posto per tutti e due: lasciate libere si infilavano nel buco rimasto e la
   barra diventava alta tre righe di pulsanti. Su una finestra larga tornano accanto alla lingua, e
   quella regola sta in fondo al foglio: una @media non alza la specificita', e una riga scritta piu'
   in basso vince comunque. */
.chips { display: flex; flex: 1 1 100%; flex-wrap: wrap; align-content: center; gap: 6px; order: 1; }

.chip {
  display: inline-flex;
  gap: 6px;
  align-items: center;
  padding: 5px 10px;
  font: inherit;
  font-size: 13px;
  color: var(--ink);
  /* The chips used to be light on a grey band of their own; the band is gone, so they carry the grey. */
  background: var(--surface-muted);
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
}
.chip:hover { border-color: var(--chip); }
.chip.on { border-color: var(--chip); background: color-mix(in srgb, var(--chip) 14%, var(--surface)); }
.chip.busy { cursor: progress; }

.chip-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--chip);
  flex: none;
}

.chip-n { color: var(--ink-muted); font-size: 12px; font-variant-numeric: tabular-nums; }

.chip.on .chip-n { color: var(--ink); }

/* --- the visitor's own file ---------------------------------------------------------------------- */

.file-bar {
  display: flex;
  gap: 12px;
  align-items: center;
  margin: 0;
  padding: 6px 16px;
  font-size: 13px;
  color: var(--ink);
  background: color-mix(in srgb, var(--accent) 14%, var(--surface));
  border-bottom: 1px solid var(--line);
}
.file-bar #file-name { flex: 1 1 auto; }

/* The veil only exists while something is being dragged over the window. */
.drop-veil {
  position: fixed;
  z-index: 2000;
  inset: 0;
  display: none;
  place-items: center;
  font-size: 18px;
  color: var(--ink);
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  border: 3px dashed var(--accent);
}
body.dropping .drop-veil { display: grid; }

/* --- map and detail ---------------------------------------------------------------------------------- */

/* /!\ The map takes what is left (1fr), and the floor is in pixels: a min-height in vh ADDS to the
   header, the chips and the footer, so 55vh made the page scroll on every laptop. */
main { position: relative; flex: 1 1 auto; min-height: 300px; }
#map { position: absolute; inset: 0; background: var(--surface-muted); }

.loading {
  position: absolute;
  inset-block-start: 50%;
  inset-inline: 0;
  text-align: center;
  color: var(--ink-muted);
}

.detail {
  position: absolute;
  z-index: 1300;
  inset-block-start: 12px;
  inset-inline-end: 12px;
  width: min(330px, calc(100% - 24px));
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.detail-head { display: flex; gap: 8px; align-items: start; justify-content: space-between; }
.detail-head h2 { font-size: 15px; margin: 0 0 2px; }

.detail-family {
  margin: 0 0 10px;
  padding-inline-start: 10px;
  font-size: 13px;
  color: var(--ink-muted);
  border-inline-start: 3px solid var(--chip, var(--line));
}

.detail dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 2px 12px;
  margin: 0 0 10px;
  font-size: 13px;
}
.detail dt { color: var(--ink-muted); }
.detail dd { margin: 0; overflow-wrap: anywhere; }
.detail dd:last-of-type { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 11px; }

/* --- footer ------------------------------------------------------------------------------------------ */

.foot {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  align-items: baseline;
  padding: 8px 16px;
  border-top: 1px solid var(--line);
  background: var(--surface-muted);
}

.stale {
  margin: 0;
  padding: 2px 8px;
  font-size: 13px;
  color: var(--warn-ink);
  background: var(--warn-surface);
  border-radius: 6px;
}

#attribution { flex: 1 1 100%; }

/* --- the 2D/3D switch and the vertical view ------------------------------------------------------- */

/* Due interruttori con la stessa forma: la vista, e la lingua. */
.views,
.langs { display: flex; flex: none; border: 1px solid var(--line); border-radius: 999px; }

.view-tab,
.lang-tab {
  padding: 5px 12px;
  font: inherit;
  font-size: 13px;
  color: var(--ink-muted);
  background: none;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
}
.view-tab.on,
.lang-tab.on { color: var(--surface); background: var(--ink); }

.lang-tab { padding-inline: 10px; font-size: 12px; font-weight: 600; letter-spacing: 0.03em; }

.stage3d {
  /* La larghezza del profilo e la quota da cui parte: le leggono il pannello E la sua maniglia, e due
     numeri scritti due volte si scollano al primo ritocco. */
  --column-w: 244px;
  --column-top: 112px;

  position: absolute;
  /* /! Over 1000, which is where Leaflet's own controls live: at 420 the zoom buttons floated on top of
     the 3D scene and ate the first word of its toolbar. The detail card and the search results sit above
     this in turn -- the three layers are 1200 / 1300 / 1400, and they are only written here. */
  z-index: 1200;
  inset: 0;
  background: var(--surface-muted);
}

/* The canvas is inserted as the first child, so everything else in here stacks above it. */
.stage3d canvas { display: block; touch-action: none; cursor: grab; }
.stage3d canvas:active { cursor: grabbing; }

/* I comandi e la riga che li spiega: un riquadro solo. Due riquadri accostati, di larghezza diversa,
   sembravano due pannelli che non si conoscevano. */
.stage3d-panel {
  position: absolute;
  inset-block-start: 10px;
  inset-inline-start: 10px;
  max-width: min(540px, calc(100% - 20px));
  padding: 6px 10px;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.stage3d-bar {
  display: flex;
  gap: 10px;
  align-items: center;
  font-size: 13px;
}
.stage3d-bar input[type="range"] { width: 110px; accent-color: var(--accent); }

/* /! It sits ON the floor texture, which is a light map in both themes: without a background of its own
   it was grey text on a grey road. */
.note3d {
  position: absolute;
  inset-block-end: 8px;
  inset-inline: 10px 120px;   /* clear of Leaflet's attribution, which stays in the corner */
  margin: 0;
  padding: 4px 8px;
  font-size: 12px;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  border-radius: 6px;
}
.note3d #count3d { color: var(--ink); font-weight: 600; }
.note3d #exaggeration { color: var(--ink); }

/* I comandi: una riga sotto la barra, che non ha senso leggere due volte. Va a capo da sola: e' una
   lista, e si faceva tagliare dal bordo della finestra proprio sulla voce che dice come salire. */
.hint3d {
  margin: 4px 0 0;
  font-size: 12px;
  line-height: 1.45;
}

.stage3d-bar label { min-width: 7.5em; }

/* --- the compass ----------------------------------------------------------------------------------- */

.compass {
  position: absolute;
  z-index: 1250;                 /* over the 3D stage, under the detail card */
  /* Staccata dall'angolo: sotto c'è l'attribuzione di Leaflet, e una bussola appoggiata al bordo
     sembra uscire dallo schermo invece di stare sulla mappa. */
  inset-block-end: 48px;
  inset-inline-end: 22px;
  /* Cinquanta e non quarantaquattro: a quella misura, su una mappa, si legge come un bollino grigio e
     l'ago si perde. Il disegno dentro e' lo stesso, il viewBox non cambia. */
  width: 50px;
  height: 50px;
  padding: 0;
  background: none;
  border: 0;
  cursor: default;
  filter: drop-shadow(0 1px 4px rgb(0 0 0 / 35%));
}
.compass.turnable { cursor: pointer; }
.compass svg { display: block; width: 100%; height: 100%; }

/* /!\ Il quadrante è pieno, non traslucido: all'88% di un `--surface` scuro spariva nello sfondo della
   scena 3D e restava solo l'ago, una lancetta che galleggiava nell'angolo della finestra. */
.compass-face { fill: var(--surface); stroke: var(--ink-muted); stroke-width: 1.4; }
.compass-index { fill: var(--ink-muted); }
.compass-north { fill: #d94436; }
.compass-south { fill: var(--ink-muted); }

/* /!\ QUI NON VA UN `transform-origin`, e qui ce n'era uno.
   L'ago gira con l'attributo `transform="rotate(angolo 20 20)"`, che il centro ce l'ha gia' dentro. Ma
   in SVG2 quell'attributo E' la proprieta' CSS `transform`, e un `transform-origin` dichiarato qui si
   SOMMA al centro: la rosa finiva per girare attorno a (40,40), cioe' all'angolo del disegno, e a ogni
   grado di rotazione scappava fuori dal quadrante. Con il nord in alto -- in pianta, e in quota appena
   aperta -- l'angolo e' zero e non si vede niente: il difetto esce solo quando la scena e' girata, che
   e' esattamente quando la bussola serve. Un meccanismo solo: l'attributo. */

/* --- the column of air ------------------------------------------------------------------------------ */

.column {
  position: absolute;
  display: flex;
  flex-direction: column;
  inset-block: var(--column-top) 56px;   /* sotto il pannello dei comandi, sopra gli avvisi */
  inset-inline-start: 10px;
  /* Tre o quattro colonne di famiglia ci devono stare con un nome leggibile dentro -- e da li' in poi
     la larghezza e' di chi guarda: la maniglia la cambia. */
  width: var(--column-w);
  padding: 6px 8px;
  /* /!\ PIENO, non al 90%: sotto c'e' una mappa, e una mappa che traspare da dietro un grafico gli
     toglie i colori -- le bande diventavano tutte dello stesso grigio slavato. Un diagramma si legge
     sul suo fondo, non su quello che ha dietro. */
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.column:empty { display: none; }

/* /! `min-height: 0`: in una colonna flex un figlio non scende sotto il suo contenuto, e l'SVG
   spingerebbe fuori la didascalia invece di adattarsi a quel che resta. */
/* La maniglia del profilo: una colonna stretta sul suo bordo destro, che si accende quando ci passi
   sopra. Sparisce con il pannello -- `:empty` e' la stessa regola che nasconde lui. */
.column-grip {
  position: absolute;
  z-index: 1260;
  inset-block: var(--column-top) 56px;
  inset-inline-start: calc(10px + var(--column-w));
  width: 12px;
  cursor: ew-resize;
  touch-action: none;                    /* o il dito trascina la pagina invece del bordo */
}
.column:empty + .column-grip { display: none; }

.column-grip::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 3px;
  width: 3px;
  border-radius: 2px;
  background: transparent;
}
.column-grip:hover::before,
.column-grip:focus-visible::before { background: var(--accent); }
.column-grip:focus-visible { outline: none; }

.col-svg { display: block; flex: 1 1 auto; width: 100%; min-height: 0; }

/* `grab`, non `ns-resize`: il disegno non si ridimensiona, si sposta -- e il cursore e' l'unica cosa
   che lo dice prima di provarci. Sta sul PANNELLO perche' li' stanno i gesti: la tela si ricrea a ogni
   ridisegno e si portava via la cattura del puntatore a meta' trascinamento. */
/* /!\ `user-select: none`: trascinare per scorrere le quote selezionava le scritte del disegno, che si
   accendevano di blu dietro al dito -- il browser crede che si stia evidenziando del testo. */
.column { cursor: grab; touch-action: none; user-select: none; }
.column.dragging { cursor: grabbing; }
.column:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* Le cornici dell'annidamento: grigie e appena accennate, una dentro l'altra, e si sommano -- piu' si
   va verso il centro, piu' il fondo e' carico. Sono l'unica cosa del grafico che parla di profondita'
   e non di quota, e si vedono anche dove non c'e' nessun volume. */
.col-step { fill: currentColor; fill-opacity: 0.05; stroke: currentColor; stroke-opacity: 0.09; }
.col-in { fill: var(--ink-muted); font-size: 9px; font-weight: 400; }

/* La riga che dichiara la convenzione: piccola, ma c'e'. */
.col-note {
  margin: 2px 0 0;
  font-size: 10px;
  line-height: 1.3;
  color: var(--ink-muted);
}

.col-grid { stroke: var(--line); stroke-width: 1; }
.col-tick { fill: var(--ink-muted); font-size: 10px; font-variant-numeric: tabular-nums; }
.col-head { font-size: 10px; font-weight: 600; }
.col-name { fill: var(--ink); font-size: 10px; pointer-events: none; }
.col-band { cursor: pointer; }
/* La scatola intera si accende poco e la striscia propria molto: l'evidenza serve a far vedere FIN DOVE
   arriva il volume, non a riempire mezzo grafico. */
.col-band:hover .col-box { fill-opacity: 0.16; }
.col-band:hover .col-own { fill-opacity: 0.44; }
.col-band:focus-visible .col-own { outline: 2px solid var(--accent); }

/* Il volume scelto e la sua catena.
   /!\ Scelto = pieno e col nome in grassetto; chi lo racchiude e chi ci sta dentro restano normali;
   tutto il resto si spegne. E' la differenza fra «eccolo» e «dentro che cosa sta». */
.col-band.on .col-own { fill-opacity: 0.6; stroke-width: 2.4; }
.col-band.on .col-box { fill-opacity: 0.2; stroke-width: 2.4; }
.col-name.on { font-weight: 700; }

.col-band.around .col-box,
.col-band.within .col-box { stroke-width: 2; stroke-dasharray: 3 2; }
.col-band.around .col-own,
.col-band.within .col-own { fill-opacity: 0.34; }

/* Quel che non c'entra con la scelta si fa da parte, ma non sparisce: a 0,28 il profilo sembrava
   spento, e la catena si legge lo stesso. */
.col-band.aside,
.col-name.aside { opacity: 0.45; }

/* The eye's altitude: dashed, because it is where you are and not where anything is. */
.col-eye { stroke: #ff4d2d; stroke-width: 1.4; stroke-dasharray: 4 3; }
.col-eye-label { fill: #ff4d2d; font-size: 10px; font-variant-numeric: tabular-nums; }

.col-caption { flex: none; margin: 4px 0 0; font-size: 11px; line-height: 1.3; }

/* /! The labels live UNDER the panels. They are laid out to avoid them, but a layout runs on the next
   frame and a panel can change size in this one -- the stacking order is what holds in between. */
.v3d-labels { position: absolute; z-index: 1; inset: 0; pointer-events: none; }
/* /! Sopra le etichette: il loro strato e' l'ultimo figlio dello stage, e senza questa riga un nome
   finirebbe per coprire i comandi -- che e' esattamente quello che la disposizione evita. */
.stage3d-panel, .column, .column-grip, .note3d { z-index: 2; }

.v3d-label {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  display: flex;
  flex-direction: column;
  padding: 2px 6px;
  font: inherit;
  font-size: 11px;
  line-height: 1.25;
  text-align: start;
  color: var(--ink);
  pointer-events: auto;
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  border: 0;
  border-inline-start: 2px solid var(--chip);
  border-radius: 3px;
  cursor: pointer;
  white-space: nowrap;
}
.v3d-label b { font-weight: 600; }
.v3d-label i { font-style: normal; color: var(--ink-muted); font-variant-numeric: tabular-nums; }
.v3d-label:hover { background: var(--surface); }

/* Il volume scelto: il suo nome resta a schermo anche a nomi spenti, ed e' questo. */
.v3d-label.on {
  background: var(--surface);
  border-color: var(--chip);
  box-shadow: 0 0 0 2px var(--chip);
}

/* --- the source page: a page of text, not a map ---------------------------------------------------- */

.prose {
  max-width: 68ch;
  padding: 20px 16px 40px;
  margin: 0 auto;
  line-height: 1.6;
}
.prose section { margin-block-end: 28px; }
.prose h2 { font-size: 15px; margin: 0 0 6px; }
.prose p { margin: 0 0 10px; }
.prose a { overflow-wrap: anywhere; }

.prose dl { display: grid; grid-template-columns: auto 1fr; gap: 2px 14px; margin: 0; font-size: 14px; }
.prose dt { color: var(--ink-muted); }
.prose dd { margin: 0; overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }

.prose ul { margin: 0; padding-inline-start: 18px; font-size: 14px; }
.prose li { margin-block-end: 6px; }

.prose table { width: 100%; font-size: 14px; border-collapse: collapse; }
.prose th { text-align: start; color: var(--ink-muted); font-weight: 500; }
.prose th, .prose td { padding: 3px 8px 3px 0; border-block-end: 1px solid var(--line); }
.prose td:not(:first-child) { text-align: end; font-variant-numeric: tabular-nums; }

/* A page of prose scrolls; it does not need the map's «fill the window» rules. */
body.page { min-height: 0; }
body.page .bar { position: sticky; inset-block-start: 0; z-index: 10; }

/* Leaflet's own chrome, dressed like the rest of the page. */
.leaflet-container { font: inherit; background: var(--surface-muted); }
.leaflet-control-attribution { font-size: 11px; }

/* The dark basemap: the tiles only, turned down and inverted. OpenStreetMap publishes no dark style, and
   this costs nothing to keep alive. /!\ Only `.leaflet-tile-pane` is filtered -- the airspace polygons live
   in the overlay pane, and inverting them would turn a restricted-area red into a reassuring green. */
.map-dark .leaflet-tile-pane {
  filter: invert(1) hue-rotate(180deg) brightness(0.92) contrast(0.86) saturate(0.7);
}

/* Finestre larghe: le chip entrano nella prima riga, accanto al selettore di lingua, e si spezzano su
   due file da sole. Sotto questa misura la riga non le reggerebbe senza buttare gli attrezzi a capo. */
@media (min-width: 1400px) {
  /* /! Base 0 e non `auto`: con `auto` le chip chiedevano la larghezza di tutte e tredici in fila e
     andavano a capo lo stesso. Cosi' prendono quel che resta della riga e si spezzano dentro. */
  .chips { flex: 1 1 0; min-width: 0; order: 0; }
  /* I sessanta pixel che la ricerca cede qui sono la differenza fra due file di chip e tre. */
  .search { flex: 0 1 320px; }
}

@media (max-width: 720px) {
  /* /! Stretto: la ricerca prende una riga sua. L'ordine va riscritto tutto, non solo il suo, se no
     finisce dopo le chip -- cioe' in fondo a quattro righe di pulsanti, che e' dove non la cerca nessuno. */
  .search { order: 1; flex-basis: 100%; max-width: none; }
  .tools { order: 2; margin-inline-start: 0; }
  .chips { order: 3; flex-basis: 100%; }
  .detail { inset-block-start: auto; inset-block-end: 12px; inset-inline: 12px; width: auto; }
  main { min-height: 420px; }
}
