/* =========================================================
   Base reset & variables
   ========================================================= */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* =========================================================
   Site title bar -- fixed chrome above everything else
   (sidebar + results area both sit below it), including the
   translation banner, which slots in just underneath it.
   ========================================================= */
#site-title-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--title-bar-h);
  z-index: 1001;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 16px;
  background: var(--bg-main);
  border-bottom: 1px solid var(--border);
}
/* Overrides .tab-btn's own tab-bar chrome (padding/border/font-weight/
   color) so the logo+title link reads as plain title text, not a nav
   pill -- an ID selector beats .tab-btn/.tab-btn:hover/.tab-btn.active
   on specificity alone, so this wins regardless of source order. */
#site-title-link {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0;
  margin-bottom: 0;
  border-bottom: none;
  font-size: inherit;
  font-weight: inherit;
  color: inherit;
  text-decoration: none;
}
#site-title-link:hover { color: inherit; }
#site-title-link.active {
  color: inherit;
  border-bottom-color: transparent;
  font-weight: inherit;
}
#site-title-icon { flex-shrink: 0; display: block; }
#site-title-text {
  font-size: calc(15px * var(--ui-scale));
  font-weight: 700;
  color: var(--text);
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* =========================================================
   Translation banner
   ========================================================= */
#translation-banner {
  position: fixed;
  top: var(--title-bar-h);
  left: 0;
  right: 0;
  z-index: 1000;
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.6rem 1rem;
  background: #fefce8;
  border-bottom: 1px solid #fde047;
  color: #713f12;
  font-size: calc(13px * var(--ui-scale));
  line-height: 1.5;
}
#translation-banner[hidden] { display: none; }
#translation-banner-text { flex: 1; }
#translation-banner-dismiss {
  flex-shrink: 0;
  background: none;
  border: none;
  font-size: calc(18px * var(--ui-scale));
  line-height: 1;
  cursor: pointer;
  color: #713f12;
  padding: 0 0.25rem;
  opacity: 0.7;
}
#translation-banner-dismiss:hover { opacity: 1; }

/* Layout always sits below the title bar; push it down further still
   when the banner is also visible (class toggled by JS), and again
   when the dev-mode excluded-countries banner is also visible --
   --dev-banner-h (set by main.js's _positionDevExcludedBanner(), 0px
   whenever that banner is hidden/absent -- see that function's own
   comment) is purely additive here, so it has no effect at all outside
   developer mode or when nothing is currently excluded. */
.layout-split { height: calc(100vh - var(--title-bar-h) - var(--dev-banner-h, 0px)); margin-top: calc(var(--title-bar-h) + var(--dev-banner-h, 0px)); }
#splash-overlay { padding-top: calc(var(--title-bar-h) + var(--dev-banner-h, 0px)); }
/* --banner-h is measured from the banner's actual rendered height (see
   _updateBannerHeightVar() in main.js) -- some languages' translated
   text wraps to two lines where English fits on one, so a fixed
   estimate would undershoot and let the layout below overlap it. The
   2.75rem fallback only matters for the instant between first paint and
   that first measurement. */
body.banner-visible .layout-split { height: calc(100vh - var(--title-bar-h) - var(--banner-h, 2.75rem) - var(--dev-banner-h, 0px)); margin-top: calc(var(--title-bar-h) + var(--banner-h, 2.75rem) + var(--dev-banner-h, 0px)); }
body.banner-visible #splash-overlay { padding-top: calc(var(--title-bar-h) + var(--banner-h, 2.75rem) + var(--dev-banner-h, 0px)); }

@media (prefers-color-scheme: dark) {
  #translation-banner {
    background: #422006;
    border-color: #78350f;
    color: #fef3c7;
  }
  #translation-banner-dismiss { color: #fef3c7; }
}

/* =========================================================
   Dev-mode: excluded-countries banner -- see main.js's own
   "Dev-mode: excluded-countries banner" section. `top` is set
   directly by JS (_positionDevExcludedBanner()), not CSS, since it has
   to sit right below whichever of the title bar/translation banner is
   currently lower -- a flat CSS offset can't express that. `top: 0` is
   just a safe fallback for the brief instant before JS first measures
   it.
   ========================================================= */
#dev-excluded-countries-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 999;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
  padding: 0.5rem 1rem;
  background: #fef2f2;
  border-bottom: 1px solid #fca5a5;
  color: #991b1b;
  font-size: calc(13px * var(--ui-scale));
  line-height: 1.4;
}
#dev-excluded-countries-banner[hidden] { display: none; }
#dev-excluded-countries-banner-text { flex: 1 1 auto; }
#dev-excluded-countries-banner label {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  flex-shrink: 0;
  cursor: pointer;
  white-space: nowrap;
  font-weight: 600;
}
@media (prefers-color-scheme: dark) {
  #dev-excluded-countries-banner {
    background: #450a0a;
    border-color: #7f1d1d;
    color: #fecaca;
  }
}

:root {
  --title-bar-h: 48px;
  /* The sidebar's own COLLAPSED width -- a constant 25% of the viewport
     at any screen size (previously a fixed 320px, whose SHARE of the
     screen drifted with viewport width instead of staying constant),
     per an explicit ask to keep the collapsed-sidebar : results-area
     ratio fixed at 1:3 regardless of screen size. main.js's own
     _setSidebarWidth() always overrides this with an inline px style
     anyway (see that rule's own comment below), so this is mostly
     "keep the intent visible here too" like #sidebar.expanded's 60vw
     already is -- but main.js's _sidebarMinWidth() can't simply read
     this value back out (a custom property holding "25vw" returns that
     literal string, not a resolved pixel number, from
     getComputedStyle().getPropertyValue()), so it hardcodes the
     matching 0.25 ratio directly instead, the same "keep in sync with
     the CSS value" pattern _sidebarMaxWidth() already uses for 60vw. */
  --sidebar-w: 25vw;
  --sidebar-expanded-w: 100vw;
  /* Global font-size scale factor: 1 at exactly 1280px of total viewport
     width (the reference configuration this app's own fixed px font
     sizes were originally authored against -- a 320px collapsed
     sidebar + a 960px results-area, 320/1280 = 25%, i.e. exactly the
     --sidebar-w ratio above), scaling linearly with viewport width
     otherwise. Every ordinary UI font-size in this file (sidebar
     fields, buttons, tab bar, modals, tooltips, titles, banners,
     on-page tables, ...) is wrapped in `calc(Npx * var(--ui-scale))` so
     it scales with this one variable; the few SVG `fill`-based chart
     text classes (scatter/stacked-area chart axis labels/ticks/point
     labels, .chart-xaxis-title-svg, .stack-axis-label, the Country
     Details per-fuel charts' own .cd-chart-tick-label/
     .cd-chart-axis-title) are deliberately EXCLUDED from this --
     they're design-space units inside each chart's own fixed viewBox,
     already scaled proportionally by the browser's native
     viewBox-to-rendered-width mapping (see _applyFixedChartWidth()/
     _scatterSvgScale() in main.js) the moment that chart's own
     container width changes; applying --ui-scale to them on TOP of
     that would double-scale them and distort their size relative to
     the rest of that same chart's own geometry (axis lines, tick
     marks, point glyphs, ...), which does NOT also carry a --ui-scale
     multiplier -- it's sized purely by the viewBox mapping already.

     The REAL, per-viewport-width value is set as a plain inline number
     by a <script> in templates/index.html's own <head> (before first
     paint) and kept current on resize by main.js's own _uiScale()/
     resize handler -- this `1` here is only the fallback for the rare
     case JS doesn't run at all. It used to be `calc(100vw / 1280px)`,
     computed in pure CSS -- dividing two different-unit lengths (vw /
     px) to yield a bare number, which Chrome/Safari's calc()
     implementation supports but Firefox's does NOT, leaving this
     property invalid (and therefore silently falling back) there --
     meaning NONE of the calc(Npx * var(--ui-scale)) font-sizes below
     ever actually scaled in Firefox. Setting a plain number via JS
     instead sidesteps that gap entirely: every one of those rules
     becomes calc(Npx * 0.825)-shaped after substitution, which is
     ordinary length-times-number arithmetic every browser (Firefox
     included) has supported for well over a decade. Don't reintroduce
     a CSS-only calc()-division expression here without re-verifying
     current Firefox support first. */
  --ui-scale: 1;
  /* The A+/A- font-adjust multiplier ON ITS OWN (not also multiplied by
     viewport width, unlike --ui-scale above) -- see main.js's
     _updateUiScaleVar() for where the real value comes from. Reaches
     the handful of SVG chart-text classes below that are deliberately
     EXCLUDED from --ui-scale (see that variable's own comment): those
     already scale with viewport width for free, via each chart's own
     viewBox-to-rendered-width mapping once its container width
     changes, so folding window.innerWidth into THIS variable too would
     double that scaling on top of itself. This fallback (1, a no-op)
     is only for the rare case JS doesn't run at all, same reasoning as
     --ui-scale's own `1` fallback above. */
  --chart-text-scale: 1;
  --accent: #2563eb;
  --accent-hover: #1d4ed8;
  --bg-sidebar: #f8fafc;
  --bg-main: #ffffff;
  --border: #e2e8f0;
  --text: #1e293b;
  --text-muted: #64748b;
  --tooltip-word-color: #0369a1;
  --radius: 6px;
  --transition: 0.25s ease;
  --positive: #15803d;
  --negative: #c2410c;
}

/* `<html>` itself is the browser's real root scrolling element -- `body`
   below already carries `overflow: hidden` (this app's whole scroll
   model is per-container: #sidebar-inner, .tab-panel, etc. each own
   their own overflow-y:auto; nothing is meant to scroll the page/
   viewport itself), but that alone doesn't stop something from still
   scrolling `<html>`, since it has no overflow/height rule of its own.
   This went unnoticed until main.js's ".tab-anchor-link" click handler
   (see "In-content tab + anchor links" there) started focusing a
   heading just switched into view: the click's own native mousedown-
   focus behavior on the clicked <a> -- which happens BEFORE the
   'click' handler's e.preventDefault() ever runs, so it can't be
   cancelled there -- scrolled the document root by exactly
   --title-bar-h's 48px once that <a>'s own ancestor tab-panel got
   `hidden` out from under it, which visibly shifted the whole fixed-
   layout page (sidebar's own header -- language picker, "«" collapse
   button -- included) even though every other per-container scroll
   involved was completely unaffected. Locking `<html>` down the same
   way `body` already is turns any such attempt into a no-op outright,
   rather than chasing down every individual way something could still
   nudge the root scroller. */
html {
  overflow: hidden;
  height: 100%;
}

body {
  font-family: system-ui, -apple-system, sans-serif;
  font-size: calc(14px * var(--ui-scale));
  color: var(--text);
  background: var(--bg-main);
  height: 100vh;
  overflow: hidden;
}

/* =========================================================
   Layout
   ========================================================= */
.layout-split {
  display: flex;
  /* height/margin-top set near the top of this file, above the title
     bar's own rules -- kept together with the site-title-bar/banner
     positioning they depend on rather than duplicated here. */
}

/* =========================================================
   Sidebar
   ========================================================= */
#sidebar {
  width: var(--sidebar-w);
  min-width: var(--sidebar-w);
  background: var(--bg-sidebar);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: width var(--transition), min-width var(--transition);
  z-index: 31;
}

/* Width itself is now set inline by main.js's _setSidebarWidth() (both
   the button's binary snap and the drag handle below use it), which
   always wins over this class's width/min-width by CSS specificity --
   the rule below is effectively unused for layout now (kept only so
   the intent -- "expanded means 60vw" -- stays visible here too); the
   drag handle's own max-width clamp uses the matching 0.6 ratio as a
   JS constant, keep the two in sync if this ever changes. */
#sidebar.expanded {
  width: 60vw;
  min-width: 60vw;
}

#sidebar-resize-handle {
  flex-shrink: 0;
  width: 6px;
  cursor: col-resize;
  z-index: 32;
}
#sidebar-resize-handle:hover,
#sidebar-resize-handle.dragging {
  background: var(--accent);
  opacity: 0.5;
}

/* Overlay/sidebar z-indexes (30-35) sit above #cd-toolbar (sticky, z-index 20) so the dimming scrim covers it; still below modals/tooltips. */
#sidebar-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.35);
  z-index: 30;
}
#sidebar-overlay.visible { display: block; }

/* Mobile phone browsers only (body.is-mobile-phone, set once at load
   from main.js's isMobilePhoneBrowser() -- a UA check, not a screen-
   width media query, so a narrow desktop/tablet BROWSER WINDOW is
   unaffected, only an actual phone). #sidebar's own collapsed width
   (25% of the viewport, --sidebar-w) still eats a quarter of a phone's
   real screen -- exactly the cramped-UI problem the mobile warning
   popup already warns about -- so on a phone the COLLAPSED sidebar
   collapses all the way to a small floating button instead of that
   narrow column.
   The width/min-width themselves are already 0 here -- no !important
   needed -- since main.js's _sidebarMinWidth() returns 0 on mobile,
   which _setSidebarWidth() sets inline exactly as it would any other
   collapsed width; only the border/padding this rule strips are purely
   cosmetic and never touched by that JS. Only the COLLAPSED state is
   touched -- #sidebar.expanded (reached via #sidebar-mobile-toggle
   below, or the drag handle) is completely untouched, still the same
   width-based mechanism desktop/tablet use, just with a mobile-specific
   expanded width (see _sidebarMaxWidth() in main.js). */
body.is-mobile-phone #sidebar:not(.expanded) {
  border-right: none;
  padding: 0;
}
body.is-mobile-phone #sidebar:not(.expanded) #sidebar-inner {
  padding: 0;
  overflow: hidden;
}
/* Dragging to resize from a 0-width edge isn't a sensible gesture on a
   touchscreen -- the button below is the only way to open the sidebar
   on a phone; the drag handle stays fully available once expanded, via
   the same #sidebar.expanded rule desktop/tablet already use. */
body.is-mobile-phone #sidebar:not(.expanded) + #sidebar-resize-handle {
  display: none;
}

#sidebar-mobile-toggle {
  display: none;
  position: fixed;
  top: calc(var(--title-bar-h) + var(--dev-banner-h, 0px) + 10px);
  left: 10px;
  z-index: 35;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  background: var(--bg-sidebar);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: calc(16px * var(--ui-scale));
  line-height: 1;
  color: var(--text);
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0, 0, 0, .15);
}
/* Same --banner-h/--dev-banner-h-aware offset .layout-split/
   #splash-overlay already use (see this file's own comment near the
   top) -- the toggle is position:fixed (viewport-relative, outside
   .layout-split's own flow), so it needs the same adjustment by hand
   when the translation banner is showing. */
body.banner-visible #sidebar-mobile-toggle {
  top: calc(var(--title-bar-h) + var(--banner-h, 2.75rem) + var(--dev-banner-h, 0px) + 10px);
}
body.is-mobile-phone #sidebar-mobile-toggle { display: flex; }
/* Hidden once the sidebar is actually expanded -- #expand-btn inside
   the sidebar's own header (now visible again, since the sidebar is no
   longer 0-width) is what collapses it back down, same as on desktop/
   tablet. */
body.is-mobile-phone #sidebar.expanded ~ #sidebar-mobile-toggle { display: none; }

#sidebar-inner {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow-y: auto;
  padding: 12px 16px 24px;
}

#sidebar-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

#sidebar-header-left {
  display: flex;
  align-items: center;
  gap: 8px;
}

#lang-picker {
  position: relative;
}

#sidebar-reset-btn {
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 3px 8px;
  cursor: pointer;
  font-size: calc(11.5px * var(--ui-scale));
  color: var(--text-muted);
  transition: background var(--transition), color var(--transition);
}
#sidebar-reset-btn:hover { background: var(--border); color: var(--text); }

/* A-/A/A+ font-size buttons -- one bordered segmented control (same
   shape as admin.html's .pt-branch-toggle/.pt-branch-btn), not three
   independently-bordered buttons: the GROUP owns the outer border/
   radius, each button is borderless on its own, and a divider line
   between adjacent segments comes from the next rule's border-left. */
.font-adjust-group {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.font-adjust-btn {
  background: none;
  border: none;
  padding: 3px 7px;
  cursor: pointer;
  font-size: calc(11.5px * var(--ui-scale));
  font-weight: 600;
  color: var(--text-muted);
  transition: background var(--transition), color var(--transition);
}
.font-adjust-btn + .font-adjust-btn { border-left: 1px solid var(--border); }
.font-adjust-btn:hover { background: var(--border); color: var(--text); }

#lang-current {
  display: flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 3px 8px;
  cursor: pointer;
  font-size: calc(11.5px * var(--ui-scale));
  color: var(--text-muted);
  white-space: nowrap;
  transition: background var(--transition), color var(--transition);
}
#lang-current:hover { background: var(--border); color: var(--text); }

#lang-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 4px 12px rgba(0,0,0,.1);
  z-index: 100;
  min-width: 100%;
  overflow: hidden;
}
#lang-dropdown[hidden] { display: none; }

.lang-option {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  background: none;
  border: none;
  padding: 7px 12px;
  text-align: left;
  cursor: pointer;
  font-size: calc(11.5px * var(--ui-scale));
  color: var(--text);
  white-space: nowrap;
}
.lang-option:hover { background: #f1f5f9; }

#lang-picker svg { display: block; flex-shrink: 0; border-radius: 2px; }

#expand-btn {
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 4px 10px;
  cursor: pointer;
  font-size: calc(14px * var(--ui-scale));
  color: var(--text-muted);
  transition: background var(--transition), color var(--transition);
}
#expand-btn:hover { background: var(--border); color: var(--text); }

/* =========================================================
   Form fields
   ========================================================= */
.field-block {
  margin-bottom: 20px;
}

.field-block label,
.slider-group-fieldset legend {
  display: block;
  font-weight: 600;
  margin-bottom: 6px;
  line-height: 1.4;
}

select {
  width: 100%;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: #fff;
  font-size: calc(11.5px * var(--ui-scale));
  cursor: pointer;
  color: var(--text);
}
select:disabled { opacity: 0.55; cursor: not-allowed; }

/* Sliders */
.slider-with-label {
  display: flex;
  align-items: center;
  gap: 10px;
}

input[type="range"] {
  flex: 1;
  accent-color: var(--accent);
  cursor: pointer;
}
input[type="range"]:disabled { opacity: 0.55; cursor: not-allowed; }

/* Tick labels under a value-list slider (field flag show_value_ticks);
   the right padding matches .slider-value-display's min-width + gap so
   the labels line up with the slider track. */
.slider-value-ticks {
  display: flex;
  justify-content: space-between;
  padding: 0 52px 0 6px;
  font-size: calc(10.5px * var(--ui-scale));
  color: var(--text-muted);
}
.slider-value-ticks .tick-disabled {
  opacity: 0.45;
  text-decoration: line-through;
}

.slider-value-display {
  min-width: 42px;
  text-align: right;
  font-size: calc(11.5px * var(--ui-scale));
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

/* Dual-ended slider (e.g. Responsibility <-> Capability): one slider,
   a translated label + live percentage above each end (left label over
   the slider's left end, right label over its right end). */
.dual-slider-wrap {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.dual-slider-labels {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}
.dual-slider-end-group {
  display: flex;
  align-items: baseline;
  gap: 5px;
}
.dual-slider-end-right {
  flex-direction: row-reverse;
}
.dual-slider-end-label {
  font-size: calc(11.5px * var(--ui-scale));
  font-weight: 600;
  color: var(--text-muted);
  white-space: nowrap;
}
.dual-slider-end-value {
  min-width: 34px;
  text-align: center;
  font-size: calc(11.5px * var(--ui-scale));
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.dual-slider-wrap input.dual-slider {
  width: 100%;
}

/* Browsers give every <fieldset> a UA-default `min-width: min-content`
   (not the `width:auto`-fills-container behavior every other block
   element gets) -- so a fieldset whose content can't shrink below some
   width (a fixed-px chart, a nowrap label pair, ...) pushes the WHOLE
   fieldset wider than its own container instead of letting that content
   overflow/clip the way an ordinary div would. This silently made the
   Dependence Weights and International finance sidebar blocks render
   wider than their sibling blocks at some sidebar widths (the weight
   chart's then-fixed-px .weight-chart-wrap, see below, being the worst
   offender). Reset for every fieldset in the sidebar so a bordered-box
   field group can always shrink to match its siblings, same as any
   other sidebar element. */
#sidebar fieldset { min-width: 0; }

/* International finance sidebar group: r_weight / resp_since / dev_needs
   grouped visually into one bordered box, matching Dependence Weights'
   .slider-group-fieldset treatment -- except these are three separate
   top-level MAIN_INPUTS entries (not one field's own sub-elements)
   rendered back to back, so the wrapper is added around them directly
   in index.html rather than inside field.html.

   Follow-up fix: r_weight's own <label> originally stood in for a
   <legend> here, on the theory that matching font-weight/line-height
   (see ".field-block label, .slider-group-fieldset legend" below) would
   make it READ the same as the radio-group/slider-group fieldsets' own
   legends -- but a <legend> only gets the browser's special "straddle
   the top border" layout when it's a DIRECT CHILD of the <fieldset>
   itself; nested one level down inside r_weight's own .field-block (as
   field.html always renders it), a same-styled <label> just sits as
   ordinary padded content INSIDE the box, never overlapping the border
   -- a different look from every other bordered field group in this
   file, not "in the frame" the same way. Fixed by adding a REAL
   <legend> as the fieldset's own direct child in index.html (duplicating
   r_weight's own data-i18n key, since switchLanguage()'s generic
   [data-i18n] sweep is happy to update two elements sharing one key) and
   hiding the now-redundant inner <label> below. Works unchanged in both
   expanded/collapsed sidebar states since neither state hides the
   fieldset itself, only the radio fields' own real vs. mirror rendering
   inside it. */
.intl-finance-fieldset {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px 12px;
  margin: 0 0 20px;
}
.intl-finance-fieldset .field-block:last-child {
  margin-bottom: 0;
}
.intl-finance-fieldset > .field-block > label {
  display: none;
}

/* gf_share ("How much fairness (%)") gets the same bordered-box frame
   as the radio groups (.radio-group-fieldset etc.) and the International
   finance section above -- same border/radius/padding values, wrapped
   around the single field-block directly in index.html. Same
   label-vs-legend follow-up fix as .intl-finance-fieldset just above:
   a real <legend> is now the fieldset's own direct child (in
   index.html), duplicating gf_share's own data-i18n key, and the
   field.html-rendered inner <label> is hidden below so there's no
   visible duplicate. The bottom-margin-zeroing on the last (only)
   field-block avoids doubling up with the fieldset's own outer margin,
   same reasoning as .intl-finance-fieldset. */
.gf-share-fieldset {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px 12px;
  margin: 0 0 20px;
}
.gf-share-fieldset .field-block:last-child {
  margin-bottom: 0;
}
.gf-share-fieldset > .field-block > label {
  display: none;
}

/* Transient "speech bubble" notice shown right ABOVE the field it
   comments on (in DOM order too -- see templates/index.html, where
   each div is placed right before that field's own fieldset/
   .radio-group-fieldset opens): #gf-share-notice (main.js's
   showGfShareAdjustedNotice(), see the CDR ambition <-> gf_share
   auto-adjustment section) and #cdr-adjusted-notice (main.js's
   showCdrAdjustedNotice(), shown instead of a modal when the
   Temperature Goal bumps ambition-cdr off "Ecosystem restoration
   only") share this one ruleset, combined by selector rather than
   duplicated, since they're the same mechanism pointed at two
   different fields. Deliberately styled DIFFERENTLY from
   #tooltip-popup (dark background, no caret, fixed-positioned) per
   spec: a yellow background + dark text (the app's own established
   warning-yellow pair, matching definitions.py's _WARNING_YELLOW /
   .chart-warning-badge) and a small downward-pointing caret (::before,
   a plain CSS border-triangle, pointing at the fieldset below it) so
   each one visually reads as a callout pointing at the control it's
   commenting on, rather than a generic glossary tooltip. A static,
   in-flow block (not position:fixed like #tooltip-popup) since it
   always appears in the same place, right above the field it
   explains -- no anchor-relative positioning math needed. Hidden by
   default via the plain [hidden] attribute; main.js toggles each on
   for exactly 3 seconds, independently. */
.gf-share-notice,
.cdr-adjusted-notice {
  position: relative;
  margin: 0 0 -12px;
  padding: 8px 14px;
  background: #facc15;
  color: #1e293b;
  border-radius: var(--radius);
  box-shadow: 0 4px 12px rgba(0,0,0,.15);
  font-size: calc(10.5px * var(--ui-scale));
  font-weight: 600;
  line-height: 1.4;
}
.gf-share-notice[hidden],
.cdr-adjusted-notice[hidden] { display: none; }
.gf-share-notice::before,
.cdr-adjusted-notice::before {
  content: '';
  position: absolute;
  bottom: -6px;
  left: 24px;
  width: 0;
  height: 0;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-top: 6px solid #facc15;
}

/* A field disabled dynamically by another field's current value (e.g.
   "Historical Emissions since" while the Responsibility/Capability
   slider is set fully to Capability) -- see main.js's International
   finance section. Radio inputs have no built-in :disabled dimming the
   way range/select already get below, so this covers the whole block. */
input[type="radio"]:disabled { opacity: 0.55; cursor: not-allowed; }
.field-block.field-disabled { opacity: 0.6; }

/* Radio group */
.radio-group-fieldset,
.radio-mirror-fieldset,
.radio-mirror-fieldset-standalone {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px 12px;
  margin: 0;
}
.radio-group-fieldset legend,
.radio-mirror-fieldset legend,
.radio-mirror-fieldset-standalone legend,
.intl-finance-fieldset legend,
.gf-share-fieldset legend,
.advanced-mirror-field-fieldset legend {
  padding: 0 6px;
  font-weight: 600;
  line-height: 1.4;
  font-size: calc(12.5px * var(--ui-scale));
}
.radio-mirror-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 2px;
}
/* A <select>'s closed box doesn't reliably shrink via flex-basis/
   min-width:0 the way generic elements do -- Chromium sizes it to fit
   its longest <option> text regardless, which pushed both it and the
   "?" button past the sidebar's edge for long labels (e.g. the CDR
   field). An explicit width -- container width minus the "?" button's
   20px plus the row's 6px gap, only when a "?" is actually present
   (.has-help, set in field.html) -- forces the browser's native
   truncate-when-closed/show-in-full-when-open <select> behavior (the
   pre-existing, preferred look) instead of asking flexbox to negotiate
   a shrink it won't actually perform. */
.radio-mirror-row.has-help .radio-mirror-select {
  width: calc(100% - 26px);
  flex-shrink: 0;
}
.radio-mirror-help {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--bg-sidebar);
  color: var(--text-muted);
  font-size: calc(10.5px * var(--ui-scale));
  font-weight: 700;
  cursor: help;
}
.radio-mirror-help:hover,
.radio-mirror-help:focus-visible {
  border-color: var(--accent);
  color: var(--accent);
}
.field-block label.radio-option {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: 6px;
  cursor: pointer;
  font-size: calc(11.5px * var(--ui-scale));
  font-weight: normal;
  line-height: 1.4;
  color: var(--text);
}
.field-block label.radio-option input[type="radio"] {
  margin-top: 2px;
  flex-shrink: 0;
  accent-color: var(--accent);
  cursor: pointer;
}
/* A single option disabled within an otherwise-enabled radio group (e.g.
   "No CDR at all" via main.js's _updateCdrNoneDisabled() -- unlike
   .field-disabled above, which dims a WHOLE field) previously only
   dimmed the radio circle itself (input[type="radio"]:disabled's own
   opacity above); the label text next to it stayed full-color, so a
   disabled option didn't read as disabled at all. */
.radio-option input[type="radio"]:disabled ~ span {
  color: var(--text-muted);
  cursor: not-allowed;
}
/* "No CDR at all"'s own label text is entirely a [[...|no-cdr]] tooltip
   word (see .tooltip-word above) -- greying it out via the rule above
   would otherwise also grey its dashed underline, since
   text-decoration-color defaults to currentColor. Keep the underline in
   the normal tooltip-word blue so the option still visibly signals "a
   tooltip exists here" even while disabled; only the fill text itself
   goes grey. */
.radio-option input[type="radio"]:disabled ~ span .tooltip-word {
  color: var(--text-muted);
  text-decoration-color: var(--tooltip-word-color);
}

/* Slider group */
.slider-group-fieldset {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px 12px;
}
.slider-group-fieldset legend {
  padding: 0 6px;
  font-size: calc(12.5px * var(--ui-scale));
}
.slider-group-row {
  margin-top: 10px;
}
.slider-group-row label {
  display: flex;
  align-items: center;
  gap: 5px;
  font-weight: 500;
  font-size: calc(11.5px * var(--ui-scale));
  color: var(--text-muted);
  margin-bottom: 4px;
}

/* Sliders share the fieldset with a weight chart (pie or stacked
   column, built by main.js's _updateWeightChart()) sitting to their
   right -- the sliders' own column just takes whatever's left, which is
   what "shrinks" them relative to the old full-width layout; no width
   rule needed on the sliders themselves beyond that. */
.slider-group-body {
  display: flex;
  align-items: center;
  gap: 14px;
}
.slider-group-sliders {
  flex: 1;
  min-width: 0;
}
.weight-chart-wrap {
  flex-shrink: 0;
  /* Was a flat 76px -- the one thing in this fieldset that didn't scale
     with viewport width the way every surrounding font-size already
     does via --ui-scale, which (combined with the UA fieldset
     min-width:min-content quirk fixed above) is what let this block
     render wider than its siblings at some sidebar widths. The SVG
     itself is sized to match in main.js's _updateWeightChart() (same
     innerWidth/1280 ratio as --ui-scale, hardcoded in JS for the same
     reason _sidebarMinWidth()/_sidebarMaxWidth() hardcode their own
     vw ratios -- a custom property holding a calc() expression reads
     back as that literal unresolved text, not a usable number). */
  width: calc(76px * var(--ui-scale));
  display: flex;
  align-items: center;
  justify-content: center;
}
.weight-chart-wrap svg { display: block; }

/* Colour key next to each slider's own label -- same colour as that
   dimension's pie slice/column segment, set inline by
   _updateWeightChart() (WEIGHT_CHART_COLORS in main.js) rather than in
   CSS, so the two can never drift apart. */
.weight-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
  flex-shrink: 0;
}
.weight-pct {
  font-weight: 400;
  color: var(--text-muted);
}

/* Field explanation: short version (collapsed sidebar) */
.field-explanation-short {
  margin-top: 2px;
  margin-bottom: 6px;
  font-size: calc(11.5px * var(--ui-scale));
  font-weight: normal;
  color: var(--text-muted);
  line-height: 1.4;
}

/* Field explanation: long version (expanded sidebar) */
.field-explanation {
  margin-top: 8px;
  padding: 8px 10px;
  background: #eff6ff;
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: calc(11.5px * var(--ui-scale));
  color: #334155;
  line-height: 1.5;
}

/* =========================================================
   Main results area — flex column, holds tab-bar + tab-panels
   ========================================================= */
#results-area {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* =========================================================
   Tab bar
   ========================================================= */
#tab-bar {
  display: flex;
  flex-shrink: 0;
  border-bottom: 1px solid var(--border);
  background: var(--bg-sidebar);
  padding: 0 16px;
  overflow-x: auto;
  scrollbar-width: none;
}
#tab-bar::-webkit-scrollbar { display: none; }

.tab-btn {
  display: inline-block;
  padding: 10px 16px;
  border: none;
  border-bottom: 3px solid transparent;
  background: none;
  cursor: pointer;
  font-size: calc(13px * var(--ui-scale));
  font-weight: 500;
  color: var(--text-muted);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--transition), border-color var(--transition);
  margin-bottom: -1px;
}
.tab-btn:hover { color: var(--text); }
.tab-btn.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
  font-weight: 600;
}

/* Sits beside the tab-bar's own .tab-btn links (see templates/
   index.html's own comment on why it isn't one itself) -- a small
   circular "?" icon button, not a tab, so it's deliberately NOT styled
   like .tab-btn (no underline-on-active, no border-bottom). */
.help-video-btn {
  flex-shrink: 0;
  align-self: center;
  margin-left: 4px;
  width: calc(22px * var(--ui-scale));
  height: calc(22px * var(--ui-scale));
  border: 1.5px solid var(--text-muted);
  border-radius: 50%;
  background: none;
  color: var(--text-muted);
  font-size: calc(12px * var(--ui-scale));
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  transition: color var(--transition), border-color var(--transition);
}
.help-video-btn:hover {
  color: var(--accent);
  border-color: var(--accent);
}
.help-video-btn[hidden] { display: none; }

/* First-visit callout, pointing up at #help-video-btn -- a small
   speech-bubble shape (not a full-width banner), with a caret pointing
   UP (border-bottom triangle) since the button it's pointing at is
   ABOVE it, the mirror image of the downward-pointing .gf-share-notice/
   .cdr-adjusted-notice carets elsewhere in this file. position: fixed
   (not absolute) -- see templates/index.html's own comment on why this
   element lives outside #tab-bar's DOM subtree; main.js sets its
   top/left inline, computed from #help-video-btn's own live position
   (see _positionHelpVideoCallout()), and keeps re-measuring it for as
   long as the callout stays open -- the sidebar's own width is
   genuinely fluid (drag handle, expand/collapse, initial-load settle),
   which moves #help-video-btn without necessarily firing a window
   `resize` event, so a one-off measurement alone isn't enough. */
/* Darker blue fill + white text (not the light-tint/dark-text look
   .information-note's own family uses) -- border is the SAME darker
   blue as the fill (a flat, solid card) rather than the lighter
   var(--accent) rim this used before, and both caret layers (::before/
   ::after) were originally two DIFFERENT shades specifically to fake a
   bordered triangle (an outer, slightly larger border-colored triangle
   behind a smaller fill-colored one); now that the border and fill are
   one and the same color, both layers were updated together so the
   caret still reads as one solid shape, not a visible seam. */
#help-video-callout {
  position: fixed;
  width: 240px;
  max-width: calc(100vw - 32px);
  background: #1e3a8a;
  border: 1.5px solid #1e3a8a;
  border-radius: 8px;
  padding: 10px 28px 10px 12px;
  font-size: calc(12.5px * var(--ui-scale));
  line-height: 1.45;
  color: #fff;
  cursor: pointer;
  z-index: 190;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
}
#help-video-callout[hidden] { display: none; }
#help-video-callout::before {
  content: "";
  position: absolute;
  top: -7px;
  right: 14px;
  width: 0;
  height: 0;
  border-left: 7px solid transparent;
  border-right: 7px solid transparent;
  border-bottom: 7px solid #1e3a8a;
}
#help-video-callout::after {
  content: "";
  position: absolute;
  top: -5.5px;
  right: 15.5px;
  width: 0;
  height: 0;
  border-left: 5.5px solid transparent;
  border-right: 5.5px solid transparent;
  border-bottom: 5.5px solid #1e3a8a;
}
#help-video-callout-close {
  position: absolute;
  top: 4px;
  right: 6px;
  width: 18px;
  height: 18px;
  border: none;
  border-radius: 50%;
  background: none;
  color: rgba(255, 255, 255, 0.75);
  font-size: calc(14px * var(--ui-scale));
  line-height: 1;
  cursor: pointer;
}
#help-video-callout-close:hover { color: #fff; }

/* =========================================================
   Tab panels
   ========================================================= */
#tab-panels {
  flex: 1;
  overflow: hidden;
  position: relative;
}

.tab-panel {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  padding: 24px 32px;
}

/* The charts have a fixed width now (main.js's _applyFixedChartWidth(),
   sized for the sidebar's COLLAPSED width -- see the "Chart sizing"
   section) and no longer shrink when the sidebar grows past that; an
   expanded/dragged-wide sidebar instead pushes them partly or fully out
   of view, so this tab specifically needs horizontal scroll to reach
   them again rather than clipping them outright. */
#tab-results {
  overflow-x: auto;
}

/* Country Details/Support: the tab panel itself no longer scrolls --
   .tab-panel-scroll (a child, sized to fill it) does that instead --
   so the loading overlay below, a THIRD sibling positioned absolute
   inset:0 against this now-static box, stays put over the visible
   viewport instead of scrolling away with the content underneath it. */
.tab-panel.has-loading-overlay {
  overflow: hidden;
  padding: 0;
}
.tab-panel-scroll {
  height: 100%;
  overflow-y: auto;
  padding: 24px 32px;
}

.field-checkbox-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  cursor: pointer;
  margin-bottom: 20px;
}
.field-checkbox-label input[type="checkbox"] {
  cursor: pointer;
  accent-color: var(--accent);
}

.advanced-fields { max-width: 80%; } /* responsive, see .about-content's own comment -- no px ceiling, see that comment for why */

/* Advanced Settings tab: every field gets the same bordered-box frame
   capacity_adjustment's own radio-group-fieldset already has natively
   -- wrapped directly in index.html's .advanced-fields loop (radio
   fields are excluded from this wrap there, since they already render
   their own fieldset and double-wrapping would nest one border inside
   another). Same border/radius/padding/margin values as
   .gf-share-fieldset/.intl-finance-fieldset, and the same
   last-child-margin-zeroing so the wrapped field-block's own 20px
   bottom margin doesn't stack with this fieldset's own. */
.advanced-field-fieldset {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px 12px;
  margin: 0 0 20px;
}
.advanced-field-fieldset .field-block:last-child {
  margin-bottom: 0;
}

/* The "Add Advanced Settings to Sidebar" mirror (#sidebar-advanced-mirror
   in index.html) gets its OWN, separately-named version of the above --
   NOT .advanced-field-fieldset itself, even though the border/radius/
   padding/margin values are identical -- because the tab's own
   .advanced-field-fieldset wrap (just above) was deliberately left with
   its field's plain <label> as ordinary content (never asked to change),
   while the sidebar-mirror copy below gets a REAL <legend> (a direct
   child of the fieldset, in index.html) so its heading reads "in the
   frame" the same way .gf-share-fieldset/.intl-finance-fieldset's now
   do -- see those two classes' own comments above for why a <legend>
   has to be the fieldset's direct child, not nested inside .field-block,
   to get the browser's border-straddling legend layout. Reusing
   .advanced-field-fieldset's class name here would have also hidden the
   TAB's own field labels via the rule below, leaving those headings
   blank with no legend to replace them. */
.advanced-mirror-field-fieldset {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 12px 12px;
  margin: 0 0 20px;
}
.advanced-mirror-field-fieldset .field-block:last-child {
  margin-bottom: 0;
}
.advanced-mirror-field-fieldset > .field-block > label {
  display: none;
}

/* Global phaseout-cost slider + cost-allocation-basis radios + pie chart
   set, relocated here from the Support tab -- see templates/index.html's
   own comment right above #tab-advanced's .advanced-cost-section for the
   full rationale. Responsive like every other tab's content width (see
   .about-content's own comment) -- no px ceiling, so on a narrow
   available width the four 140px-wide pies in #support-pies-row (4 *
   140px + 3 * 20px gaps = 620px) can wrap to more than one line, which
   .support-pie-row's own flex-wrap: wrap already handles gracefully. */
.advanced-cost-section {
  max-width: 80%;
  margin-top: 28px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
}
.advanced-cost-section .field-block { max-width: 80%; }

/* Advanced Settings sidebar mirror -- see main.js's "Advanced Settings ->
   sidebar mirror" section. */
#sidebar-advanced-mirror h3 {
  font-size: calc(12.5px * var(--ui-scale));
  font-weight: 600;
  margin: 0 0 12px;
}

#sidebar-version-footer {
  margin-top: auto;
  padding-top: 16px;
  font-size: calc(10px * var(--ui-scale));
  color: var(--text-muted);
  text-align: center;
}

.placeholder-text {
  color: var(--text-muted);
  font-size: calc(15px * var(--ui-scale));
  margin-top: 40px;
}

/* Publications & About tab. max-width used to be a flat 760px -- now
   80% of the available width (window minus the sidebar's CURRENT width,
   since #results-area/.tab-panel are plain flex/absolute layout and
   already resolve to that automatically with no JS needed), with NO px
   ceiling -- every font-size on the page already scales with viewport
   width via --ui-scale (see that var's own definition), so a fixed px
   cap on top of that would mean text that's rendering genuinely bigger
   on a big screen gets squeezed into a box that stopped growing, which
   is backwards: the box needs to keep pace with the text, not the other
   way around. An earlier version of this rule capped at 760px
   specifically to avoid "unreadably-long lines" on a wide screen -- but
   line length is governed by the CHARACTER COUNT per line, and more
   characters fit per line exactly in proportion to how much bigger the
   (also-scaled) font has gotten, so a flat px cap was solving a problem
   that scaling the font already prevents on its own. */
.about-content {
  max-width: 80%;
  font-size: calc(15px * var(--ui-scale));
  line-height: 1.75;
  color: var(--text);
}
.about-content h2 {
  font-size: calc(19px * var(--ui-scale));
  margin: 1.6em 0 0.6em;
}
.about-content h2:first-child { margin-top: 0; }
.about-content p { margin: 0 0 1em; }
.about-content ul { margin: 0.25em 0 1em 1.5em; }
.about-content li { margin-bottom: 0.4em; }
.about-content a { color: var(--tooltip-word-color); }

/* Methodology tab -- see content_pages.py's METHODOLOGY_TEXT comment and
   static/js/main.js's "Methodology tab" section. #tab-methodology's own
   `.about-content` div reuses every rule above (h2/ul/li/a) for free;
   everything below is specific to this tab's own black-text/grey-text
   (always-visible/initially-hidden) convention and its numbered
   equations. */
.methodology-not-translated-notice {
  background: #fffbeb;
  border: 1px solid #f59e0b;
  border-radius: 6px;
  padding: 10px 14px;
  margin: 0 0 1.25em;
  font-size: calc(14px * var(--ui-scale));
  max-width: 80%; /* matches .about-content, see that rule's comment */
}
.methodology-not-translated-notice[hidden] { display: none; }
.methodology-para { margin: 0 0 1em; }
/* The button itself is kept as a real, accessible "Show more"/"Show
   less" control -- main.js still toggles its literal text content on
   click, same as before -- but that text is visually replaced by a
   small arrow glyph (::before) rather than shown as a dotted-underline
   link. `font-size: 0` collapses the literal text node to zero visible
   size (screen readers still read it regardless of font-size, which
   plays no part in accessible-name computation) while `::before` gets
   its own explicit font-size so the arrow itself isn't also hidden.
   The arrow rotates 90° (▶ -> ▼) via [aria-expanded="true"], the same
   attribute main.js already flips on toggle for its own sake.
   Per a direct follow-up ask, the glyph is plain Unicode U+25B6 (▶,
   not the smaller U+25B8 ▸ used previously) sized to match
   .methodology-para's own font-size exactly -- .methodology-para has
   no font-size rule of its own, so it inherits .about-content's
   calc(15px * var(--ui-scale)) (the Methodology tab's content div
   reuses that class, see "Publications & About tab" in CLAUDE.md),
   which is why the arrow uses that same 15px figure, not .about-
   content's own OTHER font-size values (e.g. its h2's 19px) -- rather
   than an arbitrary flat/doubled px value, so the arrow reads at the
   same size as the body text it sits next to, and still scales with
   viewport width via the shared --ui-scale multiplier every other
   font-size in this file already uses. */
.methodology-expand-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: calc(6px * var(--ui-scale));
  padding: 0;
  border: none;
  background: none;
  /* The present green -- a faint (40%-toward-white) tint of
     var(--positive) (#15803d), the same green the scatter chart's
     above-average data points use (see main.js's pointStyle()) --
     rather than the plain tooltip-word blue, so this arrow reads as
     its own distinct, more eye-catching affordance. Hardcoded here
     rather than computed via main.js's own _tint() helper, since this
     is a static CSS rule with no JS involved. */
  color: #73b38b;
  cursor: pointer;
  font-size: 0;
  line-height: 0;
  vertical-align: middle;
}
.methodology-expand-btn::before {
  content: "\25B6"; /* ▶ */
  display: inline-block;
  font-size: calc(15px * var(--ui-scale));
  line-height: 1;
  transition: transform 0.15s ease;
}
.methodology-expand-btn[aria-expanded="true"]::before { transform: rotate(90deg); }
/* Hover goes to the full, solid green (not the faint tint above) rather
   than the app's blue accent -- keeps the arrow's own green identity
   consistent between its resting and interactive states. */
.methodology-expand-btn:hover { color: var(--positive); }
/* The intro paragraph's own standalone "▶" mention (pointing the
   reader at a real .methodology-expand-btn elsewhere on the page, not
   a button of its own) -- same green/size treatment as
   .methodology-expand-btn::before's glyph, so it reads as the exact
   same affordance even though this one instance is plain inline text,
   not a real button. */
.methodology-intro-arrow {
  color: #73b38b;
  font-size: calc(15px * var(--ui-scale));
  line-height: 1;
  vertical-align: middle;
}
/* "clicking here to expand all paragraphs" -- a real <button>
   (focusable/keyboard-activatable, unlike a bare <span>) styled to
   read as inline text rather than a boxed control, underlined so it
   still visibly reads as clickable. Wired generically in main.js's
   existing delegated Methodology click handler -- see that function's
   own comment for why a delegated listener (not a per-element one) is
   required here. */
.methodology-expand-all-link {
  display: inline;
  padding: 0;
  border: none;
  background: none;
  font: inherit;
  color: var(--tooltip-word-color);
  text-decoration: underline;
  cursor: pointer;
}
.methodology-expand-all-link:hover { color: var(--accent); }
/* Hidden-by-default content -- a faint grey card (consistent with the
   equation blocks' own var(--bg-sidebar) "muted panel" look elsewhere
   in this app), set very slightly smaller and a touch tighter than the
   surrounding always-visible copy (.about-content's 15px/1.75) so it
   reads as a distinct, secondary layer of detail rather than more of
   the same prose. Where several originally-separate hidden paragraphs
   (and, in one case, a table -- see content_pages.py's own comment on
   this) have been merged under ONE button (so "three hidden paragraphs
   in a row" become one expand/collapse action, not three), each
   original paragraph break survives as its own .methodology-hidden-para
   child with a bottom margin, minus the last one, instead of running
   together into a single wall of text. */
.methodology-hidden {
  display: block;
  margin-top: 6px;
  padding: 10px 12px;
  background: var(--bg-sidebar);
  border-radius: 6px;
  font-size: calc(14px * var(--ui-scale));
  line-height: 1.55;
}
.methodology-hidden[hidden] { display: none; } /* defensive, see "Known gotchas" -- [hidden] can lose to a plain-selector display rule */
.methodology-hidden-para { margin: 0 0 0.9em; }
.methodology-hidden-para:last-child { margin-bottom: 0; }
.methodology-equation {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  margin: 0.75em 0;
  padding: 10px 6px;
  background: var(--bg-sidebar);
  border: 1px solid var(--border);
  border-radius: 6px;
}
/* Serif, italic "math" font for every variable/symbol -- both inside a
   full equation block (.methodology-eq-body, which every equation's own
   fraction/radical spans inherit this from, since font-family cascades)
   and for a single variable mentioned inline in prose (em.methodology-
   math -- see content_pages.py's own comment on how these were told
   apart from genuine, non-math <em>'d emphasis words during extraction).
   Cambria Math is the actual typeface Word's own equation editor used
   for the source document (see the attached reference screenshot) --
   listed first so it's used wherever actually installed (bundled with
   Microsoft Office, so common on Windows); the fallbacks approximate
   the same "serifed, cursive" look elsewhere. font-style: italic is set
   explicitly rather than relied upon from <em>'s own UA-default italic,
   since .methodology-eq-body (a plain <span>, not an <em>) needs it
   stated outright. */
.methodology-eq-body, em.methodology-math {
  font-family: "Cambria Math", Cambria, "STIX Two Text", "Times New Roman", serif;
  font-style: italic;
}
.methodology-eq-body { grid-column: 2; text-align: center; }
.methodology-eq-num { grid-column: 3; text-align: right; color: var(--text-muted); font-size: 0.85em; padding-right: 8px; }
/* A real two-row stacked fraction (numerator over a ruled line over the
   denominator), not flat "num / den" text -- chosen since several of
   these formulas have multi-term numerators that already contain their
   own literal "("/"[" characters (typed by the source document's own
   author, not OMML delimiters), so a further pair of enclosing parens
   around the whole fraction would only add to that visual noise; a
   stacked fraction disambiguates numerator from denominator without
   needing any. */
.methodology-frac {
  display: inline-flex;
  flex-direction: column;
  vertical-align: middle;
  text-align: center;
  margin: 0 2px;
  line-height: 1.3;
}
.methodology-frac-num { border-bottom: 1px solid currentColor; padding: 0 3px; }
.methodology-frac-den { padding: 0 3px; }
.methodology-table-wrap { margin: 1em 0; overflow-x: auto; }
.methodology-table { border-collapse: collapse; width: 100%; font-size: 0.9em; }
.methodology-table th, .methodology-table td { border: 1px solid var(--border); padding: 6px 10px; text-align: center; }
.methodology-table th { background: var(--bg-sidebar); font-weight: 600; }

/* In-body photos (Santa Marta conference, Lula at COP-30) -- credit
   shown as a visible caption underneath, unlike the team bio photos
   below (whose credit is a hover/focus popup instead, since those are
   small circular thumbnails with no room for a caption). */
.about-photo {
  margin: 20px 0 24px;
}
.about-photo img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
}
.about-photo-credit {
  margin-top: 6px;
  font-size: calc(12px * var(--ui-scale));
  font-style: italic;
  color: var(--text-muted);
}

/* 2x2 in-body photo grid (Virginia coal miners / Nigeria oil spill /
   nurse and elderly woman / Bangladesh agriculture) -- a variant of the
   single-photo .about-photo above, same outer margin/credit styling,
   just with a 2x2 grid of images instead of one <img>. Sized purely by
   being 100% width of the same .about-content container the single
   photos already fill, so its overall footprint matches theirs with no
   extra width rule needed. Each cell shows a larger version of its own
   photo on hover/focus, same pure-CSS :hover/:focus-within popup
   pattern as .team-photo-wrap/.team-photo-popup above (no JS). */
.about-photo-grid-inner {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
@media (max-width: 480px) {
  .about-photo-grid-inner { grid-template-columns: 1fr; }
}
.about-photo-grid-cell {
  position: relative;
}
.about-photo-grid-thumb {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: var(--radius);
}
.about-photo-grid-hover {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 60;
  width: min(90vw, 480px);
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28);
  border-radius: var(--radius);
}
.about-photo-grid-cell:hover .about-photo-grid-hover,
.about-photo-grid-cell:focus-within .about-photo-grid-hover {
  visibility: visible;
  opacity: 1;
  pointer-events: auto;
}
.about-photo-grid-hover img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  border: 1px solid var(--border);
}

.about-team-heading {
  font-size: calc(19px * var(--ui-scale));
  margin: 1.8em 0 0.9em;
  max-width: 80%; /* matches .about-content, see that rule's comment */
}

.team-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
  max-width: 80%; /* matches .about-content, see that rule's comment */
  margin-bottom: 1.2em;
}
@media (max-width: 640px) {
  .team-grid { grid-template-columns: 1fr; }
}

.team-card {
  display: flex;
  gap: 14px;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.team-avatar {
  flex-shrink: 0;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 700;
  font-size: calc(17px * var(--ui-scale));
}

.team-info { min-width: 0; }
.team-name {
  font-weight: 600;
  margin-bottom: 4px;
}
.team-name a { color: var(--text); }
.team-bio {
  font-size: calc(13.5px * var(--ui-scale));
  line-height: 1.55;
  color: var(--text-muted);
}
.team-bio strong { color: var(--text); }

/* Team member photo + its hover/focus popup (larger photo + translated,
   often-hyperlinked credit) -- a plain <img title> can't show a link, so
   this is used instead. Pure CSS :hover/:focus-within, no JS: the popup
   is a DOM child of .team-photo-wrap, so it stays part of that element's
   hover chain even though it's visually positioned outside the wrap's
   own box (a small circular photo). */
.team-photo-wrap {
  position: relative;
  flex-shrink: 0;
}
.team-photo {
  display: block;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  object-fit: cover;
}
.team-photo-popup {
  position: absolute;
  top: 100%;
  left: 50%;
  margin-top: 8px;
  transform: translateX(-50%);
  z-index: 60;
  width: 220px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  padding: 8px;
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition);
}
.team-photo-wrap:hover .team-photo-popup,
.team-photo-wrap:focus-within .team-photo-popup {
  visibility: visible;
  opacity: 1;
  pointer-events: auto;
}
.team-photo-popup img {
  display: block;
  width: 100%;
  border-radius: calc(var(--radius) - 2px);
}
.team-photo-credit {
  margin-top: 6px;
  font-size: calc(11px * var(--ui-scale));
  font-style: italic;
  color: var(--text-muted);
  text-align: center;
  line-height: 1.4;
}

.team-footnote {
  max-width: 80%; /* matches .about-content, see that rule's comment */
  font-size: calc(13.5px * var(--ui-scale));
  color: var(--text-muted);
  font-style: italic;
  margin: 0 0 1em;
}

/* =========================================================
   Chart toolbar: country picker, fuel picker, remove-elements toggle
   ========================================================= */
#chart-toolbar,
#stack-chart-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 16px;
}
/* Plain-selector `display: flex` above beats the browser's UA default
   [hidden] { display: none } by CSS origin (author > user-agent), same
   "[hidden] can be silently overridden" gotcha noted elsewhere in this
   file -- toggling the `hidden` attribute on either toolbar (see
   _setScatterChromeVisible()/_setStackChromeVisible() in main.js) would
   otherwise have no visual effect at all. */
#chart-toolbar[hidden],
#stack-chart-toolbar[hidden] {
  display: none;
}

.picker {
  position: relative;
  display: inline-block;
}

.toolbar-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: #fff;
  cursor: pointer;
  font-size: calc(11.5px * var(--ui-scale));
  font-weight: 500;
  color: var(--text);
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.toolbar-btn:hover { background: var(--bg-sidebar); border-color: var(--accent); }
/* Several toolbar buttons also carry .tooltip-word (see CLAUDE.md's
   "Results tab: toolbar-button tooltips") purely to reuse the existing
   glossary-tooltip mechanics -- that's plumbing, not a visual cue, so a
   toolbar button must look identical whether or not it happens to have a
   tooltip wired up. .tooltip-word's own underline/color/cursor:help is
   undone here rather than never applied, since the generic tooltip system
   always adds that class regardless of element type. */
.toolbar-btn.tooltip-word {
  color: var(--text);
  text-decoration: none;
  cursor: pointer;
}
.toolbar-btn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.toolbar-btn.active:hover { background: var(--accent-hover); }

/* Remove Elements is destructive (it hides chart glyphs), so its "on"
   state uses the warning colour instead of the generic accent above. */
#remove-elements-btn.active {
  background: var(--negative);
  border-color: var(--negative);
}
#remove-elements-btn.active:hover { background: var(--negative); }

#cp-count, #fp-count, #traces-count, #sp-count { color: var(--text-muted); font-weight: normal; }

.picker-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 50;
  width: 300px;
  max-height: 440px;
  overflow-y: auto;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 4px 16px rgba(0,0,0,.12);
}
.picker-dropdown[hidden] { display: none; }

.cp-section { padding: 8px 0 4px; }
.cp-section + .cp-section { border-top: 1px solid var(--border); }

.cp-section-title {
  padding: 2px 12px 6px;
  font-size: calc(10px * var(--ui-scale));
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}

.cp-label {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 12px;
  cursor: pointer;
  font-size: calc(13px * var(--ui-scale));
  color: var(--text);
  user-select: none;
}
.cp-label:hover { background: #f1f5f9; }
.cp-label input[type="checkbox"] { cursor: pointer; accent-color: var(--accent); flex-shrink: 0; }
.cp-group { font-weight: 600; }

/* Country picker "Groups" submenu (top chart only -- see CLAUDE.md).
   .cp-groups-toggle is the entry point; clicking it expands/collapses
   .cp-groups-list right below it, in place (not a floating flyout to the
   side -- .picker-dropdown's overflow-y:auto makes overflow-x resolve to
   'auto' too per the CSS overflow spec, which would clip a side flyout).
   Styled identically to .cp-section-title (the "Countries" subheading
   right below it) rather than like a regular .cp-label row, since it
   reads as a section heading that happens to be clickable, not a
   selectable item. */
.cp-groups-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 2px 12px 6px;
  border: none;
  background: none;
  cursor: pointer;
  font-size: calc(10px * var(--ui-scale));
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  text-align: left;
}
.cp-groups-caret {
  font-size: calc(9px * var(--ui-scale));
  transition: transform var(--transition);
}
.cp-groups-toggle.cp-groups-open .cp-groups-caret { transform: rotate(90deg); }

.cp-groups-list[hidden] { display: none; }
.cp-groups-list { padding-bottom: 2px; }

.cp-groups-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px 4px 22px;
  font-size: calc(13px * var(--ui-scale));
  color: var(--text);
}
.cp-groups-row-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cp-groups-btn {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: #fff;
  cursor: pointer;
  font-size: calc(13px * var(--ui-scale));
  line-height: 1;
  color: var(--text-muted);
  padding: 0;
}
.cp-groups-add:hover { border-color: var(--positive); color: var(--positive); }
.cp-groups-remove:hover { border-color: var(--negative); color: var(--negative); }

/* "+" turns blue once every selectable member of that group (i.e. every
   member with a checkbox in the Countries section below) is already
   checked -- see _cpUpdateGroupButtonStates(). */
.cp-groups-add.cp-groups-add-full {
  border-color: var(--accent);
  background: var(--accent);
  color: #fff;
}
.cp-groups-add.cp-groups-add-full:hover { border-color: var(--accent-hover); background: var(--accent-hover); color: #fff; }

.dl-dropdown {
  width: 170px;
  max-height: none;
  padding: 4px 0;
}
.dl-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 7px 12px;
  border: none;
  background: none;
  cursor: pointer;
  font-size: calc(13px * var(--ui-scale));
  font-family: inherit;
  color: var(--text);
}
.dl-menu-item:hover { background: #f1f5f9; }

.picker-search {
  display: block;
  width: calc(100% - 24px);
  margin: 4px 12px 6px;
  padding: 5px 8px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: calc(12px * var(--ui-scale));
  outline: none;
  box-sizing: border-box;
}
.picker-search:focus { border-color: var(--accent); }

.fp-fuel-icon {
  width: 14px;
  height: 14px;
  fill: var(--text-muted);
  flex-shrink: 0;
}

#results-placeholder {
  color: var(--text-muted);
  margin-top: 60px;
  text-align: center;
  font-size: calc(15px * var(--ui-scale));
}

.results-meta {
  font-size: calc(12px * var(--ui-scale));
  color: var(--text-muted);
  margin-bottom: 16px;
}

/* Debug section */
#debug-section {
  margin-bottom: 20px;
  font-size: calc(11px * var(--ui-scale));
  color: #94a3b8;
}
#debug-section > summary {
  cursor: pointer;
  user-select: none;
  list-style: none;
  color: #94a3b8;
  font-size: calc(11px * var(--ui-scale));
}
#debug-section > summary::before { content: '▶ '; }
#debug-section[open] > summary::before { content: '▼ '; }

#debug-body {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
  margin-top: 8px;
  padding: 10px 12px;
  background: #f8fafc;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.debug-group { }
.debug-group-title {
  font-weight: 700;
  color: #64748b;
  margin-bottom: 4px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: calc(10px * var(--ui-scale));
}
.debug-row {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  line-height: 1.6;
}
.debug-key { color: #94a3b8; }
.debug-val { color: #475569; font-variant-numeric: tabular-nums; text-align: right; }

/* Debug section: IndexedDB stats / current-chart provenance / reset
   buttons -- a sibling of #debug-body (not inside it, since renderDebug()
   fully rebuilds #debug-body's innerHTML on every query and would wipe
   this out). Reuses .debug-group/.debug-row/.debug-key/.debug-val for
   visual consistency with #debug-body's own groups. */
#debug-extra {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
  margin-top: 8px;
  padding: 10px 12px;
  background: #f8fafc;
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
#debug-storage-actions {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}
.debug-danger-btn {
  font-size: calc(11px * var(--ui-scale));
  padding: 5px 10px;
  color: #b91c1c;
  border-color: #fca5a5;
  background: #fef2f2;
}
.debug-danger-btn:hover { background: #fee2e2; }

/* =========================================================
   Country Details tab
   ========================================================= */
/* Sticky: stays pinned to the top of .tab-panel-scroll (the scrolling
   container) so "Select Countries"/"Download" remain reachable while
   scrolling through the per-country results. The scroller has 24px
   top padding, so the negative margin + matching padding lets the opaque
   background reach the scrollport's very top edge when stuck, so content
   scrolling underneath doesn't show above the buttons. z-index is above
   the tables/charts but below modals and the tooltip popup. */
#cd-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  position: sticky;
  top: -24px;
  z-index: 20;
  margin: -24px -32px 16px;
  padding: 24px 32px 10px;
  background: var(--bg-main);
}

.cd-intro {
  margin: 0 0 20px;
  line-height: 1.6;
  max-width: 900px;
}

.cd-country-block {
  margin-bottom: 36px;
  padding-bottom: 24px;
  border-bottom: 1px solid var(--border);
}
.cd-country-block:last-child { border-bottom: none; }

.cd-country-title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: calc(20px * var(--ui-scale));
  margin: 0 0 14px;
}
.cd-country-title .cd-flag { font-size: calc(26px * var(--ui-scale)); line-height: 1; }

.cd-section-title {
  font-size: calc(14px * var(--ui-scale));
  font-weight: 700;
  margin: 24px 0 8px;
  color: var(--text);
}

/* Shared indentation style for a row that's a sub-item of the row above
   it (e.g. the Support table's "… in Billion $" row) -- applies across
   every Country Details table. */
tr.cd-indent-row th {
  padding-left: 28px;
  font-weight: 400;
  color: var(--text-muted);
}

/* table.cd-*-table (element + class), not just .cd-*-table -- same
   "guarantee this wins regardless of stylesheet order" reasoning the
   table-layout:fixed rule below already uses: a bare class selector
   here has the exact same (0,1,1) specificity as .result-table th/td's
   own text-align:left rule further down this file, so without the
   extra element-type selector, whichever rule happens to sit LATER in
   the file would silently win the tie -- which is exactly what was
   happening here (text-align:left always won, silently un-centering
   every one of these three tables' headers and data cells) until this
   fix. */
table.cd-overview-table th, table.cd-overview-table td,
table.cd-dependence-table th, table.cd-dependence-table td,
table.cd-phaseout-table th, table.cd-phaseout-table td,
table.cd-development-table th, table.cd-development-table td { text-align: center; }
table.cd-overview-table th:first-child, table.cd-overview-table td:first-child,
table.cd-dependence-table th:first-child, table.cd-dependence-table td:first-child,
table.cd-phaseout-table th:first-child, table.cd-phaseout-table td:first-child,
table.cd-development-table th:first-child, table.cd-development-table td:first-child {
  text-align: left;
}

/* Decimal-aligned-while-centered numeric cells (Dependence + Development
   Status tables) -- see _cdAlignDecimalCells() in main.js, which measures
   each table's own rendered int-part/rest-part spans and imposes a
   shared fixed width on each group so every row's decimal point lands
   at the same x position, while the combined (int+rest) pair, now a
   constant total width, still centers correctly via the td's own
   text-align:center above. */
.cd-decimal-int { display: inline-block; text-align: right; }
.cd-decimal-rest { display: inline-block; text-align: left; white-space: nowrap; }

/* "(est)" indicator (Dependence table only -- see _cdSetDecimalCell() in
   main.js): a separate, smaller-font line stacked BELOW the number
   (.cd-value-line) rather than appended inline after it, so it reads as
   an annotation on the figure rather than part of the figure itself.
   `.cd-est-indicator-hidden` keeps the line's own height reserved
   (`visibility: hidden`, not `display: none`) for a cell with no
   estimate -- this is what keeps every fuel column's number sitting at
   the identical vertical position within a row, whether or not that
   particular cell actually carries "(est)" underneath it. */
.cd-value-line { display: block; }
.cd-est-indicator {
  display: block;
  font-size: 0.72em;
  line-height: 1.3;
  color: var(--text-muted);
  white-space: nowrap;
}
.cd-est-indicator-hidden { visibility: hidden; }

/* Phaseout pathway table: the per-year reduction rows (2030, 2035, ...)
   read as plain data under the "Reduction below current levels:"
   section heading right above them, not as their own bold sub-headers
   -- only this table's own ordinary .result-table th styling (bold,
   shaded) is overridden; the structural heading row and the "Year to
   effectively end extraction"/"International Finance" summary rows
   below it keep the default bold look. */
tr.cd-phaseout-year-row th { font-weight: 400; background: transparent; }

/* Shared "this is a reference/comparison figure, not the country's own"
   muted-grey styling -- the Dependence table's "Median of all
   extractors" column group, the Development Status table's "Average
   of all countries" column AND the Capability and responsibility
   table's "Global" column, both of which compare the SAME country's
   own figure (in the sibling column) against some broader reference. */
.cd-dep-median-col { color: var(--text-muted); }

/* Column widths for all four Country Details tables are set via an
   explicit <colgroup> built in JS (_cdBuildColgroup()) rather than CSS,
   because the Dependence table's 2-row <thead> (a colspanned group-
   header row above the real per-fuel header row) makes table-layout's
   normal "size columns from the first row" behavior use the WRONG row
   -- a plain per-cell `width` rule ends up applying to the colspanned
   group header instead of the individual fuel columns it's supposed to
   size, and table-layout:fixed's handling of a specified width on a
   colspanned cell is unreliable. <colgroup> sizes columns directly,
   sidestepping that row entirely. Dropping width:100% (so the table
   doesn't get stretched back out to fill the container only to have
   that slack redistributed across columns) is still required -- the
   table just sizes to the sum of its <col>s. */
/* table.cd-*-table (element + class) rather than just .cd-*-table --
   .result-table's own width:100% has equal specificity as a bare class
   selector, so a later cascade position would silently win and stretch
   these back out; the extra element-type selector guarantees this wins
   regardless of stylesheet order. */
table.cd-overview-table, table.cd-support-table,
table.cd-dependence-table, table.cd-phaseout-table,
table.cd-development-table {
  width: auto;
  table-layout: fixed;
}

/* A Dependence table group-header cell ("Median of all extractors"/its
   translations) can carry a single unbreakable word wider than its own
   super-column -- table-layout:fixed still lets an unbreakable word
   force its cell (and so the whole column) wider than its <col> width,
   since it won't clip text by default. Letting it break mid-word here
   keeps the column honestly the width _cdDepGroupW() gave it instead.
   The Development Status table's own "Average of all countries"
   header carries the same risk, so it gets the same treatment. */
.cd-dependence-table th, .cd-development-table th { overflow-wrap: anywhere; }

.cd-phaseout-charts {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin: 14px 0 4px;
}
.cd-fuel-chart-block { flex: 0 0 auto; }
.cd-fuel-chart-label {
  font-size: calc(12px * var(--ui-scale));
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 4px;
  text-align: center;
}
.cd-fuel-chart { width: 260px; height: 150px; display: block; }
.cd-chart-axis, .cd-chart-tick { stroke: var(--border); stroke-width: 1; }
.cd-chart-tick-label { font-size: calc(9px * var(--chart-text-scale)); fill: var(--text-muted); }
.cd-chart-axis-title { font-size: calc(9px * var(--chart-text-scale)); font-weight: 600; fill: var(--text-muted); }
.cd-chart-line { fill: none; stroke-width: 2; }
.cd-chart-hit-area { fill: none; stroke: transparent; stroke-width: 14; cursor: crosshair; }
.cd-chart-marker { stroke: #fff; stroke-width: 1.5; }
.cd-chart-marker[hidden] { display: none; }

/* Tables */
.result-table {
  width: 100%;
  border-collapse: collapse;
  font-size: calc(12px * var(--ui-scale));
  margin-bottom: 8px;
}
.result-table th, .result-table td {
  border: 1px solid var(--border);
  padding: 5px 8px;
  text-align: left;
}
.result-table th { background: #f1f5f9; font-weight: 600; }
.result-table tr:hover td { background: #f8fafc; }

#results-tables h3, .dev-chart-table h3 {
  margin: 24px 0 8px;
  font-size: calc(14px * var(--ui-scale));
  color: var(--text);
}
#results-tables h3:first-child { margin-top: 0; }
.dev-chart-table { margin-top: 8px; }
.dev-chart-table table { max-width: 100%; }
.dev-chart-table td { font-variant-numeric: tabular-nums; }

/* "Content below is only shown in developer mode" divider, and the
   faint pink tint behind everything under it -- #dev-stack-table/
   #results-tables are the only two Results-tab sections currently
   gated on developer_mode down here (the OTHER dev-only block on this
   tab, #debug-section, sits at the very TOP instead, above the charts,
   so it's out of scope for a divider specifically about what's below
   it). A thick coloured top/bottom border plus bold, letter-spaced,
   centered text is what makes this "very clearly visible" against the
   plain prose/tables around it -- deliberately not pink itself, so it
   reads as the boundary BETWEEN the normal white area above and the
   tinted developer area below, rather than blending into either. */
#dev-mode-divider {
  margin: 32px 0 20px;
  padding: 10px 16px;
  border-top: 3px solid #be185d;
  border-bottom: 3px solid #be185d;
  text-align: center;
  font-weight: 700;
  font-size: calc(13px * var(--ui-scale));
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #be185d;
}
.dev-mode-section {
  background: #fdf2f8;
  border-radius: var(--radius);
  padding: 12px 16px;
  margin-top: 12px;
}

/* "Show Table" (#show-table-btn/#show-table-stack-btn) -- on-page mirror
   of the "Data (XLS)" download's own formatting (app.py's
   _build_chart_export_workbook()): bold white-on-dark-blue header,
   alternating light-blue/white rows, a thin box around each run of rows
   sharing a country. Colours are the same hex values used there
   (#1F4E78/#DCE6F1/#808080) so the on-page view and the downloaded file
   read as the same table. Every rule targets BOTH #show-table (the
   scatter chart's own) and #show-table-stack (the stacked area chart's,
   built by _renderShowTableStack() -- see that function's own comment
   for why it's a separate JS implementation reusing these same class
   names rather than a shared render function) so the two tables always
   look identical without duplicating this whole block. */
#show-table-wrap, #show-table-stack-wrap { margin-top: 8px; overflow-x: auto; }
#show-table-wrap[hidden], #show-table-stack-wrap[hidden] { display: none; }
#show-table, #show-table-stack {
  border-collapse: collapse;
  font-size: calc(12.5px * var(--ui-scale));
  font-variant-numeric: tabular-nums;
  min-width: 100%;
}
#show-table th, #show-table-stack th {
  background: #1F4E78;
  color: #fff;
  font-weight: 700;
  text-align: left;
  padding: 6px 10px;
  white-space: nowrap;
}
/* Every header is clickable (see main.js's _renderShowTable()/
   _renderShowTableStack(), each of which wires one delegated click
   listener on its own table element rather than per-<th>, since headers
   are rebuilt on every render) -- sorts the table by that column, click
   again to reverse. .stt-sorted (the currently-sorted column) gets a
   slightly darker background so it reads as "active" alongside its
   ▲/▼ arrow glyph. */
#show-table th.stt-sortable, #show-table-stack th.stt-sortable { cursor: pointer; user-select: none; }
#show-table th.stt-sortable:hover, #show-table-stack th.stt-sortable:hover { background: #163a5c; }
#show-table th.stt-sorted, #show-table-stack th.stt-sorted { background: #163a5c; }
/* The scatter chart's own shared "Share of" super-header (see
   _renderShowTable()'s two-row <thead> above, over the Employment/
   Government Revenue/Domestic Energy sub-columns) -- centered, since
   it spans three columns rather than sitting flush left over just one,
   and NOT also `.stt-sortable` (it has no single column of its own to
   sort by), so it gets none of that class's cursor/hover treatment. */
#show-table th.stt-super { text-align: center; }
#show-table td, #show-table-stack td { padding: 5px 10px; }
#show-table tr.stt-row-a td, #show-table-stack tr.stt-row-a td { background: #fff; }
#show-table tr.stt-row-b td, #show-table-stack tr.stt-row-b td { background: #DCE6F1; }
#show-table tr.stt-grouped td, #show-table-stack tr.stt-grouped td { border-left: 1px solid #808080; border-right: 1px solid #808080; }
#show-table tr.stt-group-start td, #show-table-stack tr.stt-group-start td { border-top: 1px solid #808080; }
#show-table tr.stt-group-end td, #show-table-stack tr.stt-group-end td { border-bottom: 1px solid #808080; }

.no-data {
  color: var(--text-muted);
  font-size: calc(13px * var(--ui-scale));
  margin: 12px 0;
}

/* Spinner */
.spinner {
  display: inline-block;
  width: 16px; height: 16px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
  vertical-align: middle;
}
@keyframes spin { to { transform: rotate(360deg); } }

#results-loading {
  text-align: center;
  margin-top: 60px;
  color: var(--text-muted);
}

/* Country Details AND Support tabs: unlike #results-loading (inline,
   pushes content down), this overlays the whole tab -- #tab-country-
   details/#tab-support are each the nearest positioned ancestor (via
   .tab-panel's position:absolute) for their own loading element, so
   inset:0 here covers that tab's full box, including over any toolbar/
   notice above the content. The [hidden] rule is required: a class
   selector setting display:flex would otherwise beat the UA
   stylesheet's [hidden] { display: none } on specificity alone (see
   CLAUDE.md's "[hidden] can be silently overridden" gotcha). */
.cd-tab-loading-overlay {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: rgba(255, 255, 255, 0.75);
  color: var(--text-muted);
}
.cd-tab-loading-overlay[hidden] { display: none; }

#results-error {
  margin-top: 60px;
  padding: 12px 16px;
  background: #fef2f2;
  border: 1px solid #fca5a5;
  border-radius: var(--radius);
  color: #b91c1c;
  font-size: calc(13px * var(--ui-scale));
}

/* =========================================================
   Support tab (International Finance)
   ========================================================= */
.support-content {
  max-width: 80%; /* responsive, see .about-content's own comment */
}
.support-heading {
  font-size: calc(20px * var(--ui-scale));
  font-weight: 700;
  margin: 0 0 16px;
  color: var(--text);
}
.support-text {
  font-size: calc(14px * var(--ui-scale));
  line-height: 1.6;
  color: var(--text);
  margin-bottom: 24px;
}
.support-text ul {
  margin: 10px 0 10px 20px;
}
.support-text li {
  margin-bottom: 8px;
}
.support-content .field-block {
  margin-bottom: 28px;
  max-width: 480px;
}

/* Collapsed-by-default "More information" disclosure wrapping
   support-costs-detail (see templates/index.html's .advanced-cost-section
   comment) -- a plain native <details>/<summary>, same element
   #debug-section already uses for its own collapsible block, just
   styled for a user-facing context instead of a dev-only one. */
.support-more-info {
  margin-bottom: 24px;
}
.support-more-info summary {
  cursor: pointer;
  font-size: calc(14px * var(--ui-scale));
  font-weight: 600;
  color: var(--tooltip-word-color);
}
.support-more-info summary::marker {
  color: var(--text-muted);
}
.support-more-info .support-text {
  margin-top: 12px;
  margin-bottom: 0;
}

/* "Share of..." pie chart set */
.support-pie-heading {
  font-size: calc(14px * var(--ui-scale));
  font-weight: 700;
  margin: 8px 0 12px;
  color: var(--text);
}
.support-pie-row {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin-bottom: 28px;
}
.support-pie-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: 140px;
  padding: 10px;
  border: 2px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  background: none;
  font: inherit;
}
.support-pie-block:hover { background: var(--bg-sidebar); }
/* Highlighted when this pie's cost-allocation-basis radio is the
   currently checked one -- toggled in JS, not via :has(), so it works
   the same regardless of whether the checked radio changed because the
   user clicked the radio itself or clicked this pie. */
.support-pie-block.support-pie-selected {
  border-color: var(--accent);
  background: #eff6ff;
}
.support-pie-caption {
  font-size: calc(13px * var(--ui-scale));
  font-weight: 600;
  color: var(--text);
  text-align: center;
}
.support-pie-svg { display: block; }
.support-pie-svg path { stroke: #fff; stroke-width: 1; cursor: pointer; }
.support-pie-legend {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: calc(11px * var(--ui-scale));
  color: var(--text-muted);
  width: 100%;
}
.support-pie-legend-row { display: flex; align-items: center; gap: 5px; }
.support-pie-legend-swatch {
  width: 9px; height: 9px; border-radius: 2px; flex-shrink: 0;
}

/* "Results -- Sharing the costs" table: same nested-indent idea as
   .cd-indent-row, but with three depths (the CD tables only ever need
   one) and an italic/muted variant for the structural "of which…" rows,
   which carry no values of their own. */
table.support-results-table-el { width: auto; }
table.support-results-table-el th:first-child { text-align: left; font-weight: 400; }
table.support-results-table-el th:not(:first-child),
table.support-results-table-el td { text-align: right; }
tr.support-row-indent-1 th:first-child { padding-left: 24px; }
tr.support-row-indent-2 th:first-child { padding-left: 48px; }
tr.support-row-indent-3 th:first-child { padding-left: 72px; }
tr.support-row-italic th:first-child {
  font-style: italic;
  color: var(--text-muted);
  font-weight: 400;
}

/* =========================================================
   Publications & About tab -- found while making .about-content's width
   responsive (see that rule's own comment, further up this file): this
   whole "Publications & About tab" section was a dead, leftover SECOND
   copy of it from an earlier design (different class names --
   .about-heading/.about-text/.about-photo [a duplicate of the real
   .about-photo above]/.about-team-grid/.about-team-card/etc. -- none of
   which templates/index.html or content_pages.py actually reference any
   more, confirmed by grep). Only its OWN .about-content sub-rule
   (max-width: 720px, no other properties) was still live, since that
   class name IS real -- it was silently overriding the real
   .about-content rule's width by cascade order, which is exactly the
   kind of "two rules fighting" ambiguity this file's own "Known
   gotchas" section warns about elsewhere. Removed outright, not
   commented out, since none of it is reachable from any current
   template. If a future "about-team-*"-prefixed class mysteriously
   doesn't have any CSS, this is why -- re-author it fresh rather than
   assuming this block is still here to restore. */

/* =========================================================
   Mobile phone warning -- NOT temporary (unlike the pre-release notice
   just below), so its z-index sits even higher (above #dev-notice-
   overlay's 2000) -- the first and only thing visible on an actual
   mobile phone browser until dismissed, ahead of both the pre-release
   notice and the splash screen underneath it.
   ========================================================= */
#mobile-warning-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  z-index: 2100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  /* Defensive fallback alongside #mobile-warning-card's own max-height
     below -- covers a mobile browser's dynamic address-bar/toolbar
     shrinking the REAL visible viewport below what 100vh reports (a
     known quirk on some phone browsers), so even on a device where the
     max-height calc undershoots slightly, the card/button are still
     reachable by scrolling the overlay itself rather than being cut off
     with no way to reach them. */
  overflow-y: auto;
}
#mobile-warning-overlay[hidden] { display: none; }

/* The whole point of this section: on a short viewport (a phone in
   landscape, or any device short enough that the card's natural height
   -- lang picker + the (now longer, see CLAUDE.md's "Mobile phone
   warning popup" section) warning text + the close button -- exceeds
   it), the card must never grow taller than the viewport itself, and
   the close button (the one way to dismiss this blocking overlay) must
   never be pushed off-screen or become unreachable. Solved with a
   bounded max-height plus an internal flex layout: the lang picker and
   close button are flex-shrink:0 (always shown at their full natural
   size), and only the <p> between them is allowed to shrink and, if it
   still doesn't fit, scroll internally (see its own rule below) -- so
   the button always sits fully visible immediately after it, never
   requiring the page itself to scroll to reach it. */
#mobile-warning-card {
  width: min(92%, 420px);
  max-height: calc(100vh - 40px); /* viewport minus the overlay's own 20px top+bottom padding */
  display: flex;
  flex-direction: column;
  background: #fff;
  border-radius: 12px;
  border-top: 6px solid var(--accent);
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.35);
  padding: 20px 24px 24px;
  text-align: center;
}
#mobile-warning-card p {
  margin: 0 0 20px;
  /* Fixed px, NOT scaled by --ui-scale: this popup only ever shows on a
     phone, where the viewport-proportional scale would make text tiny. */
  font-size: 14px;
  line-height: 1.55;
  color: var(--text);
  /* Allowed to shrink below its own content height (flex items default
     to min-height:auto, which otherwise blocks shrinking entirely in a
     column flex container -- a well-known flexbox gotcha) and scroll
     internally once it does, rather than overflowing the card's own
     bounded max-height above. */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

/* Tightens padding/font-size further on a genuinely short viewport
   (a phone in landscape is often well under 480px tall) so the text
   needs to scroll internally less often in practice -- the max-height/
   flex/scroll rules above already guarantee correctness at any height,
   this is purely to reduce how often that scrolling is actually needed. */
@media (max-height: 480px) {
  #mobile-warning-overlay { padding: 10px; }
  #mobile-warning-card {
    max-height: calc(100vh - 20px);
    padding: 14px 18px 18px;
  }
  #mobile-warning-card p { font-size: 13px; margin-bottom: 14px; }
  #mobile-warning-lang-picker { margin-bottom: 10px; }
}

#mobile-warning-lang-picker {
  position: relative;
  display: inline-block;
  flex-shrink: 0;
  margin-bottom: 14px;
}
#mobile-warning-lang-current {
  display: flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 4px 10px;
  cursor: pointer;
  font-size: 13px;
  color: var(--text-muted);
  white-space: nowrap;
}
#mobile-warning-lang-dropdown .lang-option { font-size: 13px; padding: 8px 12px; }
#mobile-warning-lang-current:hover { background: var(--bg-sidebar); color: var(--text); }
#mobile-warning-lang-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 4px 12px rgba(0,0,0,.1);
  z-index: 100;
  min-width: 160px;
  overflow: hidden;
  text-align: left;
}
#mobile-warning-lang-dropdown[hidden] { display: none; }

#mobile-warning-close {
  flex-shrink: 0;
  padding: 12px 32px;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: var(--radius);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--transition);
}
#mobile-warning-close:hover { background: var(--accent-hover); }

/* =========================================================
   TEMPORARY pre-release notice -- remove this whole block (plus the
   matching markup in templates/index.html and the JS block in main.js)
   once this tool has its public release. z-index is deliberately above
   everything except #mobile-warning-overlay (which, on an actual mobile
   phone, takes priority over this one) -- including #site-title-bar/
   #splash-overlay, so it's the first thing visible (after the mobile
   warning, if shown) until dismissed.
   ========================================================= */
#dev-notice-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
}
#dev-notice-overlay[hidden] { display: none; }

#dev-notice-card {
  width: min(90%, 480px);
  background: #fff;
  border-radius: 12px;
  border-top: 6px solid #f59e0b;
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.35);
  padding: 24px 28px;
  text-align: center;
}
#dev-notice-card p {
  margin: 0 0 20px;
  font-size: calc(15px * var(--ui-scale));
  line-height: 1.6;
  color: var(--text);
}
#dev-notice-close {
  padding: 12px 32px;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: var(--radius);
  font-size: 17px;
  font-weight: 600;
  cursor: pointer;
}
#dev-notice-close:hover { background: var(--accent-hover); }

/* =========================================================
   Splash screen
   ========================================================= */
#splash-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
}
#splash-overlay[hidden] { display: none; }

#splash-card {
  width: 60%;
  max-height: 60vh;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.3);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

#splash-content {
  padding: 32px 36px 24px;
  overflow-y: auto;
  flex: 1;
  font-size: calc(11.5px * var(--ui-scale)); /* matches .field-explanation */
  line-height: 1.75;
  color: var(--text);
}
#splash-content p { margin-bottom: 1em; }
#splash-content p:last-child { margin-bottom: 0; }
#splash-content ul { margin: 0.25em 0 1em 1.5em; }
#splash-content li { margin-bottom: 0.5em; }

#splash-footer {
  padding: 16px 36px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: #f8fafc;
  flex-shrink: 0;
}

#splash-lang-picker {
  position: relative;
}

#splash-lang-dropdown {
  position: absolute;
  bottom: calc(100% + 4px);
  left: 0;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 -4px 12px rgba(0,0,0,.1);
  z-index: 100;
  min-width: 100%;
  overflow: hidden;
}
#splash-lang-dropdown[hidden] { display: none; }

#splash-close {
  padding: 12px 32px;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: var(--radius);
  font-size: 17px;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--transition);
}
#splash-close:hover { background: var(--accent-hover); }

/* =========================================================
   Tooltip words  [[text|id]]
   ========================================================= */
.tooltip-word {
  color: var(--tooltip-word-color);
  text-decoration: underline;
  text-decoration-style: dashed;
  text-underline-offset: 2px;
  cursor: help;
}
/* Sidebar-header buttons carry tooltips but must still look like plain
   buttons (same reset .toolbar-btn.tooltip-word does). */
#sidebar-header button.tooltip-word {
  color: var(--text-muted);
  text-decoration: none;
  cursor: pointer;
}
#sidebar-header button.tooltip-word:hover { color: var(--text); }
/* A tooltip-word whose text is itself a link (e.g. a "Caveats" citation) --
   let the dashed tooltip-word underline carry the whole styling rather
   than stacking the browser's own solid link underline on top of it. */
.tooltip-word a {
  color: inherit;
  text-decoration: inherit;
}

/* =========================================================
   Tooltip popup
   ========================================================= */
#tooltip-popup {
  position: fixed;
  z-index: 1000;
  max-width: 360px;
  background: #1e293b;
  color: #f8fafc;
  border-radius: var(--radius);
  padding: 10px 14px;
  box-shadow: 0 4px 16px rgba(0,0,0,.25);
  font-size: calc(13px * var(--ui-scale));
  line-height: 1.5;
  /* Not pointer-events:none -- a combined .radio-mirror-help tooltip (see
     below) can run long enough to need #tooltip-popup-body's scrollbar,
     which needs the mouse to be able to sit over the popup itself. */
}
#tooltip-popup[hidden] { display: none; }

/* A real <a href> inside a tooltip popup's own text (e.g. a citation link
   in a tooltip's body, or inside a combined-tooltip entry) -- styled the
   same blue used for tooltip-word triggers everywhere else in the app,
   including the sidebar's own field explanations (see .tooltip-word
   above, and .about-content a / .equity-framework-text a further down),
   rather than left at the browser's default link blue, which would clash
   with both the app's own colour convention and the popup's dark
   background. */
#tooltip-popup a {
  color: var(--tooltip-word-color);
}

#tooltip-popup-body {
  max-height: 50vh;
  overflow-y: auto;
}
/* The global `* { margin: 0; padding: 0; }` reset (top of this file)
   left a tooltip's own <p>/<ol>/<ul> HTML content completely unstyled --
   <p>s ran together with no visible gap, and <ol>/<ul> markers (which
   render in the list-style-position:outside default's own space,
   normally provided by the list's own margin/padding) had no room and
   were effectively invisible. Same shape convention .about-content/
   .equity-framework-text already use for their own prose blocks
   elsewhere in this file -- margin-left on the list itself (not
   padding, which the reset above also zeroes) is what makes room for
   the marker. */
#tooltip-popup-body p { margin: 0 0 0.5em; }
#tooltip-popup-body ol,
#tooltip-popup-body ul {
  margin: 0.25em 0 0.5em 1.25em;
  /* Follow-up fix: an "outside" marker (the default) is drawn hanging
     in the list's own margin box, to the LEFT of its content edge --
     which #tooltip-popup-body's `overflow-y: auto` right above
     silently turns into `overflow-x: auto` too (per the CSS overflow
     spec, declaring only overflow-y makes the browser resolve
     overflow-x to auto rather than leaving it visible -- the exact
     same gotcha this file's own .picker-dropdown/Groups-submenu
     section already hit, see "Known gotchas"), clipping the marker
     whenever the reserved margin isn't precisely wide enough for it.
     `inside` makes the marker the first inline content of the list
     item instead, so it can never hang outside the content box for
     any overflow rule to clip -- immune to this regardless of the
     exact margin-left value. */
  list-style-position: inside;
}
#tooltip-popup-body li { margin-bottom: 0.3em; }

/* Combined tooltip for a collapsed radio-group dropdown: one entry per
   option that had its own [[text|id]] markup, each with its own small
   title + text, separated from the next by a faint divider. */
.tooltip-popup-entry + .tooltip-popup-entry {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid rgba(248, 250, 252, 0.15);
}
.tooltip-popup-entry-title {
  font-weight: 700;
  margin-bottom: 2px;
}

#tooltip-popup-title {
  font-weight: 700;
  margin-bottom: 4px;
}

.tooltip-table {
  border-collapse: collapse;
  font-size: calc(12px * var(--ui-scale));
}
.tooltip-table td {
  padding: 2px 0;
  vertical-align: top;
  white-space: nowrap;
}
.tooltip-table td:first-child {
  white-space: normal;
  padding-right: 10px;
  color: #cbd5e1;
}
.tooltip-table td:nth-child(2) {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  padding-right: 4px;
}
.tooltip-table td:nth-child(3) {
  color: #94a3b8;
}

/* Chart title -- plain HTML (data-i18n), a sibling of the chart's own
   <svg> rather than part of it, so it needed no change to either
   renderer's internal margin/coordinate math. Shared by both the
   scatter and stacked-area charts. The x-axis title is the opposite:
   a real SVG <text> INSIDE each chart's own coordinate system (see
   .chart-xaxis-title-svg below, and AXIS_TITLE_EXTRA_BOTTOM in
   main.js) -- both renderers grow their canvas/viewBox by that fixed
   amount purely to make room for it, without shifting anything else
   already drawn. */
.chart-title {
  margin: 0 0 2px;
  font-size: calc(15px * var(--ui-scale));
  font-weight: 700;
  color: var(--text);
  text-align: center;
}
/* Author-origin class rule beats the UA [hidden] default at equal
   specificity regardless of source order (author stylesheets always
   outrank user-agent ones) -- same gotcha as #chart-toolbar above,
   needed so scatter-chart-title/stack-chart-title actually disappear
   when _set{Scatter,Stack}ChromeVisible(false) hides them. */
.chart-title[hidden] {
  display: none;
}
.chart-xaxis-title-svg {
  /* 1px larger than .chart-axis-tick's own 10px (the x-axis year-number
     labels this title sits below) -- kept in sync by eye, not a CSS
     calc() off that rule, since the two live in different style blocks
     and a calc() dependency here would be easy to miss if .chart-axis-
     tick's own size ever changes. font-weight stays bold (600) rather
     than matching the tick labels' regular weight. */
  fill: var(--text-muted);
  font-size: calc(11px * var(--chart-text-scale));
  font-weight: 600;
}

/* =========================================================
   Scatter chart (capacity per capita vs. phaseout year)
   ========================================================= */
#scatter-chart {
  position: relative;
  margin: 4px 0 28px;
}

/* Warning labels: up to 4 badges stacked in the chart's top-right
   quadrant, one per key in main.js's WARNING_LABEL_KEYS, plus the chart
   legend (always last) right below them. Flex-column + align-items:
   flex-end does the actual stacking/right-alignment now (gap is set
   inline by main.js, scaled to the current badge font size) rather than
   each badge/the legend having its own absolute position -- simpler,
   and it means a hidden (level 0) badge or a taller/shorter badge (its
   font now scales with the chart, see below) never needs a manually
   recomputed slot; the browser's own flow layout handles it. */
.chart-warning-badges {
  position: absolute;
  top: 8px;
  right: 8px;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  pointer-events: none;
}
.chart-warning-badge {
  white-space: nowrap;
  padding: 4px 9px;
  border-radius: 4px;
  /* Colour (yellow/orange/red) is applied per-badge as the border plus a
     very faint (0.85-toward-white) tint of the same colour as the
     background -- see _renderWarningBadges() in main.js, which sets both
     inline from WARNING_LABELS' bg_color. #fff here is just the fallback
     for the (currently theoretical) case bg_color is missing. Text stays a
     constant dark colour regardless of severity, since text_color (tuned
     for a SOLID colored background, e.g. white-on-red) is no longer used
     here -- it's still used as-is by the warning modal's header, which is
     unaffected by this change. */
  border: 1px solid transparent;
  background-color: #fff;
  color: #1e293b;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
  /* font-size and top are set inline per-badge by _renderWarningBadges()
     in main.js -- font-size matches the chart's own y-axis label (so it
     scales with the chart's actual rendered size instead of staying a
     constant CSS px value), and top is stacked from that same measured
     height rather than the fixed per-key slots this used to be. */
  font-weight: normal;
  /* Condensed stack so long badge text still fits on one line without
     ballooning the box -- falls back gracefully to the regular
     sans-serif where no condensed variant is installed. */
  font-family: "Arial Narrow", "Liberation Sans Narrow", "Helvetica Neue Condensed", sans-serif;
  font-stretch: condensed;
  letter-spacing: -0.1px;
  line-height: 1.3;
  cursor: pointer;
  pointer-events: auto;
}
/* Legend: fuel icon + name, one row, appended as the LAST child of
   .chart-warning-badges above -- so it's simply the last item in that
   same flex-column stack, always directly below whatever badges are
   currently shown (or right at the top if none are). Font size is set
   inline by main.js's _renderWarningBadges(), independently of the
   badges' own font size -- it tracks the chart's x-axis tick labels
   (.chart-axis-tick) rather than the y-axis label the badges match, but
   for the same size-follows-chart reason (a live measured px value, so
   it scales with the chart's actual rendered size). */
.chart-legend {
  display: flex;
  align-items: center;
  gap: 12px;
  pointer-events: auto;
}
.chart-legend-item {
  display: flex;
  align-items: center;
  gap: 4px;
  color: var(--text-muted);
  font-weight: 600;
  white-space: nowrap;
}
.chart-legend-icon {
  width: 1em;
  height: 1em;
  fill: currentColor;
  flex-shrink: 0;
}

/* Warning label modal: same overlay/card shell as the splash screen, but
   the header's background/text colour is set inline per open() call to
   match whichever badge (yellow/orange/red) was clicked -- see
   showWarningModal() in main.js. */
#warning-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 220;
  display: flex;
  align-items: center;
  justify-content: center;
}
#warning-modal-overlay[hidden] { display: none; }

#warning-modal-card {
  width: 60%;
  max-width: 640px;
  max-height: 80vh;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.3);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

#warning-modal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 20px;
  flex-shrink: 0;
}

#warning-modal-title {
  font-size: calc(16px * var(--ui-scale));
  font-weight: 700;
  line-height: 1.4;
}

#warning-modal-close {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.1);
  color: inherit;
  font-size: calc(18px * var(--ui-scale));
  line-height: 1;
  cursor: pointer;
}
#warning-modal-close:hover { background: rgba(0, 0, 0, 0.2); }

#warning-modal-body {
  padding: 20px 24px 28px;
  overflow-y: auto;
  font-size: calc(14px * var(--ui-scale));
  line-height: 1.7;
  color: var(--text);
}
#warning-modal-body p { margin-bottom: 1em; }
#warning-modal-body p:last-child { margin-bottom: 0; }
#warning-modal-body img { display: block; }

/* "CDR options adjusted" modal -- same overlay/card shell as the warning
   modal above, minus its per-open() header colour theming (this one's
   header is a plain constant colour, since there's only ever one
   message here, not one per warning level). */
#cdr-adjusted-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 220;
  display: flex;
  align-items: center;
  justify-content: center;
}
#cdr-adjusted-modal-overlay[hidden] { display: none; }

#cdr-adjusted-modal-card {
  width: 60%;
  max-width: 560px;
  max-height: 80vh;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.3);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

#cdr-adjusted-modal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 20px;
  flex-shrink: 0;
  background: var(--accent);
  color: #fff;
}

#cdr-adjusted-modal-title {
  font-size: calc(16px * var(--ui-scale));
  font-weight: 700;
  line-height: 1.4;
}

#cdr-adjusted-modal-close {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.2);
  color: inherit;
  font-size: calc(18px * var(--ui-scale));
  line-height: 1;
  cursor: pointer;
}
#cdr-adjusted-modal-close:hover { background: rgba(255, 255, 255, 0.35); }

#cdr-adjusted-modal-body {
  padding: 20px 24px 28px;
  overflow-y: auto;
  font-size: calc(14px * var(--ui-scale));
  line-height: 1.7;
  color: var(--text);
}

/* Finance-note modal -- same overlay/card shell as the warning modal
   (wide enough for a long passage with a numbered list), but with the
   cdr-adjusted-modal's plain constant header colour (no per-open
   theming, since this isn't a warning level). */
#finance-note-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 220;
  display: flex;
  align-items: center;
  justify-content: center;
}
#finance-note-modal-overlay[hidden] { display: none; }

#finance-note-modal-card {
  width: 60%;
  max-width: 640px;
  max-height: 80vh;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.3);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

#finance-note-modal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 20px;
  flex-shrink: 0;
  background: var(--accent);
  color: #fff;
}

#finance-note-modal-title {
  font-size: calc(16px * var(--ui-scale));
  font-weight: 700;
  line-height: 1.4;
}

#finance-note-modal-close {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.2);
  color: inherit;
  font-size: calc(18px * var(--ui-scale));
  line-height: 1;
  cursor: pointer;
}
#finance-note-modal-close:hover { background: rgba(255, 255, 255, 0.35); }

#finance-note-modal-body {
  padding: 20px 24px 28px;
  overflow-y: auto;
  font-size: calc(14px * var(--ui-scale));
  line-height: 1.7;
  color: var(--text);
}
#finance-note-modal-body p { margin-bottom: 1em; }
#finance-note-modal-body p:last-child { margin-bottom: 0; }
#finance-note-modal-body ol { margin: 0 0 1em; padding-left: 1.4em; }
#finance-note-modal-body ol:last-child { margin-bottom: 0; }
#finance-note-modal-body a { color: var(--tooltip-word-color); }

/* Help video lightbox -- same overlay shell (fixed/inset:0/centered
   flexbox) every other modal in this app already uses, but sized for a
   16:9 video instead of a text card, and with no header bar at all
   (the close button floats over the video's own top-right corner
   instead) since there's no title/body text to make room for. */
#help-video-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.75);
  z-index: 220;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
#help-video-overlay[hidden] { display: none; }

#help-video-card {
  position: relative;
  width: 100%;
  max-width: 960px;
  background: #000;
  border-radius: 8px;
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.5);
  overflow: hidden;
}

#help-video-player {
  display: block;
  width: 100%;
  max-height: 80vh;
}

#help-video-close {
  position: absolute;
  top: 10px;
  right: 10px;
  width: calc(32px * var(--ui-scale));
  height: calc(32px * var(--ui-scale));
  border: none;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: calc(20px * var(--ui-scale));
  line-height: 1;
  cursor: pointer;
  z-index: 1;
}
#help-video-close:hover { background: rgba(0, 0, 0, 0.8); }

.scatter-chart-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
  font-family: inherit;
}

.chart-axis-label {
  font-size: calc(12px * var(--chart-text-scale));
  font-weight: 700;
  cursor: help;
}
.chart-axis-label.provides { fill: var(--positive); }
.chart-axis-label.needs    { fill: var(--negative); }

.chart-axis-arrow {
  fill: none;
  stroke-width: 1.5;
  cursor: help;
  pointer-events: all; /* fill:none shapes only hit-test their stroke by default -- make the whole outline's interior clickable/hoverable too */
}
.chart-axis-arrow.provides { stroke: var(--positive); }
.chart-axis-arrow.needs    { stroke: var(--negative); }

.chart-avg-line {
  stroke: var(--accent);
  stroke-width: 1;
  stroke-dasharray: 5 4;
}
.chart-avg-label {
  font-size: calc(11px * var(--chart-text-scale));
  fill: var(--accent);
  cursor: help;
}

.chart-x-axis-line {
  stroke: var(--text-muted);
  stroke-width: 1;
}

.chart-axis-tick {
  font-size: calc(10px * var(--chart-text-scale));
  fill: var(--text-muted);
  font-variant-numeric: tabular-nums;
  text-anchor: middle;
}
/* Multiples of 5 not part of the chart's normal tick set: rendered but
   invisible until a hovered area snaps to that year (see
   _highlightAxisYear() in main.js), then revealed bold via
   .chart-axis-tick--active -- same position, no re-render needed. Shared
   by the tick <text> and its .chart-axis-tick-bg backing <rect> (below),
   so the opacity toggle is tag-agnostic; the bold/ink recolor only makes
   sense for the text. */
.chart-axis-tick-extra {
  opacity: 0;
}
.chart-axis-tick--active {
  opacity: 1 !important;
}
text.chart-axis-tick--active {
  font-weight: 700;
  fill: var(--text);
}
.chart-axis-tickmark {
  stroke: var(--text-muted);
  stroke-width: 1;
}
/* Backing rect for a hover-revealed extra tick, so its label stays
   legible even when it lands over another (always-visible) label --
   hidden at rest, revealed together with its text via the shared
   .chart-axis-tick--active rule above. */
.chart-axis-tick-bg {
  fill: var(--bg-main);
  opacity: 0;
  pointer-events: none;
}
.chart-break-line {
  stroke: var(--border);
  stroke-width: 1;
  stroke-dasharray: 2 3;
}
.chart-break-slash {
  stroke: var(--text-muted);
  stroke-width: 2;
}

.chart-point {
  cursor: pointer;
}
#scatter-chart.remove-mode .chart-point { cursor: crosshair; }
#scatter-chart.remove-mode .chart-point:hover use { opacity: .25 !important; }
.chart-point-label {
  font-size: calc(9px * var(--chart-text-scale));
  font-weight: 600;
  fill: var(--text-muted);
  pointer-events: none;
}

/* Traces: grey "ghost" history left by earlier scenarios (see the
   Use Traces toggle). Purely decorative -- no hover/click behaviour --
   so both the dots and the connecting arrows opt out of pointer events
   entirely, unlike the live glyphs they trail behind. */
.chart-trace-dot {
  fill: #888;
  pointer-events: none;
}
.chart-trace-arrow {
  stroke: #888;
  stroke-width: 1.5;
  fill: none;
  pointer-events: none;
}

.chart-empty {
  color: var(--text-muted);
  font-size: calc(13px * var(--ui-scale));
  padding: 32px 0;
  text-align: center;
}
.chart-empty-msg {
  fill: var(--text-muted);
  font-size: calc(12px * var(--chart-text-scale));
  text-anchor: middle;
}

/* Visually-distinct callouts directly under the scatter chart --
   #result-tab-finance-note (ui:result-tab-finance-note:label) and
   #result-tab-local-impacts-note (ui:result-tab-local-impacts-note:label)
   right below it -- styled to read as "read this carefully" (tinted
   background, accent left rail, a circled "i" glyph) without the page
   ever spelling out the words "important information". Colours reuse
   the app's existing --accent blue + its own #eff6ff tint (same pair
   .support-pie-selected already uses), rather than introducing a new
   palette entry for a single box. Named .information-note (renamed from
   .finance-note once a second, non-finance-specific note reused this
   same styling) so the class name doesn't imply it's finance-only. */
.information-note {
  /* No max-width/width here on purpose -- main.js's _applyFixedChartWidth()
     sets an inline `style.width` matching the scatter chart's own fixed
     pixel width exactly (see "Chart sizing" in that file), so every box
     with this class always spans the same screen width as the chart
     above it rather than a static value that would drift from it on
     any other viewport. */
  position: relative;
  margin: 4px 0 20px;
  padding: 14px 18px 14px 46px;
  background: #eff6ff;
  border: 1px solid var(--accent);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
  color: var(--text);
  font-size: calc(12.5px * var(--ui-scale));
  line-height: 1.6;
}
.information-note::before {
  content: "i";
  position: absolute;
  left: 14px;
  top: 14px;
  width: 18px;
  height: 18px;
  line-height: 16px;
  border: 2px solid var(--accent);
  border-radius: 50%;
  text-align: center;
  font-weight: 700;
  font-style: italic;
  font-size: calc(10.5px * var(--ui-scale));
  color: var(--accent);
}

/* =========================================================
   Stacked area chart (emissions decay by country/fuel)
   ========================================================= */
#stacked-area-chart {
  margin: 4px 0 28px;
}

/* Freeform prose block right below the stacked area chart --
   EQUITY_FRAMEWORK_TEXT (definitions.py), rendered via [data-i18n] like
   any other i18n'd HTML blob. Same typography conventions as
   .about-content (Publications & About tab, style.css) -- font-size,
   line-height, p/list spacing -- but its own class rather than reusing
   that one directly, since it lives in an unrelated tab and needs h1/ol
   rules .about-content has no equivalent for (that one only ever uses
   h2/ul). */
.equity-framework-text {
  max-width: 760px;
  font-size: calc(13.5px * var(--ui-scale));
  line-height: 1.75;
  color: var(--text);
  margin: 0 0 28px;
}
.equity-framework-text h1 {
  font-size: calc(17px * var(--ui-scale));
  margin: 0 0 0.6em;
}
.equity-framework-text p { margin: 0 0 1em; }
.equity-framework-text ol { margin: 0.25em 0 1em 1.5em; }
.equity-framework-text li { margin-bottom: 0.4em; }
.equity-framework-text a { color: var(--tooltip-word-color); }

.stack-area-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
  font-family: inherit;
}

.chart-gridline {
  stroke: var(--border);
  stroke-width: 1;
}

.stack-axis-label {
  font-size: calc(11px * var(--chart-text-scale));
  font-weight: 600;
  fill: var(--text-muted);
}

.stack-y-tick {
  text-anchor: end;
}

.stack-area {
  cursor: pointer;
}
.stack-area:hover,
.stack-area:focus-visible {
  opacity: 0.85;
}

.stack-bar {
  cursor: pointer;
}
.stack-bar:hover,
.stack-bar:focus-visible {
  opacity: 0.85;
}

/* The break "cut" through the stacked bands: a thick surface-color line
   painted over the areas, with the thinner dashed .chart-break-line drawn
   on top of it (see renderStackedAreaChart()). */
.stack-break-gap {
  stroke: var(--bg-main);
  stroke-width: 5;
}

.stack-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-bottom: 6px;
  font-size: calc(12px * var(--ui-scale));
  color: var(--text-muted);
}
.stack-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.stack-legend-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
}
