.home-wrap {
  flex:       1;
  min-height: 0;
  display:    flex;
  overflow:   hidden;
  background: var(--bg0);
}
/* Light mode keeps the grey canvas (var(--bg0)) — the floating white cards and
   the left nav rail lift off it. (Was forced to #fff.) */

/* ── Header ─────────────────────────────────────────────────────── */
.home-header {
  display:       flex;
  align-items:   flex-start;
  margin-bottom: 28px;
}
.home-title {
  font-size:   22px;
  font-weight: 600;
  color:       var(--t0);
  margin-bottom: 4px;
}
.home-sub {
  font-size:   12px;
  color:       var(--t2);
  font-family: var(--font-mono);
}

/* ── Quick access row ───────────────────────────────────────────── */
.quick-row {
  display:               grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap:                   12px;
  margin-bottom:         28px;
}
.quick-card {
  background:    var(--bg1);
  border:        1px solid var(--bdr);
  border-radius: 10px;
  padding:       18px 16px;
  cursor:        pointer;
  text-decoration: none;
  transition:    all .15s;
  display:       block;
}
.quick-card:hover {
  border-color: var(--acc);
  background:   var(--bg2);
  transform:    translateY(-2px);
}
.qc-disabled {
  opacity: .45;
  cursor:  not-allowed;
  /* No hover animation on a disabled card — and dropping `transition: all`
     (inherited from .quick-card) avoids the Chromium bug where a var()-based
     background fails to re-resolve when the theme class toggles, leaving the
     card stuck on the dark --bg1 in light mode. */
  transition: none;
}
.qc-disabled:hover {
  border-color: var(--bdr);
  background:   var(--bg1);
  transform:    none;
}
.qc-icon  { font-size: 24px; margin-bottom: 10px; }
.qc-label { font-size: 13px; font-weight: 600; color: var(--t0); margin-bottom: 4px; }
.qc-desc  { font-size: 11px; color: var(--t2); line-height: 1.4; }

/* ── Placeholder / scaffold pages (Assessment, Insights) ───────────
   These workspaces aren't built yet. The dashboard's .home-wrap is a
   full-bleed flex row (for the map) — wrong here, it jams the stub into
   the corner. .stage is a tidy, centred, scrollable column instead:
   header → "under construction" notice → an organised section. So the
   stub reads as intentional, not unfinished. */
.stage {
  flex:       1;
  min-height: 0;
  overflow-y: auto;
  background: var(--bg0);
}
/* light mode keeps the grey --bg0 canvas here too (was forced #fff) */

.stage-inner {
  max-width: 860px;
  margin:    0 auto;
  padding:   52px 32px 72px;
}

/* header — title + optional status pill, mono subtitle below */
.stage-head { margin-bottom: 32px; }
.stage-title {
  display:       flex;
  align-items:   center;
  gap:           10px;
  font-size:     24px;
  font-weight:   600;
  color:         var(--t0);
  margin-bottom: 6px;
}
.stage-pill {
  font-family:    var(--font-mono);
  font-size:      10px;
  font-weight:    600;
  letter-spacing: .07em;
  color:          var(--t2);
  background:     var(--bg3);
  padding:        3px 9px;
  border-radius:  5px;
}
.stage-sub { font-size: 12.5px; color: var(--t2); font-family: var(--font-mono); }

/* "under construction" notice — one prominent card with an icon tile */
.stage-notice {
  display:       flex;
  gap:           16px;
  align-items:   flex-start;
  background:    var(--bg1);
  border:        1px solid var(--bdr);
  border-radius: 12px;
  padding:       22px 24px;
  margin-bottom: 36px;
}
.stage-notice-ic {
  flex-shrink:     0;
  width:           46px;
  height:          46px;
  display:         flex;
  align-items:     center;
  justify-content: center;
  font-size:       24px;
  background:      var(--bg2);
  border-radius:   10px;
}
.stage-notice-body  { min-width: 0; }
.stage-notice-title { font-size: 15px;   font-weight: 600; color: var(--t0); margin-bottom: 5px; }
.stage-notice-desc  { font-size: 12.5px; color: var(--t2); line-height: 1.6; }

/* section label above a group (planned features / how it works) */
.stage-label {
  font-family:    var(--font-mono);
  font-size:      9px;
  font-weight:    600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color:          var(--t2);
  margin-bottom:  14px;
}

/* numbered "how it will work" steps */
.stage-steps { display: flex; flex-direction: column; gap: 10px; }
.stage-step {
  display:       flex;
  align-items:   center;
  gap:           14px;
  background:    var(--bg1);
  border:        1px solid var(--bdr);
  border-radius: 9px;
  padding:       13px 16px;
}
.stage-step-n {
  flex-shrink:     0;
  width:           24px;
  height:          24px;
  display:         flex;
  align-items:     center;
  justify-content: center;
  font-family:     var(--font-mono);
  font-size:       11px;
  font-weight:     600;
  color:           var(--acc);
  background:      var(--bg2);
  border-radius:   50%;
}
.stage-step-text { font-size: 12.5px; color: var(--t1); }

/* on this column the planned-feature grid shouldn't stretch to giant
   tiles — cap each card so two items stay tidy, not blown up */
.stage .quick-row { grid-template-columns: repeat(auto-fill, minmax(190px, 240px)); }

/* ── Widget grid ─────────────────────────────────────────────────── */
.widget-grid {
  display:               grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap:                   16px;
}
.widget-card {
  background:    var(--bg1);
  border:        1px solid var(--bdr);
  border-radius: 10px;
  padding:       16px 18px;
}
.widget-title {
  font-family:    var(--font-mono);
  font-size:      9px;
  font-weight:    600;
  color:          var(--t2);
  letter-spacing: .12em;
  text-transform: uppercase;
  margin-bottom:  12px;
}
.widget-stat {
  font-size:   28px;
  font-weight: 600;
  color:       var(--acc);
  margin-bottom: 4px;
}
.widget-label {
  font-size: 11px;
  color:     var(--t1);
}
.widget-list {
  list-style: none;
  margin-top: 8px;
}
.widget-list li {
  display:       flex;
  align-items:   center;
  gap:           8px;
  padding:       5px 0;
  border-bottom: 1px solid var(--bdr);
  font-size:     11px;
  color:         var(--t1);
}
.widget-list li:last-child { border-bottom: none; }
.wl-name  { flex: 1; color: var(--t0); }
.wl-badge {
  font-family:  var(--font-mono);
  font-size:    9px;
  padding:      2px 6px;
  border-radius: 4px;
  background:   var(--bg3);
  color:        var(--t2);
}
.wl-ok { background: rgba(61,214,140,.15); color: var(--ok); }

/* ── Executive dashboard scaffold ───────────────────────────────── */
.exec-grid {
  display:               grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap:                   14px;
  align-items:           start;   /* panels size to their own content height */
}
.exec-panel {
  background:    var(--bg1);
  border:        1px solid var(--bdr);
  border-radius: 10px;
  padding:       16px 18px;
}
.exec-wide { grid-column: 1 / -1; }
.exec-head {
  display:         flex;
  align-items:     center;
  justify-content: space-between;
  margin-bottom:   6px;
}
.exec-t    { font-size: 13px; font-weight: 600; color: var(--t0); }
.exec-soon {
  font-family:    var(--font-mono);
  font-size:      8px;
  letter-spacing: .08em;
  color:          var(--t2);
  background:     var(--bg3);
  padding:        2px 7px;
  border-radius:  4px;
}
.exec-desc { font-size: 11px; color: var(--t2); line-height: 1.5; margin-bottom: 14px; }

.exec-prices { display: flex; gap: 10px; }
.price-tile  { flex: 1; background: var(--bg2); border-radius: 8px; padding: 12px; text-align: center; }
.pt-name     { display: block; font-family: var(--font-mono); font-size: 10px; color: var(--t2); margin-bottom: 6px; }
.pt-val      { display: block; font-size: 20px; font-weight: 600; color: var(--t1); }

.exec-kpis { display: flex; gap: 10px; }
.kpi       { flex: 1; background: var(--bg2); border-radius: 8px; padding: 12px; text-align: center; }
.kpi-v     { display: block; font-size: 22px; font-weight: 600; color: var(--t1); }
.kpi-k     { display: block; font-family: var(--font-mono); font-size: 10px; color: var(--t2); margin-top: 4px; }

.exec-map {
  height:          200px;
  background:      var(--bg2);
  border:          1px dashed var(--bdr2);
  border-radius:   8px;
  display:         flex;
  align-items:     center;
  justify-content: center;
  color:           var(--t2);
  font-family:     var(--font-mono);
  font-size:       12px;
}

.exec-news { display: flex; flex-direction: column; gap: 12px; }
.news-row  { display: flex; align-items: center; gap: 10px; }
.nr-dot    { width: 8px; height: 8px; border-radius: 50%; background: var(--bg3); flex-shrink: 0; }
.nr-line   { height: 9px; background: var(--bg3); border-radius: 4px; }

@media (max-width: 720px) {
  .exec-grid { grid-template-columns: 1fr; }
}

/* ── Dashboard layout: left column (Prices + Articles) + right column (Map) ──
   Two columns fill one screen (no page scroll). Each section has a clickable
   title that links to its detail page — same target as the left nav-rail. */
.dash-layout {
  display:    flex;
  gap:        30px;
  flex:       1;
  min-width:  0;
  min-height: 0;
  /* Bottom padding (24px) clears the map card's soft drop-shadow (~22px reach)
     so .home-wrap's overflow:hidden doesn't clip its lower edge. */
  padding:    26px 18px 24px;
}

.dash-col-left {
  flex:           0 0 clamp(420px, 32%, 680px);
  min-width:      0;
  min-height:     0;
  display:        flex;
  flex-direction: column;
  gap:            35px;
}
.dash-col-right {
  flex:           1 1 auto;
  min-width:      0;
  min-height:     0;
  display:        flex;
  flex-direction: column;
}

/* A titled section: clickable heading + body panel. */
.dash-sec {
  display:        flex;
  flex-direction: column;
  min-height:     0;
}
.dash-sec-prices   { flex: 0 0 auto; }   /* prices = natural height */
.dash-sec-articles { flex: 1 1 auto; }   /* articles fills the rest of the left col */
.dash-sec-weather  { flex: 0 0 auto; }   /* weather = natural height, like prices */
.dash-sec-map      { flex: 1 1 auto; }   /* map fills the right col */

/* Clickable section title — navigates to the detail page (like the rail icon).
   Only the text is the click target (align-self), with a chevron that slides
   in on hover to signal it's a link. */
/* Header row: section title on the left, an optional control (the Articles
   EN/KR toggle) pinned right — keeps the control out of the card and aligned
   with the title line. */
.dash-sec-head {
  display:         flex;
  align-items:     flex-end;        /* pin the toggle low so it hugs the card below */
  justify-content: space-between;
  gap:             10px;
  margin-bottom:   10px;            /* inherits the gap the title used to carry */
}
.dash-sec-head .dash-sec-title { margin-bottom: 0; align-self: flex-end; }
.dash-sec-head .nws-lang       { margin-bottom: 0; }

.dash-sec-title {
  display:         inline-flex;
  align-items:     center;
  gap:             5px;
  align-self:      flex-start;
  margin:          0 0 10px 2px;
  font-size:       24px;
  font-weight:     700;
  letter-spacing:  -.01em;
  color:           var(--t0);
  text-decoration: none;
  cursor:          pointer;
  transition:      color .13s;
}
/* Accent marker — a small rounded bar so the title anchors to its section rather
   than reading as sunken beneath the floating panel below. --acc works in both
   themes; the parent gap (5px) + margin gives ~9px to the text, while the chevron
   keeps the plain 5px gap. */
.dash-sec-title::before {
  content:       "";
  flex:          0 0 auto;
  width:         5px;
  height:        22px;
  margin-right:  5px;
  border-radius: 2.5px;
  background:    var(--acc);
}
.dash-sec-title:hover { color: var(--acc); }
.dash-sec-title .dst-arrow {
  width:      20px;
  height:     20px;
  opacity:    .5;             /* always visible — signals the title is a link */
  transition: opacity .14s ease, transform .14s ease;
}
.dash-sec-title:hover .dst-arrow { opacity: 1; transform: translateX(3px); }

/* Section body fills the remaining section height. */
.dash-sec-body {
  flex:           1 1 auto;
  min-height:     0;
  display:        flex;
  flex-direction: column;
}

/* Prices + Articles cards */
.dash-sec-body > .exec-panel {
  background:    var(--bg2);
  border:        1px solid var(--bdr);
  border-radius: 10px;
  padding:       14px;
  box-shadow:    0 4px 14px rgba(0,0,0,.22);
  min-height:    0;
}
body.light .dash-sec-body > .exec-panel {
  background:   #fff;
  border-color: #e8ebf0;
  box-shadow:   0 1px 2px rgba(16,24,40,.04), 0 6px 16px rgba(16,24,40,.07);
}

/* Articles card fills its section; the list scrolls inside. */
.dash-sec-articles .nws-panel {
  flex:           1 1 auto;
  min-height:     0;
  display:        flex;
  flex-direction: column;
}
.dash-sec-articles .nws-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

/* Weather panel: News tab reuses the Articles .nws-item, but shows title + the
   first summary line (no source/date — clips are same-day Criterion); a click
   opens the full 3-line summary popover (with Copy, no link). Capped + scrolls so
   the section stays compact at the column's foot. */
/* Weather keeps a comfortable fixed height (independent of Prices, which can shrink /
   go compact) so the radar map stays readable; the panel fills it and scrolls. */
.dash-sec-weather .exec-panel { height: 280px; }
.dash-sec-weather .nws-panel { display: flex; flex-direction: column; min-height: 0; }
.dash-sec-weather .nws-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.dash-sec-weather .wx-sum { font-size: 12px; line-height: 1.4; color: var(--t1); }

/* Maps tab: a left selector toggle (filling the space freed by right-aligning the
   map) switches between Current Weather (NWS radar loop) and Temperature Anomaly
   (DTN, credential-gated placeholder). The map is height-capped + aspect-preserved
   so it never clips, and right-aligned within its column. */
.wx-maps { display: flex; flex: 1 1 auto; min-height: 0; align-items: stretch; gap: 12px; padding: 2px 0 4px; }
.wx-map-nav { flex: 0 0 auto; min-width: 128px; display: flex; flex-direction: column; gap: 6px; }
.wx-map-btn { text-align: left; font-size: 12px; font-weight: 600; line-height: 1.3; padding: 8px 10px; border: 0; border-radius: 7px; background: transparent; color: var(--t1); cursor: pointer; transition: background .12s, color .12s; }
.wx-map-btn:hover { color: var(--t0); }
.wx-map-btn.active { background: var(--bg3); color: var(--t0); }
.wx-divider { flex: 0 0 1px; align-self: stretch; background: var(--bdr); }
.wx-map-view { flex: 1 1 auto; min-width: 0; min-height: 0; display: flex; align-items: stretch; gap: 9px; overflow: hidden; }
.wx-map-view img { flex: 1 1 0; min-width: 0; height: 100%; object-fit: contain; cursor: zoom-in; }
.wx-map-ph { margin: auto; padding: 22px 14px; font-size: 12px; line-height: 1.5; text-align: center; color: var(--t2); border: 1px dashed var(--bdr); border-radius: 7px; }
.wx-map-soon { color: var(--t2); }
/* Day-range indicator — 3 dots in a fixed column at the map's left (the image
   already labels "Days N-N"). The lit dot tracks the cycle; hover one to hold it. */
.wx-dots { flex: 0 0 auto; display: flex; flex-direction: column; justify-content: center; gap: 9px; }
.wx-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--bdr2); cursor: pointer; transition: background .2s, box-shadow .2s, transform .15s; }
.wx-dot:hover { transform: scale(1.3); }
.wx-dot.active { background: var(--acc); box-shadow: 0 0 6px 1px rgba(74, 158, 255, .6); }

/* Current/Previous radios, nested under the left "Temperature Anomaly". */
.wx-sub { display: flex; flex-direction: column; gap: 4px; margin: 2px 0 2px 11px; padding-left: 9px; border-left: 1px solid var(--bdr); }
.wx-sub-btn { display: flex; align-items: center; gap: 7px; text-align: left; font-size: 11px; font-weight: 500; padding: 4px 6px; border: 0; border-radius: 6px; background: transparent; color: var(--t2); cursor: pointer; transition: color .12s; }
.wx-sub-btn:hover { color: var(--t1); }
.wx-sub-btn.active { color: var(--t0); }
.wx-sub-btn::before { content: ""; width: 13px; height: 13px; flex-shrink: 0; border-radius: 50%; border: 1.5px solid var(--bdr2); transition: border-color .12s, background .12s; }
.wx-sub-btn.active::before { border-color: var(--acc); background: var(--acc); }

/* ── /weather detail page — curated DTN Frontier forecast ──────────── */
/* The SPA shell locks body/#spa-slot to the viewport, so the page frame stays
   fixed. The grid fills the wrap and each column scrolls on its own — so the
   discussion title stays put while its content scrolls underneath it. */

/* Paper reading surface — mirrors the Articles page (.art-paper) so the weather
   page shares the same editorial palette: a bright white sheet in light mode and
   a dark "paper" in dark mode, framed by the app's navbar + rail. Keep these
   values in sync with .art-paper in pages/articles.css. */
.wxp-paper {
  --paper: #15171e;
  --ink:   #e9ecf3;
  --ink2:  #a7afc4;
  --ink3:  #717a93;
  --rule:  #2a2f3c;
  --rule2: #3a4154;
  --rule-strong: #e9ecf3;
  --kicker: #e89379;
  --surface: #1d212b;
  --font-display:  'Playfair Display', Georgia, 'Times New Roman', serif;
  --font-headline: 'Source Serif 4', Georgia, 'Times New Roman', serif;

  flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden;
  background: var(--paper);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}
body.light .wxp-paper {
  --paper: #ffffff;
  --ink:   #1a1a1a;
  --ink2:  #5b5b5b;
  --ink3:  #8a8a8a;
  --rule:  #e3e3e3;
  --rule2: #cfcfcf;
  --rule-strong: #1a1a1a;
  --kicker: #b52c1c;   /* redder than the article's brick — runs hotter on white */
  --surface: #f4f5f6;
}
.wxp-wrap { max-width: 1600px; margin: 0 auto; padding: 70px 24px 44px;
            flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
.wxp-head { margin-bottom: 22px; }
.wxp-title { margin: 0; font-size: 30px; font-weight: 800; letter-spacing: -.02em; color: var(--t0); }
.wxp-sub { margin: 6px 0 0; font-size: 14px; color: var(--t2); }
.wxp-grid { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 28px;
            flex: 1; min-height: 0; align-items: stretch; }
.wxp-col { min-width: 0; min-height: 0; }
/* Both columns: a fixed section title up top + a flex:1 area that scrolls under it
   (.wxp-scroll holds the maps + table; .wxp-disc is the discussion card). */
.wxp-maps-col, .wxp-disc-col { display: flex; flex-direction: column; }
/* Extra breathing room between the maps and the discussion. The centre gap is
   widened from both sides with padding inside each grid track (box-sizing
   border-box): the maps content gives up 15px on its right, the discussion 20px on
   its left. The grid tracks are unchanged — only the gap between the content grows. */
.wxp-maps-col { padding-right: 15px; }
.wxp-disc-col { padding-left: 20px; }
/* Scrolls, but the scrollbar is hidden (same as the discussion column). */
.wxp-scroll { flex: 1; min-height: 0; overflow-y: auto;
              scrollbar-width: none; -ms-overflow-style: none; }
.wxp-scroll::-webkit-scrollbar { width: 0; height: 0; display: none; }
.wxp-h { margin: 0 0 13px; font-size: 13px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase; color: var(--t2); }
.wxp-h:not(:first-child) { margin-top: 28px; }
.wxp-maps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.wxp-map { margin: 0; }
.wxp-map img { display: block; width: 100%; height: auto; border-radius: 8px; border: 1px solid var(--bdr); background: #fff; }
.wxp-map figcaption { margin-top: 5px; font-size: 11px; text-align: center; color: var(--t2); }
.wxp-table { overflow-x: auto; }
.wxp-table table { width: 100%; border-collapse: collapse; font-size: 12px; }
.wxp-table td { padding: 5px 8px; border: 1px solid var(--bdr); color: var(--t1); white-space: nowrap; text-align: center; }
.wxp-table tr:first-child td { font-weight: 700; color: var(--t0); background: var(--bg3); }
/* Section-label style — a 1px rule across the top, then a small, tracked, all-caps
   heading. Small, but the strong colour + letter-spacing + the rule above read as
   "this is a section title". Used as-is by the discussion column; the maps column
   overrides it into a big title-case display heading (below). */
.wxp-sec-title { display: block; flex: 0 0 auto;
                 margin: 0 0 14px; padding-top: 11px;
                 border-top: 1px solid var(--rule-strong);
                 font-family: var(--font-sans); font-size: 16px; font-weight: 700;
                 letter-spacing: .08em; text-transform: uppercase; color: var(--kicker); }
/* Maps column heading — the big title-case display heading. Direct child only, so
   the map sub-section labels inside the scroll keep the small red-label style. */
.wxp-maps-col > .wxp-sec-title { border-top: none; padding-top: 0; font-size: 36px;
                                 letter-spacing: -.01em; text-transform: none; color: var(--ink); }
/* Forecaster discussion — an editorial reading column on the paper surface,
   styled to match the Articles page: Playfair display titles, Source Serif body,
   the paper ink palette, and hairline rules between entries (no card). */
/* Scrolls, but the scrollbar is hidden — it left a grey track beside the reading
   column. (Firefox: scrollbar-width; Chromium/Edge/Safari: ::-webkit-scrollbar.) */
.wxp-disc { flex: 1; min-height: 0; overflow-y: auto; padding: 2px 6px 0 2px;
            scrollbar-width: none; -ms-overflow-style: none; }
.wxp-disc::-webkit-scrollbar { width: 0; height: 0; display: none; }
.wxp-note { padding: 20px 0; border-top: 1px solid var(--rule); }
.wxp-note:first-child { border-top: none; padding-top: 4px; }
.wxp-note-title { margin: 0; font-family: var(--font-display); font-weight: 700;
                  font-size: 19px; line-height: 1.25; letter-spacing: .005em; color: var(--ink); }
.wxp-note-time  { margin: 6px 0 11px; font-family: var(--font-sans); font-size: 11px;
                  letter-spacing: .02em; color: var(--ink3); }
.wxp-note-body  { margin: 0; font-family: var(--font-headline); font-size: 15px;
                  line-height: 1.7; color: var(--ink); }
.wxp-empty { padding: 48px 20px; text-align: center; font-family: var(--font-sans);
             font-size: 14px; color: var(--ink3); }

/* ── Weather maps widget (dashboard-style: left rail + right map panel) ───────────
   Categories (Current · Next 15 Days · Monthly) on the left; the selected one's
   maps on the right with a Play/Grid toggle and dot pagination. Mirrors the
   dashboard .wx-* widget, paper-themed. Built by static/js/weather/maps.js. */
.wxm-area { margin-top: 4px; }
.wxm-wx { display: flex; align-items: flex-start; gap: 16px; }

/* Left rail — category list + nested sub-group radios. */
.wxm-rail { flex: 0 0 auto; width: 166px; display: flex; flex-direction: column; gap: 3px; }
.wxm-cat { text-align: left; font-family: var(--font-sans); font-size: 13px; font-weight: 600;
           line-height: 1.3; padding: 9px 11px; border: 0; border-radius: 8px; background: transparent;
           color: var(--ink2); cursor: pointer; transition: background .12s, color .12s; }
.wxm-cat:hover { color: var(--ink); }
.wxm-cat.on { background: var(--surface); color: var(--ink); }
.wxm-sub { display: flex; flex-direction: column; gap: 2px; margin: 1px 0 6px 12px;
           padding-left: 11px; border-left: 1px solid var(--rule); }
.wxm-radio { display: flex; align-items: center; gap: 8px; text-align: left; font-family: var(--font-sans);
             font-size: 12px; font-weight: 500; padding: 5px 6px; border: 0; border-radius: 6px;
             background: transparent; color: var(--ink3); cursor: pointer; transition: color .12s; }
.wxm-radio:hover { color: var(--ink2); }
.wxm-radio.on { color: var(--ink); }
.wxm-radio::before { content: ""; width: 13px; height: 13px; flex-shrink: 0; border-radius: 50%;
                     border: 1.5px solid var(--rule2); transition: border-color .12s, background .12s; }
.wxm-radio.on::before { border-color: var(--kicker); background: var(--kicker);
                        box-shadow: inset 0 0 0 2px var(--paper); }

.wxm-divider { flex: 0 0 1px; align-self: stretch; background: var(--rule); }

/* Right panel — toolbar (Play/Grid, top-right) + the map view. */
.wxm-panel { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.wxm-panel-bar { display: flex; justify-content: flex-end; min-height: 28px; margin-bottom: 10px; }
.wxm-seg { display: inline-flex; border: 1px solid var(--rule2); border-radius: 7px; overflow: hidden; }
.wxm-seg button { display: inline-flex; align-items: center; gap: 5px; font-family: var(--font-sans);
                  font-size: 12px; font-weight: 600; color: var(--ink3); background: transparent;
                  border: none; padding: 5px 12px; cursor: pointer; transition: background .12s, color .12s; }
.wxm-seg button + button { border-left: 1px solid var(--rule2); }
.wxm-seg button:hover { color: var(--ink); }
.wxm-seg button.on { background: var(--ink); color: var(--paper); }
.wxm-seg svg { width: 13px; height: 13px; }

/* Map image — shared by the radar view and the play frame. */
.wxm-map-img { display: block; width: 100%; height: auto; border: 1px solid var(--rule);
               border-radius: 10px; background: #fff; cursor: zoom-in; }
.wxm-view-radar { position: relative; }
.wxm-view-radar .wxm-live { position: absolute; left: 10px; top: 10px; }
.wxm-live { display: inline-flex; align-items: center; gap: 5px; background: rgba(8, 11, 18, .6);
            color: #fff; font-family: var(--font-sans); font-size: 10px; font-weight: 600;
            letter-spacing: .06em; text-transform: uppercase; padding: 3px 8px; border-radius: 6px; }
.wxm-live-dot { width: 6px; height: 6px; border-radius: 50%; background: #ff5e5e; }

/* Play view — one frame + caption + dot pagination (one lit dot per image). */
.wxm-frame { margin: 0; }
.wxm-frame-cap { margin: 8px 0 0; text-align: center; font-family: var(--font-sans);
                 font-size: 12px; color: var(--ink2); }
.wxm-dots { display: flex; justify-content: center; flex-wrap: wrap; gap: 9px; margin-top: 13px; }
.wxm-dot { width: 9px; height: 9px; padding: 0; border: 0; border-radius: 50%; background: var(--rule2);
           cursor: pointer; transition: background .2s, box-shadow .2s, transform .15s; }
.wxm-dot:hover { transform: scale(1.3); }
.wxm-dot.on { background: var(--kicker); box-shadow: 0 0 6px 1px rgba(181, 44, 28, .5); }

/* Grid view — thumbnails (click to enlarge). */
.wxm-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.wxm-cell { margin: 0; min-width: 0; }
.wxm-cell img { display: block; width: 100%; height: auto; border: 1px solid var(--rule);
                border-radius: 8px; background: #fff; cursor: zoom-in; }
.wxm-cell img:hover { border-color: var(--ink3); }
.wxm-cell figcaption { margin-top: 5px; font-family: var(--font-sans); font-size: 11px;
                       text-align: center; color: var(--ink3); }

@media (max-width: 900px) {
  .wxm-wx { flex-direction: column; }
  .wxm-divider { display: none; }
  .wxm-rail { width: auto; flex-direction: row; flex-wrap: wrap; align-items: center; }
  .wxm-sub { flex-direction: row; margin: 0; padding-left: 0; border-left: 0; }
  .wxm-grid { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); }
}

/* Map lightbox — a clicked forecast map opens in an in-page popup (not a new tab).
   Backdrop fades in; click anywhere / × / Esc closes. */
.wxp-map a { display: block; cursor: zoom-in; }
.wxp-lightbox { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center;
                justify-content: center; padding: 5vh 5vw; background: rgba(8, 11, 18, .8);
                opacity: 0; visibility: hidden; pointer-events: none; cursor: zoom-out;
                transition: opacity .18s ease, visibility .18s ease; }
.wxp-lightbox.show { opacity: 1; visibility: visible; pointer-events: auto; }
.wxp-lb-fig { margin: 0; display: flex; flex-direction: column; align-items: center; gap: 11px;
              transform: scale(.97); transition: transform .18s ease; }
.wxp-lightbox.show .wxp-lb-fig { transform: scale(1); }
.wxp-lb-fig img { display: block; max-width: 100%; max-height: 86vh; border-radius: 8px;
                  background: #fff; box-shadow: 0 18px 54px rgba(0,0,0,.55); }
.wxp-lb-fig figcaption { font-size: 13px; color: rgba(255,255,255,.85); letter-spacing: .01em; }
.wxp-lb-close { position: fixed; top: 16px; right: 20px; width: 40px; height: 40px; border: 0;
                border-radius: 50%; background: rgba(255,255,255,.13); color: #fff; font-size: 25px;
                line-height: 1; cursor: pointer; transition: background .14s ease; }
.wxp-lb-close:hover { background: rgba(255,255,255,.26); }

@media (max-width: 900px) {
  .wxp-wrap { overflow-y: auto; }
  .wxp-grid { grid-template-columns: 1fr; flex: 0 0 auto; }
  .wxp-scroll,
  .wxp-disc { overflow: visible; flex: 0 0 auto; }
  .wxp-maps-col { padding-right: 0; }  /* stacked — no inter-column gap needed */
  .wxp-disc-col { padding-left: 0; }
}

/* Map & Assessments: the section body is the positioned, rounded map container
   that the legend + Assessments panel float over (rules below). Like the
   Prices/Articles cards on the left, it's lifted off the canvas with a soft
   shadow (the SAME elevation tokens as those cards) rather than a heavier
   border — so all three panels read as one "floating surface" language and the
   map stops blending into the light-mode grey canvas. */
.dash-sec-map .dash-sec-body {
  position:      relative;
  border-radius: 12px;
  overflow:      hidden;
  border:        1px solid var(--bdr);
  box-shadow:    0 4px 14px rgba(0,0,0,.22);
}
/* Dark mode: shadows die on the near-black canvas, so separation comes mostly
   from the slightly thicker (1.5px) border. Its colour sits at the card-border
   tone (--bdr) so the map doesn't out-shout the side cards — with just a hint
   of a lit top edge (--bdr2) for a touch of depth. */
body:not(.light) .dash-sec-map .dash-sec-body {
  border-width:     1.5px;
  border-color:     var(--bdr);
  border-top-color: var(--bdr2);
}
body.light .dash-sec-map .dash-sec-body {
  /* A hairline you feel more than see: sides + bottom a hair darker than the
     grey canvas give a just-perceptible edge, while the top stays lighter than
     the canvas so it reads as catching light (luminate) rather than being boxed
     in. Paired with the soft shadow below, the panel reads lit-from-above. */
  border-color:     #e2e7ef;
  border-top-color: #f7f9fc;
  box-shadow:       0 1px 2px rgba(16,24,40,.04), 0 6px 16px rgba(16,24,40,.07);
}

/* Narrow viewports — stack the two columns; give the map a fixed slice.
   (Mobile polish is a later pass; this just keeps the page usable.) */
@media (max-width: 900px) {
  /* Hide the vertical scrollbar's gutter — it only eats the RIGHT side, which
     nudges the whole page slightly left of center. Hiding it (scroll still works
     by touch/wheel) lets the content fill to both edges evenly. Same pattern the
     tab strips already use. */
  .home-wrap   { overflow-y: auto; scrollbar-width: none; -ms-overflow-style: none; }
  .home-wrap::-webkit-scrollbar { display: none; }
  .dash-layout { flex-direction: column; }
  .dash-col-left,
  .dash-col-right    { flex: 0 0 auto; }
  .dash-sec-articles { flex: 0 0 auto; }
  .dash-sec-articles .nws-list { max-height: 320px; }
  .dash-sec-map      { flex: 0 0 auto; }
  .dash-sec-map .dash-sec-body { height: 70vh; }

  /* The EN/KR toggle now lives on the section title row (outside the card), so
     the category tabs get the full card width — just tighten their gap a touch
     to fit more per line on a phone. */
  .nws-tabs { column-gap: 12px; }
}

/* ── Market panel (Investing-style real-time prices) ───────────── */
.mkt-live {
  display:        inline-flex;
  align-items:    center;
  gap:            5px;
  font-family:    var(--font-mono);
  font-size:      8px;
  letter-spacing: .1em;
  color:          var(--ok);
}
.mkt-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--ok);
  animation: mktpulse 2.2s infinite;
}
@keyframes mktpulse {
  0%   { box-shadow: 0 0 0 0   rgba(61,214,140,.5); }
  70%  { box-shadow: 0 0 0 6px rgba(61,214,140,0);  }
  100% { box-shadow: 0 0 0 0   rgba(61,214,140,0);  }
}

/* category tabs (Gas / Oil) + mock flag on the right */
.mkt-cats {
  display:       flex;
  align-items:   center;
  gap:           16px;
  border-bottom: 1px solid var(--bdr);
  margin:        0 0 12px;
}
.mkt-cat {
  font-size:     14px;
  font-weight:   600;
  color:         var(--t2);
  padding-bottom: 9px;
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  cursor:        pointer;
  transition:    color .12s;
}
.mkt-cat:hover  { color: var(--t1); }
.mkt-cat.active { color: var(--acc); border-bottom-color: var(--acc); }
.mkt-mock {
  display:        inline-flex;
  align-items:    center;
  gap:            5px;
  margin-left:    auto;
  padding-bottom: 9px;
  font-family:    var(--font-mono);
  font-size:      8px;
  letter-spacing: .1em;
  color:          var(--t2);
}
/* source credit — bottom-right corner of the card, muted gray (no purple link) */
.mkt-credit {
  margin-top:     8px;
  text-align:     right;
  font-family:    var(--font-mono);
  font-size:      9px;
  letter-spacing: .04em;
  color:          var(--t2);
}
.mkt-credit a       { color: var(--t2); text-decoration: none; }
.mkt-credit a:hover { color: var(--t1); text-decoration: underline; }
/* chart hover — crosshair + price/date tooltip */
.mkt-cross          { stroke: var(--t2); stroke-width: 1; opacity: .5; }
.mkt-cross-dot.up   { fill: var(--ok); }
.mkt-cross-dot.down { fill: var(--err); }
.mkt-tip {
  position: fixed; z-index: 60; pointer-events: none;
  transform: translate(-50%, -100%);
  padding: 3px 8px; border-radius: 6px;
  background: var(--bg1); border: 1px solid var(--bdr2);
  box-shadow: 0 2px 10px rgba(0, 0, 0, .14);
  font-size: 11px; white-space: nowrap;
  opacity: 0; transition: opacity .08s;
}
.mkt-tip.show { opacity: 1; }
.mkt-tip-v    { font-family: var(--font-mono); font-weight: 500; color: var(--t0); }
.mkt-tip-d    { color: var(--t2); margin-left: 6px; }

/* Left/right split — graph (left) + price list (right). Uses the card's width
   instead of stacking tall, so the Prices card stays short. */
.mkt-split { display: flex; gap: 14px; align-items: stretch; }
.mkt-left  { flex: 0.8 1 0; min-width: 0; display: flex; flex-direction: column; }
/* fixed min-height (sized for the longest list — 5 gas hubs) so the card
   doesn't grow/shrink when switching Gas/Oil; shorter lists leave whitespace. */
.mkt-split .mkt-rows { flex: 1.1 1 0; min-width: 0; min-height: 152px; }
.mkt-left .mkt-chart { flex: 1 1 auto; height: auto; min-height: 64px; margin-bottom: 0; }
/* selected readout stacks (name over price+change) to fit the narrow left */
.mkt-left .mkt-sel       { flex-wrap: wrap; gap: 1px 7px; }
.mkt-left .mkt-sel-name  { flex: 1 0 100%; }
.mkt-left .mkt-sel-price { margin-left: 0; }

/* selected-instrument header + big price */
.mkt-sel { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; }
.mkt-sel-name  { font-size: 14px; font-weight: 600; color: var(--t0); }
.mkt-sel-price { font-family: var(--font-mono); font-size: 23px; font-weight: 600; color: var(--t0); margin-left: auto; }
.mkt-sel-chg   { font-family: var(--font-mono); font-size: 12px; font-weight: 600; }

/* timeframe tabs */
.mkt-tfs { display: flex; gap: 5px; margin-bottom: 8px; }
.mkt-tf {
  font-family:   var(--font-mono);
  font-size:     10px;
  color:         var(--t2);
  padding:       2px 9px;
  border-radius: 6px;
  cursor:        pointer;
  transition:    all .12s;
}
.mkt-tf:hover  { background: var(--bg2); color: var(--t1); }
.mkt-tf.active { background: var(--bg3); color: var(--t0); }

/* chart */
.mkt-chart { width: 100%; height: 80px; display: block; margin-bottom: 8px; }
.mkt-line  { fill: none; stroke-width: 1.6; vector-effect: non-scaling-stroke; }
.mkt-fill  { stroke: none; fill-opacity: .10; }
.up   { color: var(--ok);  }
.down { color: var(--err); }
.mkt-line.up   { stroke: var(--ok);  }
.mkt-line.down { stroke: var(--err); }
.mkt-fill.up   { fill: var(--ok);  }
.mkt-fill.down { fill: var(--err); }
.mkt-sel-chg.up   { color: var(--ok);  }
.mkt-sel-chg.down { color: var(--err); }

/* price rows — compact single line: name | price | Δ | Δ% | clock */
.mkt-rows { display: flex; flex-direction: column; }
.mkt-row {
  display:               grid;
  grid-template-columns: minmax(0,1fr) auto 56px 60px;
  align-items:           center;
  gap:                   8px;
  padding:               6px 7px;
  border-top:            1px solid var(--bdr);
  border-radius:         5px;
  cursor:                pointer;
  transition:            background .12s;
}
.mkt-row:first-child { border-top: none; }
.mkt-row:hover,
.mkt-row.active { background: var(--bg2); }
.mkt-r-name {
  font-size:     13px;
  color:         var(--t0);
  font-weight:   500;
  white-space:   nowrap;
  overflow:      hidden;
  text-overflow: ellipsis;
}
.mkt-r-price { font-family: var(--font-mono); font-size: 13.5px; color: var(--t0); text-align: right; }
.mkt-r-abs   { font-family: var(--font-mono); font-size: 12px;   text-align: right; }
.mkt-r-pct   { font-family: var(--font-mono); font-size: 12px;   text-align: right; }
.mkt-r-abs.up,  .mkt-r-pct.up   { color: var(--ok);  }
.mkt-r-abs.down,.mkt-r-pct.down { color: var(--err); }
.mkt-r-clk   { display: flex; align-items: center; justify-content: center; }
.mkt-clk     { color: var(--t2); opacity: .5; }
/* small muted delay label next to EOD index names (e.g. "(1-day delay)") */
.mkt-r-dly   { margin-left: 5px; font-size: 10px; font-weight: 400; color: var(--t2); }

/* The prices card is its own query container, so rows adapt to the card's
   actual width (works for both 1-up and 2-up mobile layouts). When the card
   gets narrow, drop the Δ% column so the row never overflows / pushes wider. */
.mkt-rows { container-type: inline-size; }
@container (max-width: 230px) {
  .mkt-row   { grid-template-columns: minmax(0, 1fr) auto 56px; }
  .mkt-r-pct { display: none; }
}

/* ── Compact Prices (short viewports) ──────────────────────────────
   The Prices controller adds .is-compact to .dash-sec-prices when the column is too
   short to keep Articles as tall as the full Prices card: the title + Gas/Oil tabs
   hide and the split collapses to a fixed strip of fancy mini quote tiles (HH/HSC/
   WTI/Brent), freeing height for Articles. */
.dash-sec-prices.is-compact > .dash-sec-title { display: none; }
.dash-sec-prices.is-compact .mkt-split { display: none; }
.dash-sec-prices.is-compact .mkt-cats  { display: none; }
.dash-sec-prices.is-compact .mkt-credit { display: none; }
.mkt-mini { display: none; }
.dash-sec-prices.is-compact .mkt-mini { display: flex; gap: 10px; }
/* dissolve the panel chrome so the tiles float on the canvas (reference look) rather
   than sitting inside a white card */
.dash-sec-prices.is-compact .exec-panel { background: transparent; border: 0; box-shadow: none; padding: 0; }
/* mini quote tile — elevated card: name, price, coloured %+arrow, gradient sparkline */
.mkt-m { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 2px;
         padding: 10px 11px 9px; border-radius: 12px; cursor: pointer; background: var(--bg2);
         transition: transform .12s ease, box-shadow .12s ease; }
body.light .mkt-m { background: #fff;
                    box-shadow: 0 1px 2px rgba(16,24,40,.05), 0 5px 14px rgba(16,24,40,.08); }
body:not(.light) .mkt-m { box-shadow: 0 2px 10px rgba(0,0,0,.28); border: 1px solid var(--bdr); }
.mkt-m:hover { transform: translateY(-1px); }
body.light .mkt-m:hover { box-shadow: 0 2px 4px rgba(16,24,40,.07), 0 9px 22px rgba(16,24,40,.12); }
.mkt-m-name  { font-size: 13px; font-weight: 700; letter-spacing: -.01em; color: var(--t0);
               white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mkt-m-price { font-family: var(--font-mono); font-size: 12px; color: var(--t2); }
.mkt-m-chg   { display: flex; align-items: center; gap: 5px; margin-top: 1px; }
.mkt-m-pct   { font-family: var(--font-mono); font-size: 11.5px; font-weight: 600; }
.mkt-m.up   .mkt-m-pct { color: var(--ok);  }
.mkt-m.down .mkt-m-pct { color: var(--err); }
.mkt-m-arr  { width: 15px; height: 15px; border-radius: 50%; display: inline-flex;
              align-items: center; justify-content: center; font-size: 8px; line-height: 1; color: #fff; }
.mkt-m.up   .mkt-m-arr { background: var(--ok);  }
.mkt-m.down .mkt-m-arr { background: var(--err); }
.mkt-m-chart { width: 100%; height: 30px; display: block; margin-top: 4px; }
.mkt-m.up   .mkt-m-chart { color: var(--ok);  }
.mkt-m.down .mkt-m-chart { color: var(--err); }

/* ── News panel (title-only · category tabs) ───────────────────── */
.nws-bar {
  display:       flex;
  align-items:   flex-end;
  gap:           10px;
  margin-bottom: 10px;
  flex-shrink:   0;
}
.nws-tabs {
  display:       flex;
  flex-wrap:     wrap;             /* category tabs — wrap instead of clipping */
  gap:           4px 13px;
  flex:          1 1 auto;
  min-width:     0;
  border-bottom: 1px solid var(--bdr);
}
/* EN / 한 title-language toggle — sits at the right of the tab bar */
.nws-lang {
  flex-shrink:   0;
  display:       flex;
  gap:           3px;
  margin-bottom: 7px;
}
.nws-lang button {
  font-family:   var(--font-mono);
  font-size:     10px;
  font-weight:   600;
  padding:       2px 8px;
  border:        1px solid var(--bdr);
  border-radius: 5px;
  background:    transparent;
  color:         var(--t2);
  cursor:        pointer;
  transition:    background .12s, color .12s, border-color .12s;
}
.nws-lang button:hover  { color: var(--t0); border-color: var(--bdr2); }
/* Outside the card now → a high-contrast filled state reads cleaner than the
   blue accent. --t0 is black in light mode, near-white in dark, so it stays
   visible on the page background in both themes. */
.nws-lang button.active { background: var(--t0); border-color: var(--t0); color: var(--bg1); }
.nws-tab {
  font-size:      14px;
  font-weight:    600;
  color:          var(--t2);
  padding-bottom: 9px;
  margin-bottom:  -1px;
  border-bottom:  2px solid transparent;
  cursor:         pointer;
  transition:     color .12s;
  white-space:    nowrap;
  flex-shrink:    0;
}
.nws-tab:hover  { color: var(--t1); }
.nws-tab.active { color: var(--acc); border-bottom-color: var(--acc); }

.nws-list { display: flex; flex-direction: column; }
/* simple 2-row item: title (row 1) over source + date (row 2) */
.nws-item {
  display:        flex;
  flex-direction: column;
  gap:            3px;
  padding:        9px 4px;
  border-top:     1px solid var(--bdr);
  cursor:         pointer;
}
.nws-item:first-child { border-top: none; }
.nws-headline {
  font-family:   var(--font-sans);
  font-size:     13.5px;
  font-weight:   600;
  line-height:   1.35;
  color:         var(--t0);
  white-space:   nowrap;          /* older items: one line + ellipsis */
  overflow:      hidden;
  text-overflow: ellipsis;
}
.nws-item:hover .nws-headline { color: var(--acc); }
.nws-meta {
  font-family: var(--font-mono);
  font-size:   10px;
  color:       var(--t2);
}
.nws-empty {
  padding:   16px 4px;
  font-size: 12px;
  color:     var(--t2);
}
/* Featured items (last 2 days): thumbnail + larger card to draw attention. */
.nws-feat {
  display:     flex;
  gap:         11px;
  align-items: flex-start;
  padding:     11px 4px;
  border-top:  1px solid var(--bdr);
  cursor:      pointer;
}
.nws-feat:first-child { border-top: none; }
.nws-feat-thumb {
  flex:          0 0 auto;
  width:         96px;
  height:        70px;
  border-radius: 7px;
  object-fit:    cover;
  background:    var(--bg3);
}
.nws-feat-body { flex: 1 1 auto; min-width: 0; }
.nws-feat-title {
  font-family:        var(--font-sans);
  font-size:          15px;
  font-weight:        600;
  line-height:        1.32;
  color:              var(--t0);
  display:            -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow:           hidden;
  margin-bottom:      4px;
}
.nws-feat:hover .nws-feat-title { color: var(--acc); }

/* ── Article hover summary popover (sheet F:H Korean / I:K English) ── */
/* Passive tooltip (pointer-events:none) appended to <body>, positioned to the
   side of the hovered article; closes on mouse-out. Squareish, not a wide bar. */
.nws-pop {
  position:       fixed;
  z-index:        2000;
  width:          363px;
  max-width:      calc(100vw - 24px);
  background:     var(--bg1);
  border:         1px solid var(--bdr);
  border-radius:  12px;
  box-shadow:     0 14px 38px rgba(0, 0, 0, .28);
  padding:        15px 17px;
  opacity:        0;
  transform:      translateX(-6px);
  pointer-events: none;
  transition:     opacity .15s ease, transform .15s ease;
}
.nws-pop.show { opacity: 1; transform: none; pointer-events: auto; }
.nws-pop-top {
  display:         flex;
  align-items:     center;
  justify-content: space-between;
  gap:             10px;
  padding-bottom:  9px;
  margin-bottom:   10px;
  border-bottom:   1px solid var(--bdr);
}
.nws-pop-h {
  font-size:      12px;
  font-weight:    700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color:          var(--acc);
}
.nws-pop-actions { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.nws-pop-copy,
.nws-pop-link {
  font-family:   var(--font-sans);
  color:         var(--t1);
  background:    var(--bg3);
  border:        1px solid var(--bdr);
  border-radius: 6px;
  cursor:        pointer;
  transition:    all .12s;
}
.nws-pop-copy { font-size: 11px; font-weight: 600; padding: 3px 9px; }
.nws-pop-link {
  display:         inline-flex;
  align-items:     center;
  justify-content: center;
  width:           26px;
  height:          22px;
  padding:         0;
}
.nws-pop-link svg { width: 14px; height: 14px; display: block; }
.nws-pop-copy:hover,
.nws-pop-link:hover { color: var(--t0); border-color: var(--bdr2); }
.nws-pop-copy.ok,
.nws-pop-link.ok    { color: var(--ok); border-color: var(--ok); }
/* Explicit close — only on touch/no-hover, where there's no mouse-out to dismiss. */
.nws-pop-close {
  display:         none;
  align-items:     center;
  justify-content: center;
  width:           24px;
  height:          22px;
  padding:         0;
  font-family:     var(--font-sans);
  color:           var(--t1);
  background:      var(--bg3);
  border:          1px solid var(--bdr);
  border-radius:   6px;
  cursor:          pointer;
  transition:      all .12s;
}
.nws-pop-close svg   { width: 14px; height: 14px; display: block; }
.nws-pop-close:hover { color: var(--t0); border-color: var(--bdr2); }
@media (hover: none) { .nws-pop-close { display: inline-flex; } }
.nws-pop-list {
  list-style:     none;
  margin:         0;
  padding:        0;
  display:        flex;
  flex-direction: column;
  gap:            9px;
}
.nws-pop-list li {
  position:     relative;
  padding-left: 18px;
  font-size:    14px;
  line-height:  1.55;
  color:        var(--t0);
}
.nws-pop-list li::before {
  content:     '›';
  position:    absolute;
  left:        3px;
  top:         -1px;
  color:       var(--acc);
  font-weight: 700;
}

/* ── US pipeline map (Leaflet + layer legend) ──────────────────── */
/* Full-bleed: no bezel, fills the main column top-to-bottom. */
.dash-map-wrap { position: absolute; inset: 0; overflow: hidden; }
.dash-map { position: absolute; inset: 0; background: var(--bg2); }
/* Dark Carto basemap (dark_all) is dim + low-contrast beside the near-black
   canvas, so the map reads as sunken/blurry. Lift the BASE tiles only (the
   .dash-base layer — pipelines + facilities are separate panes, untouched) a
   touch in dark mode. Light mode keeps the bright light_all tiles as-is. */
body:not(.light) .dash-map .dash-base { filter: brightness(1.12) contrast(1.05); }

/* Leaflet control restyle to match theme */
.dash-map .leaflet-control-zoom a {
  background:   var(--bg2);
  border-color: var(--bdr2);
  color:        var(--t0);
}
.dash-map .leaflet-control-zoom a:hover { background: var(--bg3); }

/* Search sits at the top-left of the map; the legend collapses below it. */
.dash-map .map-search-wrap { left: 14px; top: 14px; }

/* Layer toggle legend (overlay, top-LEFT corner). z-index sits above the
   Assessments panel (.dap = 800) so an opened legend is never hidden behind
   it on mobile, where both float over the map. */
.dml {
  position:      absolute;
  top:           60px;          /* sits below the search box */
  left:          14px;
  right:         auto;
  z-index:       850;
  width:         auto;          /* collapsed to the layers-icon toggle */
  background:    var(--bg1);
  border:        1px solid var(--bdr2);
  border-radius: 8px;
  padding:       4px;
  box-shadow:    0 6px 20px rgba(0,0,0,.25);
}
.dml-group + .dml-group { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--bdr); }
.dml-ghead {
  font-family:    var(--font-mono);
  font-size:      8.5px;
  font-weight:    600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color:          var(--t2);
  padding:        2px 10px 5px;
}
/* clickable group header = show/hide all children */
.dml-ghead-btn { cursor: pointer; border-radius: 4px; transition: color .1s, opacity .1s; }
.dml-ghead-btn:hover { color: var(--t1); }
.dml-ghead.dml-off { opacity: .5; }
.dml-item {
  display:       flex;
  align-items:   center;
  gap:           9px;
  padding:       5px 10px;
  border-radius: 5px;
  cursor:        pointer;
  transition:    background .1s, opacity .1s;
}
.dml-item:hover { background: var(--bg2); }
.dml-item.dml-off { opacity: .38; }
.dml-label { font-size: 11px; color: var(--t0); white-space: nowrap; }
.dml-line  { width: 16px; height: 3px; border-radius: 2px; flex-shrink: 0; }
/* facility icon slot — same 16px gutter as the pipeline line swatch */
.dml-ic    { width: 16px; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.dml-ic svg { display: block; }
.dml-interstate { background: var(--gp-interstate); }
.dml-intrastate { background: var(--gp-intrastate); }
.dml-gathering  { background: var(--gp-gathering); }

/* facility map markers (Leaflet divIcon) — strip default white box */
.dash-map .fac-icon { background: none; border: none; }

/* collapse-to-icon toggle — the legend is collapsed to this layers icon by
   default; hovering previews it, clicking (#dmlToggle) pins it open/closed. */
.dml-toggle {
  display:         flex;
  align-items:     center;
  justify-content: center;
  width:           34px;
  height:          34px;
  padding:         0;
  background:      none;
  border:          none;
  border-radius:   6px;
  color:           var(--t1);
  cursor:          pointer;
  transition:      background .12s, color .12s;
}
.dml-toggle:hover { background: var(--bg2); color: var(--t0); }
.dml.dml-open .dml-toggle { color: var(--acc); }

/* Collapsed by default → body hidden; hover-preview OR click-pinned expands. */
.dml-body { display: none; }
.dml:hover, .dml.dml-open { width: 196px; }
.dml:hover .dml-toggle,
.dml.dml-open .dml-toggle {
  width:           100%;
  justify-content: flex-start;
  padding:         0 8px;
  border-radius:   6px 6px 0 0;
}
.dml:hover .dml-body,
.dml.dml-open .dml-body {
  display:     block;
  margin-top:  4px;
  padding-top: 4px;
  border-top:  1px solid var(--bdr);
}

/* ── Mobile (≤900px): search spans the full width; the legend's collapse
   behaviour is now shared with desktop (rules above). ── */
@media (max-width: 900px) {
  .dash-map .map-search-wrap { left: 14px; right: 14px; top: 14px; width: auto; }
}

/* ── Right-click context menu + measure tool (same as Extractor) ─── */
.map-ctx-menu {
  position:      absolute;
  z-index:       9000;
  min-width:     185px;
  background:    var(--bg1);
  border:        1px solid var(--bdr);
  border-radius: 6px;
  box-shadow:    0 8px 24px rgba(0,0,0,.30);
  overflow:      hidden;
  font-family:   var(--font-sans);
  font-size:     12px;
}
.ctx-coord {
  padding:       8px 12px;
  color:         var(--t2);
  font-size:     11px;
  font-family:   var(--font-mono);
  letter-spacing: .3px;
  cursor:        pointer;
  border-bottom: 1px solid var(--bdr);
}
.ctx-coord:hover { background: var(--bg2); }
.ctx-sep  { border-top: 1px solid var(--bdr); }
.ctx-item { padding: 8px 12px; cursor: pointer; color: var(--t0); }
.ctx-item:hover    { background: var(--bg2); }
.ctx-item-clear    { color: var(--err); }

.measure-panel {
  position:      absolute;
  bottom:        14px;
  right:         14px;
  z-index:       9000;
  min-width:     155px;
  background:    var(--bg1);
  border:        1px solid var(--bdr);
  border-radius: 7px;
  box-shadow:    0 8px 24px rgba(0,0,0,.30);
  padding:       10px 13px;
  font-family:   var(--font-sans);
}
.mp-head {
  display:         flex;
  justify-content: space-between;
  align-items:     center;
  font-size:       11px;
  font-weight:     600;
  color:           var(--t1);
  margin-bottom:   6px;
}
.mp-close { background: none; border: none; cursor: pointer; color: var(--t2); font-size: 13px; padding: 0; line-height: 1; }
.mp-close:hover { color: var(--t0); }
.mp-dist { font-size: 18px; font-weight: 700; color: var(--acc); }
.mp-area { font-size: 12px; color: var(--t1); margin-top: 3px; }
.mp-hint { font-size: 10px; color: var(--t2); margin-top: 7px; }

.measure-tip {
  background:     rgba(74,158,255,.92) !important;
  color:         #fff !important;
  border:        none !important;
  border-radius: 4px !important;
  padding:       4px 8px !important;
  font-size:     11px !important;
  font-weight:   500 !important;
  box-shadow:    0 1px 5px rgba(0,0,0,.3) !important;
  white-space:   nowrap !important;
  pointer-events:none !important;
}
.measure-tip::before { display: none !important; }

/* ── Assessments panel (saved feasibility results) ─────────────────
   Desktop: floats on the RIGHT of the map, mirroring the layer legend
   on the left. Narrow (≤900px): floats over the BOTTOM of the map as a
   horizontal, left-right scrollable row of folder chips. */
.dap {
  position:       absolute;
  top:            14px;
  right:          14px;
  bottom:         14px;
  z-index:        800;            /* above Leaflet marker/tooltip/popup panes */
  width:          195px;
  display:        flex;
  flex-direction: column;
  background:     var(--bg1);
  border:         1px solid var(--bdr2);
  border-radius:  8px;
  box-shadow:     0 6px 20px rgba(0,0,0,.25);
  overflow:       hidden;
}
body.light .dap { box-shadow: 0 6px 20px rgba(16,24,40,.12); }

.dap-head {
  display:       flex;
  align-items:   center;
  gap:           8px;
  padding:       11px 13px;
  border-bottom: 1px solid var(--bdr);
  flex-shrink:   0;
  cursor:        pointer;        /* click to collapse / expand */
  user-select:   none;
}
/* collapse chevron (rotates when folded) + collapsed state (desktop only). */
.dap-chev {
  margin-left: 2px;
  color:       var(--t2);
  flex-shrink: 0;
  transition:  transform .18s ease, color .12s;
}
.dap-head:hover .dap-chev { color: var(--t0); }
@media (min-width: 901px) {
  .dap.dap-collapsed           { bottom: auto; height: auto; }
  .dap.dap-collapsed .dap-head { border-bottom: none; }
  .dap.dap-collapsed .dap-list { display: none; }
  .dap.dap-collapsed .dap-chev { transform: rotate(-90deg); }
}
.dap-ic    { display: inline-flex; color: var(--acc); }
.dap-title { font-size: 13px; font-weight: 600; color: var(--t0); }
.dap-count {
  margin-left:   auto;
  font-family:   var(--font-mono);
  font-size:     11px;
  color:         var(--t1);
  background:     var(--bg3);
  border-radius: 10px;
  padding:       1px 9px;
}

/* Desktop: folders as a single vertical column — folder icon with the name
   below each. Mobile turns this into a 2-row horizontal scroller (see @media). */
.dap-list {
  flex:           1;
  min-height:     0;
  overflow-y:     auto;
  display:        flex;
  flex-direction: column;
  gap:            8px;
  padding:        9px;
}
.dap-empty {
  margin:      auto;
  padding:     24px 16px;
  text-align:  center;
  font-size:   11.5px;
  line-height: 1.6;
  color:       var(--t2);
}

/* ── Assessment "project folder" row ──────────────────────────────
   Outline folder icon + project name on one line. Desktop = full-width rows
   stacked vertically; mobile = compact chips in a 2-row horizontal scroller
   (see the @media block below). */
.asmt-card {
  display:        flex;
  flex-direction: row;
  align-items:    center;
  gap:            8px;
  text-align:     left;
  cursor:         pointer;
  background:     var(--bg2);
  border:         1px solid var(--bdr);
  border-radius:  8px;
  padding:        9px 10px;
  font-family:    inherit;
  transition:     border-color .12s, background .12s, box-shadow .12s;
}
.asmt-card:hover { border-color: var(--bdr2); background: var(--bg3); }
.asmt-card.sel {
  border-color: var(--acc);
  box-shadow:   inset 0 0 0 1px var(--acc);
}

/* Left block: small folder icon with the project name centred below it.
   A single outline icon in one muted brand tone — no per-item / per-tier
   colour (it stops being meaningful once there are many assessments). */
.asmt-main {
  flex:           0 0 78px;
  min-width:      0;
  display:        flex;
  flex-direction: column;
  align-items:    center;
  gap:            5px;
  text-align:     center;
}
.asmt-folder {
  flex-shrink:     0;
  width:           26px;
  height:          26px;
  display:         flex;
  align-items:     center;
  justify-content: center;
  color:           var(--acc);
}
.asmt-folder svg { width: 22px; height: 22px; display: block; }
.asmt-name {
  max-width:          100%;
  font-size:          11.5px;
  font-weight:        600;
  line-height:        1.3;
  color:              var(--t0);
  display:            -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow:           hidden;
}

/* Right block: brief meta — when it was created + who wrote it. */
.asmt-meta {
  flex:           1;
  min-width:      0;
  display:        flex;
  flex-direction: column;
  gap:            3px;
  font-size:      10px;
  line-height:    1.35;
  color:          var(--t2);
}
.asmt-meta-date { font-family: var(--font-mono); color: var(--t1); }
.asmt-meta-by   { color: var(--t2); }

/* ── Map markers (Leaflet divIcon) — tier-coloured dot, teal ring when selected ── */
.dash-map .asmt-mk { background: none; border: none; }
.asmt-dot {
  display:       block;
  box-sizing:    border-box;
  width:         16px;
  height:        16px;
  border-radius: 50%;
  background:    var(--acc);
  border:        2px solid var(--bg0);
  box-shadow:    0 0 0 1px rgba(0,0,0,.45), 0 1px 4px rgba(0,0,0,.5);
}
body.light .asmt-dot { border-color: #fff; }
.asmt-mk-sel .asmt-dot {
  box-shadow: 0 0 0 3px rgba(0,212,170,.85), 0 0 0 7px rgba(0,212,170,.30);
}

/* ── Narrow / mobile: panel becomes a horizontal scroll row below the map ── */
@media (max-width: 900px) {
  /* Float the section over the BOTTOM of the map (not below it), inset 14px
     like the search box. Border / radius / shadow inherited from base .dap. */
  .dap {
    position: absolute;
    top:      auto;
    left:     14px;
    right:    14px;
    bottom:   14px;
    width:    auto;
    margin:   0;
  }
  /* Hide the "Assessments" title on mobile (desktop-only) — the panel sits
     right under the map, so a label is redundant here. */
  .dap-head { display: none; }

  /* Mobile: 2-row horizontal scroller — folder chips flow top→bottom, then
     into the next column, scrolling left↔right. */
  .dap-list {
    display:            grid;          /* override the desktop column */
    grid-auto-flow:     column;
    grid-template-rows: repeat(2, auto);
    grid-auto-columns:  max-content;
    overflow-x:           auto;
    overflow-y:           hidden;
    gap:                  8px 9px;
    padding:              10px 12px;
    scroll-snap-type:     x proximity;
    /* without this, snap aligns the first chip's edge to the scrollport and
       eats the 12px left padding, so the list opens mid-scroll. */
    scroll-padding-inline: 12px;
  }
  /* chips: folder LEFT + name RIGHT on one line; meta hidden on mobile. */
  .asmt-card {
    padding:           8px 12px;
    scroll-snap-align: start;
  }
  .asmt-main {
    flex:           1 1 auto;
    flex-direction: row;
    align-items:    center;
    gap:            9px;
    text-align:     left;
  }
  .asmt-meta       { display: none; }
  .asmt-folder     { width: 22px; height: 22px; }
  .asmt-folder svg { width: 18px; height: 18px; }
  .asmt-name {
    display:       block;
    white-space:   nowrap;
    overflow:      hidden;
    text-overflow: ellipsis;
  }
}
