:root {
  color-scheme: light;

  /* Warm paper neutrals keep long research sessions easy on the eyes. */
  --bg: #f4f1ea;
  --surface: #ffffff;
  --surface-2: #f3f0e8;
  --surface-3: #ece8de;
  --ink: #1b1d1f;
  --ink-2: #41464c;
  --muted: #646970; /* darkened from #6b7178: now clears WCAG AA 4.5:1 on bg and tinted surfaces (was 4.0-4.4) */
  --line: #e4e0d6;
  --line-strong: #d2cdbf;

  /* Teal = interactive / data / research. Never used to encode risk. */
  --accent: #0f6e6e;
  --accent-ink: #0a4f4f;
  --accent-soft: #e3efed;

  /* Heat ramp is reserved strictly for risk levels. */
  /* Risk colours darkened so white pill text clears WCAG AA 4.5:1
     (was 4.04 / 3.01 / 3.61 — all failing). Used for pills, legend swatches,
     and risk-band/nudge border stripes. */
  --low: #2c8656;
  --guarded: #9c6c15;
  --high: #c45427;
  --critical: #c01f2e;
  --low-soft: #e7f1ea;
  --guarded-soft: #f6ecd8;
  --high-soft: #f8e6dc;
  --critical-soft: #f7dde0;

  --radius: 12px;
  --radius-sm: 9px;
  --shadow: 0 1px 2px rgba(27, 29, 31, 0.05), 0 14px 34px rgba(27, 29, 31, 0.06);
  --shadow-sm: 0 1px 2px rgba(27, 29, 31, 0.06);
  --ring: 0 0 0 3px rgba(15, 110, 110, 0.18);
}

* {
  box-sizing: border-box;
}

html {
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Guarantee no page-level horizontal scroll on any device (a common
     "not responsive" flag); wide tables/maps scroll inside their own wrappers. */
  overflow-x: hidden;
}

/* Media never forces the page wider than the screen. */
img, svg, canvas, .leaflet-container {
  max-width: 100%;
}

body {
  margin: 0;
  min-width: 320px;
  min-height: 100vh;
  background: var(--bg);
  color: var(--ink);
  font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-size: 15px;
  line-height: 1.55;
}

/* Skip link: first tab stop, hidden until focused, so keyboard users can jump
   past the sidebar (~12 stops) straight to content. */
.skip-link {
  position: absolute;
  left: 12px;
  top: -48px;
  z-index: 1000;
  padding: 9px 16px;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: #fff;
  font-weight: 700;
  text-decoration: none;
  transition: top 0.15s ease;
}

.skip-link:focus {
  top: 12px;
}

/* Programmatic focus target — no outline on the region itself. */
#mainContent:focus {
  outline: none;
}

/* Every number reads as data: monospaced figures, aligned columns. */
strong,
dd,
td,
.metric strong,
.driver-row strong,
.pill {
  font-variant-numeric: tabular-nums;
}

button,
select,
input {
  font: inherit;
  color: inherit;
}

a {
  color: var(--accent-ink);
}

.app-shell {
  display: grid;
  grid-template-columns: 268px minmax(0, 1fr);
  min-height: 100vh;
}

/* ---------- Sidebar ---------- */

.sidebar {
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  display: flex;
  flex-direction: column;
  gap: 26px;
  border-right: 1px solid var(--line);
  background: linear-gradient(180deg, #fbf9f4, #f6f3ec);
  padding: 22px 20px;
  overflow-y: auto;
}

.brand-logo {
  display: block;
  padding: 6px 4px 2px;
}

.brand-logo img {
  display: block;
  width: 100%;
  max-width: 210px;
  height: auto;
}

.app-title {
  display: grid;
  gap: 2px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
}

.app-title h1,
.topbar h2,
.panel h3,
.pipeline-grid h4 {
  margin: 0;
}

.app-title h1 {
  font-size: 1.18rem;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.brand-links {
  display: grid;
  gap: 7px;
}

.brand-links a {
  display: flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--accent-ink);
  padding: 9px 11px;
  font-size: 0.8rem;
  font-weight: 700;
  text-decoration: none;
  transition: border-color 0.15s, background 0.15s;
}

.brand-links a::before {
  content: "↗";
  color: var(--accent);
  font-weight: 800;
}

.brand-links a:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.eyebrow {
  margin: 0 0 5px;
  color: var(--muted);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.role-switch {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 3px;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}

.role-btn {
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--muted);
  padding: 7px 4px;
  font-size: 0.8rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.role-btn:hover {
  color: var(--ink);
}

.role-btn.active {
  background: var(--accent);
  color: #fff;
  box-shadow: var(--shadow-sm);
}

.nav-list {
  display: grid;
  gap: 4px;
}

.nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--ink-2);
  padding: 10px 12px;
  text-align: left;
  font-size: 0.92rem;
  font-weight: 650;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.nav-item span:first-child {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 7px;
  background: var(--surface-3);
  color: var(--muted);
  font-weight: 800;
  font-size: 0.85rem;
  transition: background 0.15s, color 0.15s;
}

.nav-item:hover {
  background: var(--surface-2);
  color: var(--ink);
}

.nav-item.active {
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-weight: 750;
}

.nav-item.active::before {
  content: "";
  position: absolute;
  left: -20px;
  top: 8px;
  bottom: 8px;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--accent);
}

.nav-item.active span:first-child {
  background: var(--accent);
  color: #fff;
}

.data-freshness {
  margin-top: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  padding: 14px;
}

.data-freshness .eyebrow {
  margin-bottom: 10px;
}

.data-freshness dl {
  display: grid;
  gap: 9px;
  margin: 0;
}

.data-freshness div {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 0.84rem;
}

.data-freshness dt {
  color: var(--muted);
}

.data-freshness dd {
  margin: 0;
  font-weight: 700;
}

/* ---------- Workspace + header ---------- */

.workspace {
  display: grid;
  align-content: start;
  gap: 18px;
  padding: 26px 28px 40px;
}

.topbar {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 18px;
  padding-bottom: 4px;
}

.topbar .eyebrow {
  color: var(--accent-ink);
}

.topbar h2 {
  font-size: clamp(1.6rem, 3vw, 2.3rem);
  font-weight: 820;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.controls {
  display: flex;
  align-items: center;
  gap: 10px;
  white-space: nowrap;
}

.controls label {
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* Model-option toggle (e.g. vulnerability layer opt-out). */
.toggle-control {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  text-transform: none !important;
  letter-spacing: 0 !important;
}

.toggle-control input {
  width: 15px;
  height: 15px;
  accent-color: var(--accent);
  cursor: pointer;
}

select {
  min-height: 44px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  padding: 0 38px 0 13px;
  font-weight: 600;
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%);
  background-position: calc(100% - 18px) center, calc(100% - 13px) center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s;
}

select:focus-visible,
input:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--ring);
}

/* Inline error state for failed form validation (see failField in app.js). */
input[aria-invalid="true"] {
  border-color: var(--critical);
  box-shadow: 0 0 0 3px rgba(182, 32, 43, 0.16);
}

/* Keyboard focus ring for all interactive controls (buttons, links, map
   markers). outline-offset keeps it visible on dark/coloured button fills
   such as the role switch and WhatsApp CTA. */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.secondary-button {
  min-height: 38px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  padding: 0 14px;
  font-weight: 700;
  font-size: 0.88rem;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}

.secondary-button:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent-ink);
}

/* ---------- Metric summary ---------- */

.scenario-caption {
  margin: 0;
  border: 1px solid var(--line);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  padding: 11px 15px;
  color: var(--ink-2);
  font-size: 0.9rem;
  line-height: 1.5;
}

/* 7-day risk strip: at-a-glance per-day risk, clickable to select a day. */
.forecast-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.fday {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--ink-2);
  font-size: 0.74rem;
  font-weight: 700;
  cursor: pointer;
  transition: border-color 0.12s, box-shadow 0.12s;
}

.fday:hover {
  border-color: var(--line-strong);
}

.fday.active {
  border-color: var(--accent);
  box-shadow: var(--ring);
}

.fday-dot {
  width: 9px;
  height: 9px;
  border-radius: 999px;
  background: var(--low);
}

.fday.low .fday-dot { background: var(--low); }
.fday.guarded .fday-dot { background: var(--guarded); }
.fday.high .fday-dot { background: var(--high); }
.fday.critical .fday-dot { background: var(--critical); }
/* Cold-mode days use a blue ramp, matching the map's cold colours. */
.fday.cold.low .fday-dot { background: #6b8fb0; }
.fday.cold.guarded .fday-dot { background: #3f72a0; }
.fday.cold.high .fday-dot { background: #2f5d96; }
.fday.cold.critical .fday-dot { background: #1f3f7a; }

.summary-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
}

.metric {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  padding: 16px 18px;
  overflow: hidden;
}

.metric::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: var(--accent);
  opacity: 0.65;
}

.metric:first-child::before {
  background: var(--high);
}

.metric p {
  margin: 0;
  color: var(--muted);
  font-size: 0.74rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.metric strong {
  display: block;
  margin: 8px 0 4px;
  font-size: 1.85rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
}

.metric span {
  color: var(--muted);
  font-size: 0.82rem;
}

/* ---------- Views + panels ---------- */

.view {
  display: none;
}

.view.active {
  display: grid;
  gap: 18px;
}

.main-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(330px, 0.8fr);
  gap: 18px;
  /* Each panel takes its own height. Default stretch made the map panel grow to
     match the detail column, and since the map has a fixed height that surfaced
     as dead white space under it whenever "Underlying layers & drivers" opened. */
  align-items: start;
}

.panel {
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow);
  overflow: hidden;
}

.panel-heading {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  border-bottom: 1px solid var(--line);
  padding: 15px 18px;
}

.panel-heading h3 {
  font-size: 1.05rem;
  font-weight: 780;
  letter-spacing: -0.01em;
}

.panel-heading .eyebrow {
  margin-bottom: 3px;
}

/* ---------- Map ---------- */

.map-panel .map-stage {
  padding: 16px;
}

.map-note {
  margin: 10px 2px 0;
  color: var(--muted);
  font-size: 0.78rem;
  font-style: italic;
}

/* Shown inside a map container when Leaflet is unavailable (see showMapFallback). */
.map-fallback {
  display: grid;
  place-items: center;
  height: 100%;
  min-height: 180px;
  margin: 0;
  padding: 24px;
  text-align: center;
  color: var(--muted);
  font-size: 0.9rem;
}

.legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 12px;
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 600;
}

.legend span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.legend i {
  width: 11px;
  height: 11px;
  border-radius: 3px;
}

.low {
  background: var(--low);
}

.guarded {
  background: var(--guarded);
}

.high {
  background: var(--high);
}

.critical {
  background: var(--critical);
}

#riskMap {
  height: 480px;
  width: 100%;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: #e7eef0;
  z-index: 0;
}

.map-tip {
  border: 1px solid var(--line);
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.9);
  box-shadow: var(--shadow-sm);
  color: var(--ink);
  font-weight: 650;
  font-size: 0.68rem;
  padding: 1px 5px;
}

.leaflet-container {
  font: inherit;
}

/* ---------- Area detail ---------- */

.area-detail,
.user-risk-output {
  display: grid;
  gap: 16px;
  padding: 18px;
}

.risk-band {
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  border-left: 4px solid var(--low);
  background: var(--low-soft);
  padding: 12px 14px;
}

.risk-band.guarded {
  border-left-color: var(--guarded);
  background: var(--guarded-soft);
}

.risk-band.high {
  border-left-color: var(--high);
  background: var(--high-soft);
}

.risk-band.critical {
  border-left-color: var(--critical);
  background: var(--critical-soft);
}

.risk-band h4 {
  margin: 0 0 3px;
  font-size: 1.25rem;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.risk-band p,
.detail-grid p,
.pipeline-grid p,
.response-card p,
.driver-card p {
  margin: 0;
  color: var(--muted);
}

.detail-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.detail-grid div {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  padding: 11px 12px;
}

.detail-grid p {
  font-size: 0.74rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.detail-grid strong {
  display: block;
  margin-top: 5px;
  font-size: 1.05rem;
  font-weight: 750;
}

/* ---------- Driver bars (SHAP) ---------- */

.driver-list {
  display: grid;
  gap: 9px;
}

.driver-row {
  display: grid;
  grid-template-columns: minmax(110px, 160px) minmax(0, 1fr) 46px;
  gap: 12px;
  align-items: center;
  font-size: 0.86rem;
}

.driver-row span:first-child {
  color: var(--ink-2);
}

.driver-row strong {
  text-align: right;
  font-weight: 750;
}

.bar-track {
  height: 8px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--surface-3);
}

.bar-fill {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--accent), #2a9a8f);
}

/* ---------- Tables ---------- */

.table-wrap {
  overflow-x: auto;
}

table {
  width: 100%;
  border-collapse: collapse;
  min-width: 760px;
}

th,
td {
  border-bottom: 1px solid var(--line);
  padding: 13px 18px;
  text-align: left;
  vertical-align: middle;
}

thead th {
  position: sticky;
  top: 0;
  background: var(--surface-2);
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

tbody tr {
  transition: background 0.12s;
}

tbody tr:hover {
  background: var(--accent-soft);
}

td strong {
  font-weight: 700;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 25px;
  border-radius: 999px;
  padding: 0 11px;
  color: #fff;
  font-size: 0.8rem;
  font-weight: 750;
}

.pill::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.92);
}

.pill.low {
  background: var(--low);
}

.pill.guarded {
  background: var(--guarded);
}

.pill.high {
  background: var(--high);
}

.pill.critical {
  background: var(--critical);
}

/* ---------- Form ---------- */

.risk-form {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 15px;
  padding: 18px;
}

.risk-form label,
.risk-form fieldset {
  display: grid;
  gap: 7px;
  min-width: 0;
  margin: 0;
  color: var(--ink-2);
  font-size: 0.82rem;
  font-weight: 650;
}

.risk-form > label > select {
  font-weight: 600;
}

/* display:grid above out-ranks the UA's [hidden] { display: none }, so a field
   hidden because it does not apply to today's hazard (water reliability on a
   cold day) would still render. Restore the intent explicitly. */
.risk-form label[hidden],
.resident-form label[hidden] {
  display: none;
}

.risk-form fieldset {
  grid-column: 1 / -1;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  padding: 13px 14px;
}

.risk-form legend {
  padding: 0 6px;
  color: var(--ink);
  font-weight: 800;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.risk-form fieldset label {
  display: flex;
  align-items: center;
  gap: 9px;
  font-weight: 550;
  color: var(--ink-2);
}

.risk-form fieldset input {
  width: 17px;
  height: 17px;
  accent-color: var(--accent);
}

/* ---------- Driver / response / pipeline grids ---------- */

.driver-grid,
.response-plan,
.pipeline-grid,
.model-strip {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  padding: 18px;
}

.model-strip {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border-bottom: 1px solid var(--line);
  background: var(--surface-2);
}

.model-strip article {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  padding: 14px;
}

.model-strip strong {
  display: block;
  font-weight: 750;
}

.model-strip span {
  display: block;
  margin-top: 5px;
  color: var(--muted);
  font-size: 0.88rem;
}

.driver-card,
.response-card,
.pipeline-grid article {
  display: grid;
  gap: 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 16px;
}

.driver-card h4,
.response-card h4,
.pipeline-grid h4 {
  margin: 0;
  font-size: 1rem;
  font-weight: 780;
}

.pipeline-grid article {
  background: var(--surface-2);
}

.pipeline-grid h4 {
  color: var(--accent-ink);
}

.response-card.full-span {
  grid-column: 1 / -1;
}

.response-card ul,
.pipeline-grid ul {
  display: grid;
  gap: 7px;
  margin: 0;
  padding-left: 18px;
  color: var(--ink-2);
  font-size: 0.9rem;
}

.status-line {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--line);
}

.status-line strong {
  font-weight: 780;
}

.status-line span {
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 600;
}

.channel-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.channel-grid div {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  padding: 12px 13px;
}

.channel-grid strong {
  font-weight: 700;
}

/* ---------- WhatsApp composer ---------- */

.whatsapp-composer {
  display: grid;
  gap: 16px;
  padding: 18px;
}

.wa-preview {
  max-height: none;
  margin: 0;
  white-space: pre-wrap;
  word-break: break-word;
  border: 1px solid #cfe8d8;
  border-radius: var(--radius-sm);
  background: #f0faf3;
  color: var(--ink);
  padding: 14px 16px;
  font-family: inherit;
  font-size: 0.9rem;
}

.wa-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 14px;
}

.wa-phone-label {
  display: grid;
  gap: 7px;
  flex: 1 1 240px;
  color: var(--ink-2);
  font-size: 0.82rem;
  font-weight: 650;
}

.wa-phone-label input {
  min-height: 42px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  padding: 0 13px;
}

.wa-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.wa-button {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 42px;
  border: 1px solid #1aa856;
  border-radius: var(--radius-sm);
  background: #25d366;
  color: #08251a;
  padding: 0 18px;
  font-weight: 800;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s, transform 0.05s;
}

.wa-button::before {
  content: "✆";
  font-size: 1rem;
}

.wa-button:hover {
  background: #1fbe5b;
}

.wa-button:active {
  transform: translateY(1px);
}

.wa-button.outline {
  background: var(--surface);
  color: var(--accent-ink);
  border-color: var(--accent);
}

.wa-button.outline::before {
  content: "↩";
}

.wa-button.outline:hover {
  background: var(--accent-soft);
}

.wa-hint {
  margin: 0;
  color: var(--muted);
  font-size: 0.83rem;
}

/* Translation-gap notice in the WhatsApp composer: the sender must see, before
   they tap send, that cold copy goes out in English. Guarded amber, not a risk
   colour — this is a caveat about the message, not a hazard level. */
.wa-warning {
  margin: 0 0 4px;
  border: 1px solid var(--line);
  border-left: 4px solid var(--guarded);
  border-radius: var(--radius-sm);
  background: var(--guarded-soft);
  padding: 10px 12px;
  color: var(--ink-2);
  font-size: 0.85rem;
  line-height: 1.5;
}

.wa-hint code,
.gee-provenance code,
.gee-note code {
  background: var(--surface-3);
  border-radius: 4px;
  padding: 1px 5px;
  font-size: 0.82rem;
}

.map-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin: 0 0 10px;
}

.map-district select {
  font: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink);
  background: var(--surface-2, #f4f6f8);
  border: 1px solid var(--surface-3, #d9dee3);
  border-radius: 999px;
  padding: 6px 12px;
  cursor: pointer;
}

.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;
}

.map-btn {
  font: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink);
  background: var(--surface-2, #f4f6f8);
  border: 1px solid var(--surface-3, #d9dee3);
  border-radius: 999px;
  padding: 6px 12px;
  cursor: pointer;
}

.map-btn:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
}

.ward-legend {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 6px 0 0;
  font-size: 0.76rem;
  color: var(--muted);
}

.ward-legend-bar {
  flex: 1;
  max-width: 180px;
  height: 8px;
  border-radius: 4px;
  border: 1px solid rgba(0, 0, 0, 0.08);
}

.risk-eyebrow {
  margin: 0 0 2px;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.8;
}

.risk-headline {
  margin: 2px 0 0;
  font-size: 1.05rem;
  font-weight: 700;
}

.risk-metric {
  margin: 2px 0 0;
  font-size: 0.9rem;
  opacity: 0.9;
}

.area-section {
  margin: 14px 0 0;
}

.area-section-label {
  margin: 0 0 4px;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}

.action-line {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--ink);
}

.lead-line {
  margin: 4px 0 0;
  font-size: 0.82rem;
  color: var(--muted);
}

.assumptions summary {
  cursor: pointer;
  font-weight: 700;
  padding: 6px 0;
}

.assumptions ul {
  margin: 10px 0 0;
  padding-left: 18px;
  display: grid;
  gap: 8px;
  color: var(--ink-2, #3a4048);
  font-size: 0.9rem;
  line-height: 1.5;
}

/* Research/PhD methodology. Always collapsed, and hidden outright unless the
   Researcher role is active — a district team issuing warnings should not have
   to scroll past coefficients and cross-validation to reach the actions. */
.tech-note {
  margin: 12px 0 0;
  border: 1px solid var(--surface-3);
  border-radius: var(--radius);
  background: var(--surface-2, rgba(15, 18, 20, 0.02));
  padding: 10px 14px;
}

.tech-note[hidden] {
  display: none;
}

.tech-note > summary {
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--muted);
  letter-spacing: 0.01em;
}

.tech-note > summary:hover {
  color: var(--ink);
}

.tech-note > p,
.tech-note > ul {
  margin: 10px 0 0;
  font-size: 0.86rem;
  line-height: 1.55;
  color: var(--ink-2, #3a4048);
}

.tech-note h4 {
  margin: 14px 0 4px;
  font-size: 0.9rem;
}

/* Response playbook: which scope each card actually covers. */
.response-scope {
  margin: 0 0 14px;
  padding: 10px 14px;
  border-left: 3px solid var(--accent-ink);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--surface-2, rgba(15, 18, 20, 0.02));
  font-size: 0.86rem;
  line-height: 1.55;
  color: var(--ink-2, #3a4048);
}

.response-target {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--muted);
}

.response-target select {
  font: inherit;
  font-weight: 700;
  color: var(--ink);
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
}

/* Distinguishes "city-wide" from "for Alexandra" at a glance on each card. */
.scope-tag {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--muted);
  text-align: right;
}

.more-areas {
  color: var(--muted);
  font-style: italic;
}

.area-details {
  margin: 14px 0 0;
  border-top: 1px solid var(--surface-3);
  padding-top: 10px;
}

.area-details summary {
  cursor: pointer;
  font-size: 0.82rem;
  color: var(--muted);
  font-weight: 600;
}

.area-details .detail-grid {
  margin-top: 10px;
}

.why-line {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.45;
  color: var(--ink);
  font-weight: 500;
}

.model-line {
  margin: 10px 0 0;
  padding: 9px 12px;
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
  border-radius: var(--radius-sm);
  font-size: 0.85rem;
  color: var(--ink-2);
}

/* ---------- GEE provenance ---------- */

.gee-provenance {
  margin: 0 18px 18px;
  border: 1px solid #cfe3df;
  border-left: 4px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  padding: 14px 16px;
  font-size: 0.88rem;
}

.gee-provenance p {
  margin: 0 0 8px;
}

.gee-provenance ul {
  margin: 0 0 8px;
  padding-left: 18px;
  display: grid;
  gap: 4px;
  color: var(--ink-2);
}

.gee-provenance .gee-note {
  margin: 0;
  color: var(--muted);
}

.gee-panel {
  border-top: 1px solid var(--line);
}

.panel-heading.inline {
  border-bottom: 0;
}

pre {
  max-height: 480px;
  margin: 0 18px 18px;
  overflow: auto;
  border: 1px solid #20323a;
  border-radius: var(--radius-sm);
  background: #15202b;
  color: #e9f1f0;
  padding: 16px;
  font-size: 0.82rem;
  line-height: 1.55;
}

/* ---------- Trained-model screening nudge ---------- */

.trained-nudge {
  border: 1px solid var(--line);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--accent-soft);
  padding: 14px 16px;
}

.trained-nudge.guarded {
  border-left-color: var(--guarded);
  background: var(--guarded-soft);
}

.trained-nudge.high {
  border-left-color: var(--high);
  background: var(--high-soft);
}

.nudge-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  margin-bottom: 6px;
}

.nudge-head strong {
  font-weight: 780;
}

/* .nudge-head now doubles as a <summary>. `display: flex` suppresses the
   default disclosure triangle, so draw one explicitly — otherwise the card
   looks like static text and nobody discovers the weights inside. */
summary.nudge-head {
  cursor: pointer;
  list-style: none;
  margin-bottom: 0;
}

summary.nudge-head::-webkit-details-marker {
  display: none;
}

summary.nudge-head::before {
  content: "▸";
  font-size: 0.72rem;
  color: var(--muted);
}

details[open] > summary.nudge-head::before {
  content: "▾";
}

details[open] > summary.nudge-head {
  margin-bottom: 6px;
}

.nudge-badge {
  border-radius: 999px;
  background: var(--ink);
  color: #fff;
  padding: 2px 9px;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.nudge-score {
  margin: 4px 0 8px;
  font-size: 2rem;
  font-weight: 820;
  letter-spacing: -0.02em;
  line-height: 1;
}

.nudge-score span {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--muted);
}

.trained-nudge p {
  margin: 0 0 6px;
  color: var(--ink-2);
  font-size: 0.86rem;
}

.nudge-caveat {
  margin: 0;
  font-weight: 650;
  color: var(--muted);
}

/* Validation-metrics line: tabular figures, set apart from the prose. */
.nudge-metrics {
  font-size: 0.8rem !important;
  color: var(--muted) !important;
  border-left: 3px solid var(--line-strong);
  padding-left: 10px;
}

.nudge-drivers-label {
  font-weight: 700;
  font-size: 0.82rem !important;
  color: var(--ink-2);
  margin-bottom: 2px !important;
}

/* ---------- Data / research view ---------- */

.data-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.data-note {
  margin: 0;
  padding: 14px 18px 0;
  color: var(--muted);
  font-size: 0.86rem;
}

td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);
}

.source-tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border-radius: 999px;
  padding: 2px 9px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}

.source-tag.gee {
  background: var(--accent-soft);
  color: var(--accent-ink);
}

.source-tag.sample {
  background: var(--surface-3);
  color: var(--muted);
}

/* ---------- Resident view ---------- */

.resident-locate {
  display: grid;
  gap: 10px;
  padding: 18px 18px 0;
}

#residentMap {
  height: 340px;
  width: 100%;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: #e7eef0;
  z-index: 0;
  cursor: crosshair;
}

.locate-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.pin-label {
  color: var(--muted);
  font-size: 0.84rem;
}

.resident-form {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 15px;
  padding: 18px;
}

.resident-form label {
  display: grid;
  gap: 7px;
  color: var(--ink-2);
  font-size: 0.86rem;
  font-weight: 650;
}

.resident-form .resident-check {
  grid-column: 1 / -1;
  flex-direction: row;
  display: flex;
  align-items: center;
  gap: 9px;
  font-weight: 550;
}

.resident-form .resident-check input {
  width: 17px;
  height: 17px;
  accent-color: var(--accent);
}

.resident-result {
  display: grid;
  gap: 16px;
  border-top: 1px solid var(--line);
  padding: 18px;
}

.resident-band {
  border-width: 1px;
  border-left-width: 5px;
  padding: 14px 16px;
}

.resident-band.cold {
  border-left-color: #2f5d96;
  background: #e8eef6;
}

.resident-band h4 {
  font-size: 1.5rem;
}

.resident-actions ul {
  display: grid;
  gap: 8px;
  margin: 6px 0 0;
  padding-left: 20px;
  font-size: 0.95rem;
  color: var(--ink);
}

.resident-note {
  margin: 0;
  color: var(--muted);
  font-size: 0.84rem;
  line-height: 1.5;
}

.subscribe-box {
  margin: 0 18px 18px;
  border: 1px solid #cfe8d8;
  border-left: 4px solid #1aa856;
  border-radius: var(--radius-sm);
  background: #f0faf3;
  padding: 16px;
}

.subscribe-box h4 {
  margin: 2px 0 4px;
  font-size: 1.05rem;
  font-weight: 800;
}

.subscribe-box > p {
  margin: 0 0 12px;
  color: var(--ink-2);
  font-size: 0.9rem;
}

.subscribe-form {
  display: grid;
  gap: 11px;
}

.subscribe-form input[type="tel"] {
  min-height: 44px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  padding: 0 13px;
}

.subscribe-consent {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  color: var(--ink-2);
  font-size: 0.84rem;
  line-height: 1.45;
}

.subscribe-consent input {
  margin-top: 2px;
  width: 17px;
  height: 17px;
  flex: 0 0 auto;
  accent-color: #1aa856;
}

.subscribe-form .wa-button {
  justify-content: center;
}

.subscribe-status {
  margin: 10px 0 0;
  color: var(--accent-ink);
  font-size: 0.86rem;
  font-weight: 650;
}

@media (max-width: 640px) {
  .resident-form {
    grid-template-columns: 1fr;
  }
}

/* ---------- PhD Aim 3 machine-learning panel ---------- */

.aim3-panel {
  display: grid;
  gap: 14px;
  padding: 18px;
}

.aim3-flow,
.aim3-stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
}

.aim3-flow div,
.aim3-stats div {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  padding: 10px 12px;
}

.aim3-flow p,
.aim3-stats p {
  margin: 0;
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.aim3-flow strong,
.aim3-stats strong {
  display: block;
  margin-top: 4px;
  font-size: 1.05rem;
  font-weight: 780;
}

.aim3-flow span,
.aim3-stats span {
  display: block;
  margin-top: 3px;
  color: var(--muted);
  font-size: 0.78rem;
}

.aim3-note {
  margin: 0;
  color: var(--ink-2);
  font-size: 0.88rem;
  line-height: 1.55;
}

@media (max-width: 640px) {
  .aim3-flow,
  .aim3-stats {
    grid-template-columns: 1fr;
  }
}

/* ---------- Scope / honesty box (top of the researcher view) ----------
   Warm neutral surface with the restrained teal accent stripe already used by
   .trained-nudge, so the box reads as part of the research surface rather than
   as an alarm. Deliberately the first thing in the About view. */

.scope-box {
  margin: 18px 18px 0;
  border: 1px solid var(--line);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  padding: 14px 16px;
}

.scope-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  margin-bottom: 8px;
}

.scope-head strong {
  font-size: 0.98rem;
  font-weight: 780;
  color: var(--ink);
}

.scope-badge {
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  padding: 2px 9px;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.scope-box ul {
  margin: 0;
  padding-left: 20px;
  display: grid;
  gap: 5px;
}

.scope-box li {
  color: var(--ink-2);
  font-size: 0.9rem;
  line-height: 1.5;
}

/* ---------- About / references ---------- */

.about {
  display: grid;
  gap: 8px;
  padding: 18px;
}

.about h4 {
  margin: 10px 0 0;
  font-size: 0.96rem;
  font-weight: 780;
  color: var(--ink);
}

.about p,
.about li {
  margin: 0;
  color: var(--ink-2);
  font-size: 0.92rem;
  line-height: 1.55;
}

.about ul {
  margin: 2px 0;
  padding-left: 20px;
  display: grid;
  gap: 4px;
}

.references {
  margin: 0;
  padding: 18px 18px 18px 40px;
  display: grid;
  gap: 9px;
  color: var(--ink-2);
  font-size: 0.86rem;
  line-height: 1.5;
}

.references li {
  padding-left: 4px;
}

.references em {
  color: var(--ink);
  font-style: italic;
}

/* ---------- First-run guided tour ---------- */

.tour {
  position: fixed;
  inset: 0;
  z-index: 2000;
}

.tour[hidden] {
  display: none;
}

.tour-highlight {
  position: fixed;
  border: 2px solid var(--accent);
  border-radius: 10px;
  box-shadow: 0 0 0 9999px rgba(15, 18, 20, 0.62);
  pointer-events: none;
  transition: top 0.2s ease, left 0.2s ease, width 0.2s ease, height 0.2s ease;
}

.tour-highlight--full {
  border-color: transparent;
}

.tour-card {
  position: fixed;
  width: 320px;
  max-width: calc(100vw - 24px);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: 0 22px 60px rgba(15, 18, 20, 0.35);
  padding: 16px 18px;
}

/* Carries "Step 2 of 7 · District board" — the view name tells you which tour
   you're in, now that every view has its own. Wraps rather than overflows on
   narrow cards. */
.tour-step {
  margin: 0 0 4px;
  color: var(--accent-ink);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  line-height: 1.4;
  text-transform: uppercase;
}

.tour-card h4 {
  margin: 0 0 6px;
  font-size: 1.08rem;
  font-weight: 820;
  letter-spacing: -0.01em;
}

.tour-card > p {
  margin: 0 0 14px;
  color: var(--ink-2);
  font-size: 0.9rem;
  line-height: 1.5;
}

.tour-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.tour-nav {
  display: flex;
  gap: 8px;
}

.tour-skip {
  border: 0;
  background: none;
  color: var(--muted);
  font-weight: 650;
  cursor: pointer;
}

.tour-skip:hover {
  color: var(--ink);
}

.tour-next {
  min-height: 38px;
  border: 1px solid var(--accent-ink);
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: #fff;
  padding: 0 18px;
  font-weight: 800;
  cursor: pointer;
}

.tour-next:hover {
  background: var(--accent-ink);
}

.tour [disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}

/* ---------- Responsive ---------- */

@media (max-width: 1040px) {
  .app-shell {
    grid-template-columns: 1fr;
  }

  .sidebar {
    position: static;
    height: auto;
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: 16px 20px;
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }

  .brand-logo {
    grid-column: 1;
  }

  .brand-logo img {
    max-width: 180px;
  }

  .app-title {
    grid-column: 2;
    align-self: center;
    border-bottom: 0;
    padding-bottom: 0;
  }

  .brand-links {
    grid-column: 1 / -1;
    grid-template-columns: repeat(2, 1fr);
  }

  .nav-list {
    grid-column: 1 / -1;
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }

  .nav-item {
    flex-direction: column;
    gap: 6px;
    text-align: center;
  }

  .nav-item.active::before {
    display: none;
  }

  .data-freshness {
    grid-column: 1 / -1;
    margin-top: 0;
  }

  .data-freshness dl {
    grid-template-columns: repeat(4, 1fr);
  }

  .data-freshness div {
    flex-direction: column;
    gap: 2px;
  }

  .main-grid,
  .summary-grid,
  .driver-grid,
  .response-plan,
  .pipeline-grid,
  .model-strip,
  .risk-form,
  .channel-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 640px) {
  .workspace {
    padding: 18px 16px 32px;
  }

  .sidebar {
    grid-template-columns: 1fr;
  }

  .app-title {
    grid-column: 1 / -1;
  }

  .brand-links {
    grid-column: 1 / -1;
  }

  .nav-list {
    grid-template-columns: repeat(3, 1fr);
  }

  .topbar {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }

  .controls {
    flex-direction: column;
    align-items: stretch;
  }

  .summary-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .detail-grid {
    grid-template-columns: 1fr;
  }

  .driver-row {
    grid-template-columns: 1fr auto;
  }

  .driver-row .bar-track {
    display: none;
  }
}

/* Narrow viewports: the alert and data tables have 7 and 13 columns. A 760px
   min-width inside a horizontally scrolling wrapper pushed the Action column
   (the one that says what to actually do) off-screen with no affordance at
   375px. Below 768px each row becomes a stacked, labelled card driven by the
   data-label attributes emitted in renderTable/renderDataView. The desktop
   table above 768px is untouched. */
@media (max-width: 767px) {
  .table-wrap {
    overflow-x: visible;
  }

  .table-wrap table {
    min-width: 0;
    display: block;
  }

  .table-wrap thead {
    /* Column headings become the per-cell data-labels instead. */
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden; clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }

  .table-wrap tbody {
    display: grid;
    gap: 12px;
  }

  .table-wrap tbody tr {
    display: block;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--surface);
    padding: 4px 14px;
  }

  .table-wrap tbody td {
    display: grid;
    grid-template-columns: minmax(0, 8.5rem) minmax(0, 1fr);
    gap: 6px 12px;
    align-items: baseline;
    padding: 9px 0;
    text-align: left;
    overflow-wrap: anywhere;
  }

  .table-wrap tbody td:last-child {
    border-bottom: 0;
  }

  .table-wrap tbody td::before {
    content: attr(data-label);
    color: var(--muted);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
  }

  /* Cells with no data-label (none expected) still read as a single column. */
  .table-wrap tbody td:not([data-label]) {
    display: block;
  }

  .table-wrap tbody td.num {
    text-align: left;
  }
}

/* Touch devices: guarantee a 44px minimum target on every interactive control
   regardless of viewport width (covers a desktop-class screen on a tablet).
   The persona role-switch and secondary/tour buttons are otherwise 31-42px.
   WCAG 2.5.5 Target Size; pointer:coarse leaves mouse users' compact UI alone. */
@media (pointer: coarse) {
  .role-btn,
  .nav-item,
  .secondary-button,
  .wa-button,
  .tour-next,
  .tour-skip,
  .fday,
  .map-btn,
  .brand-links a,
  .map-district select {
    min-height: 44px;
  }

  .role-btn {
    padding-block: 10px;
  }

  .map-btn {
    padding-block: 10px;
  }

  .brand-links a {
    padding-block: 12px;
  }

  /* Leaflet ships 26x26 (30x30 on touch) zoom controls. Override here rather
     than editing the vendored assets/vendor/leaflet/leaflet.css. */
  .leaflet-touch .leaflet-bar a,
  .leaflet-bar a {
    width: 44px;
    height: 44px;
    line-height: 44px;
    font-size: 22px;
  }
}

/* Stronger contrast when the OS requests it (WCAG 1.4.6): darken the light
   borders and secondary text, and ring the risk pills so their level stays
   distinct independent of fill. */
@media (prefers-contrast: more) {
  :root {
    --line: #b3ad9f;
    --line-strong: #847c6d;
    --muted: #474c52;
    --ink-2: #25292e;
  }
  .pill { outline: 1px solid rgba(0, 0, 0, 0.4); }
  .scenario-caption,
  .risk-band,
  .trained-nudge { border-width: 1px 1px 1px 5px; }
}

/* Windows High Contrast / forced-colors: when the OS replaces our palette,
   keep surfaces outlined so structure survives, and preserve the risk-colour
   swatches (legend + 7-day dots) whose colour is the information — the adjacent
   text label is the fallback. WCAG 1.4.1 / 1.4.3. */
@media (forced-colors: active) {
  .pill,
  .metric,
  .panel,
  .fday,
  .map-fallback { border: 1px solid CanvasText; }
  .legend i,
  .fday-dot { forced-color-adjust: none; }
}

/* Respect the OS "reduce motion" setting: near-instant transitions/animations
   for vestibular-sensitive users. Covers the tour spotlight, which physically
   travels across the screen. WCAG 2.3.3. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Dark mode: warm dark neutrals + brighter teal, risk ramp preserved. Most of
   the UI is token-driven, so dark = token overrides + a few hardcoded-light
   elements re-themed. Contrast kept at WCAG AA (light text on dark surfaces;
   risk pills keep white text on their AA-checked fills). */
@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --bg: #1b1a16;
    --surface: #242219;
    --surface-2: #2b2920;
    --surface-3: #333026;
    --ink: #f2efe8;
    --ink-2: #c7c2b8;
    --muted: #a29d93; /* clears AA 4.5:1 on the lightest dark surface */
    --line: #3a382f;
    --line-strong: #4e4b40;

    --accent: #11807d;
    --accent-ink: #6fd3d0;
    --accent-soft: #14302f;

    /* Risk solids unchanged (white pill text stays AA, and they read on dark);
       only the soft tints flip to dark so band text stays light-on-dark. */
    --low-soft: #163025;
    --guarded-soft: #2f2814;
    --high-soft: #34211a;
    --critical-soft: #341a1e;

    --shadow: 0 1px 2px rgba(0, 0, 0, 0.45), 0 14px 34px rgba(0, 0, 0, 0.55);
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);
    --ring: 0 0 0 3px rgba(64, 200, 195, 0.35);
  }

  /* Hardcoded-light elements re-themed for dark. */
  .sidebar {
    background: linear-gradient(180deg, #211f17, #1a1913);
  }
  .wa-preview {
    background: #15241f;
    border-color: #2c4a40;
    color: var(--ink);
  }
  .subscribe-box {
    background: #15241c;
    border-color: #2c4a3a;
  }
  .resident-band.cold {
    background: #1a2436;
    border-left-color: #5a8ac4;
  }
}

/* Resident view: an explicit "get my result" affordance.
   The result panel already re-rendered live, but with no button and no lead-in
   a resident had nothing to click and no cue that an answer had appeared below
   the form. The CTA spans the form grid so it reads as the end of the flow. */
.resident-submit {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 4px;
}

.resident-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 46px;
  padding: 0 22px;
  border: 1px solid var(--accent-line, #b6202b);
  border-radius: var(--radius-sm);
  background: var(--accent, #b6202b);
  color: #fff;
  font-weight: 800;
  font-size: 0.98rem;
  cursor: pointer;
}

.resident-cta:hover { filter: brightness(1.08); }

.resident-cta:focus-visible,
.resident-result:focus-visible {
  outline: 3px solid #2E6F9E;
  outline-offset: 2px;
}

.resident-live-hint {
  font-size: 0.82rem;
  color: var(--muted, #6E6E6E);
}

.resident-translation-review {
  margin: 12px 0 0;
  color: var(--muted);
  font-size: 0.78rem;
  line-height: 1.45;
}

.resident-result-lead {
  margin: 0;
  font-size: 0.92rem;
  color: var(--muted, #6E6E6E);
}

/* A control that cannot do anything today should look inert, not broken. */
.toggle-control.is-inert {
  opacity: 0.55;
  cursor: not-allowed;
}
.toggle-control.is-inert input {
  cursor: not-allowed;
}

/* Demo mode (?demo=heat): an unmissable, honest banner above everything, in the
   heat ramp's high tone so it cannot be mistaken for part of the live board. */
.demo-banner {
  position: sticky;
  top: 0;
  z-index: 4000;
  background: var(--high);
  color: #ffffff;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1.4;
  padding: 7px 16px;
  text-align: center;
}

/* Presentation-mode switch. Deliberately quiet next to the role switcher on the
   live board, and unmistakably hot once demo mode is on. */
.demo-switch {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

.demo-toggle {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: var(--ink, #1a1a1a);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.3;
  padding: 8px 10px;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
}

.demo-toggle:hover {
  border-color: var(--high);
}

.demo-toggle.is-demo {
  background: var(--high);
  border-color: var(--high);
  color: #ffffff;
}

.demo-switch-note {
  margin: 6px 0 0;
  color: var(--muted);
  font-size: 11px;
  line-height: 1.4;
}

/* Demo-mode caveat inside the resident result. The localized copy says "today"
   in ten languages; rather than machine-translate a scenario caveat into packs
   that are already awaiting local-speaker review, qualify it here. */
.resident-demo-note {
  margin: 10px 0 0;
  padding: 8px 10px;
  border-left: 3px solid var(--high);
  background: color-mix(in srgb, var(--high) 8%, transparent);
  color: var(--ink, #1a1a1a);
  font-size: 0.78rem;
  line-height: 1.45;
}
