:root {
  /* Surfaces */
  --bg:           #f8f9fa;
  --surface:      #ffffff;
  --surface-low:  #f3f4f5;
  --surface-dim:  #edeeef;

  /* Brand */
  --primary:      #00205b;
  --primary-mid:  #455c99;
  --primary-deep: #00163e;
  --on-primary:   #ffffff;

  /* Text */
  --text:         #191c1d;
  --text-muted:   #444650;
  --text-subtle:  #757681;

  /* Accent (gold — eyebrow only) */
  --accent:       #c5b358;
  --accent-soft:  #f7e382;

  /* Borders */
  --border:       #e1e3e4;
  --border-input: #dee2e6;
  --outline:      #757681;

  /* Hazard */
  --hz-low:   #2a9d6f;
  --hz-mid:   #e0a53b;
  --hz-high:  #d2483f;
  --hz-none:  #93a4a8;

  /* Elevation */
  --shadow-card: 0px 4px 20px rgba(0, 32, 91, 0.05);

  /* Radius */
  --r-sm:   2px;
  --r-md:   4px;
  --r-lg:   8px;
  --r-full: 9999px;

  /* Typography */
  --display: 'IBM Plex Sans Condensed', system-ui, sans-serif;
  --body:    'IBM Plex Sans', system-ui, sans-serif;

  --maxw: 1280px;

  /* Backward-compat aliases (C4) */
  --accent-deep:  #003a7a;
  --teal:         #0d9488;
  --surface-2:    var(--surface-low);
  --line-strong:  #c5c8ca;

  /* Atlas Ledger (#136 Stage 1 — hero index.html only, additive) */
  --ink:               #0B1F3A;
  --chart-white:       #F7F8F6;
  --grid-line:         #C7D0D6;
  --mono:              'IBM Plex Mono', ui-monospace, monospace;

  /* Dimension colors (#136 Stage 1b — Executive Summary + dashboard legend swatches).
     --dim-physical was #A6763A in the original spec draft; Task 0 UX Review (2026-07-20)
     found it hue-collided with --hz-mid severity amber and changed it to #6F5029. */
  --dim-risk:          var(--teal);  /* #0d9488, reuse existing token */
  --dim-physical:      #6F5029;      /* dark ochre */
  --dim-connectivity:  #4C6B85;      /* steel */
  --dim-investment:    #6B4C7A;      /* plum */
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  font-family: var(--body);
  background: var(--bg);
  color: var(--text);
  line-height: 1.55;
  min-height: 100vh;
  font-size: 15px;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--primary-mid); }

.eyebrow {
  font-family: var(--body);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-subtle); /* #136: gold (--accent) reserved for calcBtn only (rosette removed #248) */
  display: block;
}

/* ---------------- TOP NAV ---------------- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 1000;
  background: #ffffff;
  border-bottom: 1px solid var(--border);
}
.topbar-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 24px;
  height: 56px;
  display: flex;
  align-items: center;
  gap: 32px;
}
.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  flex-shrink: 0;
}
.brand:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
  border-radius: var(--r-md);
}
.logo {
  display: flex;
  align-items: center;
  justify-content: center;
}
.brand-text h1 {
  font-family: var(--display);
  font-size: 18px;
  font-weight: 600;
  color: var(--primary);
  line-height: 1;
}
.brand-text h1 span { color: var(--primary); font-weight: 600; }
.brand-text p {
  font-family: var(--body);
  font-size: 9px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-subtle);
  margin-top: 2px;
  white-space: nowrap;
}
.nav {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: auto;
}
.nav-links {
  display: flex;
  align-items: center;
  gap: 4px;
}
.nav-links a {
  font-family: var(--body);
  font-size: 14px;
  font-weight: 500;
  color: var(--text-muted);
  text-decoration: none;
  padding: 4px 10px;
  border-bottom: 2px solid transparent;
  transition: color 0.15s, border-color 0.15s;
}
.nav-links a:hover,
.nav-links a.active {
  color: var(--primary);
  border-bottom-color: var(--primary);
}
.nav .nav-cta { display: none; }
.std-badge { display: none; }

.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin-left: 8px;
  background: none;
  border: none;
  border-radius: var(--r-md);
  color: var(--text-muted);
  cursor: pointer;
}
.nav-toggle:hover { color: var(--primary); }
.nav-toggle:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

.lang-toggle {
  display: flex;
  gap: 2px;
  margin-left: 16px;
  padding-left: 16px;
  border-left: 1px solid var(--border);
}
.lang-toggle button {
  font-family: var(--body);
  font-size: 12px;
  font-weight: 500;
  color: var(--text-subtle);
  background: none;
  border: none;
  cursor: pointer;
  padding: 4px 6px;
  border-radius: var(--r-md);
}
.lang-toggle button.active,
.lang-toggle button[data-active="true"] {
  color: var(--primary);
  font-weight: 600;
}
/* #205: dot disclosure JA/ZH konten-EN — absolute, 0px kontribusi lebar layout,
   tidak memengaruhi breakpoint 978px/446px (style.css:213-256 sebelumnya) */
#langToggle button[data-lang="ja"],
#langToggle button[data-lang="zh"] {
  position: relative;
}
.lang-beta-dot {
  position: absolute;
  top: 1px;
  right: 1px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
  pointer-events: none;
}
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
/* #315: dot disclosure (#205) punya teks screen-reader-only tapi tanpa
   tampilan visual saat hover mouse. Selector lebih spesifik (ID + attr +
   pseudo-class) daripada .sr-only sendirian (0,1,0) — menang tanpa mengubah
   definisi dasar .sr-only, jadi pemakai .sr-only lain tidak kena regresi.
   right:0 (bukan center via left:50%/translateX) sengaja: anchor ke tepi
   kanan tombol (sisi yang sama dengan .lang-beta-dot) supaya tooltip tumbuh
   ke KIRI, bukan ke kanan — cegah kepotong tepi viewport kanan untuk tombol
   ZH (paling kanan di cluster) terutama di breakpoint 446px (topbar
   padding turun ke 16px). position:absolute = 0px kontribusi lebar layout,
   sama seperti dot, tidak memengaruhi breakpoint 978px/446px.
   top:100% (bukan bottom:100%) — `.topbar` header adalah position:sticky;
   top:0 (selalu di puncak viewport), jadi tooltip yang muncul ke ATAS tombol
   selalu kepotong tepi atas browser, di viewport manapun (ketahuan verifikasi
   visual QA COO, bukan spec/diff review). Tumbuh ke BAWAH aman karena selalu
   ada konten di bawah topbar. */
#langToggle button[data-lang="ja"]:hover .sr-only,
#langToggle button[data-lang="zh"]:hover .sr-only,
#langToggle button[data-lang="ja"]:focus-visible .sr-only,
#langToggle button[data-lang="zh"]:focus-visible .sr-only {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 6px;
  width: auto;
  height: auto;
  padding: 6px 10px;
  overflow: visible;
  clip: auto;
  white-space: nowrap;
  background: var(--primary-deep);
  color: var(--on-primary);
  font-size: 11px;
  font-weight: 500;
  line-height: 1.4;
  border-radius: var(--r-md);
  box-shadow: var(--shadow-card);
  z-index: 10;
}
/* C6: mobile nav collapse — hamburger + slide-down disclosure panel (#231) */
/* Breakpoint N=978px measured live (#293): widest width where JA tagline
   (longest label, binding constraint) still wraps to 2 lines with full
   nav+lang-toggle inline = 958px; N = 958+20. */
@media (max-width: 978px) {
  .nav-toggle { display: inline-flex; }

  .nav-links {
    position: absolute;
    top: 100%; left: 0; right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow-card);
    padding: 4px 24px;
    max-height: 0;
    overflow: hidden;
    visibility: hidden;
    transition: max-height 0.18s ease, visibility 0s linear 0.18s;
  }
  .nav-links.is-open {
    max-height: 320px;
    visibility: visible;
    transition: max-height 0.18s ease, visibility 0s linear;
  }
  .nav-links a {
    padding: 13px 4px;
    border-bottom: 1px solid var(--border);
    font-size: 15px;
  }
  .nav-links a:last-child { border-bottom: none; }
}

/* #231/#293: extreme-narrow viewports overflow with hamburger + full
   lang-toggle cluster in the topbar. Tagline is decorative — "IndoFSR" h1
   alone is enough brand identity at this width. Tighten divider spacing
   too (button tap targets themselves untouched, only surrounding gaps).
   Threshold raised 360->446px (#293): after Fix 2's white-space:nowrap +
   flex-shrink:0 on the brand, the tagline no longer yields room to the
   hamburger+lang-toggle cluster, so horizontal overflow starts as high as
   442px (measured live, JA worst case) — 446 = measured worst case +4px
   buffer, confirmed overflow-free 361-430px across all 4 languages. */
@media (max-width: 446px) {
  .brand-text p { display: none; }
  .topbar-inner { gap: 12px; padding: 0 16px; }
  .lang-toggle { margin-left: 8px; padding-left: 8px; }
}

/* ---------------- CONTEXT STRIP ---------------- */
.context {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 52px 24px 40px;
}
.context .eyebrow { margin-bottom: 12px; }
.context h2 {
  font-family: var(--display);
  font-size: 36px;
  font-weight: 600;
  color: var(--primary);
  line-height: 1.3;
  margin-bottom: 12px;
}
.context h2 .accent { color: var(--primary-mid); }
.context .lede {
  font-family: var(--body);
  font-size: 15px;
  color: var(--text-muted);
  max-width: 680px;
  line-height: 1.6;
}
.value-props {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin-top: 28px;
}
@media (max-width: 900px) { .value-props { grid-template-columns: 1fr 1fr; } }
@media (max-width: 600px) { .value-props { grid-template-columns: 1fr; } }

/* #157: quiet single-line trust signal replacing .value-props on index.html —
   scoped under .context (not modifying the shared base rule, since spectrum.html
   reuses .context too). Mono + text-subtle matches the site's existing pattern
   for short fixed attribution strings (.hm-source, .tb-* fields). */
.context .credential-line {
  margin-top: 14px;
  max-width: 680px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--text-subtle);
  line-height: 1.6;
}

.value-prop-body {
  font-size: 13.5px;
  color: var(--text-muted);
  line-height: 1.6;
  margin-top: 6px;
}

.context .meta-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.meta-pill {
  font-family: var(--body);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  padding: 5px 12px;
}
.meta-pill b { color: var(--text); font-weight: 600; }

/* ---------------- LAYOUT ---------------- */
.layout {
  display: grid;
  grid-template-columns: 380px 1fr;
  gap: 22px;
  padding: 18px 24px;
  max-width: var(--maxw);
  margin: 0 auto;
  align-items: stretch; /* #136: explicit (was the implicit default everywhere already) — .atlas-hero #map's height:100% below depends on .map-panel being stretched to the row height */
}
@media (max-width: 1040px) { .layout { grid-template-columns: 1fr; } }

/* ---------------- MAP ---------------- */
.map-panel { position: relative; }
#map {
  height: 620px;
  border-radius: var(--r-lg);
  border: 1px solid var(--border);
}
.atlas-hero #map {
  height: 100%; /* #136 Task 0 fix: fills whatever height .map-panel is stretched to by the grid row (driven by .control-panel's content) — a fixed 620px left a gap below the map once the ink strip's content grew taller than 620px, and .map-hint (anchored to .map-panel, not #map) would float in that gap instead of sitting on the map's actual bottom edge. Scoped to .atlas-hero so spectrum.html's #map (identical id, same base rule) keeps its original fixed 620px. */
  min-height: 480px;
}
/* #172: after a result is computed, show the map BEFORE the form on mobile (map-panel
   moves to the first row) — scoped via .atlas-hero (index.html only, spectrum.html's
   <main> lacks this class) + .has-result (toggled by JS post-submit, see app.js renderResults) */
@media (max-width: 480px) {
  .atlas-hero.has-result .map-panel { order: -1; }
}
.map-hint {
  position: absolute;
  bottom: 14px; left: 14px; right: 14px;
  background: rgba(255,255,255,0.95);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 9px 13px;
  font-size: 12px;
  color: var(--text-muted);
  z-index: 500;
}
.map-hint strong { color: var(--primary); font-weight: 600; }
.atlas-hero .map-hint {
  background: rgba(11, 31, 58, 0.85);
  border-color: var(--grid-line);
  color: var(--chart-white);
}
.atlas-hero .map-hint strong { color: var(--accent); }

/* #136: decorative coordinate ruler — purely visual, no numbers (avoids implying live accuracy) */
.map-ruler {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 18px;
  background-color: rgba(11, 31, 58, 0.08);
  background-image: repeating-linear-gradient(
    to right,
    var(--grid-line) 0px, var(--grid-line) 1px,
    transparent 1px, transparent 24px
  );
  border-top-left-radius: var(--r-lg);
  border-top-right-radius: var(--r-lg);
  z-index: 400;
  pointer-events: none;
}

/* #152: bottom-left corner. top-right is fully occluded by .leaflet-control-layers
   (topright, expands to ~170x265px with all hazard checkboxes loaded). bottom-right was
   tried next but collides with the conditional .overlay-legend (Leaflet bottomright control,
   ~140x135px, shown when the Vs30 or any hazard checkbox is checked — app.js vs30Legend/
   hazardLegend). #159 Task 7 (2026-07-21) moved the vs30/hazard/socio legends here from
   bottomright (CEO decision, to resolve collision with the topright layers-control panel).
   #248 (2026-09-19): the .rosette decoration that used to occupy this corner (bottom:70px,
   40px tall) was removed per CEO decision — the 120px bottom margin below was originally
   sized to clear it (70+40+10px gap). Left unchanged rather than shrunk: #159 Task 8's
   max-height/scroll sizing (below) was measured against this same 120px baseline, and
   re-tightening it is a separate follow-up, not part of #248.
   #159 Task 8: with all 3 legend boxes populated (vs30 + hazard + both socio sections)
   the stack's real content height measures ~533px — taller than the room available at
   either breakpoint (measured via Playwright: ~467px available on desktop 1280x900,
   ~360px on mobile 375x667 before the stack's top edge would reach the map's own top
   edge). Mobile is the binding constraint. 320px leaves a ~40px gap under the map's top
   edge on mobile and a larger unused margin on desktop — one fixed value works for both
   breakpoints because content (533px) exceeds even the larger desktop allowance, so a
   scrollbar is required either way. overflow-y:auto makes the excess reachable by scroll
   instead of clipped/hidden. */
#map .leaflet-bottom.leaflet-left {
  margin-bottom: 120px;
  max-height: 320px;
  overflow-y: auto;
}

/* ---------------- INPUT CARD ---------------- */
.control-panel { display: flex; flex-direction: column; gap: 18px; }
.atlas-hero .control-panel {
  background: var(--ink);
  border-radius: var(--r-lg);
  padding: 24px;
}
.atlas-hero .control-panel .card {
  background: transparent;
  border: none;
  padding: 0;
}
.atlas-hero .control-panel .field-label {
  color: rgba(247, 248, 246, 0.65);
}
.atlas-hero .control-panel input,
.atlas-hero .control-panel select {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.4); /* #136 Task 0 fix: 0.18 measured ~1.5-1.75:1 contrast, fails WCAG 1.4.11 (needs 3:1) for a UI-component boundary; 0.4 measures ~3.7:1 against the input fill / ~4.3:1 against bare --ink */
  color: var(--chart-white);
}
.atlas-hero .control-panel option {
  color: var(--text);
  background: var(--surface);
}
.atlas-hero .control-panel input:focus,
.atlas-hero .control-panel select:focus {
  border-color: var(--accent);
}
.atlas-hero .control-panel .eyebrow {
  color: var(--grid-line);
}
.atlas-hero #lat,
.atlas-hero #lon {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 22px;
}
.card-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 15px;
}

/* ---------------- FORM ---------------- */
.field { display: block; margin-bottom: 14px; }
.field-label {
  font-family: var(--body);
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  display: block;
  margin-bottom: 6px;
}
.coord-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
input, select {
  font-family: var(--body);
  font-size: 14px;
  color: var(--text);
  background: #ffffff;
  border: 1px solid var(--border-input);
  border-radius: var(--r-md);
  padding: 8px 12px;
  width: 100%;
  transition: border-color 0.15s;
}
input:focus, select:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: none;
}
select { cursor: pointer; }

/* ---------------- BUTTONS ---------------- */
.primary-btn,
#calcBtn {
  font-family: var(--body);
  font-size: 14px;
  font-weight: 600;
  background: var(--primary);
  color: #ffffff;
  border: none;
  border-radius: var(--r-md);
  padding: 10px 20px;
  cursor: pointer;
  width: 100%;
  transition: opacity 0.15s;
}
.atlas-hero #calcBtn {
  background: var(--accent);
  color: var(--ink);
}
.primary-btn:hover { opacity: 0.88; }
.primary-btn:active { opacity: 0.76; }
.primary-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.primary-btn.small { width: auto; padding: 8px 16px; font-size: 13px; margin-top: 0; }
/* #233: loading spinner inside primary-btn (PDF download, 8-14s operation) —
   reuses card-spin keyframe (line ~863), border tinted white for contrast on
   the solid navy button background instead of --accent. */
.primary-btn .btn-spinner {
  display: inline-block;
  width: 12px; height: 12px;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  border-radius: 50%;
  margin-right: 6px;
  vertical-align: -2px;
  animation: card-spin 0.7s linear infinite;
}

.ghost-btn {
  font-family: var(--body);
  font-size: 13px;
  font-weight: 500;
  background: transparent;
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 8px 16px;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}
.ghost-btn:hover {
  border-color: var(--primary);
  color: var(--primary);
}

.status { font-size: 12px; margin-top: 10px; min-height: 15px; font-family: var(--body); }
.status.loading { color: var(--primary-mid); }
.status.error { color: var(--hz-high); }
.status.ok { color: var(--hz-low); }

/* ---------------- EMPTY STATE ---------------- */
.empty-state {
  text-align: center;
  padding: 36px 22px;
  color: var(--text-subtle);
}
.empty-state svg { color: var(--border); margin-bottom: 12px; }
.empty-state h3 {
  font-family: var(--display);
  font-size: 15px;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 5px;
}
.empty-state p { font-size: 12.5px; max-width: 260px; margin: 0 auto; }

/* ---------------- RISK SUMMARY ---------------- */
.risk-summary { padding: 20px 22px; }
.risk-top {
  display: flex; align-items: center; justify-content: space-between;
  padding-bottom: 14px; margin-bottom: 14px;
  border-bottom: 1px solid var(--border);
}
.risk-loc { font-family: var(--body); font-size: 12px; color: var(--text-muted); }
.risk-loc b { color: var(--text); }
.siteclass-tag {
  font-family: var(--body);
  font-size: 11px;
  font-weight: 600;
  color: var(--primary);
  background: rgba(0,32,91,0.06);
  border-radius: var(--r-md);
  padding: 5px 10px;
}
.hz-rows { display: flex; flex-direction: column; gap: 9px; }
.hz-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 11px 13px;
  background: var(--surface-low);
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: var(--r-md);
}
.hz-row .hz-name { font-size: 13px; font-weight: 500; color: var(--text); }
.hz-row .hz-sub  { font-size: 11px; color: var(--text-subtle); font-family: var(--body); margin-top: 1px; }
.hz-chip {
  font-family: var(--body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: #fff;
  border-radius: var(--r-full);
  padding: 4px 11px;
  white-space: nowrap;
}
.hz-row.lvl-low    { border-left-color: var(--hz-low); }
.hz-row.lvl-mid    { border-left-color: var(--hz-mid); }
.hz-row.lvl-high   { border-left-color: var(--hz-high); }
.hz-row.lvl-none   { border-left-color: var(--hz-none); }
.hz-chip.lvl-low   { background: var(--hz-low); }
.hz-chip.lvl-mid   { background: var(--hz-mid); }
.hz-chip.lvl-high  { background: var(--hz-high); }
.hz-chip.lvl-none  { background: var(--hz-none); }
.risk-note { font-size: 11px; color: var(--text-subtle); margin-top: 12px; line-height: 1.5; }

/* ---------------- READOUT ---------------- */
.readout-card { display: flex; flex-direction: column; gap: 22px; }
.readout-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 12px;
}
.src-tag {
  font-family: var(--body);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 3px 8px;
  border-radius: var(--r-md);
}
.src-rock    { color: #8a6410; background: #f7eeda; }
.src-surface { color: var(--primary); background: rgba(0,32,91,0.06); }

.param-grid { display: grid; gap: 9px; }
.param-grid.four { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1240px) { .param-grid.four { grid-template-columns: repeat(2, 1fr); } }
/* .dash-card's real width comes from .panel-grid's auto-fill(280px) track sizing, not
   viewport — it lands ~280-390px regardless of viewport once >=3 cards share the row,
   so the 1240px viewport breakpoint above never fires in time here. Force 2 columns
   unconditionally for this container so the 4th param (e.g. T_L) never overflows. */
.dash-card .param-grid.four { grid-template-columns: repeat(2, 1fr); }
.param {
  background: var(--surface-low);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 12px 8px 10px;
  text-align: center;
}
/* C2: .param.key uses navy-tint, NOT gold-soft */
.param.key { background: rgba(0,32,91,0.06); border-color: var(--border); }
.pname { display: block; font-size: 12px; color: var(--text-muted); margin-bottom: 5px; font-weight: 500; }
.pval {
  display: block; font-family: var(--body); font-size: 21px; font-weight: 600;
  color: var(--text); line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.param.key .pval { color: var(--primary); }
.punit { display: block; font-size: 10.5px; color: var(--text-subtle); margin-top: 3px; }

/* ---------------- UNIFIED REPORT (spectrum.html) ---------------- */
.report {
  max-width: var(--maxw);
  margin: 4px auto 8px;
  padding: 0 24px;
}
.report-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.report-head {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  flex-wrap: wrap;
  padding: 18px 24px;
  background: var(--surface-low);
  border-bottom: 1px solid var(--border);
}
.report-head .rh-left { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.report-head .rh-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; }
.report-head .rh-loc { font-family: var(--body); font-size: 13px; color: var(--text-muted); }
.report-head .rh-loc b { color: var(--text); }
.report-grid {
  display: grid;
  grid-template-columns: 0.95fr 1.25fr;
  gap: 0;
}
@media (max-width: 1040px) { .report-grid { grid-template-columns: 1fr; } }
.report-left {
  padding: 22px 24px;
  border-right: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 22px;
}
@media (max-width: 1040px) { .report-left { border-right: none; border-bottom: 1px solid var(--border); } }
.report-right { padding: 20px 24px; display: flex; flex-direction: column; }
.report-right .chart-title {
  display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 10px;
}
.report-right .chart-title h2 { font-family: var(--display); font-size: 16px; font-weight: 600; color: var(--primary); }

.chart-section { max-width: var(--maxw); margin: 4px auto 22px; padding: 24px 26px; }
.chart-header { display: flex; align-items: flex-end; justify-content: space-between; margin-bottom: 14px; }
.chart-header h2 { font-family: var(--display); font-size: 18px; font-weight: 600; margin-top: 4px; color: var(--primary); }
#spectrumChart { width: 100%; height: 430px; min-height: 340px; flex: 1; }

/* ---------------- EXECUTIVE SUMMARY ---------------- */
.exec-section { max-width: var(--maxw); margin: 0 auto 24px; padding: 0 24px; }
.exec-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 24px 28px;
}
.exec-loc { font-family: var(--body); font-size: 13px; color: var(--text-muted); margin-right: 8px; }
.exec-loc b { color: var(--text); }
.exec-narrative { margin: 14px 0 18px; }
.exec-dim-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 12px;
}
.exec-dim-card {
  background: var(--surface-low);
  border-radius: var(--r-md);
  padding: 10px 13px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.exec-dim-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}
/* #136 Stage 1b Task 0 fix (M2): .exec-dim-card is flex-direction:column, so a bare
   .dim-swatch placed as a direct sibling before .exec-dim-label would fall onto its
   own row instead of sitting inline before the label text. This row wrapper keeps
   swatch+label on one line while .exec-dim-card's own column layout is untouched. */
.exec-dim-label-row {
  display: flex;
  align-items: center;
  gap: 6px;
}
.exec-dim-chip {
  font-size: 12px;
  font-weight: 600;
  padding: 3px 9px;
  border-radius: var(--r-md);
  display: inline-block;
  width: fit-content;
}
.exec-dim-chip.dim-low  { background: #d1fae5; color: #065f46; }
.exec-dim-chip.dim-mid  { background: #fef3cd; color: #92400e; }
.exec-dim-chip.dim-high { background: #fde8e8; color: #b91c1c; }
.exec-dim-chip.dim-na   { background: #f3f4f6; color: #6b7280; }
.exec-dim-micro {
  font-size: 10.5px;
  font-weight: 400;
  color: var(--text-subtle);
}
.exec-rec { font-size: 0.93em; line-height: 1.6; color: var(--text-muted); margin: 0; }

.title-block {
  margin-top: 16px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  font-family: 'IBM Plex Mono', monospace;
  font-size: 10.5px;
  color: var(--text-muted);
}
.tb-row { display: flex; justify-content: space-between; gap: 12px; padding: 2px 0; flex-wrap: wrap; }
.tb-row + .tb-row { border-top: 1px solid var(--border); }
.tb-brand { font-weight: 600; color: var(--text); }
.tb-label { font-weight: 600; color: var(--text-subtle); margin-right: 4px; }
.tb-field { font-variant-numeric: tabular-nums; }

@media (max-width: 600px) {
  .tb-row { flex-direction: column; gap: 2px; }
  .title-block { font-size: 10px; }
}

.exec-actions { display: flex; gap: 12px; flex-wrap: wrap; }

/* ---------------- DASHBOARD GRID ---------------- */
.dashboard { max-width: var(--maxw); margin: 0 auto 32px; padding: 0 24px; }
.dashboard-inner > .eyebrow { display: block; margin-bottom: 16px; }

/* ---------------- DASH-CARD ---------------- */
.dash-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
}

.card-summary {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px;
}
.card-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  color: var(--text-subtle);
  flex-shrink: 0;
}
.card-info { flex: 1; min-width: 0; }
.card-info h4,
.dash-card h4 {
  font-family: var(--display);
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  margin: 0;
  text-transform: none;
  letter-spacing: 0;
}
.card-metric {
  font-family: var(--body);
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
/* #136 Stage 1b Task 0 fix (H2): NOT a blanket .card-metric font-family swap — 6 of
   10 dashboard cards show category text (e.g. land-cover class names), not numbers.
   Only the 4 genuinely numeric-led cards (seismic/terrain/socio/dibi) get this
   modifier, added by updateCardSummary()'s new isNumeric parameter. */
.card-metric.is-numeric {
  font-family: var(--mono);
}
/* #140: loading placeholder — turn the metric element into a small spinner circle.
   The "…" text is hidden (font-size:0/transparent); reduced-motion fallback below
   restores the static "…" so it stays informative when the animation is killed. */
.card-metric.is-loading {
  display: inline-block;
  width: 15px; height: 15px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  font-size: 0; color: transparent;
  vertical-align: middle;
  animation: card-spin 0.7s linear infinite;
}
@keyframes card-spin { to { transform: rotate(360deg); } }
/* C1: keep .g-* class names exactly */
.card-grade {
  display: inline-block;
  font-family: var(--body);
  font-size: 11px;
  font-weight: 500;
  padding: 2px 8px;
  border-radius: var(--r-sm);
  border: 1px solid currentColor;
  margin-left: 6px;
  vertical-align: middle;
}
.g-low    { color: var(--hz-low);  background: rgba(42, 157, 111, 0.08); }
.g-medium { color: var(--hz-mid);  background: rgba(224, 165, 59, 0.08); }
.g-high   { color: var(--hz-high); background: rgba(210, 72, 63, 0.08); }
.g-none   { color: var(--hz-none); background: rgba(147, 164, 168, 0.08); }
.g-kek    { color: var(--primary); background: rgba(0, 32, 91, 0.08); }
.g-good   { color: var(--hz-low);  background: rgba(42, 157, 111, 0.08); }
.g-fair   { color: var(--hz-mid);  background: rgba(224, 165, 59, 0.08); }
.g-poor   { color: var(--hz-high); background: rgba(210, 72, 63, 0.08); }

.card-detail {
  padding: 0 16px 16px;
  border-top: 1px solid var(--border);
}
/* #144: detail loading placeholder — legible text token, reduced-motion safe */
.detail-loading {
  padding: 14px 0 2px;
  font-size: 13px;
  color: var(--text-subtle);
  font-style: italic;
}

.card-source {
  padding: 6px 16px 10px;
  font-size: 11px;
  color: var(--text-subtle);
  font-style: italic;
  display: flex;
  align-items: center;
  gap: 5px;
}

/* C5: card_admin header/body */
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 8px;
  padding: 16px 16px 0;
}
.card-title {
  font-family: var(--display);
  font-size: 15px;
  font-weight: 600;
  color: var(--primary);
}
.card-body { padding: 0 16px 16px; }

.src-pro-link {
  display: inline-flex;
  align-items: center;
  color: var(--text-subtle);
  opacity: 0.45;
  cursor: default;
  flex-shrink: 0;
  user-select: none;
}

/* ---------------- HAZARD MAP GRID ---------------- */
.hazard-maps {
  max-width: var(--maxw);
  margin: 4px auto 8px;
  padding: 0 24px;
}
.hazard-maps-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.hm-head {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 18px 24px;
  background: var(--surface-low);
  border-bottom: 1px solid var(--border);
}
.hm-sub { font-size: 12.5px; color: var(--text-muted); margin-top: 4px; }
.hm-loc { font-family: var(--body); font-size: 12px; color: var(--text-subtle); white-space: nowrap; }
.hm-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
}
@media (max-width: 1100px) { .hm-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px)  { .hm-grid { grid-template-columns: 1fr; } }
.hm-cell {
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  display: flex; flex-direction: column;
}
.hm-cell:nth-child(3n) { border-right: none; }
.hm-cell:nth-last-child(-n+3) { border-bottom: none; }
@media (max-width: 1100px) {
  .hm-cell:nth-child(3n) { border-right: 1px solid var(--border); }
  .hm-cell:nth-child(2n) { border-right: none; }
  .hm-cell:nth-last-child(-n+3) { border-bottom: 1px solid var(--border); }
  .hm-cell:nth-last-child(-n+2) { border-bottom: none; }
}
@media (max-width: 640px) {
  .hm-cell { border-right: none !important; border-bottom: 1px solid var(--border) !important; }
  .hm-cell:last-child { border-bottom: none !important; }
}
.hm-label {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 14px;
  background: var(--surface-low);
  border-bottom: 1px solid var(--border);
}
.hm-layer-name {
  font-family: var(--display);
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}
.hm-chip {
  font-family: var(--body);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: #fff;
  border-radius: var(--r-full);
  padding: 3px 9px;
  white-space: nowrap;
}
.hm-chip.lvl-low   { background: var(--hz-low); }
.hm-chip.lvl-mid   { background: var(--hz-mid); }
.hm-chip.lvl-high  { background: var(--hz-high); }
.hm-chip.lvl-none  { background: var(--hz-none); }
.hm-chip {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}
.hm-map-wrap {
  position: relative;
  padding: 6px; /* #136 Stage 1b Task 0 fix (C1): gutter keeps registration marks off live map tiles instead of overlapping arbitrary basemap colors */
}
.hm-map-wrap::before {
  /* #136 Stage 1b: corner registration marks (crop-mark/map-sheet convention). Each
     corner is drawn as 2 background-image layers (one short horizontal bar, one short
     vertical bar) meeting at the same anchor point to form an L. z-index sits above
     .hm-map (implicit z-index:auto/0, so any explicit positive z-index paints above it
     regardless of DOM order) but below .hm-map-spinner (z-index:20) so the loading
     overlay still fully covers the marks while loading. */
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
  filter: drop-shadow(0 0 1px rgba(255, 255, 255, 0.9)); /* keeps the mark visible over dark basemap tiles too */
  background-repeat: no-repeat;
  background-image:
    linear-gradient(var(--text-subtle), var(--text-subtle)),
    linear-gradient(var(--text-subtle), var(--text-subtle)),
    linear-gradient(var(--text-subtle), var(--text-subtle)),
    linear-gradient(var(--text-subtle), var(--text-subtle)),
    linear-gradient(var(--text-subtle), var(--text-subtle)),
    linear-gradient(var(--text-subtle), var(--text-subtle)),
    linear-gradient(var(--text-subtle), var(--text-subtle)),
    linear-gradient(var(--text-subtle), var(--text-subtle));
  background-size:
    12px 1.5px, 1.5px 12px,
    12px 1.5px, 1.5px 12px,
    12px 1.5px, 1.5px 12px,
    12px 1.5px, 1.5px 12px;
  background-position:
    left 2px top 2px, left 2px top 2px,
    right 2px top 2px, right 2px top 2px,
    left 2px bottom 2px, left 2px bottom 2px,
    right 2px bottom 2px, right 2px bottom 2px;
}
.hm-map {
  height: 260px;
  background: var(--surface-dim);
}
.hm-map .leaflet-control-zoom { display: none; }
.hm-map .leaflet-control-attribution { font-size: 8px; opacity: 0.5; }
/* #142: per-mini-map loading overlay while its filtered tiles are still loading —
   reuses the .card-metric.is-loading ring/keyframe from #140 as-is, just placed
   inside a full-cover backdrop instead of inline metric text. */
.hm-map-spinner {
  position: absolute; inset: 6px; /* #136 Stage 1b: was inset:0 — match the new .hm-map-wrap padding so the spinner backdrop doesn't bleed into the registration-mark gutter */
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-dim);
  z-index: 20;
}
.hm-map-spinner.hm-spin-hidden { display: none; }
.hm-source {
  padding: 5px 14px;
  font-family: var(--mono); /* #136 Stage 1b: was var(--body) — short fixed attribution strings, consistent with .hm-chip which is already mono */
  font-size: 9.5px;
  color: var(--text-subtle);
  letter-spacing: 0.03em;
  background: var(--surface-low);
  border-top: 1px solid var(--border);
}

/* ---------------- MAP LAYERS PANEL (#160 — below map, replaces L.control.layers) ---------------- */
.map-layers {
  max-width: var(--maxw);
  margin: 4px auto 8px;
  padding: 0 24px;
}
.map-layers-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.ml-head {
  padding: 18px 24px;
  background: var(--surface-low);
  border-bottom: 1px solid var(--border);
}
.ml-sub { font-size: 12.5px; color: var(--text-muted); margin-top: 4px; }
.ml-body {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(0, 1.3fr) max-content;
  gap: 24px;
  padding: 18px 24px;
}
.ml-group-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--display);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text);
  margin: 0 0 10px;
}
.ml-options { display: flex; flex-wrap: wrap; gap: 8px 10px; }
.ml-option {
  display: inline-flex;
  position: relative;
  cursor: pointer;
}
.ml-option input[type="checkbox"],
.ml-option input[type="radio"] {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.ml-option span {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 14px;
  border-radius: var(--r-full);
  border: 1px solid var(--border-input);
  font-size: 12.5px;
  color: var(--text-muted);
  background: var(--surface);
  transition: background 0.15s, border-color 0.15s, color 0.15s;
  user-select: none;
}
.ml-option span::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--grid-line);
  flex-shrink: 0;
  transition: background 0.15s;
}
.ml-option input:checked + span {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}
.ml-option input:checked + span::before {
  content: "\2713";
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--primary);
  font-size: 9px;
  line-height: 12px;
  text-align: center;
}
.ml-option:hover span {
  border-color: var(--primary-mid);
}
.ml-option input:focus-visible + span {
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--primary);
}

/* Basemap group (#mapLayersSection .ml-group--basemap): segmented control, no dot */
.ml-group--basemap .ml-options {
  display: inline-flex;
  gap: 0;
  border: 1px solid var(--border-input);
  border-radius: var(--r-md);
  overflow: hidden;
}
.ml-group--basemap .ml-option + .ml-option {
  border-left: 1px solid var(--border-input);
}
.ml-group--basemap .ml-option span {
  border: none;
  border-radius: 0;
  padding: 6px 16px;
}
.ml-group--basemap .ml-option span::before {
  display: none;
}
.ml-group--basemap .ml-option input:checked + span::before {
  display: none;
}
.ml-group--basemap .ml-option input:focus-visible + span {
  box-shadow: inset 0 0 0 2px var(--accent);
}
@media (max-width: 640px) {
  .ml-body { grid-template-columns: 1fr; gap: 18px; }
}

/* ---------------- FOOTER ---------------- */
.app-footer,
.site-footer {
  background: var(--primary);
  border-top: 2px solid var(--accent);
}
.footer-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 40px;
  padding: 32px 24px 24px;
  align-items: start;
}
@media (max-width: 760px) { .footer-inner { grid-template-columns: 1fr; gap: 18px; } }
.footer-col h4 {
  font-family: var(--body); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase;
  color: rgba(255,255,255,0.62); margin-bottom: 12px; font-weight: 600;
}
.footer-col p, .footer-col a {
  font-size: 12.5px; color: rgba(255,255,255,0.65); text-decoration: none; display: block; margin-bottom: 6px;
}
.footer-col a:hover { color: rgba(255,255,255,0.95); }
.footer-col strong { color: rgba(255,255,255,0.9); }
.footer-brand .fb-name {
  font-family: var(--display);
  font-weight: 600;
  font-size: 17px;
  color: #ffffff;
  margin-bottom: 8px;
  letter-spacing: 0.01em;
}
.footer-brand > p {
  font-size: 12.5px;
  color: rgba(255,255,255,0.6);
  line-height: 1.5;
}
/* Tier 2 — fine print, visually demoted onto a deeper tone (was flat var(--primary) with
   several sub-4.5:1 text opacities; see contrast table in spec 2026-07-21-161). */
.footer-legal {
  background: var(--primary-deep);
  border-top: 1px solid rgba(255,255,255,0.12);
}
.footer-legal > * {
  max-width: var(--maxw); margin-left: auto; margin-right: auto;
}
.footer-legal {
  padding: 16px 24px 28px;
}
.footer-disc-text {
  font-size: 11px; color: rgba(255,255,255,0.65); line-height: 1.6; margin-bottom: 8px;
}
.footer-warranty {
  font-size: 10.5px; color: rgba(255,255,255,0.62); line-height: 1.5;
}
.footer-warranty strong { color: rgba(255,255,255,0.85); }
.footer-copy {
  font-family: var(--body); font-size: 11px; color: rgba(255,255,255,0.62);
  margin-top: 12px;
}
.footer-copy a { color: rgba(255,255,255,0.72); text-decoration: none; }
.footer-copy a:hover { color: rgba(255,255,255,0.92); }

/* ---------------- VS30 NOTE ---------------- */
.vs30-note {
  display: none; margin-top: 7px; font-family: var(--body); font-size: 11.5px;
  color: var(--text-muted); padding: 7px 10px; background: var(--surface-low);
  border: 1px solid var(--border); border-radius: var(--r-md);
}
.vs30-note.show { display: block; }
.vs30-note b { color: var(--primary); }
.vs30-note.nocover { color: #8a6410; background: #f7eeda; border-color: #ecdcb6; }
.vs30-note.ok { color: var(--accent-deep); background: rgba(0,58,122,0.06); border-color: var(--border); }

/* ---------------- GMAPS ROW ---------------- */
.gmaps-row { display: flex; gap: 8px; align-items: stretch; }
.gmaps-row input { flex: 1 1 auto; min-width: 0; }
.gmaps-row .ghost-btn { flex: 0 0 auto; white-space: nowrap; }

/* ---------------- OVERLAY LEGENDS ---------------- */
.overlay-legend {
  background: rgba(255,255,255,0.97); border: 1px solid var(--border); border-radius: var(--r-md);
  padding: 9px 11px; font-size: 11px; line-height: 1.7;
  color: var(--text-muted); margin-top: 6px;
}
.overlay-legend .lg-title {
  font-family: var(--body); font-size: 10px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text); margin-bottom: 5px;
}
.overlay-legend .lg-row { display: flex; align-items: center; gap: 7px; }
.overlay-legend .lg-swatch { width: 13px; height: 13px; border-radius: 3px; border: 1px solid rgba(0,0,0,0.15); }
.overlay-legend .lg-title:not(:first-child) {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}

/* ---------------- LEAFLET RESTYLE ---------------- */
.leaflet-control-layers {
  border: 1px solid var(--border) !important;
  border-radius: var(--r-md) !important;
  box-shadow: var(--shadow-card) !important;
  font-family: var(--body) !important;
  font-size: 12px !important;
  color: var(--text-muted) !important;
  background: var(--surface) !important;
  min-width: 130px;
}
.leaflet-control-layers-expanded {
  padding: 10px 12px !important;
}
.leaflet-control-layers-list label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  color: var(--text-muted);
  font-family: var(--body);
  padding: 3px 0;
  cursor: pointer;
}
.leaflet-control-layers-list input[type="radio"],
.leaflet-control-layers-list input[type="checkbox"] {
  accent-color: var(--primary);
  width: 13px;
  height: 13px;
  cursor: pointer;
  flex-shrink: 0;
}
.leaflet-control-layers-separator {
  border-top: 1px solid var(--border) !important;
  margin: 6px 0 !important;
}
.leaflet-control-layers-overlays .leaflet-control-layers-selector {
  margin-top: 0;
}
.leaflet-popup-content-wrapper { border-radius: var(--r-md); }
.leaflet-popup-content { font-size: 13px; font-family: var(--body); }
.leaflet-popup-content b { color: var(--primary); font-family: var(--body); }
.leaflet-container { font-family: var(--body); }

/* ---------------- TERMS GATE ---------------- */
.terms-gate {
  position: fixed; inset: 0; background: rgba(25,28,29,0.6);
  display: flex; align-items: center; justify-content: center; z-index: 2000; padding: 20px;
}
.terms-gate[hidden] { display: none; }
.terms-box {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  max-width: 500px; width: 100%; padding: 30px 32px;
}
.terms-box h2 { font-family: var(--display); font-size: 19px; font-weight: 600; color: var(--primary); margin: 8px 0 16px; }
.terms-box ul { margin: 0 0 16px; padding-left: 18px; }
.terms-box li { font-size: 13px; color: var(--text-muted); line-height: 1.55; margin-bottom: 9px; }
.terms-box li strong { color: var(--text); font-weight: 600; }
.terms-contact { font-size: 13px; color: var(--text-muted); margin-bottom: 18px; }
.terms-contact a { color: var(--primary-mid); text-decoration: none; font-weight: 600; }

/* ---------------- DOC / METHODOLOGY PAGE ---------------- */
.doc-wrap { max-width: 980px; margin: 0 auto; padding: 30px; }
.doc-hero { padding: 14px 0 26px; border-bottom: 1px solid var(--border); margin-bottom: 30px; }
.doc-hero h2 { font-family: var(--display); font-size: 30px; font-weight: 600; color: var(--primary); margin: 8px 0 10px; }
.doc-hero p { color: var(--text-muted); font-size: 15px; max-width: 720px; }
.doc-toc { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; }
.doc-toc a {
  font-size: 12.5px; color: var(--text-muted); text-decoration: none;
  border: 1px solid var(--border); border-radius: var(--r-full); padding: 6px 13px; background: var(--surface);
  transition: all 0.15s;
}
.doc-toc a:hover { border-color: var(--primary-mid); color: var(--primary-mid); }
.doc-section {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  padding: 26px 28px; margin-bottom: 20px;
  scroll-margin-top: 80px;
}
.doc-section h3 {
  font-family: var(--display); font-size: 20px; font-weight: 600; color: var(--primary);
  display: flex; align-items: center; gap: 11px; margin-bottom: 6px;
}
.doc-section h3 .ico {
  width: 34px; height: 34px; border-radius: 9px; display: flex; align-items: center; justify-content: center;
  background: rgba(0,32,91,0.06); color: var(--primary); flex: none;
}
.doc-section .sub { font-family: var(--body); font-size: 11px; letter-spacing: 0.04em; color: var(--text-subtle); text-transform: uppercase; margin-bottom: 16px; }
.doc-section h4 { font-size: 13.5px; font-weight: 600; color: var(--text); margin: 16px 0 7px; }
.doc-section p, .doc-section li { font-size: 13.5px; color: var(--text-muted); line-height: 1.62; }
.doc-section ul { padding-left: 20px; margin: 6px 0; }
.doc-section li { margin-bottom: 5px; }
.doc-section .formula {
  font-family: var(--body); font-size: 12.5px; color: var(--text);
  background: var(--surface-low); border: 1px solid var(--border); border-left: 3px solid var(--primary);
  border-radius: var(--r-md); padding: 11px 14px; margin: 12px 0; overflow-x: auto;
}
.limit-box {
  background: #fbf6ec; border: 1px solid #ecdcb6; border-radius: var(--r-md);
  padding: 13px 15px; margin-top: 14px;
}
.limit-box .lb-title {
  font-family: var(--body); font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: #8a6410; margin-bottom: 7px; display: flex; align-items: center; gap: 6px;
}
.limit-box p, .limit-box li { color: #7a5c1e; font-size: 12.5px; }
.limit-box.limit-box--note {
  background: rgba(0,58,122,0.06); border-color: var(--border);
}
.limit-box.limit-box--note .lb-title { color: var(--accent-deep); }
.limit-box.limit-box--note p { color: var(--text-muted); }
.src-line { font-size: 12px; color: var(--text-subtle); margin-top: 14px; }
.ver-tag { font-family: var(--body); font-size: 11.5px; background: rgba(0,32,91,0.06); color: var(--primary); padding: 2px 8px; border-radius: var(--r-md); }
.ver-line { margin: 4px 0 14px; font-size: 13px; color: var(--text-muted); }
.ref-link { font-size: 9.5px; color: var(--primary-mid); text-decoration: none; margin-left: 1px; }
.ref-link:hover { text-decoration: underline; }
.cl-table { width: 100%; border-collapse: collapse; font-size: 13px; margin-top: 12px; }
.cl-table th { text-align: left; padding: 7px 10px; border-bottom: 2px solid var(--border); font-size: 11.5px; color: var(--text-muted); font-weight: 600; }
.cl-table td { padding: 8px 10px; border-bottom: 1px solid var(--border); vertical-align: top; color: var(--text-muted); }
.cl-table td:first-child { white-space: nowrap; color: var(--primary); }
.cl-table tr:last-child td { border-bottom: none; }
.cl-table td:nth-child(2) { white-space: nowrap; font-size: 11.5px; color: var(--text-subtle); }
.table-scroll { overflow-x: auto; }

/* ---------------- CONTACT PAGE ---------------- */
.contact-grid {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: 22px;
  align-items: start;
}
@media (max-width: 820px) { .contact-grid { grid-template-columns: 1fr; } }
/* grid item default min-width:auto ignores overflow-wrap on descendant text, causing
   track blowout on narrow viewports (e.g. long email/LinkedIn token) — scoped to this
   grid only, not the shared .doc-section base rule (also used unscoped elsewhere). */
.contact-grid .doc-section { min-width: 0; }
.contact-methods { display: flex; flex-direction: column; gap: 14px; }
.contact-method {
  display: flex; align-items: center; gap: 14px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  padding: 16px 18px; text-decoration: none;
  transition: border-color 0.15s;
}
.contact-method:hover { border-color: var(--primary); }
.cm-ico {
  width: 42px; height: 42px; border-radius: 11px; flex: none;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,32,91,0.06); color: var(--primary);
}
.cm-text { display: flex; flex-direction: column; min-width: 0; }
.cm-text .cm-label { font-family: var(--body); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-subtle); }
.cm-text .cm-value { font-size: 14px; font-weight: 600; color: var(--text); margin-top: 2px; overflow-wrap: break-word; }
.contact-form { display: flex; flex-direction: column; gap: 13px; }
.contact-form textarea {
  width: 100%; min-height: 120px; resize: vertical;
  background: #ffffff; border: 1px solid var(--border-input); border-radius: var(--r-md);
  padding: 11px 12px; font-family: var(--body); font-size: 14px; color: var(--text);
}
.contact-form textarea:focus { outline: none; border-color: var(--primary); box-shadow: none; }
.contact-form .form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 13px; }
@media (max-width: 520px) { .contact-form .form-row { grid-template-columns: 1fr; } }
.contact-intro {
  background: rgba(0,32,91,0.04); border: 1px solid var(--border); border-radius: var(--r-lg);
  padding: 16px 18px; margin-bottom: 22px;
}
.contact-intro p { color: var(--primary); font-size: 13.5px; line-height: 1.6; }

/* C13: Accessibility — prefers-reduced-motion MUST be preserved */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; scroll-behavior: auto !important; }
  /* #140: with the spin animation killed, revert the circle to the static "…" text
     so the loading state stays legible instead of a motionless ring. */
  .card-metric.is-loading {
    width: auto; height: auto;
    border: none; border-radius: 0;
    font-size: 15px; color: var(--text-subtle);
  }
  /* #233: static loading text alone still conveys state, spinner is purely
     decorative motion — hide rather than leave a frozen ring. */
  .btn-spinner { display: none; }
}

/* ---------------- DISASTER HISTORY (DIBI) ---------------- */
#dibiCard { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--border); }
.dibi-grp { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--text-subtle); margin: 0.6rem 0 0.25rem; }
.dibi-kab { margin: 0.3rem 0 0.55rem; }
.dibi-kabname { font-weight: 600; color: var(--text); font-size: 0.9rem; }
.dibi-tot { font-weight: 400; color: var(--text-subtle); }
.dibi-hz { font-size: 0.82rem; color: var(--text-muted); margin: 0.1rem 0 0.1rem 0.6rem; }
.dibi-haz { font-weight: 600; color: var(--primary); }
.dibi-last { color: var(--text-subtle); }
.dibi-period { font-size: 0.74rem; color: var(--text-subtle); margin-top: 0.5rem; }

/* ---------------- TRANSPORT ---------------- */
#transportCard { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--border); }
.tr-row { display: flex; align-items: center; gap: 8px; padding: 3px 0; font-size: 0.85em; }
.tr-cat { width: 80px; color: var(--primary); font-weight: 600; flex-shrink: 0; }
.tr-name { flex: 1; color: var(--text); }
.tr-km { width: 60px; text-align: right; color: var(--text-subtle); }
.tr-chip { padding: 1px 8px; border-radius: var(--r-lg); font-size: 0.75em; color: #fff; }
.tr-close { background: #2a9d6f; }
.tr-mid { background: #e0a53b; }
.tr-far { background: #d2483f; }
.tr-none { color: var(--text-subtle); font-style: italic; }
.tr-level { margin-top: 8px; font-size: 0.85em; color: var(--text); }

/* ---------------- TERRAIN ---------------- */
#terrainCard { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--border); }
#terrainCard h3 { font-family: var(--body); font-size: 10.5px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--accent); margin-bottom: 12px; }
.tn-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.socio-sub-title { font-size: 11px; font-weight: 600; color: var(--teal, #0d9488); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 4px; }
.tn-item { display: flex; flex-direction: column; gap: 2px; }
.tn-label { font-size: 0.75em; color: var(--text-subtle); }
.tn-val { font-size: 1.05em; color: var(--text); font-weight: 600; }
.tn-narr { margin-top: 8px; font-size: 0.85em; color: var(--text-muted); line-height: 1.4; }
.tn-src  { margin-top: 6px; font-size: 0.75em; color: var(--text-muted); font-style: italic; }
.tn-sub  { margin-top: 10px; font-size: 0.8em; font-weight: 600; color: var(--text-muted); }
.tn-list { margin: 4px 0 0 18px; font-size: 0.85em; color: var(--text-muted); line-height: 1.5; }

/* Land cover composition bars */
.lc-comp { margin-top: 10px; }
.lc-bar-row { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; }
.lc-bar-label { font-size: 0.75em; color: var(--text-muted); width: 110px; flex-shrink: 0; text-align: right; }
.lc-bar { height: 10px; background: var(--teal, #0d9488); border-radius: 2px; min-width: 2px; }
.lc-bar-pct { font-size: 0.75em; color: var(--text-subtle); width: 40px; }

/* Age-group composition bars (#148) — values copied from .lc-* above, kept as
   a separate class set so a future landcover-only tweak doesn't silently
   ship to the age chart (148-ux-recommendation.md §2). */
.age-comp { margin-top: 10px; }
.age-bar-row { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; }
.age-bar-label { font-size: 0.75em; color: var(--text-muted); width: 110px; flex-shrink: 0; text-align: right; }
.age-bar { height: 10px; background: var(--teal, #0d9488); border-radius: 2px; min-width: 2px; }
.age-bar-pct { font-size: 0.75em; color: var(--text-subtle); width: 40px; }

/* Age-group detail disclosure — native <details>, collapsed by default */
.age-detail { margin-top: 10px; }
.age-detail summary {
  cursor: pointer;
  font-size: 0.8em;
  font-weight: 600;
  color: var(--text-muted);
  list-style: none;
}
.age-detail summary::-webkit-details-marker { display: none; }
.age-detail summary::before {
  content: "▸";
  display: inline-block;
  width: 0.9em;
  color: var(--teal, #0d9488);
  transition: transform 0.15s ease;
}
.age-detail[open] summary::before { transform: rotate(90deg); }
.age-detail summary:focus-visible {
  outline: 2px solid var(--teal, #0d9488);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Rainfall monthly bars (#90) — row/label/pct copied from .age-bar-row, but
   color comes from 3 opacity tiers of --teal (wet/moist/dry intensity) rather
   than one solid fill, and the label column is narrower (month abbreviations
   vs. age-band names). Kept as its own class family, not a .age-bar rename,
   so a future age-chart tweak can't silently ship here (same rationale as
   the #148 comment above .age-comp). */
.rain-comp { margin-top: 10px; }
.rain-bar-row { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; }
.rain-bar-label { font-size: 0.75em; color: var(--text-muted); width: 32px; flex-shrink: 0; text-align: right; }
.rain-bar { height: 10px; border-radius: 2px; min-width: 2px; background: var(--teal, #0d9488); }
.rain-bar-wet   { opacity: 1; }
.rain-bar-moist { opacity: .55; }
.rain-bar-dry   { opacity: .3; }
.rain-bar-pct { font-size: 0.75em; color: var(--text-subtle); width: 40px; }

/* Rainfall 12-month disclosure — copy of .age-detail (#148) with the class
   renamed; mechanics (chevron, focus ring) intentionally identical. */
.rain-detail { margin-top: 10px; }
.rain-detail summary {
  cursor: pointer;
  font-size: 0.8em;
  font-weight: 600;
  color: var(--text-muted);
  list-style: none;
}
.rain-detail summary::-webkit-details-marker { display: none; }
.rain-detail summary::before {
  content: "▸";
  display: inline-block;
  width: 0.9em;
  color: var(--teal, #0d9488);
  transition: transform 0.15s ease;
}
.rain-detail[open] summary::before { transform: rotate(90deg); }
.rain-detail summary:focus-visible {
  outline: 2px solid var(--teal, #0d9488);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Admin location card */
.admin-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
.admin-table td { padding: 3px 6px 3px 0; vertical-align: top; }
.admin-label { color: var(--text-muted); white-space: nowrap; width: 40%; }
.admin-val { font-weight: 500; }

/* Header enrichment */
.admin-header { margin-top: 4px; font-size: 0.82rem; color: var(--text-muted); line-height: 1.5; }
.admin-line1 { font-weight: 500; color: var(--text); }

/* ---- DASHBOARD INVESTOR-FIRST LAYOUT ---- */
.dashboard-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 24px 0;
  display: flex;
  flex-direction: column;
  gap: 24px;
}
/* #233: shortcut CTA at the end of the dashboard — reuses .ghost-btn, not a
   second .primary-btn, so it doesn't compete with the CTA above the
   dashboard; spacing above it comes from .dashboard-inner's flex gap. */
.dashboard-footer-cta { text-align: center; }
.result-2col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
.result-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.panel-title {
  font-family: var(--body);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-subtle); /* #136 Stage 1b: was var(--accent) gold for all 4 groups undifferentiated — gold reserved for rare accents per Stage 1 §3.4, dimension identity now carried by .dim-swatch instead */
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
  margin: 0;
  display: flex;
  align-items: center; /* #136 Task 0 fix (M1): was baseline — a swatch span has no text baseline and rendered visually offset from the label */
  gap: 8px;
}
.panel-title-num {
  color: var(--border-input);
  font-weight: 600;
}

/* #136 Stage 1b: legend swatch — reusable dimension-identity marker, consumed here
   and by .exec-dim-card (Task 3). Square (r-sm), not a pill — mirrors a printed map
   legend key, not a generic SaaS tag. */
.dim-swatch {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: var(--r-sm);
  flex-shrink: 0;
}
.dim-swatch.dim-risk         { background: var(--dim-risk); }
.dim-swatch.dim-physical     { background: var(--dim-physical); }
.dim-swatch.dim-connectivity { background: var(--dim-connectivity); }
.dim-swatch.dim-investment   { background: var(--dim-investment); }
.panel-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 12px;
  align-items: start;
}

/* ---- ACTION BAR ---- */
.action-bar {
  max-width: var(--maxw);
  margin: 0 auto 20px;
  padding: 0 24px;
}
.action-bar-inner {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  padding: 16px 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  border-left: 3px solid var(--primary);
  align-items: center;
}

/* Mobile responsive for new layout */
@media (max-width: 768px) {
  .result-2col { grid-template-columns: 1fr; }
  .context h2 { font-size: 26px; }
  .status-table th { padding: 8px 10px; }
  .status-table td { padding: 10px 10px; }
}

/* ---- STATUS PAGE TABLE ---- */
.table-scroll { overflow-x: auto; margin-top: 20px; }
.status-table {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
  font-size: 13.5px;
  margin-top: 0;
}
.status-table th {
  font-family: var(--body);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-subtle);
  text-align: left;
  padding: 8px 14px;
  border-bottom: 2px solid var(--line-strong);
}
.status-table td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  color: var(--text-muted);
  vertical-align: top;
}
.status-table tr:last-child td { border-bottom: none; }
.status-table .src-name { font-weight: 600; color: var(--text); display: block; }
.status-table .src-desc { font-size: 12px; color: var(--text-subtle); margin-top: 2px; }
.status-table .src-note { font-size: 11.5px; font-style: italic; color: var(--text-subtle); margin-top: 3px; display: block; }
.status-table .ver-tag { display: inline-block; line-height: 1.4; }
.status-table .status-group-label {
  font-family: var(--body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-subtle);
  text-align: left;
  padding: 16px 14px 6px;
  background: transparent;
  border-bottom: 1px solid var(--border);
}
.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  padding: 4px 10px;
  border-radius: var(--r-full);
  white-space: nowrap;
}
.status-badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.badge-live     { background: rgba(42, 157, 111, .12); color: #1d7a52; }
.badge-live::before { background: var(--hz-low); box-shadow: 0 0 0 3px rgba(42,157,111,.2); }
.badge-partial  { background: rgba(224, 165, 59, .14); color: #8a6200; }
.badge-partial::before { background: var(--hz-mid); box-shadow: 0 0 0 3px rgba(224,165,59,.2); }
.badge-unavailable { background: rgba(210, 72, 63, .12); color: #9c2f28; }
.badge-unavailable::before { background: var(--hz-high); box-shadow: 0 0 0 3px rgba(210,72,63,.2); }
.badge-err { background: rgba(210, 72, 63, .12); color: #9c2f28; }
.badge-err::before { background: var(--hz-high); box-shadow: 0 0 0 3px rgba(210,72,63,.2); }
.badge-static   { background: var(--surface-low); color: var(--text-subtle); }
.badge-static::before { background: var(--hz-none); }
.badge-checking { background: rgba(197, 179, 88, 0.15); color: #7a5c1e; }
.badge-checking::before { background: var(--accent); animation: pulse-dot 1.2s infinite; }
@keyframes pulse-dot { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
.status-note {
  font-size: 12px; color: var(--text-subtle);
  border-top: 1px solid var(--border);
  padding-top: 14px; margin-top: 14px; font-style: italic;
}
/* ---- METODOLOGI / ABOUT PAGE ---- */
.about-dev { display: flex; align-items: flex-start; gap: 20px; margin: 16px 0; }
.about-dev-photo {
  width: 84px; height: 84px;
  border-radius: 50%;
  object-fit: cover;
  flex: none;
  border: 1px solid var(--border);
}
.about-dev-info { flex: 1; }
.about-dev-name {
  font-family: var(--display);
  font-size: 16px; font-weight: 600; color: var(--primary);
}
.about-dev-cred { font-size: 13px; color: var(--text-muted); margin-bottom: 10px; }
.about-dev-link {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--body); font-size: 12.5px; font-weight: 600;
  color: var(--primary-mid); text-decoration: none;
  margin: 2px 0 10px;
}
.about-dev-link svg { flex: none; }
.about-dev-link:hover { color: var(--primary); text-decoration: underline; }
.about-dev-link:focus-visible {
  outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 2px;
}

@media (max-width: 820px) {
  .about-dev { flex-direction: column; gap: 14px; }
  .about-dev-photo { width: 64px; height: 64px; }
}

/* ---- GENERIC PAGE HEADING ---- */
.page-heading, .page-title {
  font-family: var(--display);
  font-size: 28px; font-weight: 600; color: var(--primary); margin-bottom: 8px;
}
.page-lede { font-family: var(--body); font-size: 15px; color: var(--text-muted); margin-bottom: 32px; }
