/* Weather Data Atlas styles. Design tokens follow the Treefera branding spine. */
body { margin: 0; }
:root {
  --ground: #F9FBFB;
  --surface: #FFFFFF;
  --surface-2: #F1F3F6;
  --ink: #040A0E;
  --ink-2: #3A4550;
  --ink-3: #6A7580;
  --line: #D5DCE3;
  --line-2: #E3E8EC;
  --canvas: #F5F9FB;
  --dots: #C5DCE7;
  --accent: #3A5A78;
  --focus: #6CA9C3;

  --k-source: #B9A17A;  --k-source-bg: #FEF8ED;
  --k-control: #7C7C7C; --k-control-bg: #F5F5F5;
  --k-stage: #4E7C90;   --k-stage-bg: #ECF4F7;
  --k-store: #3A5A78;   --k-store-bg: #F1F3F6;
  --k-model: #59745C;   --k-model-bg: #EDF2ED;
  --k-deliver: #A3517A; --k-deliver-bg: #F8F0F3;
  --k-legacy: #9B9B9B;  --k-legacy-bg: #F6F6F6;
  --k-dir: #5F7992;     --k-dir-bg: #FFFFFF;

  --e-data: #5F7992;
  --e-forecast: #4E7C90;
  --e-bypass: #B9A17A;
  --e-control: #A7A7A7;
  --e-retired: #BBBBBB;

  --warn-bg: #FFF6C2; --warn-ink: #5C4A00;
  --risk-ink: #A12020; --risk-bg: #FDE7E7;
  --ok-ink: #3A4D3C; --ok-bg: #E4EBE4;

  --sans: "Saans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --ground: #040A0E; --surface: #0B151C; --surface-2: #122029; --ink: #F9FBFB; --ink-2: #C5DCE7; --ink-3: #8599AD;
    --line: #284157; --line-2: #182939; --canvas: #070F14; --dots: #192C34; --accent: #8ABACF; --focus: #6CA9C3;
    --k-source: #F9D9A6; --k-source-bg: #1D1A14; --k-control: #A7A7A7; --k-control-bg: #141414;
    --k-stage: #6CA9C3; --k-stage-bg: #0F1D24; --k-store: #8599AD; --k-store-bg: #111B25;
    --k-model: #94B197; --k-model-bg: #121B13; --k-deliver: #BC7C9A; --k-deliver-bg: #1E0F17;
    --k-legacy: #6A6A6A; --k-legacy-bg: #141414; --k-dir: #8599AD; --k-dir-bg: #0B151C;
    --e-data: #8599AD; --e-forecast: #6CA9C3; --e-bypass: #B9A17A; --e-control: #5E5E5E; --e-retired: #444444;
    --warn-bg: #3A3000; --warn-ink: #FFE680; --risk-ink: #FF9A9A; --risk-bg: #3A1010; --ok-ink: #AEC4B0; --ok-bg: #1D291F;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --ground: #040A0E; --surface: #0B151C; --surface-2: #122029; --ink: #F9FBFB; --ink-2: #C5DCE7; --ink-3: #8599AD;
  --line: #284157; --line-2: #182939; --canvas: #070F14; --dots: #192C34; --accent: #8ABACF; --focus: #6CA9C3;
  --k-source: #F9D9A6; --k-source-bg: #1D1A14; --k-control: #A7A7A7; --k-control-bg: #141414;
  --k-stage: #6CA9C3; --k-stage-bg: #0F1D24; --k-store: #8599AD; --k-store-bg: #111B25;
  --k-model: #94B197; --k-model-bg: #121B13; --k-deliver: #BC7C9A; --k-deliver-bg: #1E0F17;
  --k-legacy: #6A6A6A; --k-legacy-bg: #141414; --k-dir: #8599AD; --k-dir-bg: #0B151C;
  --e-data: #8599AD; --e-forecast: #6CA9C3; --e-bypass: #B9A17A; --e-control: #5E5E5E; --e-retired: #444444;
  --warn-bg: #3A3000; --warn-ink: #FFE680; --risk-ink: #FF9A9A; --risk-bg: #3A1010; --ok-ink: #AEC4B0; --ok-bg: #1D291F;
}

* { box-sizing: border-box; }
body { background: var(--ground); color: var(--ink); font-family: var(--sans); font-weight: 380; line-height: 1.5; }
.wrap { padding-inline: 20px; padding-block: 18px 40px; max-width: 1680px; margin: 0 auto; display: grid; gap: 18px; }

header.top { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 28px; justify-content: space-between; }
.brand { display: flex; align-items: center; gap: 16px; }
.brand img { height: 30px; width: auto; }
.logo-w { display: none; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .logo-b { display: none; } :root:not([data-theme="light"]) .logo-w { display: block; } }
:root[data-theme="dark"] .logo-b { display: none; }
:root[data-theme="dark"] .logo-w { display: block; }
.brand-text h1 { margin: 0; font-size: 20px; line-height: 30px; font-weight: 570; text-wrap: balance; }
.brand-text p { margin: 0; font-size: 13px; line-height: 20px; color: var(--ink-3); }

nav.tabs { display: flex; flex-wrap: wrap; gap: 4px; background: var(--surface-2); padding: 4px; border-radius: 10px; }
nav.tabs button { font: inherit; font-size: 14px; font-weight: 570; border: 0; background: transparent; color: var(--ink-2); padding: 6px 14px; border-radius: 7px; cursor: pointer; }
nav.tabs button[aria-selected="true"] { background: var(--surface); color: var(--ink); box-shadow: 0 0 0 1px var(--line); }
nav.tabs button:focus-visible, .btn:focus-visible, .row:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

.blurb { margin: 0; color: var(--ink-2); font-size: 14px; max-width: 110ch; }

.stage-grid { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: 16px; align-items: start; }
@media (max-width: 1000px) { .stage-grid { grid-template-columns: minmax(0, 1fr); } }
.canvas { height: 74vh; min-height: 520px; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; background: var(--canvas); }
/* Fullscreen paints its own backdrop (black by default), so the canvas restates its background
   and drops the rounding that would otherwise show as notched corners against the screen edge. */
.canvas:fullscreen { height: 100%; width: 100%; border: 0; border-radius: 0; background: var(--canvas); }

/* Our own fit-view button replaces the stock one, whose corner-bracket icon reads the same as
   the fullscreen button's at this size. */
.react-flow__controls-fitview { display: none; }
.react-flow__controls-fitdiagram svg,
.react-flow__controls-fullscreen svg { width: 14px; height: 14px; }

.react-flow {
  --xy-background-color: var(--canvas);
  --xy-background-pattern-color: var(--dots);
  --xy-edge-label-background-color: var(--canvas);
  --xy-edge-label-color: var(--ink-2);
  --xy-controls-button-background-color: var(--surface);
  --xy-controls-button-background-color-hover: var(--surface-2);
  --xy-controls-button-color: var(--ink);
  --xy-controls-button-border-color: var(--line);
  --xy-minimap-background-color: var(--surface);
  --xy-minimap-mask-background-color: color-mix(in srgb, var(--ground) 70%, transparent);
  --xy-handle-background-color: var(--ink-3);
  --xy-handle-border-color: var(--surface);
  --xy-attribution-background-color: transparent;
}
.react-flow__edge-textbg { fill: var(--canvas); }
.react-flow__edge-text { font-family: var(--sans); font-size: 11px; fill: var(--ink-2); }
.react-flow__attribution a { color: var(--ink-3); }

/* HTML label for the ELK-routed custom edge (RoutedEdge in app.js) — the SVG
   .react-flow__edge-text/-textbg rules above only apply to React Flow's built-in edge types. */
/* An edge label sits ON the edge, so where two containers meet it can graze a node box
   (measured 2026-09-25 on Canonical (09F): five label/node overlaps of 6-12px2, e.g.
   "forecasts + best_guess_obs" clipping `compute` inside coverage-calculator). ELK reserves
   the label's box but tolerates a few px of proximity across a container boundary, so rather
   than fight the layout the label is made to win the paint: an opaque background matching the
   canvas, a hairline ring so it reads as a chip rather than smudging into whatever is behind
   it, and a z-index above the node boxes. The text stays legible even when it grazes. */
.edge-label {
  background: var(--canvas); padding: 2px 6px; border-radius: 4px; white-space: nowrap;
  box-shadow: 0 0 0 1px var(--line-2); z-index: 6;
}
.edge-label .react-flow__edge-text { font-size: 11px; color: var(--ink-2); fill: none; }

.node {
  width: 272px; border-radius: 3px; background: var(--k-bg); border: 1px solid var(--line);
  border-left: 5px solid var(--k); padding: 9px 12px 10px; color: var(--ink); cursor: pointer;
  transition: box-shadow .12s ease, transform .12s ease;
}
.node.legacy { border-style: dashed; border-left-style: solid; opacity: .85; }
/* Data = cylinder: elliptical corners draw the curved top and bottom, ::before draws the lid. */
.node.cyl { position: relative; border: 1.5px solid var(--k); border-radius: 136px / 16px; padding: 42px 16px 20px; text-align: center; }
.node.cyl::before { content: ""; position: absolute; left: -1.5px; right: -1.5px; top: -1.5px; height: 32px; border: 1.5px solid var(--k); border-radius: 50%; background: color-mix(in srgb, var(--k) 14%, var(--k-bg)); pointer-events: none; }
.node.cyl .kind { justify-content: center; }
.node.cyl .flags { justify-content: center; }
.node.cyl.legacy, .node.cyl.legacy::before { border-style: dashed; }
.node.cyl.selected { box-shadow: 0 0 0 3px var(--focus); }
.node.selected { box-shadow: 0 0 0 2px var(--focus); }
.node.dim { opacity: .35; }
.node .kind { font-size: 10px; line-height: 15px; letter-spacing: .08em; text-transform: uppercase; color: var(--k); font-weight: 570; display: flex; gap: 6px; align-items: center; }
.node .title { font-size: 15px; line-height: 22px; font-weight: 570; margin-top: 1px; }
.node .sub { font-family: var(--mono); font-size: 11px; line-height: 16px; color: var(--ink-2); overflow-wrap: anywhere; }
.node .path { margin-top: 6px; font-family: var(--mono); font-size: 10.5px; line-height: 15px; color: var(--ink-3); overflow-wrap: anywhere; border-top: 1px solid var(--line-2); padding-top: 5px; }
.node .flags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.react-flow__node-container { pointer-events: none; cursor: default; }
.container {
  width: 100%; height: 100%; border-radius: 8px; background: color-mix(in srgb, var(--k) 6%, transparent);
  border: 1.5px dashed var(--k); box-sizing: border-box;
}
.container.selected { box-shadow: 0 0 0 2px var(--focus); }
.container-handle { visibility: hidden; }
.container-label {
  position: absolute; top: 8px; left: 10px; display: flex; align-items: center; gap: 6px;
}
.container-label .kind { font-size: 10px; line-height: 15px; letter-spacing: .08em; text-transform: uppercase; color: var(--k); font-weight: 570; }
.container-label .title { font-size: 12px; line-height: 15px; font-weight: 570; color: var(--ink-2); }
.pill { font-size: 10px; line-height: 16px; padding: 0 6px; border-radius: 999px; font-weight: 570; letter-spacing: .02em; background: var(--warn-bg); color: var(--warn-ink); }
.pill.risk { background: var(--risk-bg); color: var(--risk-ink); }
.pill.link { background: var(--surface-2); color: var(--accent); }
.pill.ok { background: var(--ok-bg); color: var(--ok-ink); }
.pill.env { background: var(--surface-2); color: var(--ink-2); box-shadow: inset 0 0 0 1px var(--line); }

aside.inspect { background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 16px 18px; max-height: 74vh; overflow: auto; display: grid; gap: 14px; align-content: start; }
@media (max-width: 1000px) { aside.inspect { max-height: none; } }
.inspect .kind { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; font-weight: 570; color: var(--k); }
.inspect h2 { margin: 2px 0 0; font-size: 20px; line-height: 30px; font-weight: 570; text-wrap: balance; }
.inspect .sub { font-family: var(--mono); font-size: 12px; color: var(--ink-2); overflow-wrap: anywhere; }
.inspect p { margin: 0; font-size: 14px; color: var(--ink-2); }
.inspect h3 { margin: 0 0 6px; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-3); font-weight: 570; }
.kv { display: grid; gap: 8px; }
.kv .item { display: grid; gap: 2px; }
.kv .label { font-size: 12px; color: var(--ink-3); display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.kv code, .list code { font-family: var(--mono); font-size: 12px; line-height: 18px; color: var(--ink); background: var(--surface-2); border-radius: 6px; padding: 4px 7px; display: block; overflow-wrap: anywhere; }
.list { margin: 0; padding: 0; list-style: none; display: grid; gap: 6px; font-size: 13px; color: var(--ink-2); }
.list li { padding-left: 12px; position: relative; }
.list li::before { content: ""; position: absolute; left: 0; top: .6em; width: 5px; height: 5px; border-radius: 50%; background: var(--line); }
.list.code li { padding-left: 0; }
.list.code li::before { display: none; }
.btn { font: inherit; font-size: 12px; font-weight: 570; border: 1px solid var(--line); background: var(--surface); color: var(--ink-2); border-radius: 6px; padding: 1px 8px; cursor: pointer; }
.btn:hover { background: var(--surface-2); }
.btn.primary { color: var(--accent); }
.empty { color: var(--ink-3); font-size: 14px; }

.legend { display: flex; flex-wrap: wrap; gap: 10px 18px; font-size: 12px; color: var(--ink-2); align-items: center; }
.legend .sw { display: inline-block; width: 12px; height: 12px; border-radius: 2px; border-left: 4px solid var(--k); background: var(--k-bg); box-shadow: inset 0 0 0 1px var(--line); vertical-align: -2px; margin-right: 6px; }
.legend .shape { display: inline-flex; align-items: center; gap: 6px; font-weight: 570; color: var(--ink); }
.legend svg { overflow: visible; }
.legend .ln { display: inline-block; width: 26px; height: 0; border-top: 2px solid var(--c); vertical-align: middle; margin-right: 6px; }
.legend .ln.dash { border-top-style: dashed; }
.legend .ln.dot { border-top-style: dotted; }

section.index { background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 16px 18px; display: grid; gap: 12px; }
.index-head { display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: center; justify-content: space-between; }
.index-head h2 { margin: 0; font-size: 18px; line-height: 27px; font-weight: 570; }
.index-head .controls { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.index-head input[type="search"] { font: inherit; font-size: 14px; padding: 6px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--ground); color: var(--ink); width: min(340px, 100%); }
.index-head select { font: inherit; font-size: 14px; padding: 6px 8px; border: 1px solid var(--line); border-radius: 8px; background: var(--ground); color: var(--ink); }
.tbl-wrap { overflow-x: auto; max-height: 460px; overflow-y: auto; border: 1px solid var(--line-2); border-radius: 8px; }
table { border-collapse: collapse; width: 100%; font-size: 13px; }
th { position: sticky; top: 0; background: var(--surface-2); color: var(--ink-3); text-align: left; font-weight: 570; font-size: 11px; letter-spacing: .06em; text-transform: uppercase; padding: 8px 10px; }
td { padding: 7px 10px; border-top: 1px solid var(--line-2); vertical-align: top; }
td.p { font-family: var(--mono); font-size: 12px; overflow-wrap: anywhere; min-width: 360px; }
tr.row { cursor: pointer; }
tr.row:hover td { background: var(--surface-2); }
.where { font-size: 11px; font-weight: 570; padding: 1px 7px; border-radius: 999px; background: var(--surface-2); color: var(--ink-2); white-space: nowrap; }
.where.s3 { color: var(--k-deliver); }
.where.local { color: var(--k-model); }
.count { font-size: 13px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
footer { font-size: 12px; color: var(--ink-3); }
@media (prefers-reduced-motion: reduce) { .node { transition: none; } }

/* Download menu (top-right of the canvas). Not captured in exports: only .react-flow__viewport is. */
.export { display: grid; gap: 6px; justify-items: end; }
.export-toggle { font: inherit; font-size: 13px; font-weight: 570; display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--line); background: var(--surface); color: var(--ink); border-radius: 8px; padding: 5px 11px; cursor: pointer; }
.export-toggle:hover { background: var(--surface-2); }
.export-toggle:disabled { opacity: .6; cursor: progress; }
.export-toggle:focus-visible, .export-menu button:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.export-menu { display: grid; min-width: 210px; background: var(--surface); border: 1px solid var(--line); border-radius: 8px; padding: 4px; }
.export-menu button { font: inherit; display: grid; gap: 1px; text-align: left; border: 0; background: transparent; color: var(--ink); border-radius: 6px; padding: 7px 10px; cursor: pointer; }
.export-menu button:hover { background: var(--surface-2); }
.export-menu strong { font-size: 13px; font-weight: 570; }
.export-menu span { font-size: 12px; color: var(--ink-3); }
.export-status { font-size: 12px; color: var(--ink-2); background: var(--surface); border: 1px solid var(--line); border-radius: 6px; padding: 3px 8px; }
