/* Oblast alert map (issue #36).
 *
 * Colour is a validated single-hue sequential ramp on the count of alerted
 * places, chosen against THIS dark surface rather than flipped from a light
 * one. On a dark surface luminance carries magnitude, so the brightest step is
 * the worst, and the nearest-surface step still clears 2:1 (#8c2e28 at 2.10:1
 * on #1a1a19). The scale ran through the data-viz validator: one hue (4 deg
 * spread), monotone lightness, every adjacent gap over 0.06.
 *
 * FOUR classes, not five, and that is a colour decision rather than a taste
 * one. The dim end has to clear 2:1 against the surface and every step has to
 * gain at least 0.06 in lightness, so a fifth class pushes the top into a pale
 * pink that reads as LESS urgent than the dark low end. Four classes keep the
 * worst step a vivid red, which is the one thing a reader must not misread.
 *
 * There is deliberately NO basemap. An oblast choropleth gains nothing from
 * street tiles, loses contrast against them, and costs a phone its data during
 * a raid. No tiles also means the surface is known, which is what makes the
 * contrast numbers above mean anything.
 *
 * The lightest ramp step sits under 3:1, which obliges relief: the table view
 * at the bottom is not optional decoration, it is that relief. It carries the
 * count and the level in words, so nothing here is conveyed by colour alone.
 */
:root {
  --surface:        #1a1a19;   /* the map plane, and the validator's surface */
  --plane:          #0d0d0d;   /* the page behind it */
  --panel:          #232321;
  --ink:            #ffffff;
  --ink-2:          #c3c2b7;
  --ink-muted:      #898781;
  --hairline:       #383835;
  --no-alert:       #2c2c2a;   /* recedes toward the surface: nothing happening */

  /* TWO ramps, dim to vivid = few places to many. The hue carries the worst
     level in the oblast, the step carries how many places. An oblast whose
     alerts are ALL yellow must not read as red.
     Every pair at the same step clears the colour-blind floors: deutan dE 13.3
     to 17.8 and normal-vision 17.2 to 24.6, measured against the dark surface,
     and each ramp passes the ordinal gate on its own. */
  --n1:  #8c2e28;   /* red level */
  --n2:  #b23a30;
  --n3:  #d94b3a;
  --n4:  #ff6a52;
  --y1:  #967011;   /* yellow level only */
  --y2:  #bb8d17;
  --y3:  #e0ab20;
  --y4:  #ffd44f;

  /* Status, fixed and never themed. Each ships with a word, never colour alone. */
  --critical: #d03b3b;
  --warning:  #fab219;
  --good:     #0ca30c;
}

* { box-sizing: border-box; }
html, body { margin: 0; background: var(--plane); color: var(--ink);
  font: 15px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif; }

.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

#bar { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px 16px;
  padding: 12px 16px; background: var(--panel);
  border-bottom: 1px solid var(--hairline); }
#bar h1 { font-size: 17px; font-weight: 600; margin: 0; }
#summary, #freshness { margin: 0; font-size: 13px; color: var(--ink-2); }
#freshness.stale { color: var(--warning); font-weight: 600; }
#freshness.dead { color: var(--critical); font-weight: 600; }

.windows { display: flex; gap: 4px; }
.windows button {
  background: #2e2e2b; color: var(--ink-2); border: 1px solid var(--hairline);
  border-radius: 6px; padding: 5px 11px; cursor: pointer; font: inherit;
  font-size: 13px; min-height: 32px;        /* a thumb-sized target */
}
.windows button:hover { color: var(--ink); }
.windows button.active { background: #4a4a46; color: var(--ink);
  border-color: #5c5c57; font-weight: 600; }
.windows button:focus-visible { outline: 2px solid var(--ink-2); outline-offset: 2px; }

#banner { margin: 0; padding: 10px 16px; font-size: 14px; font-weight: 600;
  background: #3a1d1d; color: #ffd9d9; border-bottom: 1px solid var(--critical); }
#banner.warn { background: #3a2f12; color: #ffeabf; border-bottom-color: var(--warning); }

/* Height, not aspect-ratio. Ukraine's box is about 3:2 in this projection, so
   66vw is the height that suits the width, and 62vh caps it on a short window.
   aspect-ratio plus max-height was tried and shrank the ELEMENT's width when
   the height clamped, which left a dead band down the right of the page. */
#stage { display: flex; align-items: stretch; }
#map { flex: 1 1 auto; height: min(62vh, 52vw); min-height: 220px;
  background: var(--surface); }

/* The detail panel. Fixed width, its own scroll, so a long place list never
   pushes the map around or runs off the edge. */
#detail { flex: 0 0 310px; height: min(62vh, 52vw); min-height: 220px;
  overflow-y: auto; padding: 12px 14px; background: var(--panel);
  border-left: 1px solid var(--hairline); font-size: 13px; }
#detail .hint { color: var(--ink-muted); margin: 0; }
#detail h2 { margin: 0; font-size: 16px; font-weight: 600; color: var(--ink);
  text-transform: none; letter-spacing: 0; }
#detail .uk { display: block; font-size: 12px; color: var(--ink-muted);
  margin-bottom: 8px; }
#detail .headline { display: flex; align-items: center; gap: 8px;
  margin-bottom: 10px; }
#detail .headline .count { font-size: 22px; font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums; }
#detail .headline .unit { color: var(--ink-2); }
#detail ul { list-style: none; margin: 0; padding: 0; }
#detail li { padding: 6px 0; border-top: 1px solid #2c2c2a; }
#detail li .place { color: var(--ink); }
#detail li .meta { display: block; color: var(--ink-muted); font-size: 12px; }
#detail .pinned { color: var(--ink-muted); font-size: 12px; margin: 10px 0 0; }
#detail dl { margin: 0; }
#detail dt { color: var(--ink-muted); font-size: 12px; margin-top: 8px; }
#detail dd { margin: 0; color: var(--ink); font-variant-numeric: tabular-nums; }

/* One short line. It cannot hold a list, and it does not try to. */
.leaflet-tooltip.ob { max-width: 220px; }
.leaflet-container { background: var(--surface); outline: none; }

/* Leaflet's tooltip, restyled to this page's ink and surface. */
.leaflet-tooltip.ob {
  background: var(--panel); color: var(--ink); border: 1px solid var(--hairline);
  box-shadow: none; font-size: 13px; line-height: 1.45; max-width: 280px;
  white-space: normal; padding: 7px 9px;
}
.leaflet-tooltip.ob b { font-weight: 600; }
.leaflet-tooltip.ob .places { margin: 4px 0 0; padding-left: 16px; color: var(--ink-2); }
.leaflet-tooltip.ob::before { border: none; }

#legend, #table-view { padding: 14px 16px; }
#legend h2, #table-view h2 { font-size: 13px; font-weight: 600; margin: 0 0 8px;
  color: var(--ink-2); text-transform: uppercase; letter-spacing: .04em; }
#ramp { margin: 0; padding: 0; list-style: none; font-size: 13px; }
#ramp li { display: flex; align-items: center; gap: 6px; color: var(--ink-2);
  margin-bottom: 4px; }
#ramp li .label { width: 92px; flex: none; }
#ramp i { width: 30px; height: 13px; border-radius: 2px; display: block;
  border: 1px solid var(--hairline); }
#ramp .heads { color: var(--ink-muted); font-size: 12px; }
/* :not(.label) matters. A bare ".heads span" has the same specificity as
   "li .label" and, coming later, shrank the row label to 30px, so the class
   headings sat 30px left of the swatches they name. */
#ramp .heads span:not(.label) { width: 30px; flex: none; text-align: center; }
.note { margin: 8px 0 0; font-size: 12px; color: var(--ink-muted); }

#table-view table { width: 100%; border-collapse: collapse; font-size: 13px; }
#table-view th { text-align: left; font-weight: 600; color: var(--ink-muted);
  border-bottom: 1px solid var(--hairline); padding: 5px 8px 5px 0; }
#table-view td { padding: 5px 8px 5px 0; border-bottom: 1px solid #262624;
  vertical-align: top; color: var(--ink-2); }
#table-view td.n { font-variant-numeric: tabular-nums; color: var(--ink); }
/* English leads and Ukrainian sits under it. The reader of this page may not
   read Ukrainian, but the Ukrainian name is the one on every official channel,
   so it never goes away. */
#table-view th.name { text-align: left; font-weight: 400; color: inherit;
  padding: 5px 8px 5px 0; border-bottom: 1px solid #262624; }
#table-view th.name .en { display: block; color: var(--ink); }
#table-view th.name .uk { display: block; font-size: 12px; color: var(--ink-muted); }
#table-view tr.quiet th.name .en { color: var(--ink-muted); }
.leaflet-tooltip.ob .uk { color: var(--ink-muted); font-size: 12px; }
#table-view tr.quiet td { color: var(--ink-muted); }
#table-hint { font-weight: 400; text-transform: none; letter-spacing: 0; }

.chip { display: inline-block; padding: 1px 7px; border-radius: 10px;
  font-size: 12px; font-weight: 600; color: #141413; white-space: nowrap; }
.chip.red { background: var(--critical); color: #fff; }
.chip.yellow { background: var(--warning); }
.chip.none { background: #33332f; color: var(--ink-muted); }
.chip.unknown { background: #33332f; color: var(--ink-muted); }

footer { display: flex; flex-wrap: wrap; gap: 6px 18px; padding: 12px 16px 24px;
  font-size: 12px; color: var(--ink-muted); border-top: 1px solid var(--hairline); }
footer a { color: var(--ink-2); }

@media (max-width: 560px) {
  #bar { gap: 8px 12px; }
  #stage { display: block; }
  #map { height: min(54vh, 72vw); }
  #detail { height: auto; max-height: 40vh; flex: none;
    border-left: 0; border-top: 1px solid var(--hairline); }
  #table-view td:nth-child(4), #table-view th:nth-child(4) { display: none; }
}

/* Forced colours and print: the fill cannot be trusted, so the table carries
   the data and the map keeps only its outlines. */
@media (forced-colors: active) {
  .leaflet-interactive { forced-color-adjust: none; }
}
