/* ───────────────────────────────────────────────────────────────────────
   GEF — CLS Stability
   ───────────────────────────────────────────────────────────────────────
   Purpose: reserve vertical space for containers that get filled by JS
   after the initial HTML paint. Without this, every JS-populated tile/
   panel/list contributes a layout shift when its content streams in,
   driving Core Web Vitals "Poor" CLS scores (39% site-wide on May 15).

   Strategy: explicit `min-height` per container, sized to roughly match
   the typical filled height. If actual content turns out larger than the
   reserved space, the page will still shift — but only by the small delta,
   not the full 0→N transition. Sizing here is conservative; we lean
   slightly large rather than slightly small.

   All containers receiving a reservation are documented inline below so
   future-us can audit + revert if any layout breaks.

   Convention: this file loads AFTER gef.css and any page-specific inline
   styles, so its rules win on cascade order. Specificity is intentionally
   single-class to keep it overridable for legitimate edge cases.

   Added: May 16, 2026 — response to Search Console CLS report
   ─────────────────────────────────────────────────────────────────────── */

/* ── 1. Scrolling ticker strip (homepage) ────────────────────────────────
   Renderer: assets/js/dashboard-main-render.js → renderTicker()
   Fills: #gef-ticker-track with 15-20 ticker items
   Without reservation: container is ~20px (padding only) pre-JS,
                       grows to ~42px when content arrives.
   Reservation: 42px matches the post-JS height precisely.
   ───────────────────────────────────────────────────────────────────── */
.ticker-strip { min-height: 42px; }

/* ── 2. Dashboard KPI "spot" tiles (homepage, row 1) ─────────────────────
   Renderer: assets/js/dashboard-main-render.js → renderKpiSpots()
   Fills: #gef-hormuz-day / -status / -detail, #gef-eugas-*, etc.
   Without reservation: tiles render at ~60px (label + dashes), grow to
                       ~130px when day count + status + detail populate.
   Reservation: 130px matches the typical filled height across all 4 tiles.
   ───────────────────────────────────────────────────────────────────── */
.spot { min-height: 130px; }

/* ── 3. Dashboard live-alerts panel (homepage, row 2 right) ──────────────
   Renderer: assets/js/dashboard-main-render.js → renderAlerts()
   Fills: #gef-alerts-list with 6-7 alert entries
   Without reservation: empty container, grows to its max-height of 520px.
   Reservation: 480px is just under max-height; final entries may overflow
                slightly (scrollbar appears) which is preferable to under-
                reserving and pushing the page below.
   ───────────────────────────────────────────────────────────────────── */
.alerts-list { min-height: 480px; }

/* ── 4. Cross-system connection box (homepage, row 3) ────────────────────
   Renderer: assets/js/dashboard-main-render.js → renderCrossSystem()
   Fills: #gef-cross-system-text + sources + time
   Without reservation: ~30px (chrome only), grows to ~140px (text takes
                       4-5 lines on desktop, 7-8 on narrow viewports).
   Reservation: 160px to cover the wider narrow-viewport case.
   ───────────────────────────────────────────────────────────────────── */
#gef-cross-system, .cross-system-box { min-height: 160px; }

/* ── 5. Shortages page sidebar containers (/shortages/) ──────────────────
   Renderer: assets/js/shortages-data-render.js
   Fills:
     #shortages-active-alerts   → 7 gef-incident rows, ~52px each
     #shortages-why-it-matters  → narrative paragraph, ~150px desktop
   These two empty containers are the dominant CLS contributors on
   /shortages/ (worst CLS URL site-wide per Search Console May 15).
   Reservations: 364px (7 × 52px) and 170px respectively.
   ───────────────────────────────────────────────────────────────────── */
#shortages-active-alerts { min-height: 364px; }
#shortages-why-it-matters { min-height: 170px; }

/* The four shortages KPI counter tiles at the top of /shortages/ are
   populated by renderKpiStrip() (countries, active, jet, resolved). The
   numbers + notes inflate from "—" to multi-line strings. */
#shortages-kpi-countries-note,
#shortages-kpi-active-note,
#shortages-kpi-jet-note,
#shortages-kpi-resolved-note { min-height: 48px; }

/* ── 6. Storage page KPI cards (/storage/) ───────────────────────────────
   Inline CSS already styles .kpi-card with padding only; no min-height.
   Each card includes label + dot + KPI value + fill bar + note. The note
   is the longest line and inflates from "—" to 2-3 line paragraph.
   Reservation: 150px covers all three cards consistently.
   ───────────────────────────────────────────────────────────────────── */
.kpi-card { min-height: 150px; }

/* Chokepoint status sidebar on /storage/ and /marine-traffic/chokepoints/
   Five rows of cp-name + cp-flow text, populated from tanker-data.js. */
#chokepoint-rows { min-height: 280px; }

/* ── 7. Generic gef-kpi-card pattern (used on pipelines, oil, gas) ───────
   Dashboard-style 6-column KPI strip on pipelines/gas/ and pipelines/oil/.
   Each card has label + value + delta + footnote.
   Reservation: 100px matches the narrower padding (12px-14px) used there.
   ───────────────────────────────────────────────────────────────────── */
.gef-kpi-card { min-height: 100px; }

/* ── 8. Generic gef-card body (shortages + storage sidebar cards) ────────
   Card containers used for sidebar incidents + why-it-matters across the
   data pages. The .gef-card-body inside is empty pre-JS on several pages.
   Reservation is small (covers the chrome only) since most card bodies
   already have explicit reservations above.
   ───────────────────────────────────────────────────────────────────── */
.gef-card-body:empty { min-height: 80px; }

/* ── 9. Mobile adjustments ───────────────────────────────────────────────
   On narrow viewports, .spot tiles stack to 1-column and individual cards
   take MORE vertical space (text wraps to more lines), so reservations
   that are tight on desktop can become too tight on mobile. Be generous.
   ───────────────────────────────────────────────────────────────────── */
@media (max-width: 600px) {
  .spot { min-height: 110px; }              /* Smaller because padding shrinks too */
  .alerts-list { min-height: 600px; }       /* Alerts stack longer on narrow */
  #shortages-active-alerts { min-height: 480px; }  /* Rows wrap to 2 lines */
  #shortages-why-it-matters { min-height: 240px; }  /* Paragraph wraps to ~10 lines */
  .kpi-card { min-height: 130px; }
  .gef-kpi-card { min-height: 90px; }
  .ticker-strip { min-height: 38px; }       /* Slightly smaller font on mobile */
}

/* ── 10. /shortages/ landing — SDM (Shortages Disruption Map) section ────
   Added May 19, 2026 in response to Cloudflare Web Analytics showing
   /shortages/ as the worst-CLS URL site-wide (CLS 2.014 on html>body>main,
   180 Poor counts in 24h). The existing reservations covered the KPI strip
   and sidebar but missed the four FIG 1/2/3 containers below them, which
   together represent ~80% of the page height and were all empty pre-JS.

   Renderer: inline <script> in shortages/index.html (renderHeatmap,
   renderTabs, renderFilterBar, renderPinList).
   ───────────────────────────────────────────────────────────────────── */
#sdm-heatmap    { min-height: 620px; }   /* 12 rows × ~48px + header ~ 600-640px */
#sdm-tabs       { min-height: 56px; }    /* Single row of 4 pill tabs + padding */
#sdm-filterbar  { min-height: 44px; }    /* Single line of filter pills */
#sdm-pinlist    { min-height: 720px; }   /* 8-12 pin rows × ~60-80px = baseline */

@media (max-width: 600px) {
  #sdm-heatmap   { min-height: 720px; }  /* Stacked grid takes more vertical space */
  #sdm-pinlist   { min-height: 900px; }  /* Rows wrap to 2-3 lines on narrow */
}

/* ── 11. Country shortage pages — Leaflet map + disruption list ──────────
   Pages: /shortages/{united-states,canada,australia,eu}/  (UK has no map)
   The map iframe-equivalent renders into #xx-map after Leaflet boots, and
   the text-list fallback fills #xx-disruption-list. Both are empty in the
   initial HTML and cause large layout shifts when populated.

   Map container: explicit height already set via inline style on most
   pages (440-480px). Reservation here is defensive — covers any page
   that loses the inline style.

   Disruption list: ~8 entries × ~80px = ~640px.
   ───────────────────────────────────────────────────────────────────── */
#us-map, #ca-map, #au-map, #eu-map           { min-height: 440px; }
#us-disruption-list, #ca-disruption-list,
#au-disruption-list, #eu-disruption-list     { min-height: 640px; }

@media (max-width: 600px) {
  #us-map, #ca-map, #au-map, #eu-map         { min-height: 360px; }
  #us-disruption-list, #ca-disruption-list,
  #au-disruption-list, #eu-disruption-list   { min-height: 820px; }
}
