/* =========================================================
   Market Weather — Interactive prototype
   ========================================================= */

:root {
  /* ===== LIGHT (default) ===== */
  --page-0: #FAFAFA;
  --page-1: #F3F3F3;
  --page-2: #ECECEC;

  --ink:        #0A0A0A;
  --ink-90:     rgba(10,10,10,0.92);
  --ink-70:     rgba(10,10,10,0.70);
  --ink-55:     rgba(10,10,10,0.55);
  --ink-40:     rgba(10,10,10,0.40);
  --ink-25:     rgba(10,10,10,0.25);
  --ink-12:     rgba(10,10,10,0.12);
  --ink-06:     rgba(10,10,10,0.06);

  --warm:    #D9B68C;
  --warm-2:  #E8C9A8;
  --cool:    #9FB3C7;
  --cool-2:  #BFCEDC;
  --neutral: #C8C0B4;

  --glass-bg:     rgba(255,255,255,0.62);
  --glass-bg-2:   rgba(255,255,255,0.78);
  --glass-stroke: rgba(10,10,10,0.08);
  --glass-shadow:
    0 1px 0 rgba(255,255,255,0.9) inset,
    0 0 0 0.5px rgba(10,10,10,0.04),
    0 1px 2px rgba(10,10,10,0.04),
    0 20px 40px -20px rgba(10,10,10,0.12);

  --display: "JetBrains Mono", "SF Mono", "Menlo", ui-monospace, monospace;
  --ui: "Geist", -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
  --display-settings: "wght" 450;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);

  color-scheme: light;
}

/* ===== DARK — scoped to the phone screen, not the desktop gallery chrome ===== */
[data-theme="dark"] .phone__screen,
[data-theme="dark"] .sector-sheet,
[data-theme="dark"] .install-sheet {
  --page-0: #0F1012;
  --page-1: #16171A;
  --page-2: #1D1E22;

  --ink:        #F4F2EC;
  --ink-90:     rgba(244,242,236,0.92);
  --ink-70:     rgba(244,242,236,0.65);
  --ink-55:     rgba(244,242,236,0.48);
  --ink-40:     rgba(244,242,236,0.34);
  --ink-25:     rgba(244,242,236,0.22);
  --ink-12:     rgba(244,242,236,0.12);
  --ink-06:     rgba(244,242,236,0.06);

  --warm:    #B79068;
  --warm-2:  #C7A37D;
  --cool:    #7A8FA4;
  --cool-2:  #8FA3B7;
  --neutral: #8E867B;

  --glass-bg:     rgba(255,255,255,0.03);
  --glass-bg-2:   rgba(255,255,255,0.06);
  --glass-stroke: rgba(255,255,255,0.08);
  --glass-shadow:
    0 1px 0 rgba(255,255,255,0.04) inset,
    0 0 0 0.5px rgba(255,255,255,0.04),
    0 1px 2px rgba(0,0,0,0.4),
    0 20px 40px -20px rgba(0,0,0,0.5);

  color-scheme: dark;
  background: var(--page-0);
  color: var(--ink);
}

/* Auto: follow OS if no explicit choice — same scope */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="dark"]) .phone__screen,
  :root:not([data-theme="light"]):not([data-theme="dark"]) .sector-sheet,
  :root:not([data-theme="light"]):not([data-theme="dark"]) .install-sheet {
    --page-0: #0F1012;
    --page-1: #16171A;
    --page-2: #1D1E22;
    --ink: #F4F2EC;
    --ink-90: rgba(244,242,236,0.92);
    --ink-70: rgba(244,242,236,0.65);
    --ink-55: rgba(244,242,236,0.48);
    --ink-40: rgba(244,242,236,0.34);
    --ink-25: rgba(244,242,236,0.22);
    --ink-12: rgba(244,242,236,0.12);
    --ink-06: rgba(244,242,236,0.06);
    --warm: #B79068; --warm-2: #C7A37D;
    --cool: #7A8FA4; --cool-2: #8FA3B7;
    --neutral: #8E867B;
    --glass-bg: rgba(255,255,255,0.03);
    --glass-bg-2: rgba(255,255,255,0.06);
    --glass-stroke: rgba(255,255,255,0.08);
    --glass-shadow:
      0 1px 0 rgba(255,255,255,0.04) inset,
      0 0 0 0.5px rgba(255,255,255,0.04),
      0 1px 2px rgba(0,0,0,0.4),
      0 20px 40px -20px rgba(0,0,0,0.5);
    color-scheme: dark;
    background: var(--page-0);
    color: var(--ink);
  }
}

/* On mobile/standalone, the phone__screen IS the viewport — make body match
   so safe-area edges don't show light when the rest is dark. */
@media (max-width: 480px), (display-mode: standalone) {
  [data-theme="dark"] body,
  [data-theme="dark"] html { background: #0F1012; }
}
@media ((max-width: 480px) or (display-mode: standalone)) and (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="dark"]) body,
  :root:not([data-theme="light"]):not([data-theme="dark"]) html { background: #0F1012; }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--page-1);
  color: var(--ink);
  font-family: var(--ui);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  min-height: 100vh;
  overflow-x: hidden;
  max-width: 100vw;
}

img, svg { display: block; }
button { font: inherit; cursor: pointer; border: 0; background: transparent; color: inherit; text-align: left; padding: 0; }

/* Apply Fraunces variable axes to all display headings */
.climate__title,
.mapscreen__title,
.radar__title,
.signals__title,
.brief__title,
.signal-card__quote,
.brief__lede,
.reading__value,
.climate__cta-title,
.confidence-row__val,
.climate__confidence-val,
.signal-list__conf,
.install-sheet__title,
.stage__hint h2,
.event__time > span:first-child {
  font-variation-settings: var(--display-settings);
}

::selection { background: var(--ink); color: var(--page-0); }

/* =========================================================
   Ambient background
   ========================================================= */
.ambient {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  background:
    radial-gradient(1200px 800px at 80% -10%, #FFFFFF, transparent 60%),
    radial-gradient(900px 700px at -10% 50%, #F8F6F2, transparent 60%),
    linear-gradient(180deg, #F6F6F4 0%, #EFEFED 100%);
}
.ambient-blob {
  position: absolute;
  border-radius: 50%;
  filter: blur(80px);
  opacity: 0.55;
  mix-blend-mode: multiply;
}
.ambient-blob--a {
  width: 720px; height: 720px;
  left: -120px; top: 8%;
  background: radial-gradient(circle at 30% 30%, #E7DFD2, transparent 60%);
  animation: drift-a 28s var(--ease) infinite alternate;
}
.ambient-blob--b {
  width: 820px; height: 820px;
  right: -180px; top: 38%;
  background: radial-gradient(circle at 60% 40%, #D9E0E8, transparent 60%);
  animation: drift-b 36s var(--ease) infinite alternate;
}
.ambient-grain {
  position: absolute; inset: 0;
  opacity: 0.035;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' seed='3'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.6 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  pointer-events: none;
}
@keyframes drift-a { 0%{transform:translate3d(0,0,0) scale(1);} 100%{transform:translate3d(40px,30px,0) scale(1.05);} }
@keyframes drift-b { 0%{transform:translate3d(0,0,0) scale(1);} 100%{transform:translate3d(-50px,20px,0) scale(1.08);} }

/* =========================================================
   Stage nav
   ========================================================= */
.stage-nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 32px;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--ink-70);
  backdrop-filter: blur(18px) saturate(1.2);
  -webkit-backdrop-filter: blur(18px) saturate(1.2);
  background: rgba(250,250,250,0.55);
  border-bottom: 1px solid var(--ink-06);
}
.stage-nav__brand {
  display: flex; align-items: center; gap: 8px;
  color: var(--ink); font-weight: 500;
  text-decoration: none;
}
.stage-nav__mark {
  width: 18px;
  height: auto;
  color: var(--ink);
  flex-shrink: 0;
}
.stage-nav__meta { display: flex; gap: 10px; align-items: center; }
.stage-nav__meta .sep { opacity: 0.4; }
.stage-nav__link {
  color: var(--ink-70);
  text-decoration: none;
  transition: color 200ms;
}
.stage-nav__link:hover { color: var(--ink); }
@keyframes pulse { 0%,100%{transform:scale(1);opacity:0.6;} 50%{transform:scale(1.35);opacity:0;} }

/* Install CTA */
.install-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: 8px;
  padding: 8px 14px;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  background: var(--ink);
  color: var(--page-0);
  border-radius: 999px;
  cursor: pointer;
  transition: transform 200ms var(--ease), background 200ms;
}
.install-btn:hover { transform: translateY(-1px); background: #1a1a1a; }
.install-btn svg { stroke: currentColor; flex-shrink: 0; }

/* Hide install button when running standalone (already installed) */
@media (display-mode: standalone) {
  .install-btn { display: none !important; }
  .stage-nav__label::before { content: "Standalone · "; opacity: 0.5; }
}

/* iOS install instructions sheet */
.install-sheet {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  pointer-events: none;
}
.install-sheet[hidden] { display: none; }
.install-sheet__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(10,10,10,0.32);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  pointer-events: auto;
  animation: fadeIn 280ms var(--ease) forwards;
}
.install-sheet__card {
  position: relative;
  pointer-events: auto;
  width: min(440px, calc(100% - 24px));
  margin: 0 12px 12px;
  background:
    radial-gradient(120% 60% at 100% 0%, #FBF7EF 0%, transparent 60%),
    radial-gradient(120% 60% at 0% 100%, #F3F5F7 0%, transparent 60%),
    var(--page-0);
  border: 1px solid var(--glass-stroke);
  border-radius: 26px;
  padding: 26px 26px 28px;
  box-shadow: 0 20px 60px rgba(10,10,10,0.25);
  transform: translateY(20px);
  opacity: 0;
  animation: sheetUp 380ms var(--ease) 60ms forwards;
}
@media (min-width: 720px) {
  .install-sheet { align-items: center; }
  .install-sheet__card { margin: 0; }
}
@keyframes fadeIn { to { opacity: 1; } }
@keyframes sheetUp {
  to { transform: translateY(0); opacity: 1; }
}

.install-sheet__close {
  position: absolute;
  top: 16px; right: 16px;
  width: 32px; height: 32px;
  display: grid; place-items: center;
  color: var(--ink-55);
  border-radius: 50%;
  transition: background 200ms, color 200ms;
}
.install-sheet__close:hover { background: var(--ink-06); color: var(--ink); }
.install-sheet__kicker {
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-55);
}
.install-sheet__title {
  font-family: var(--display);
  font-weight: 400;
  font-size: 32px;
  line-height: 1;
  letter-spacing: -0.02em;
  margin: 8px 0 12px;
}
.install-sheet__lede {
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink-70);
  margin: 0 0 20px;
}
.install-sheet__steps {
  list-style: none;
  padding: 0;
  margin: 0;
  border-top: 1px solid var(--ink-12);
}
.install-sheet__steps li {
  display: grid;
  grid-template-columns: 32px 1fr;
  gap: 14px;
  align-items: center;
  padding: 14px 0;
  border-bottom: 1px solid var(--ink-06);
  font-size: 14px;
  color: var(--ink-90);
}
.install-sheet__steps li:last-child { border-bottom: 0; }
.install-sheet__steps li > div {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.install-sheet__steps li svg { stroke: currentColor; fill: none; flex-shrink: 0; }
.install-sheet__step-n {
  width: 28px; height: 28px;
  display: grid; place-items: center;
  background: var(--ink);
  color: var(--page-0);
  border-radius: 50%;
  font-family: var(--display);
  font-style: italic;
  font-size: 14px;
}

/* =========================================================
   Stage layout
   ========================================================= */
.stage {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 64px;
  padding: 100px 48px 60px;
  max-width: 1500px;
  margin: 0 auto;
}

.stage__hint {
  align-self: center;
  max-width: 280px;
}
.stage__hint-num {
  font-family: var(--display);
  font-style: italic;
  font-size: 14px;
  color: var(--ink-55);
  display: block;
  margin-bottom: 14px;
}
.stage__hint h2 {
  font-family: var(--display);
  font-weight: 400;
  font-size: 36px;
  line-height: 1;
  letter-spacing: -0.02em;
  margin: 0 0 14px;
}
.stage__hint p {
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink-70);
  margin: 0 0 24px;
}
.stage__index {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--ink-12);
}
.stage__index li {
  border-bottom: 1px solid var(--ink-06);
}
.stage__index button {
  width: 100%;
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 12px 0;
  font-size: 14px;
  color: var(--ink-70);
  transition: color 200ms var(--ease);
}
.stage__index em {
  font-family: var(--display);
  font-style: italic;
  font-size: 15px;
  color: var(--ink-40);
  font-weight: 400;
  transition: color 200ms;
}
.stage__index button:hover { color: var(--ink); }
.stage__index button:hover em { color: var(--ink-70); }
.stage__index button.is-active { color: var(--ink); font-weight: 500; }
.stage__index button.is-active em { color: var(--ink); }

.stage__hint--right {
  justify-self: end;
  display: flex;
  align-items: flex-end;
  height: 100%;
  padding-bottom: 20px;
}
.kbd-hint {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--ink-55);
  letter-spacing: 0.04em;
}
.kbd-hint kbd {
  font-family: var(--ui);
  font-size: 11px;
  padding: 4px 7px;
  background: rgba(255,255,255,0.8);
  border: 1px solid var(--ink-12);
  border-radius: 6px;
  box-shadow: 0 1px 0 rgba(10,10,10,0.04);
  color: var(--ink);
}
.kbd-hint span { margin-left: 4px; }

/* =========================================================
   iPhone frame
   ========================================================= */
.phone {
  --phone-w: 390px;
  --phone-h: 844px;
  width: var(--phone-w);
  height: var(--phone-h);
  position: relative;
  filter:
    drop-shadow(0 50px 80px rgba(10,10,10,0.18))
    drop-shadow(0 10px 20px rgba(10,10,10,0.06));
}
.phone__bezel {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, #1A1A1B 0%, #0A0A0A 100%);
  border-radius: 56px;
  padding: 11px;
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,0.08),
    inset 0 0 0 2px rgba(0,0,0,0.6);
}
.phone__bezel::before {
  content: "";
  position: absolute;
  inset: 1px;
  border-radius: 55px;
  background: linear-gradient(135deg, rgba(255,255,255,0.05), transparent 30%, transparent 70%, rgba(255,255,255,0.03));
  pointer-events: none;
}
.phone__notch {
  position: absolute;
  top: 18px;
  left: 50%;
  transform: translateX(-50%);
  width: 115px;
  height: 34px;
  background: #050505;
  border-radius: 999px;
  z-index: 5;
  box-shadow: 0 0 0 1px rgba(255,255,255,0.04);
}
.phone__screen {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 46px;
  overflow: hidden;
  background: var(--page-0);
  isolation: isolate;
  display: flex;
  flex-direction: column;
}

/* Status bar */
.status {
  position: relative;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 30px 6px;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  flex-shrink: 0;
}
.status__time { font-variant-numeric: tabular-nums; }
.status__icons { display: flex; align-items: center; gap: 6px; }
.status__icons svg { fill: currentColor; }

/* =========================================================
   Screens container
   ========================================================= */
.screens {
  position: relative;
  flex: 1;
  overflow: hidden;
}
.screen {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  touch-action: pan-y;
  opacity: 0;
  visibility: hidden;
  transform: translateY(6px);
  transition:
    opacity 380ms var(--ease),
    transform 480ms var(--ease),
    visibility 0s linear 480ms;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.screen::-webkit-scrollbar { display: none; }
.screen.is-active {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition:
    opacity 380ms var(--ease),
    transform 480ms var(--ease),
    visibility 0s linear 0s;
}
.screen__body {
  min-height: 100%;
  padding: 18px 22px 110px; /* bottom: tabbar height */
  position: relative;
  z-index: 1;
}

/* =========================================================
   01 — CLIMATE
   ========================================================= */
.climate {
  position: relative;
}
.climate__atmosphere {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
.climate__halo {
  position: absolute;
  border-radius: 50%;
  filter: blur(40px);
  opacity: 0.75;
}
.climate__halo--a {
  width: 320px; height: 320px;
  top: -80px; right: -80px;
  background: radial-gradient(circle at 40% 40%, #EBE2D2, transparent 65%);
  animation: drift-a 22s var(--ease) infinite alternate;
}
.climate__halo--b {
  width: 360px; height: 360px;
  bottom: 60px; left: -120px;
  background: radial-gradient(circle at 60% 50%, #DDE3EB, transparent 65%);
  animation: drift-b 26s var(--ease) infinite alternate;
}
.climate__halo--c {
  width: 240px; height: 240px;
  top: 320px; right: 40px;
  background: radial-gradient(circle at 50% 50%, #E0DBD0, transparent 65%);
  animation: drift-a 30s var(--ease) infinite alternate-reverse;
}

.climate > * { position: relative; z-index: 1; }

.climate__head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-55);
  padding-top: 14px;
}
.climate__label { color: var(--ink); }

/* =========================================================
   Climate — atmospheric pieces
   ========================================================= */

/* ====== The Living Barograph ======
   The iconic visual of Climate. A single ink line draws across the
   screen over the trading day, with yesterday's trace ghosted and a
   30-day envelope band behind. */
/* Barograph canvas — wraps the SVG + pen + halos so they share one
   coordinate system. JS computes the visible chart band (between the
   summary text and the readings cluster) and sets both --barograph-top
   (band top) and --barograph-h (SVG total height, sized so viewBox y=200
   lands at the readings top edge). Spans full width; the time labels'
   X coordinates are computed in JS so they always land 22px from each
   screen edge (matching the readings cluster), on any device width. */
.climate__barograph-canvas {
  position: absolute;
  top: var(--barograph-top, 0);
  left: 0;
  right: 0;
  /* Visible clipped band: the SVG inside renders at the larger
     --barograph-h (so the horizon math stays consistent), but the
     canvas itself is sized to --barograph-band-h and clips any
     overflow. Net effect: chart content never paints into the 09:30
     / 16:00 timestamps or the readings cards below. Width is
     preserved edge-to-edge so the atmospheric gradients / glow still
     read full-bleed. */
  height: var(--barograph-band-h, var(--barograph-h, 100%));
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}
.climate__barograph {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  /* Full render height so viewBox y=200 (horizon) lands at the
     intended 62% of the band. The canvas clips the unused bottom. */
  height: var(--barograph-h, 100%);
  pointer-events: none;
  color: var(--ink);
  z-index: 0;
  opacity: 0.42;          /* much lower so it sits behind content in light mode */
}
[data-theme="dark"] .climate__barograph { opacity: 0.62; }

/* Thinner stroke for today's trace so it reads as an instrument line, not a hero line */
.climate__barograph .barograph__today { stroke-width: 1.1; }

/* Horizon line — the parent .climate__barograph is dimmed (~0.42), so the
   horizon needs higher inner opacity to remain visible as a reference. */
.climate__barograph .barograph__horizon {
  stroke-opacity: 0.5;
  stroke-width: 0.9;
  stroke-dasharray: 3 6;
}

/* SVG zone labels are hidden. They were dimmed by the parent SVG
   opacity (~0.42 light / ~0.62 dark) which kept them stuck at a faint
   effective opacity no matter how high we set their fill-opacity. We
   render them as HTML overlays instead (see .barograph__zone-label-html
   below) so they live outside the dimmed group and read crisply. */
.climate__barograph .barograph__zone-label { display: none; }

/* HTML zone labels (ELEVATED / TYPICAL DAY). Positioned via calc on
   --barograph-h so they track the SVG's viewBox y positions (56 and
   130) exactly, at any band height. Right-aligned for stable rhythm
   with the rest of the chart's right edge instruments. */
.barograph__zone-label-html {
  position: absolute;
  right: 16px;
  font-family: var(--display);
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--ink-70);
  opacity: 0.82;
  pointer-events: none;
  z-index: 1;
  white-space: nowrap;
  transform: translateY(-50%);
}
.barograph__zone-label-html--elevated {
  top: calc(var(--barograph-h, 0px) * 56 / 460);
  font-size: 10.5px;
}
.barograph__zone-label-html--typical {
  top: calc(var(--barograph-h, 0px) * 130 / 460);
  opacity: 0.68;
}
[data-theme="dark"] .barograph__zone-label-html {
  color: var(--ink-90);
  opacity: 0.85;
}
[data-theme="dark"] .barograph__zone-label-html--typical {
  opacity: 0.70;
}
/* Zone-boundary contour line gets a tiny bit more presence in dark mode
   so it doesn't disappear against the deep page background. */
[data-theme="dark"] .climate__barograph .barograph__zone-line {
  stroke-opacity: 0.55;
}

/* Pen (the dot at the line's current end) — HTML circle so it's always round.
   Two animations layered: pen-pulse rides on `transform` (centering + scale),
   pen-shake rides on the independent `translate` property (high-frequency
   jitter). They coexist. The shake amplitude is driven by --turbulence, set
   by JS based on how high the pen sits above the calm floor: rock-solid
   near the floor, perceptible at typical pressure, visibly unsteady above
   the typical-day band. Plane-at-altitude metaphor. */
/* Pre-market: pen pins at the 09:30 marker with a nervous, jittery
   treatment — "waiting at the start, doesn't know what to expect."
   The solid today line is suppressed entirely (JS sets dashoffset to
   full length), the pressure halo and now-line are hidden, and the
   yesterday ghost is bumped so the comparator carries the chart. */
.climate__barograph-canvas.is-premarket .pressure-halo { display: none; }
.climate__barograph-canvas.is-premarket .barograph__now-line { display: none; }
/* Yesterday ghost: promoted from comparator to lead reference. */
.climate__barograph-canvas.is-premarket .barograph__ghost {
  stroke-opacity: 0.5;
}
/* Pre-market pen: scaled up + soft glow so it reads as a deliberate
   "waiting at the open" state, not absence. Nervous jitter conveys
   "doesn't know what to expect yet." Pulse animation disabled — that
   reads as live heartbeat, which is the wrong cue pre-open. */
.climate__barograph-canvas.is-premarket .barograph__pen {
  width: 12px; height: 12px;
  background: var(--ink);
  box-shadow:
    0 0 0 2px rgba(255,255,255,0.18),
    0 0 12px 4px rgba(255,255,255,0.35),
    0 0 22px 8px rgba(255,255,255,0.18);
  animation: pen-nervous 140ms steps(6, end) infinite;
}
.climate__barograph-canvas.is-premarket .barograph__pen-halo {
  width: 26px; height: 26px;
  opacity: 0.55;
  border-color: var(--ink);
  animation: pen-nervous 140ms steps(6, end) infinite reverse;
}
@keyframes pen-nervous {
  0%   { transform: translate(-50%, -50%) translate(0, 0); }
  20%  { transform: translate(-50%, -50%) translate(0.8px, -0.6px); }
  40%  { transform: translate(-50%, -50%) translate(-0.6px, 0.8px); }
  60%  { transform: translate(-50%, -50%) translate(0.7px, 0.5px); }
  80%  { transform: translate(-50%, -50%) translate(-0.7px, -0.4px); }
  100% { transform: translate(-50%, -50%) translate(0, 0); }
}

.barograph__pen {
  position: absolute;
  width: 8px; height: 8px;
  background: var(--ink);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  z-index: 0;
  /* Higher amplitude so the shake reads at moderate pen heights. */
  --turb-amp: calc(var(--turbulence, 0) * 3.2px);
  animation:
    pen-pulse 2.6s ease-in-out infinite,
    pen-shake 220ms steps(5, end) infinite;
}
.barograph__pen-halo {
  position: absolute;
  width: 18px; height: 18px;
  border: 1.2px solid var(--ink);
  border-radius: 50%;
  opacity: 0.55;
  transform: translate(-50%, -50%);
  pointer-events: none;
  z-index: 0;
  --turb-amp: calc(var(--turbulence, 0) * 2.4px);
  animation:
    pen-halo 2.6s ease-in-out infinite,
    halo-shake 180ms steps(4, end) infinite;
}
@keyframes pen-pulse {
  0%, 100% { transform: translate(-50%, -50%) scale(1);   }
  50%      { transform: translate(-50%, -50%) scale(1.38); }
}
@keyframes pen-halo {
  0%   { transform: translate(-50%, -50%) scale(0.55); opacity: 0.65; }
  100% { transform: translate(-50%, -50%) scale(3.0);  opacity: 0;    }
}
/* Turbulence shake. Uses the CSS `translate` property (not transform) so
   it stacks cleanly with the pulse/expand animations above. Step easing
   gives the jitter a slightly mechanical, instrument-pen feel rather than
   a soft sine wobble. */
@keyframes pen-shake {
  0%   { translate: 0 0; }
  20%  { translate: calc(var(--turb-amp) *  0.8) calc(var(--turb-amp) * -0.5); }
  40%  { translate: calc(var(--turb-amp) * -0.7) calc(var(--turb-amp) *  0.6); }
  60%  { translate: calc(var(--turb-amp) *  0.4) calc(var(--turb-amp) *  0.7); }
  80%  { translate: calc(var(--turb-amp) * -0.5) calc(var(--turb-amp) * -0.3); }
  100% { translate: 0 0; }
}
@keyframes halo-shake {
  0%   { translate: 0 0; }
  25%  { translate: calc(var(--turb-amp) *  0.5) calc(var(--turb-amp) * -0.4); }
  50%  { translate: calc(var(--turb-amp) * -0.4) calc(var(--turb-amp) *  0.5); }
  75%  { translate: calc(var(--turb-amp) *  0.3) calc(var(--turb-amp) *  0.4); }
  100% { translate: 0 0; }
}
@media (prefers-reduced-motion: reduce) {
  .barograph__pen, .barograph__pen-halo { animation: none !important; }
}


/* Environmental grain — drifting noise across the whole screen */
.climate__grain {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' seed='4'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.7 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  background-size: 240px 240px;
  animation: grain-drift 16s steps(8) infinite;
}
[data-theme="dark"] .climate__grain { mix-blend-mode: screen; opacity: 0.04; }
@keyframes grain-drift {
  0%   { background-position: 0 0; }
  12%  { background-position: -40px 24px; }
  24%  { background-position: 20px -32px; }
  36%  { background-position: -28px -16px; }
  48%  { background-position: 36px 12px; }
  60%  { background-position: -12px 40px; }
  72%  { background-position: 24px -8px; }
  84%  { background-position: -36px 20px; }
  100% { background-position: 0 0; }
}

/* Directional vignette — "elevated pressure" has a slightly cooler edge feel */
.climate__vignette {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(120% 60% at 50% 110%, color-mix(in oklab, var(--cool) 18%, transparent), transparent 60%),
    radial-gradient(140% 80% at 50% -10%, transparent 60%, color-mix(in oklab, var(--ink) 8%, transparent));
  opacity: 0.85;
}

/* Title wrap holds the pressure halo behind the title */
.climate__title-wrap {
  position: relative;
  margin: 32px 0 22px;
}

/* Confidence chip — tappable annotation pinned to the top-right of the title */
.climate__title-confidence {
  position: absolute;
  top: 4px;
  right: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  text-align: right;
  background: transparent;
  border: 0;
  padding: 4px 0 4px 12px;
  margin: -4px 0 -4px -12px;
  cursor: pointer;
  color: inherit;
  font: inherit;
  transition: transform 180ms var(--ease), opacity 180ms;
}
.climate__title-confidence:hover { opacity: 0.85; }
.climate__title-confidence:active { transform: scale(0.96); }
.climate__title-confidence-value {
  font-family: var(--display);
  font-size: 18px;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  letter-spacing: -0.01em;
}
.climate__title-confidence-label {
  font-size: 9px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-55);
}
.climate__title-confidence-bar {
  width: 56px;
  height: 2px;
  border-radius: 999px;
  background: var(--ink-06);
  overflow: hidden;
  margin-top: 2px;
}
.climate__title-confidence-bar span {
  display: block;
  height: 100%;
  width: var(--c, 78%);
  background: var(--ink);
  border-radius: 999px;
}

/* Pressure halo — soft expanding rings emanating from the barograph pen,
   so the dot and the breathing rings read as one element. JS positions
   this via left/top % matching the pen; transform centers it on that point. */
.pressure-halo {
  position: absolute;
  left: 50%;
  top: 50%;
  /* Halo diameter reduced 30% (280px -> 196px) per design review —
     was reading too large relative to the pen and the chart band. */
  width: 196px;
  height: 196px;
  margin-left: -98px;
  margin-top: -98px;
  pointer-events: none;
  z-index: 0;
  opacity: 0.85;
}
.pressure-halo__ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  /* Light mode — warm ring on #FAFAFA */
  border: 1.5px solid rgba(155, 110, 65, 0.55);
  opacity: 0;
  transform: scale(0.2);
}
[data-theme="dark"] .pressure-halo__ring {
  border-width: 1px;
  border-color: color-mix(in oklab, var(--warm) 60%, transparent);
}
.pressure-halo__ring--1 { animation: halo-breath 7.5s ease-out infinite; animation-delay: 0s; }
.pressure-halo__ring--2 { animation: halo-breath 7.5s ease-out infinite; animation-delay: 2.5s; }
.pressure-halo__ring--3 { animation: halo-breath 7.5s ease-out infinite; animation-delay: 5s; }
/* Start small and tight to the pen, fade out well before reaching full size
   so big rings don't muddy the headline or readings below. */
@keyframes halo-breath {
  0%   { opacity: 0;    transform: scale(0.15); }
  20%  { opacity: 0.7;  }
  60%  { opacity: 0.18; }
  100% { opacity: 0;    transform: scale(1); }
}
[data-theme="dark"] .pressure-halo__ring--1,
[data-theme="dark"] .pressure-halo__ring--2,
[data-theme="dark"] .pressure-halo__ring--3 {
  animation-name: halo-breath-dark;
}
@keyframes halo-breath-dark {
  0%   { opacity: 0;    transform: scale(0.15); }
  25%  { opacity: 0.5;  }
  60%  { opacity: 0.14; }
  100% { opacity: 0;    transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .pressure-halo__ring { animation: none !important; opacity: 0.18; transform: scale(0.5); }
  .climate__grain { animation: none !important; }
}

.climate__title {
  position: relative;
  z-index: 1;
  font-family: var(--display);
  font-weight: 500;
  font-size: 42px;
  line-height: 1.0;
  letter-spacing: -0.04em;
  margin: 0;
  text-transform: uppercase;
  font-variation-settings: "wght" 500;
  cursor: pointer;
}

/* Per-condition typography moods — JetBrains Mono is mono so width is fixed.
   We modulate weight only (and letter-spacing) to convey pressure. */
[data-condition="calm"]    .climate__title { font-variation-settings: "wght" 380; letter-spacing: -0.02em; }
[data-condition="elevated"].climate__title { font-variation-settings: "wght" 520; letter-spacing: -0.04em; }
[data-condition="storm"]   .climate__title { font-variation-settings: "wght" 640; letter-spacing: -0.05em; }

.climate__summary {
  /* Supporting copy under the headline. Bumped from 13.5px → 15px and
     ink-55 → ink-70 after user feedback that it was hard to read. The
     chart is still the hero, but copy needs to clear the readability bar
     on small screens in mixed lighting. */
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink-70);
  /* Margin-bottom defines the chart band height. The barograph canvas
     sits in this gap (positioned by JS via --barograph-top). Trimmed
     to 196px after user feedback that calm scenarios left a tall dead
     band of air between the paragraph and the chart. Pairs with the JS
     HORIZON_PCT=0.62 fix so the line sits naturally centered. */
  margin: 0 0 196px;
  max-width: none;
  letter-spacing: 0.005em;
}

/* Readings cluster: three compact gauges. Pressure is dropped because the
   barograph above already visualises it (line height = pressure). The
   remaining three each add a dimension the chart can't show: Currents
   (where money is rotating), Momentum (trend persistence), Sentiment
   (positioning + risk appetite). Three columns give each reading more
   breathing room than the prior four-up.
   minmax(0, 1fr) (not just 1fr) prevents cells from growing past their
   fair share when the value text is wider than the column. Without this,
   `white-space: nowrap` on .reading__value lets cells expand and the
   row overflows the screen. */
.climate__readings {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  column-gap: 10px;
  row-gap: 0;
  margin: 0 0 14px;
}
/* Reading "instruments" — soft observational panels, not buttons.
   No border, no shadow, very faint background; a thin top rule reads as
   the boundary of a gauge rather than a pill. */
.reading {
  background: rgba(255, 255, 255, 0.025);
  border: 0;
  border-top: 1px solid var(--ink-12);
  border-radius: 0;
  padding: 12px 6px 14px;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
  transition: background 240ms var(--ease), border-color 240ms;
  cursor: pointer;
  position: relative;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
[data-theme="dark"] .reading {
  background: rgba(255, 255, 255, 0.02);
  border-top-color: rgba(244, 242, 236, 0.10);
}
.reading:hover {
  background: rgba(255, 255, 255, 0.05);
  border-top-color: var(--ink-25);
}
.reading:active { background: rgba(255, 255, 255, 0.04); }

.reading__head {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  letter-spacing: 0.16em;
  color: var(--ink-55);
  text-transform: uppercase;
  white-space: nowrap;
}
.reading__head svg { stroke: currentColor; fill: none; width: 12px; height: 12px; flex: 0 0 12px; }
.reading__value {
  font-family: var(--display);
  /* Sized so the longest value ("Defensive", 9 monospace chars) fits the
     ~80px text area inside each cell on a narrow phone without ellipsis. */
  font-size: 15px;
  line-height: 1;
  margin: 0;
  letter-spacing: -0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Compact mode drops the per-reading instrument visualizations; the
   horizontal row keeps the data dense and lets the chart breathe. */
.climate__readings .reading__bar,
.climate__readings .reading__instrument { display: none; }
.reading__bar {
  height: 3px;
  border-radius: 999px;
  background: var(--ink-06);
  overflow: hidden;
}
.reading__bar span {
  display: block;
  height: 100%;
  width: var(--v, 50%);
  background: var(--ink);
  border-radius: 999px;
}

/* Pressure: bar gently breathes (very subtle scale + opacity on the fill) */
.reading__bar--breathe span {
  animation: bar-breath 4.2s ease-in-out infinite;
  transform-origin: left center;
}
@keyframes bar-breath {
  0%, 100% { transform: scaleX(1);    opacity: 1;   }
  50%      { transform: scaleX(0.92); opacity: 0.7; }
}

/* Generic instrument slot */
.reading__instrument {
  height: 10px;
  margin-top: 0;
  position: relative;
  color: var(--ink);
}
.reading__instrument svg {
  width: 100%;
  height: 100%;
}

/* Currents: flowing dashes that drift across */
.reading__instrument .currents-flow {
  animation: currents-flow 3.6s linear infinite;
}
@keyframes currents-flow {
  to { stroke-dashoffset: -36; }
}

/* Momentum: a track with a dot that accelerates/decelerates */
.reading__instrument--track {
  height: 4px;
  display: flex;
  align-items: center;
  margin-top: 0;
}
.momentum-track {
  position: absolute;
  left: 0; right: 0;
  height: 1px;
  background: var(--ink-12);
  top: 50%;
}
.momentum-dot {
  position: absolute;
  top: 50%;
  left: 0;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ink);
  transform: translateY(-50%);
  animation: momentum-run 5s cubic-bezier(0.7, 0, 0.3, 1) infinite;
}
@keyframes momentum-run {
  0%   { left: 0%;   }
  45%  { left: 70%;  }
  55%  { left: 70%;  }
  100% { left: 0%;   }
}

/* Sentiment: a single dot with a halo that pulses + drifts in stability */
.reading__instrument--glow {
  height: 12px;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: 0;
  position: relative;
}
.sentiment-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ink);
  position: relative;
}
.sentiment-dot::before {
  content: "";
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  border: 1px solid var(--ink-25);
  animation: sentiment-pulse 3.4s ease-in-out infinite;
}
@keyframes sentiment-pulse {
  0%, 100% { transform: scale(0.6); opacity: 0.45; }
  50%      { transform: scale(1.4); opacity: 0;    }
}

@media (prefers-reduced-motion: reduce) {
  .reading__bar--breathe span,
  .reading__instrument .currents-flow,
  .momentum-dot,
  .sentiment-dot::before { animation: none !important; }
}

/* =========================================================
   Climate mini-map — atmospheric thumbnail of the Map
   ========================================================= */
.climate__minimap {
  display: block;
  position: relative;
  margin: 0 0 14px;
  padding: 12px 14px 10px;
  border-radius: 14px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-stroke);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: var(--ink-70);
  text-decoration: none;
  overflow: hidden;
  transition: transform 200ms var(--ease), background 200ms;
}
.climate__minimap:hover { transform: translateY(-1px); background: var(--glass-bg-2); }
.climate__minimap svg {
  display: block;
  width: 100%;
  height: 64px;
  border-radius: 8px;
  overflow: hidden;
  color: var(--ink);
}
.climate__minimap-label {
  display: block;
  margin-top: 8px;
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-55);
}
[data-theme="dark"] .climate__minimap { background: rgba(255,255,255,0.04); }

.climate__cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  width: 100%;
  padding: 14px 16px;
  background: var(--glass-bg-2);
  border: 1px solid var(--glass-stroke);
  border-radius: 18px;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  box-shadow: var(--glass-shadow);
  margin: 0 0 14px;
  transition: transform 200ms var(--ease);
  cursor: pointer;
}
.climate__cta:hover { transform: translateY(-1px); }
.climate__cta div { display: flex; flex-direction: column; gap: 2px; }
.climate__cta-eyebrow {
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-55);
}
.climate__cta-title {
  font-family: var(--display);
  font-size: 17px;
  line-height: 1.1;
  letter-spacing: -0.01em;
}
.climate__cta svg { stroke: var(--ink); flex-shrink: 0; }

.climate__confidence {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 12px;
  align-items: center;
  padding: 14px 16px;
  background: var(--glass-bg-2);
  border: 1px solid var(--glass-stroke);
  border-radius: 16px;
  backdrop-filter: blur(12px);
}
.climate__confidence-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--ink-70);
}
.climate__confidence-val {
  font-family: var(--display);
  font-size: 18px;
  font-variant-numeric: tabular-nums;
}
.confidence {
  height: 3px;
  border-radius: 999px;
  background: var(--ink-06);
  overflow: hidden;
  position: relative;
}
.confidence span {
  display: block;
  height: 100%;
  width: var(--c, 70%);
  background: linear-gradient(90deg, var(--ink-25), var(--ink));
  border-radius: 999px;
}

/* =========================================================
   02 — MAP
   ========================================================= */
.mapscreen { display: flex; flex-direction: column; min-height: 100%; }
.mapscreen__head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--ink-55);
  padding-top: 10px;
}
.mapscreen__head .climate__label { color: var(--ink); }
.mapscreen__title {
  font-family: var(--display);
  font-weight: 500;
  font-size: 28px;
  line-height: 1.05;
  letter-spacing: -0.03em;
  margin: 18px 0 10px;
  text-transform: uppercase;
}
.mapviz {
  position: relative;
  flex: 1;
  min-height: 440px;
  border-radius: 26px;
  overflow: hidden;
  background:
    radial-gradient(120% 80% at 80% 20%, #FAF4EA 0%, transparent 60%),
    radial-gradient(120% 80% at 10% 90%, #EEF2F5 0%, transparent 60%),
    linear-gradient(180deg, #F6F5F2, #EFEFEC);
  border: 1px solid var(--glass-stroke);
  box-shadow: var(--glass-shadow);
}
.mapviz__svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.mapviz__svg .currents .current {
  animation: flow 8s linear infinite;
}
.mapviz__svg .currents .current--b { animation-duration: 11s; }
.mapviz__svg .currents .current--c { animation-duration: 13s; }
@keyframes flow { to { stroke-dashoffset: -240; } }

/* ===== Map v2 ===== */
.mapscreen__sub {
  /* Matches .climate__summary so supporting copy reads the same on every
     screen. Bumped 13.5px → 15px and ink-55 → ink-70 for readability
     (matches the Climate summary change). The map sits below in its own
     bounded box, so the larger text has no chance to collide with it. */
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink-70);
  margin: 0 0 10px;
  max-width: none;
  letter-spacing: 0.005em;
}
.mapscreen__hint {
  font-size: 12px;
  color: var(--ink-55);
  letter-spacing: 0.04em;
  margin: 12px 0 0;
  text-align: center;
}
.mapviz--v2 {
  background: transparent;
  border: 1px solid var(--glass-stroke);
}
.mapviz--v2 .active-front__line {
  stroke-dasharray: 0;
  animation: front-pulse 4.2s ease-in-out infinite;
}
@keyframes front-pulse {
  0%, 100% { stroke-opacity: 0.40; }
  50%      { stroke-opacity: 0.65; }
}
.mapviz--v2 .trails path {
  animation: trail-fade 5s ease-in-out infinite;
}
.mapviz--v2 .trails path:nth-child(2) { animation-delay: -1.4s; }
.mapviz--v2 .trails path:nth-child(3) { animation-delay: -2.6s; }
.mapviz--v2 .trails path:nth-child(4) { animation-delay: -3.8s; }
@keyframes trail-fade {
  0%, 100% { stroke-opacity: 0.14; }
  50%      { stroke-opacity: 0.30; }
}

.chip--tap {
  border: 1px solid var(--glass-stroke);
  cursor: pointer;
  font-family: var(--ui);
  transition: transform 200ms var(--ease), background 200ms;
  animation: chip-drift 14s ease-in-out infinite;
}
.chip--tap:nth-of-type(2) { animation-duration: 17s; animation-delay: -2s; }
.chip--tap:nth-of-type(3) { animation-duration: 19s; animation-delay: -4s; }
.chip--tap:nth-of-type(4) { animation-duration: 16s; animation-delay: -6s; }
.chip--tap:nth-of-type(5) { animation-duration: 18s; animation-delay: -8s; }
.chip--tap:nth-of-type(6) { animation-duration: 20s; animation-delay: -10s; }
.chip--tap:nth-of-type(7) { animation-duration: 15s; animation-delay: -12s; }
.chip--tap:nth-of-type(8) { animation-duration: 21s; animation-delay: -3s; }
.chip--tap:active { transform: translate(-50%, -50%) scale(0.95); }
.chip--tap:hover { background: rgba(255,255,255,0.95); }

@keyframes chip-drift {
  0%, 100% { transform: translate(-50%, -50%) translateY(0); }
  50%      { transform: translate(-50%, -50%) translateY(-3px); }
}

/* Active front pill — tappable, sits on the front line */
.front-tag {
  position: absolute;
  left: 50%;
  top: 56%;
  transform: translate(-50%, -50%);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--ink);
  background: var(--ink);
  color: var(--page-0);
  border: 0;
  border-radius: 999px;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 4px 12px rgba(10,10,10,0.18);
  white-space: nowrap;
  cursor: pointer;
  z-index: 2;
}
.front-tag svg { stroke: currentColor; fill: none; }
.front-tag:active { transform: translate(-50%, -50%) scale(0.97); }

/* ===== Sector detail sheet ===== */
/* Detail slide-over — full-screen panel that slides in from the right.
   Treats detail views as a navigation stack instead of a modal pop-up. */
.detail-screen {
  position: absolute;
  inset: 0;
  z-index: 9;
  background: var(--page-0);
  transform: translate3d(100%, 0, 0);
  transition: transform 380ms var(--ease);
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  display: flex;
  flex-direction: column;
}
.detail-screen[hidden] { display: none; }
.detail-screen.is-open {
  transform: translate3d(0, 0, 0);
}
.detail-screen .app-header {
  padding: 18px 22px 14px;
  margin-bottom: 0;
  flex-shrink: 0;
  background: linear-gradient(180deg, var(--page-0) 80%, transparent);
}
.detail-screen__body {
  padding: 4px 22px 80px;
  flex: 1;
}
.detail-screen__title {
  font-family: var(--display);
  font-weight: 500;
  font-size: 34px;
  line-height: 1.0;
  letter-spacing: -0.035em;
  margin: 0 0 14px;
  text-transform: none;
}
.detail-screen__lede {
  font-size: 16px;
  line-height: 1.5;
  color: var(--ink-70);
  margin: 0 0 8px;
}

/* Hide the prototype's bottom tabbar while a detail panel is open */
.phone__screen:has(.detail-screen.is-open) .tabbar { display: none; }
.sector-sheet__close {
  position: absolute;
  top: 14px; right: 14px;
  width: 28px; height: 28px;
  display: grid; place-items: center;
  color: var(--ink-55);
  border-radius: 50%;
  background: transparent;
  border: 0;
  cursor: pointer;
}
.sector-sheet__close:hover { background: var(--ink-06); color: var(--ink); }
.sector-sheet__kicker {
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-55);
}
.sector-sheet__title {
  font-family: var(--display);
  font-weight: 500;
  font-size: 28px;
  line-height: 1.05;
  letter-spacing: -0.015em;
  margin: 6px 0 4px;
}
.sector-sheet__condition {
  font-size: 13px;
  color: var(--ink-70);
  margin: 0 0 14px;
}
.sector-sheet__drivers {
  list-style: none;
  padding: 0;
  margin: 0;
  border-top: 1px solid var(--ink-12);
}
.sector-sheet__drivers li {
  display: grid;
  grid-template-columns: 14px 1fr;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--ink-06);
  font-size: 13px;
  line-height: 1.45;
  color: var(--ink-90);
}
.sector-sheet__drivers li:last-child { border-bottom: 0; }
.sector-sheet__drivers li::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--ink);
  margin-top: 8px;
}

/* Section blocks inside the detail sheet (why / changed / follows / related) */
.ss-block {
  margin-top: 20px;
}
.ss-block[hidden] { display: none; }
.ss-block__label {
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-55);
  margin: 0 0 10px;
  font-weight: 500;
  font-family: var(--ui);
}
.ss-block__body {
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink-90);
  margin: 0;
  padding-top: 12px;
  border-top: 1px solid var(--ink-12);
}
.ss-related {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding-top: 12px;
  border-top: 1px solid var(--ink-12);
}
.ss-related button {
  font-family: var(--ui);
  font-size: 12px;
  letter-spacing: 0.02em;
  padding: 6px 12px;
  border: 1px solid var(--ink-12);
  border-radius: 999px;
  background: transparent;
  cursor: pointer;
  color: var(--ink-70);
  transition: background 200ms, border-color 200ms, color 200ms, transform 180ms var(--ease);
}
.ss-related button:hover {
  background: var(--ink-06);
  color: var(--ink);
  border-color: var(--ink-25);
}
.ss-related button:active { transform: scale(0.96); }

/* Annotated diagram inside an explainer sheet */
.ss-diagram {
  border-top: 1px solid var(--ink-12);
  padding-top: 14px;
  margin-bottom: 14px;
}
.ss-diagram svg {
  display: block;
  width: 100%;
  height: auto;
  color: var(--ink);
}
.ss-diagram__callout circle {
  fill: var(--page-0);
  stroke: var(--ink);
  stroke-width: 0.8;
}
.ss-diagram__callout text {
  fill: var(--ink);
  font-family: "JetBrains Mono", monospace;
  font-size: 9px;
  font-weight: 600;
}
.ss-diagram__key {
  list-style: none;
  padding: 0;
  margin: 0;
  counter-reset: ss-key;
}
.ss-diagram__key li {
  display: grid;
  grid-template-columns: 22px 1fr;
  gap: 10px;
  align-items: baseline;
  padding: 8px 0;
  border-bottom: 1px solid var(--ink-06);
  font-size: 13px;
  line-height: 1.45;
  color: var(--ink-90);
  counter-increment: ss-key;
}
.ss-diagram__key li:last-child { border-bottom: 0; }
.ss-diagram__key li::before {
  content: counter(ss-key);
  display: grid;
  place-items: center;
  width: 18px; height: 18px;
  border-radius: 50%;
  border: 0.8px solid var(--ink);
  font-family: "JetBrains Mono", monospace;
  font-size: 9px;
  font-weight: 600;
  color: var(--ink);
  background: var(--page-0);
}
.ss-diagram__key li strong {
  font-weight: 500;
  color: var(--ink);
  margin-right: 4px;
}

/* =========================================================
   Onboarding — first-launch calibration overlay
   Mission-control atmosphere: dark, mono, slow.
   ========================================================= */
.onboarding {
  position: absolute;
  inset: 0;
  z-index: 30;
  background: #0B0C0F;
  color: #F4F2EC;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  font-family: var(--ui);
  animation: onb-in 480ms var(--ease);
}
.onboarding[hidden] { display: none; }
@keyframes onb-in { from { opacity: 0; } to { opacity: 1; } }

.onboarding__bg {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}
.onboarding__sweep {
  position: absolute;
  inset: -10% 0;
  background:
    radial-gradient(60% 40% at 50% 30%, rgba(216, 182, 140, 0.10), transparent 70%),
    radial-gradient(60% 40% at 50% 80%, rgba(159, 179, 199, 0.12), transparent 70%);
  filter: blur(40px);
  animation: onb-sweep 16s ease-in-out infinite alternate;
}
@keyframes onb-sweep {
  0%   { transform: translateY(-2%); }
  100% { transform: translateY(2%); }
}
.onboarding__grid {
  position: absolute;
  inset: 0;
  opacity: 0.06;
  background-image:
    repeating-linear-gradient(0deg, rgba(255,255,255,0.4) 0 1px, transparent 1px 56px),
    repeating-linear-gradient(90deg, rgba(255,255,255,0.4) 0 1px, transparent 1px 56px);
}

/* Header — progress + skip */
.onboarding__head {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: env(safe-area-inset-top, 20px) 22px 0;
  padding-top: calc(env(safe-area-inset-top, 0px) + 20px);
}
.onboarding__progress {
  font-family: var(--display);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(244, 242, 236, 0.62);
  font-variant-numeric: tabular-nums;
}
.onboarding__skip {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(244, 242, 236, 0.55);
  background: none;
  border: 0;
  padding: 8px 10px;
  cursor: pointer;
  transition: color 200ms;
}
.onboarding__skip:hover { color: #F4F2EC; }

/* Stage — holds the steps */
.onboarding__stage {
  position: relative;
  z-index: 1;
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.onboarding__step {
  position: absolute;
  inset: 0;
  padding: 36px 22px 20px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
  transition: opacity 380ms var(--ease), transform 420ms var(--ease);
}
.onboarding__step.is-active {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.onboarding__kicker {
  display: inline-block;
  font-family: var(--display);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(244, 242, 236, 0.55);
  margin-bottom: 22px;
  padding: 4px 10px;
  border: 1px solid rgba(244, 242, 236, 0.18);
  border-radius: 999px;
}
.onboarding__title {
  font-family: var(--display);
  font-weight: 500;
  font-size: 32px;
  line-height: 1.05;
  letter-spacing: -0.04em;
  margin: 0 0 14px;
  text-transform: uppercase;
}
.onboarding__lede {
  font-size: 15px;
  line-height: 1.45;
  color: rgba(244, 242, 236, 0.65);
  margin: 0 0 28px;
  max-width: 40ch;
}

/* Tall list — single-select tappable rows */
.onb-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  border-top: 1px solid rgba(244, 242, 236, 0.12);
}
.onb-list li {
  border-bottom: 1px solid rgba(244, 242, 236, 0.08);
}
.onb-list button {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 16px 4px;
  background: transparent;
  border: 0;
  text-align: left;
  color: inherit;
  cursor: pointer;
  transition: background 200ms;
}
.onb-list button:hover { background: rgba(244, 242, 236, 0.04); }
.onb-list button strong {
  font-family: var(--ui);
  font-size: 16px;
  font-weight: 500;
  letter-spacing: -0.005em;
}
.onb-list button small {
  font-size: 13px;
  color: rgba(244, 242, 236, 0.55);
  line-height: 1.4;
}
.onb-list button.is-on {
  background: rgba(244, 242, 236, 0.06);
}
.onb-list button.is-on::after {
  content: "✓";
  position: absolute;
  right: 22px;
  font-family: var(--display);
}
.onb-list li { position: relative; }

/* Multi-select chip grid */
.onb-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.onb-chips button {
  font-family: var(--ui);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.02em;
  padding: 9px 14px;
  background: transparent;
  color: rgba(244, 242, 236, 0.75);
  border: 1px solid rgba(244, 242, 236, 0.18);
  border-radius: 999px;
  cursor: pointer;
  transition: background 200ms, color 200ms, border-color 200ms;
}
.onb-chips button:hover { border-color: rgba(244, 242, 236, 0.4); color: #F4F2EC; }
.onb-chips button.is-on {
  background: #F4F2EC;
  color: #0B0C0F;
  border-color: #F4F2EC;
}
.onb-hint {
  margin-top: 18px;
  font-size: 12px;
  letter-spacing: 0.04em;
  color: rgba(244, 242, 236, 0.45);
}

/* Theme cards */
.onb-themes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.onb-themes button {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 12px 14px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 14px;
  color: inherit;
  cursor: pointer;
  text-align: left;
  transition: background 200ms, border-color 200ms;
}
.onb-themes button:hover { background: rgba(255, 255, 255, 0.07); }
.onb-themes button.is-on {
  background: rgba(244, 242, 236, 0.10);
  border-color: rgba(244, 242, 236, 0.6);
}
.onb-themes strong {
  font-family: var(--ui);
  font-size: 13px;
  font-weight: 500;
}
.onb-themes small {
  font-size: 10px;
  color: rgba(244, 242, 236, 0.5);
  letter-spacing: 0.02em;
}
.onb-theme-preview {
  display: block;
  height: 56px;
  border-radius: 10px;
  position: relative;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.08);
}
.onb-theme-preview--atmospheric {
  background:
    radial-gradient(60% 50% at 70% 30%, rgba(216, 182, 140, 0.45), transparent 70%),
    radial-gradient(60% 50% at 30% 80%, rgba(159, 179, 199, 0.45), transparent 70%),
    #161719;
}
.onb-theme-preview--minimal {
  background: #161719;
  position: relative;
}
.onb-theme-preview--minimal::before {
  content: "M";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--display);
  font-size: 26px;
  color: #F4F2EC;
}
.onb-theme-preview--radar {
  background: #161719;
  position: relative;
}
.onb-theme-preview--radar::before,
.onb-theme-preview--radar::after {
  content: "";
  position: absolute;
  border: 1px solid rgba(244, 242, 236, 0.4);
  border-radius: 50%;
  left: 50%; top: 60%;
  transform: translate(-50%, -50%);
}
.onb-theme-preview--radar::before { width: 36px; height: 36px; }
.onb-theme-preview--radar::after  { width: 60px; height: 60px; opacity: 0.5; }
.onb-theme-preview--editorial {
  background: #161719;
  position: relative;
}
.onb-theme-preview--editorial::before {
  content: "Today is\A elevated";
  white-space: pre;
  position: absolute;
  inset: 10px;
  font-family: var(--display);
  font-size: 11px;
  line-height: 1.05;
  color: #F4F2EC;
}
.onb-theme-preview--telemetry {
  background:
    repeating-linear-gradient(90deg, transparent 0 12px, rgba(244,242,236,0.08) 12px 13px),
    repeating-linear-gradient(0deg,  transparent 0 12px, rgba(244,242,236,0.08) 12px 13px),
    #161719;
  position: relative;
}
.onb-theme-preview--telemetry::before {
  content: "";
  position: absolute;
  left: 10px; top: 12px;
  width: 24px; height: 24px;
  border: 1px solid #F4F2EC;
  border-radius: 50%;
}

/* Footer — back + continue */
.onboarding__foot {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 22px calc(env(safe-area-inset-bottom, 0px) + 22px);
  border-top: 1px solid rgba(244, 242, 236, 0.08);
}
.onboarding__back,
.onboarding__next {
  font-family: var(--ui);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.04em;
  padding: 12px 22px;
  border-radius: 999px;
  cursor: pointer;
  border: 0;
  transition: opacity 200ms, transform 200ms;
}
.onboarding__back {
  background: transparent;
  color: rgba(244, 242, 236, 0.6);
}
.onboarding__back:hover { color: #F4F2EC; }
.onboarding__back[disabled] { opacity: 0; pointer-events: none; }
.onboarding__next {
  background: #F4F2EC;
  color: #0B0C0F;
}
.onboarding__next:hover { transform: translateY(-1px); }
.onboarding__next[disabled] {
  background: rgba(244, 242, 236, 0.12);
  color: rgba(244, 242, 236, 0.35);
  pointer-events: none;
}

/* Welcome step */
.onboarding__step--welcome { padding-top: 56px; }
.onboarding__lede--lg { font-size: 16px; max-width: 42ch; margin-bottom: 32px; }
.onb-welcome-list {
  list-style: none;
  padding: 0;
  margin: 0 0 32px;
  border-top: 1px solid rgba(244, 242, 236, 0.10);
}
.onb-welcome-list li {
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: 14px;
  align-items: baseline;
  padding: 14px 0;
  border-bottom: 1px solid rgba(244, 242, 236, 0.06);
}
.onb-welcome-num {
  font-family: var(--display);
  font-size: 12px;
  letter-spacing: 0.16em;
  color: rgba(244, 242, 236, 0.45);
}
.onb-welcome-list strong {
  display: block;
  font-family: var(--ui);
  font-size: 15px;
  font-weight: 500;
  margin-bottom: 2px;
}
.onb-welcome-list small {
  font-size: 13px;
  color: rgba(244, 242, 236, 0.55);
}
.onb-welcome-foot {
  font-size: 12px;
  letter-spacing: 0.02em;
  color: rgba(244, 242, 236, 0.45);
}
.onb-welcome-foot strong {
  color: rgba(244, 242, 236, 0.85);
  font-weight: 500;
}

/* Toast — "you can re-run from preferences" after dismissing welcome */
.onb-toast {
  position: absolute;
  left: 50%;
  bottom: max(env(safe-area-inset-bottom, 0px) + 96px, 96px);
  transform: translateX(-50%);
  z-index: 40;
  background: rgba(20, 22, 26, 0.92);
  color: #F4F2EC;
  border: 1px solid rgba(244, 242, 236, 0.16);
  border-radius: 999px;
  padding: 10px 18px;
  font-size: 12px;
  letter-spacing: 0.02em;
  white-space: nowrap;
  box-shadow: 0 14px 30px rgba(0,0,0,0.45);
  opacity: 0;
  pointer-events: none;
  transition: opacity 280ms var(--ease), transform 280ms var(--ease);
}
.onb-toast.is-visible {
  opacity: 1;
  transform: translateX(-50%) translateY(-4px);
}
.onb-toast strong { font-weight: 500; opacity: 0.85; }

/* =========================================================
   Calibration — answers apply visible side effects
   ========================================================= */
/* Theme variants set on <html> by the calibration applier. */
[data-vis-theme="minimal"] .climate__currents,
[data-vis-theme="minimal"] .mapviz__currents { display: none; }
[data-vis-theme="minimal"] .pressure-halo { display: none; }
[data-vis-theme="minimal"] .climate__grain { display: none; }

[data-vis-theme="radar"] .pressure-halo__ring {
  border-color: rgba(244, 242, 236, 0.45);
}
[data-vis-theme="radar"] .pressure-halo__ring--1,
[data-vis-theme="radar"] .pressure-halo__ring--2,
[data-vis-theme="radar"] .pressure-halo__ring--3 {
  animation-duration: 4s;
}

[data-vis-theme="editorial"] .climate__currents,
[data-vis-theme="editorial"] .pressure-halo { display: none; }
[data-vis-theme="editorial"] .climate__title { letter-spacing: -0.05em; }

[data-vis-theme="telemetry"] .screen[data-screen="climate"]::after,
[data-vis-theme="telemetry"] .screen[data-screen="map"]::after,
[data-vis-theme="telemetry"] .screen[data-screen="radar"]::after {
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  z-index: 0;
  opacity: 0.04;
  background-image:
    repeating-linear-gradient(0deg, currentColor 0 1px, transparent 1px 24px),
    repeating-linear-gradient(90deg, currentColor 0 1px, transparent 1px 24px);
}

/* Posture-driven changes are applied as data-posture attribute by JS;
   visible micro-copy lives in JS. */

/* Sensitivity-driven changes — fewer or more signals on Signals screen */
[data-sensitivity="calm"]     .signal-list li:nth-child(n+2) { display: none; }
[data-sensitivity="tactical"] .signal-list li:nth-child(n+3) { display: none; }
/* active = all 3; storm = all 3 (or more — same set for now) */

/* Forces filter — events on the Radar hide when no selected force tags them */
.event[data-hidden="true"] { display: none; }

/* Final step */
.onboarding__step--final { text-align: center; padding-top: 80px; }
.onboarding__step--final .onboarding__kicker { display: inline-block; }
.onboarding__step--final .onboarding__title { font-size: 36px; }
.onb-loading {
  width: 56px;
  height: 56px;
  margin: 32px auto 24px;
  position: relative;
}
.onb-loading__arc {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  border: 1.6px solid rgba(244, 242, 236, 0.14);
  border-top-color: #F4F2EC;
  animation: onb-spin 1s linear infinite;
}
@keyframes onb-spin { to { transform: rotate(360deg); } }
.onb-summary {
  list-style: none;
  padding: 0;
  margin: 32px auto 0;
  max-width: 280px;
  text-align: left;
  font-size: 12px;
  letter-spacing: 0.04em;
}
.onb-summary li {
  display: flex;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid rgba(244, 242, 236, 0.08);
  color: rgba(244, 242, 236, 0.7);
}
.onb-summary li strong {
  color: #F4F2EC;
  font-weight: 500;
}

@media (prefers-reduced-motion: reduce) {
  .onboarding__sweep, .onb-loading__arc { animation: none !important; }
}

/* =========================================================
   Pull to refresh
   ========================================================= */
/* Pull indicator sits behind content at top of screen; revealed when content slides down */
.pull {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 68px;
  color: var(--ink-70);
  pointer-events: none;
  opacity: 0;
  transition: opacity 200ms var(--ease);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.pull.is-visible { opacity: 1; }

/* Content (the screens container) moves down to reveal the pull indicator */
.screens {
  transform: translate3d(0, var(--pull-h, 0px), 0);
  transition: transform 320ms var(--ease);
  z-index: 2;
  background: var(--page-0);
}
.screens.is-pulling { transition: none; }
.pull__arc {
  display: block;
  color: var(--ink);
}
/* Arc fills proportionally to pull distance via CSS var */
.pull.is-pulling .pull__arc circle {
  stroke-dashoffset: calc(100 - var(--pull-progress, 0) * 100);
}
.pull.is-refreshing .pull__arc {
  animation: pull-spin 1.1s linear infinite;
}
.pull.is-refreshing .pull__arc circle {
  stroke-dasharray: 30 100;
  stroke-dashoffset: 0;
}
.pull.is-complete .pull__arc circle {
  stroke-dasharray: 100;
  stroke-dashoffset: 0;
  animation: pull-fade 600ms ease-out;
}
@keyframes pull-spin {
  to { transform: rotate(360deg); }
}
@keyframes pull-fade {
  0%   { opacity: 1; }
  100% { opacity: 0.7; }
}

/* Dark theme: keep visible */
[data-theme="dark"] .pull { color: var(--ink-70); }
[data-theme="dark"] .pull__arc { color: var(--ink); }

/* =========================================================
   Universal tap-press feedback — "moving back in space"
   ========================================================= */
.reading,
.climate__cta,
.event,
.signal-card,
.signal-list li,
.impact,
.icon-btn,
.tabbar__btn,
.brief__cta,
.theme-card,
.select-chip,
.seg-row,
.switch,
.theme-seg__btn,
[data-sector],
[data-detail],
[data-go] {
  transition: transform 180ms var(--ease), background 200ms, color 200ms, opacity 200ms;
}
.reading:active,
.climate__cta:active,
.event:active,
.signal-card:active,
.signal-list li:active,
.brief__cta:active,
.icon-btn:active,
.theme-card:active,
.select-chip:active,
.seg-row:active,
[data-go]:active {
  transform: scale(0.97);
}
/* For chip--tap which has translate(-50%,-50%) already, use only the existing :active rule */

/* Make signal-list rows tappable */
.signal-list li {
  cursor: pointer;
  border-radius: 12px;
  margin: 0 -8px;
  padding-left: 12px;
  padding-right: 8px;
}
.signal-list li:hover { background: var(--ink-06); }

/* Make event rows tappable */
.event {
  cursor: pointer;
}

/* =========================================================
   Warp transition — element pulls toward center as its detail opens
   ========================================================= */
.warp-out {
  animation: warp-out 320ms var(--ease) forwards;
  z-index: 9;
}
@keyframes warp-out {
  0%   { transform: translate(-50%, -50%) scale(1); opacity: 1; }
  60%  { transform: translate(-50%, -50%) scale(1.18); opacity: 0.7; }
  100% { transform: translate(-50%, -50%) scale(1.4); opacity: 0; }
}
/* Non-chip element warp (no translate offset) */
.warp-out--flat {
  animation: warp-out-flat 320ms var(--ease) forwards;
  z-index: 9;
  position: relative;
}
@keyframes warp-out-flat {
  0%   { transform: scale(1); opacity: 1; }
  60%  { transform: scale(1.04); opacity: 0.6; }
  100% { transform: scale(1.08); opacity: 0; }
}

/* =========================================================
   Map — environmental motion system (4 coordinated layers)
   ========================================================= */

/* Layer 1 — Atmospheric field. Two soft radial blobs slowly breathing
   in/out of phase. The SVG base gradient stays static; this overlays it
   to create the "ink in water" effect with no visible animation start/end. */
.mapviz--v2 {
  position: relative;
  isolation: isolate;
}
.mapviz--v2::before,
.mapviz--v2::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  mix-blend-mode: multiply;
  filter: blur(40px);
  opacity: 0.5;
}
.mapviz--v2::before {
  background: radial-gradient(
    50% 38% at var(--atmos-warm-x, 65%) var(--atmos-warm-y, 18%),
    color-mix(in oklab, var(--warm-2) 80%, transparent),
    transparent 70%
  );
  animation: atmos-warm 240s ease-in-out infinite;
}
.mapviz--v2::after {
  background: radial-gradient(
    55% 45% at var(--atmos-cool-x, 35%) var(--atmos-cool-y, 82%),
    color-mix(in oklab, var(--cool) 70%, transparent),
    transparent 70%
  );
  animation: atmos-cool 300s ease-in-out infinite;
}
[data-theme="dark"] .mapviz--v2::before,
[data-theme="dark"] .mapviz--v2::after { mix-blend-mode: screen; opacity: 0.32; }

/* Slow 4-min cycles, out of phase. Never reaches a clean "start/end". */
@keyframes atmos-warm {
  0%   { --atmos-warm-x: 62%; --atmos-warm-y: 18%; opacity: 0.50; }
  25%  { --atmos-warm-x: 72%; --atmos-warm-y: 22%; opacity: 0.58; }
  50%  { --atmos-warm-x: 68%; --atmos-warm-y: 14%; opacity: 0.42; }
  75%  { --atmos-warm-x: 58%; --atmos-warm-y: 20%; opacity: 0.52; }
  100% { --atmos-warm-x: 62%; --atmos-warm-y: 18%; opacity: 0.50; }
}
@keyframes atmos-cool {
  0%   { --atmos-cool-x: 35%; --atmos-cool-y: 82%; opacity: 0.50; }
  30%  { --atmos-cool-x: 28%; --atmos-cool-y: 78%; opacity: 0.58; }
  55%  { --atmos-cool-x: 40%; --atmos-cool-y: 86%; opacity: 0.46; }
  80%  { --atmos-cool-x: 32%; --atmos-cool-y: 80%; opacity: 0.54; }
  100% { --atmos-cool-x: 35%; --atmos-cool-y: 82%; opacity: 0.50; }
}

/* Layer 2 — Flow currents. The canvas sits between the SVG base
   (z-index 0) and the chip overlay (z-index 3). */
.mapviz__currents {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0.75;
}
[data-theme="dark"] .mapviz__currents { opacity: 0.55; }

/* Chips always above field + currents */
.mapviz--v2 .chip { z-index: 4; }
.mapviz--v2 .front-tag { z-index: 5; }

/* Layer 3 — Sector entities. JS drives subtle drift via CSS vars.
   Remove the old per-chip CSS animation so motion comes from one
   coherent system (the JS loop) instead of independent timers. */
.chip--tap { animation: none; transition: transform 240ms var(--ease); }

/* Layer 4 — Pressure front. Already in SVG; we slow + soften its drift. */
.mapviz--v2 .active-front {
  animation: front-drift 60s ease-in-out infinite alternate;
}
@keyframes front-drift {
  0%   { transform: translateY(-3px) translateX(-2px); }
  100% { transform: translateY(3px)  translateX(2px); }
}
.mapviz--v2 .active-front__line { animation: front-pulse 9s ease-in-out infinite; }
@keyframes front-pulse {
  0%, 100% { stroke-opacity: 0.45; }
  50%      { stroke-opacity: 0.65; }
}

/* Bands: keep but slower + lower amplitude — environmental, not animated */
.mapviz--v2 .bands {
  animation: bands-shift 90s ease-in-out infinite alternate;
}
@keyframes bands-shift {
  0%   { transform: translateY(-1px); opacity: 0.9; }
  100% { transform: translateY(2px);  opacity: 0.6; }
}

/* Active front pill — subtle breath */
.front-tag {
  animation: tag-breath 6s ease-in-out infinite;
}
@keyframes tag-breath {
  0%, 100% { box-shadow: 0 4px 12px rgba(10,10,10,0.18); transform: translate(-50%, -50%) scale(1); }
  50%      { box-shadow: 0 6px 18px rgba(10,10,10,0.28); transform: translate(-50%, -50%) scale(1.02); }
}

@media (prefers-reduced-motion: reduce) {
  .mapviz--v2::before, .mapviz--v2::after,
  .mapviz--v2 .active-front, .mapviz--v2 .active-front__line,
  .mapviz--v2 .bands, .front-tag { animation: none !important; }
  .mapviz__currents { display: none; }
}

/* =========================================================
   Settings — slide up over the app, slide down on close
   ========================================================= */
.screen[data-screen="settings"] {
  transform: translate3d(0, 100%, 0);
  opacity: 1 !important;
  visibility: visible !important;
  transition: transform 420ms var(--ease);
  z-index: 8;
  background: var(--page-0);
}
.screen[data-screen="settings"].is-active {
  transform: translate3d(0, 0, 0);
}
[data-theme="dark"] .screen[data-screen="settings"],
[data-theme="dark"] [data-screen="settings"] { background: var(--page-0); }

/* =========================================================
   ICON BUTTON (gear, back, etc.)
   ========================================================= */
.icon-btn {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  color: var(--ink);
  background: var(--glass-bg);
  border: 1px solid var(--glass-stroke);
  backdrop-filter: blur(10px) saturate(1.2);
  -webkit-backdrop-filter: blur(10px) saturate(1.2);
  cursor: pointer;
  transition: transform 200ms var(--ease), background 200ms;
}
.icon-btn:hover { background: var(--glass-bg-2); }
.icon-btn:active { transform: scale(0.94); }
.icon-btn svg { stroke: currentColor; }

.climate__head-right {
  display: flex;
  align-items: center;
  gap: 14px;
}

/* =========================================================
   Unified app header — every primary screen uses this.
   Left: section kicker.   Right: meta (last updated) + settings.
   ========================================================= */
.app-header {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 14px;
  padding-top: 8px;
  margin-bottom: 18px;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-55);
  min-height: 34px;
}
/* Floating watchlist-manage action on the Map. Anchored to the top-right
   of the map field itself so the relationship reads immediately ("this
   button affects this thing"). Glass treatment + soft shadow so it sits
   clearly above the atmospheric field in either theme. */
.mapviz__manage {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 6;                 /* above sector chips (z=4) and watchlist (z=5) */
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--glass-stroke);
  background: rgba(255, 255, 255, 0.82);
  color: var(--ink);
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(10, 10, 10, 0.10);
  -webkit-backdrop-filter: blur(10px) saturate(1.4);
          backdrop-filter: blur(10px) saturate(1.4);
  transition: background 200ms var(--ease), transform 120ms var(--ease), box-shadow 200ms var(--ease);
}
.mapviz__manage:hover {
  background: rgba(255, 255, 255, 0.95);
  box-shadow: 0 6px 16px rgba(10, 10, 10, 0.14);
}
.mapviz__manage:active { transform: scale(0.94); }
[data-theme="dark"] .mapviz__manage {
  background: rgba(46, 48, 54, 0.82);
  border-color: rgba(244, 242, 236, 0.16);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
}
[data-theme="dark"] .mapviz__manage:hover {
  background: rgba(56, 58, 64, 0.95);
}

/* =========================================================
   Watchlist sheet — slide-up panel from the Map's + button.
   Sits inside .phone__screen (constrained to device frame
   on desktop). Same visual vocabulary as the install sheet
   but lighter; designed for repeat use, not one-time install.
   ========================================================= */
.watchlist-sheet {
  position: absolute;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  pointer-events: none;
}
.watchlist-sheet[hidden] { display: none; }
.watchlist-sheet__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(10, 10, 10, 0.34);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
  opacity: 0;
  pointer-events: auto;
  animation: fadeIn 260ms var(--ease) forwards;
}
.watchlist-sheet__card {
  position: relative;
  pointer-events: auto;
  width: calc(100% - 16px);
  margin: 0 8px 8px;
  background: var(--page-0);
  border: 1px solid var(--ink-12);
  border-radius: 22px;
  padding: 22px 22px 18px;
  box-shadow: 0 20px 60px rgba(10, 10, 10, 0.28);
  transform: translateY(20px);
  opacity: 0;
  animation: sheetUp 360ms var(--ease) 50ms forwards;
}
[data-theme="dark"] .watchlist-sheet__card {
  background: var(--page-1);
  border-color: rgba(244, 242, 236, 0.10);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.55);
}
.watchlist-sheet__close {
  position: absolute;
  top: 12px; right: 12px;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  background: transparent;
  border: 0;
  color: var(--ink-55);
  border-radius: 50%;
  cursor: pointer;
  transition: background 180ms, color 180ms;
}
.watchlist-sheet__close:hover { background: var(--ink-06); color: var(--ink); }
.watchlist-sheet__kicker {
  display: block;
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-55);
  margin-bottom: 6px;
}
.watchlist-sheet__title {
  font-family: var(--display);
  font-size: 22px;
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin: 0 0 6px;
}
.watchlist-sheet__lede {
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--ink-55);
  margin: 0 0 16px;
  max-width: 28em;
}
.watchlist-sheet__chips {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 14px;
}
.watch-chip {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  gap: 8px;
  padding: 12px 14px;
  background: var(--page-1);
  border: 1px solid var(--ink-12);
  border-radius: 12px;
  text-align: left;
  cursor: pointer;
  color: var(--ink);
  font-family: var(--ui);
  transition: border-color 180ms var(--ease), background 180ms var(--ease), transform 100ms;
}
.watch-chip:hover { border-color: var(--ink-25); }
.watch-chip:active { transform: scale(0.985); }
.watch-chip__sym {
  font-family: var(--display);
  font-size: 16px;
  font-weight: 500;
  letter-spacing: -0.01em;
}
.watch-chip__desc {
  font-size: 11px;
  color: var(--ink-55);
  letter-spacing: 0.02em;
}
.watch-chip.is-on {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--page-0);
}
.watch-chip.is-on .watch-chip__desc {
  color: color-mix(in oklab, var(--page-0) 70%, transparent);
}
.watchlist-sheet__foot {
  font-size: 11px;
  color: var(--ink-55);
  letter-spacing: 0.02em;
  margin: 0;
}
.watchlist-sheet__foot strong { color: var(--ink-70); font-weight: 500; }
.app-header__kicker {
  color: var(--ink);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-size: 11px;
  font-weight: 500;
}
.app-header__meta {
  color: var(--ink-55);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.app-header__action {
  /* the icon-btn that lives in the action slot — fixed size */
  width: 34px; height: 34px;
}
.app-header__action--left { justify-self: start; }

/* Settings variant: back-arrow on the left, centered kicker, spacer on right */
.app-header--settings {
  grid-template-columns: 34px 1fr 34px;
}
.app-header--settings .app-header__kicker {
  text-align: center;
  color: var(--ink-55);
}
.app-header__spacer { width: 34px; height: 34px; }

/* =========================================================
   SETTINGS SCREEN
   ========================================================= */
/* Preferences uses a pure flat background — no warm/cool radial
   tinting. Previous version had two soft gradients giving the
   screen a slight tinted bloom; removed so the surface reads as
   pure black (dark) or pure white (light). Hard-coded rather than
   using --page-0 because that token is off-black / off-white
   (#0F1012 / #FAFAFA) and the user asked for pure values on this
   surface specifically. */
.settings,
[data-screen="settings"] {
  background: #FFFFFF;
}
[data-theme="dark"] .settings,
[data-theme="dark"] [data-screen="settings"] {
  background: #000000;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .settings,
  :root:not([data-theme="light"]) [data-screen="settings"] {
    background: #000000;
  }
}

.settings__head {
  display: grid;
  grid-template-columns: 34px 1fr 34px;
  align-items: center;
  margin: 0 0 28px;
}
.settings__kicker {
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-55);
  text-align: center;
}
.settings__spacer { width: 34px; height: 34px; }
.icon-btn--back { justify-self: start; }

.settings__title {
  font-family: var(--display);
  font-weight: 500;
  font-size: 36px;
  line-height: 1.0;
  letter-spacing: -0.04em;
  margin: 0 0 12px;
  text-transform: uppercase;
}
.settings__lede {
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink-70);
  margin: 0 0 28px;
  max-width: 32ch;
}

/* Profile card */
.profile-card {
  display: grid;
  grid-template-columns: 44px 1fr auto;
  gap: 14px;
  align-items: center;
  padding: 14px;
  border-radius: 22px;
  background: var(--glass-bg-2);
  border: 1px solid var(--glass-stroke);
  backdrop-filter: blur(14px) saturate(1.2);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  box-shadow: var(--glass-shadow);
  margin-bottom: 32px;
}
.profile-card__avatar {
  width: 44px; height: 44px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 30% 30%, var(--warm-2), var(--cool) 75%);
  box-shadow: inset 0 0 0 1px var(--glass-stroke);
}
.profile-card__name {
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.005em;
}
.profile-card__meta {
  font-size: 11px;
  color: var(--ink-55);
  margin-top: 2px;
  letter-spacing: 0.02em;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.badge {
  display: inline-flex;
  align-items: center;
  padding: 1px 7px;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.14em;
  border-radius: 999px;
  background: var(--ink);
  color: var(--page-0);
}

/* Theme segmented control (light/dark/auto) */
.theme-seg {
  display: inline-flex;
  padding: 4px;
  background: var(--ink-06);
  border-radius: 999px;
  gap: 2px;
}
.theme-seg__btn {
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: 999px;
  color: var(--ink-55);
  background: transparent;
  transition: background 200ms var(--ease), color 200ms;
  border: 0;
  cursor: pointer;
}
.theme-seg__btn.is-on {
  background: var(--page-0);
  color: var(--ink);
  box-shadow: 0 1px 2px rgba(10,10,10,0.06), 0 0 0 0.5px var(--glass-stroke);
}
[data-theme="dark"] .theme-seg__btn.is-on {
  background: var(--page-2);
  box-shadow: 0 0 0 0.5px var(--glass-stroke);
}

/* Section label */
.pref { margin-bottom: 28px; }
.pref__label {
  display: flex;
  align-items: baseline;
  gap: 12px;
  font-family: var(--ui);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-70);
  margin: 0 4px 12px;
  font-weight: 500;
}
.pref__num {
  font-family: var(--display);
  font-style: normal;
  font-weight: 400;
  font-size: 13px;
  color: var(--ink);
  letter-spacing: 0;
  text-transform: none;
}

/* Posture switcher — six tappable tiles that swap top-level copy across
   every screen. Built so demos can feel the difference between trader
   shorthand and plain-language for someone learning the market. */
.posture-seg {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-top: 4px;
}
.posture-seg__btn {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  background: var(--page-1);
  border: 1px solid var(--ink-12);
  border-radius: 12px;
  padding: 12px 12px 11px;
  text-align: left;
  color: var(--ink);
  font-family: var(--ui);
  cursor: pointer;
  transition: border-color 180ms var(--ease), background 180ms var(--ease), transform 120ms var(--ease);
}
.posture-seg__btn:hover {
  border-color: var(--ink-25);
}
.posture-seg__btn:active {
  transform: scale(0.985);
}
.posture-seg__btn strong {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: -0.01em;
}
.posture-seg__btn small {
  font-size: 11px;
  color: var(--ink-55);
  letter-spacing: 0;
  line-height: 1.3;
}
.posture-seg__btn.is-on {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--page-0);
}
.posture-seg__btn.is-on small {
  color: color-mix(in oklab, var(--page-0) 70%, transparent);
}
.pref__sub {
  font-size: 12px;
  color: var(--ink-55);
  margin: -4px 4px 14px;
  letter-spacing: 0.02em;
}

/* Settings card */
.pref-card {
  background: var(--glass-bg-2);
  border: 1px solid var(--glass-stroke);
  border-radius: 18px;
  backdrop-filter: blur(14px) saturate(1.2);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  box-shadow: var(--glass-shadow);
  overflow: hidden;
}
.pref-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 16px;
  align-items: center;
  padding: 14px 16px;
  border-bottom: 1px solid var(--ink-06);
}
.pref-row:last-child { border-bottom: 0; }
.pref-row--slider {
  grid-template-columns: 1fr 100px auto;
}
.pref-row__body { min-width: 0; }
.pref-row__title { font-size: 13px; font-weight: 500; }
.pref-row__hint {
  font-size: 11px;
  color: var(--ink-55);
  margin-top: 2px;
  letter-spacing: 0.01em;
}
.pref-row__value {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--ink-70);
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
}
.pref-row__value svg { stroke: currentColor; fill: none; opacity: 0.6; }

/* Switch */
.switch {
  width: 42px;
  height: 24px;
  border-radius: 999px;
  background: var(--ink-12);
  position: relative;
  border: 0;
  cursor: pointer;
  transition: background 240ms var(--ease);
  flex-shrink: 0;
  padding: 0;
}
.switch span {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 20px; height: 20px;
  border-radius: 50%;
  background: var(--page-0);
  box-shadow: 0 1px 2px rgba(10,10,10,0.18);
  transition: transform 240ms var(--ease), background 240ms;
}
.switch.is-on { background: var(--ink); }
.switch.is-on span { transform: translateX(18px); }

/* Chip rows */
.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 16px 14px;
  border-bottom: 1px solid var(--ink-06);
}
.chip-row:last-child { border-bottom: 0; }
.select-chip {
  display: inline-flex;
  align-items: center;
  padding: 6px 12px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--ink-70);
  background: transparent;
  border: 1px solid var(--ink-12);
  border-radius: 999px;
  cursor: pointer;
  transition: background 200ms, color 200ms, border-color 200ms;
}
.select-chip:hover { border-color: var(--ink-25); }
.select-chip.is-on {
  background: var(--ink);
  color: var(--page-0);
  border-color: var(--ink);
}

/* Slider */
.slider {
  height: 4px;
  background: var(--ink-06);
  border-radius: 999px;
  position: relative;
  overflow: visible;
}
.slider span {
  display: block;
  height: 100%;
  width: var(--v, 50%);
  background: var(--ink);
  border-radius: 999px;
  position: relative;
}
.slider span::after {
  content: "";
  position: absolute;
  right: -7px;
  top: 50%;
  transform: translateY(-50%);
  width: 14px; height: 14px;
  border-radius: 50%;
  background: var(--page-0);
  box-shadow: 0 0 0 0.5px var(--ink-25), 0 2px 4px rgba(10,10,10,0.2);
}
[data-theme="dark"] .slider span::after {
  background: var(--ink);
  box-shadow: 0 0 0 0.5px var(--ink-25);
}

/* Vertical segmented list (alert sensitivity) */
.seg-vertical { display: grid; }
.seg-row {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: 14px;
  align-items: center;
  padding: 14px 16px;
  border-bottom: 1px solid var(--ink-06);
  text-align: left;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--ink-06);
  cursor: pointer;
  transition: background 200ms;
}
.seg-row:last-child { border-bottom: 0; }
.seg-row:hover { background: var(--ink-06); }
.seg-row__bullet {
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--glass-bg);
  box-shadow: inset 0 0 0 1px var(--ink-25);
  display: grid;
  place-items: center;
}
.seg-row.is-on .seg-row__bullet {
  background: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
}
.seg-row.is-on .seg-row__bullet::after {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--page-0);
}
.seg-row__title {
  font-size: 13px;
  font-weight: 500;
}
.seg-row__hint {
  font-size: 11px;
  color: var(--ink-55);
  margin-top: 2px;
}

/* Theme cards (visualization themes) */
.theme-cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}
.theme-card {
  background: var(--glass-bg-2);
  border: 1px solid var(--glass-stroke);
  border-radius: 18px;
  padding: 10px 12px 14px;
  text-align: left;
  cursor: pointer;
  transition: transform 200ms var(--ease), border-color 200ms;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
.theme-card:hover { transform: translateY(-1px); }
.theme-card.is-on { border-color: var(--ink); box-shadow: 0 0 0 2px var(--ink); }
.theme-card__preview {
  height: 70px;
  border-radius: 12px;
  margin-bottom: 10px;
  overflow: hidden;
  position: relative;
  border: 1px solid var(--glass-stroke);
}
.theme-card__name {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: -0.005em;
}
.theme-card__hint {
  font-size: 10px;
  color: var(--ink-55);
  margin-top: 2px;
  letter-spacing: 0.02em;
}

/* Preview variations */
.theme-card__preview--atmospheric {
  background:
    radial-gradient(60% 50% at 70% 30%, color-mix(in oklab, var(--warm-2) 60%, transparent), transparent 70%),
    radial-gradient(60% 50% at 30% 80%, color-mix(in oklab, var(--cool-2) 60%, transparent), transparent 70%),
    var(--page-1);
}
.theme-card__preview--minimal {
  background: var(--page-1);
  position: relative;
}
.theme-card__preview--minimal::before {
  content: "M";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--display);
  font-size: 38px;
  color: var(--ink);
  opacity: 0.85;
}
.theme-card__preview--radar {
  background: var(--page-1);
  position: relative;
}
.theme-card__preview--radar::before,
.theme-card__preview--radar::after {
  content: "";
  position: absolute;
  border: 1px solid var(--ink-25);
  border-radius: 50%;
  left: 50%; top: 60%;
  transform: translate(-50%, -50%);
}
.theme-card__preview--radar::before { width: 50px; height: 50px; }
.theme-card__preview--radar::after  { width: 90px; height: 90px; opacity: 0.5; }
.theme-card__preview--editorial {
  background: var(--page-1);
  position: relative;
}
.theme-card__preview--editorial::before {
  content: "Today is\A elevated";
  white-space: pre;
  position: absolute;
  inset: 10px;
  font-family: var(--display);
  font-size: 13px;
  line-height: 1.05;
  color: var(--ink);
  letter-spacing: -0.01em;
}
.theme-card__preview--editorial::after {
  content: "";
  position: absolute;
  left: 10px;
  bottom: 10px;
  width: 18px; height: 1.5px;
  background: var(--ink);
}
.theme-card__preview--telemetry {
  background:
    repeating-linear-gradient(90deg, transparent 0 14px, var(--ink-06) 14px 15px),
    repeating-linear-gradient(0deg, transparent 0 14px, var(--ink-06) 14px 15px),
    var(--page-1);
  position: relative;
}
.theme-card__preview--telemetry::before {
  content: "";
  position: absolute;
  left: 12px; top: 18px;
  width: 36px; height: 36px;
  border: 1px solid var(--ink);
  border-radius: 50%;
}
.theme-card__preview--telemetry::after {
  content: "";
  position: absolute;
  right: 14px; bottom: 14px;
  width: 30px; height: 4px;
  background: var(--ink);
}

.settings__footer {
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-40);
  text-align: center;
  margin: 32px 0 0;
}

/* The map field gradient adapts to theme via these stops */
[data-theme="dark"] .mapviz--v2 svg #field-grad stop:nth-child(1) { stop-color: #2A2118; }
[data-theme="dark"] .mapviz--v2 svg #field-grad stop:nth-child(5) { stop-color: #1A2330; }

.chip {
  position: absolute;
  left: var(--x); top: var(--y);
  transform: translate(-50%, -50%);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px 5px 8px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--ink);
  background: rgba(255,255,255,0.78);
  border: 1px solid var(--glass-stroke);
  border-radius: 999px;
  backdrop-filter: blur(10px) saturate(1.4);
  -webkit-backdrop-filter: blur(10px) saturate(1.4);
  box-shadow: 0 4px 10px rgba(10,10,10,0.06);
  white-space: nowrap;
}
.chip em { font-style: normal; margin-left: 2px; opacity: 0.55; }
.chip__dot {
  width: 6px; height: 6px; border-radius: 50%;
}
.chip__dot--warm    { background: var(--warm); }
.chip__dot--cool    { background: var(--cool); }
.chip__dot--neutral { background: var(--neutral); }

/* Watchlist container fills the map field; chips inside are absolutely
   positioned via inline --x / --y just like sector chips. */
.mapviz__watchlist {
  position: absolute;
  inset: 0;
  pointer-events: none; /* chips re-enable their own pointer events */
}
.mapviz__watchlist .chip { pointer-events: auto; }

/* Watchlist chip — distinguished from sector chips by a thin ring
   around it ("this is mine"), slightly more presence in type weight,
   and a small star indicator. The position math is unchanged. */
.chip--watch {
  box-shadow: 0 0 0 1px var(--ink), 0 4px 10px rgba(10,10,10,0.10);
  font-weight: 600;
  letter-spacing: 0.08em;
  z-index: 5;
}
.chip--watch:hover {
  box-shadow: 0 0 0 1.5px var(--ink), 0 6px 14px rgba(10,10,10,0.14);
}
.chip__watch-star {
  width: 8px;
  height: 8px;
  display: inline-block;
  background: var(--ink);
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'><path d='M5 0.6 L 6.1 3.9 L 9.5 3.9 L 6.7 6 L 7.8 9.3 L 5 7.3 L 2.2 9.3 L 3.3 6 L 0.5 3.9 L 3.9 3.9 Z' fill='black'/></svg>") center / contain no-repeat;
          mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'><path d='M5 0.6 L 6.1 3.9 L 9.5 3.9 L 6.7 6 L 7.8 9.3 L 5 7.3 L 2.2 9.3 L 3.3 6 L 0.5 3.9 L 3.9 3.9 Z' fill='black'/></svg>") center / contain no-repeat;
  margin-right: 1px;
  flex-shrink: 0;
}
[data-theme="dark"] .chip--watch {
  box-shadow: 0 0 0 1px var(--ink), 0 6px 14px rgba(0,0,0,0.45);
}

.mapscreen__legend {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 4px 0;
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--ink-70);
}
.mapscreen__legend > div { display: flex; align-items: center; gap: 6px; }
.mapscreen__legend .dot { width: 8px; height: 8px; border-radius: 50%; }
.mapscreen__legend .dot--warm    { background: var(--warm); }
.mapscreen__legend .dot--cool    { background: var(--cool); }
.mapscreen__legend .dot--neutral { background: var(--neutral); }
.mapscreen__legend .legend-sep { color: var(--ink-25); margin: 0 4px; }

/* =========================================================
   03 — RADAR
   ========================================================= */
.radar { display: flex; flex-direction: column; }
.radar__head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 10px;
}
.radar__title {
  font-family: var(--display);
  font-weight: 500;
  font-size: 36px;
  line-height: 1.05;
  letter-spacing: -0.03em;
  margin: 18px 0 18px;
  text-transform: uppercase;
}
.radar__viz {
  height: 130px;
  margin: 0 -8px 18px;
  border-bottom: 1px solid var(--ink-12);
  position: relative;
}
.radar__viz svg { width: 100%; height: 100%; }
.radar__sweep {
  transform-origin: 140px 100px;
  animation: sweep 6s linear infinite;
}
@keyframes sweep {
  0%   { transform: rotate(-90deg); opacity: 0.6; }
  100% { transform: rotate(90deg); opacity: 0.6; }
}

.events {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.event {
  display: grid;
  grid-template-columns: 60px 1fr;
  gap: 14px;
  padding: 14px 14px 14px 12px;
  border: 1px solid var(--glass-stroke);
  border-radius: 18px;
  background: var(--glass-bg);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  box-shadow: var(--glass-shadow);
  transition: transform 200ms var(--ease);
}
.event:hover { transform: translateY(-1px); }
.event--high {
  background: linear-gradient(180deg, rgba(255,255,255,0.86), rgba(255,255,255,0.62));
  border-color: rgba(10,10,10,0.14);
}
.event__time {
  display: flex;
  flex-direction: column;
  gap: 4px;
  border-right: 1px solid var(--ink-06);
  padding-right: 8px;
}
.event__time > span:first-child {
  font-family: var(--display);
  font-size: 28px;
  line-height: 1;
}
.event__when {
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--ink-55);
  text-transform: uppercase;
}
.event__title {
  font-size: 16px;
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}
.event__title svg { stroke: currentColor; fill: none; }
.event__body p {
  font-size: 14px;
  line-height: 1.45;
  color: var(--ink-70);
  margin: 0 0 10px;
}
.event__meta {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--ink-55);
  text-transform: uppercase;
}
.severity { display: inline-flex; gap: 3px; }
.severity i {
  width: 8px; height: 3px;
  background: var(--ink);
  border-radius: 1px;
}
.severity i.dim { background: var(--ink-12); }

/* =========================================================
   04 — SIGNALS
   ========================================================= */
.signals { display: flex; flex-direction: column; }
.signals__head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 10px;
}
.signals__title {
  font-family: var(--display);
  font-weight: 500;
  font-size: 36px;
  line-height: 1.05;
  letter-spacing: -0.03em;
  margin: 18px 0 20px;
  text-transform: uppercase;
}
.signal-card {
  background: var(--glass-bg-2);
  border: 1px solid var(--glass-stroke);
  border-radius: 22px;
  padding: 18px;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: var(--glass-shadow);
  margin-bottom: 14px;
  position: relative;
  overflow: hidden;
}
.signal-card--lead::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 80% at 100% 0%, rgba(232,201,168,0.18) 0%, transparent 50%);
  pointer-events: none;
}
.signal-card > * { position: relative; }
.signal-card__eyebrow {
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-55);
}
.signal-card__quote {
  font-family: var(--display);
  font-weight: 400;
  font-size: 22px;
  line-height: 1.32;
  margin: 12px 0 16px;
  color: var(--ink);
  letter-spacing: -0.015em;
}
.signal-card__impacts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 14px;
}
.impact {
  font-size: 13px;
  letter-spacing: 0.04em;
  padding: 5px 11px;
  border: 1px solid var(--ink-12);
  border-radius: 999px;
  background: rgba(255,255,255,0.6);
  color: var(--ink);
}
.impact em { font-style: normal; opacity: 0.55; margin-left: 2px; }
.signal-card__foot {
  padding-top: 12px;
  border-top: 1px solid var(--ink-06);
}
.confidence-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 10px;
  align-items: center;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-70);
}
.confidence-row__val {
  font-family: var(--display);
  font-size: 14px;
  text-transform: none;
  letter-spacing: 0;
  color: var(--ink);
}

.signal-list {
  list-style: none;
  padding: 0;
  margin: 0;
  border-top: 1px solid var(--ink-12);
}
.signal-list li {
  display: grid;
  grid-template-columns: 34px 1fr auto;
  gap: 12px;
  align-items: center;
  padding: 14px 4px;
  border-bottom: 1px solid var(--ink-06);
}
.signal-list__icon {
  width: 34px; height: 34px;
  display: grid;
  place-items: center;
  background: var(--page-1);
  border: 1px solid var(--glass-stroke);
  border-radius: 12px;
}
.signal-list__icon svg { stroke: currentColor; fill: none; }
.signal-list__title { font-size: 15px; font-weight: 500; }
.signal-list__meta {
  font-size: 13px;
  color: var(--ink-55);
  margin-top: 3px;
}
.signal-list__conf {
  font-family: var(--display);
  font-size: 16px;
  font-variant-numeric: tabular-nums;
}

/* =========================================================
   05 — BRIEF
   ========================================================= */
/* Brief gradient lives on the screen container so it bleeds edge-to-edge
   while .brief itself uses the same paddings as every other screen body. */
.screen[data-screen="brief"] {
  background:
    radial-gradient(120% 60% at 100% 0%, #FBF7EF 0%, transparent 60%),
    radial-gradient(120% 60% at 0% 100%, #F3F5F7 0%, transparent 60%),
    #FBFBFA;
}
.brief {
  display: flex;
  flex-direction: column;
}
.brief__rule {
  width: 28px; height: 2px; background: var(--ink); margin: 10px 0 18px;
}
.brief__head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-55);
}
.brief__kicker { color: var(--ink); }
.brief__title {
  font-family: var(--display);
  font-weight: 500;
  font-size: 38px;
  line-height: 1.0;
  letter-spacing: -0.04em;
  margin: 22px 0 22px;
  text-transform: uppercase;
}
.brief__title em { font-style: normal; font-weight: 300; color: var(--ink-70); }
.brief__lede {
  font-family: var(--display);
  font-weight: 400;
  font-size: 21px;
  line-height: 1.35;
  color: var(--ink-70);
  margin: 0 0 24px;
  padding-bottom: 24px;
  border-bottom: 1px solid var(--ink-12);
}
.brief__body {
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-90);
  flex: 1;
}
.brief__body p { margin: 0 0 14px; }
.brief__body em {
  font-style: italic;
  font-family: var(--display);
  font-size: 15px;
  color: var(--ink);
}
.brief__foot {
  margin-top: auto;
  padding-top: 16px;
  border-top: 1px solid var(--ink-12);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
}
.brief__byline { display: flex; align-items: center; gap: 10px; }
.brief__avatar {
  width: 28px; height: 28px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, #E8C9A8, #9FB3C7 70%);
  box-shadow: inset 0 0 0 1px rgba(10,10,10,0.1);
}
.brief__author { font-size: 12px; font-weight: 500; }
.brief__updated { font-size: 10px; letter-spacing: 0.1em; color: var(--ink-55); text-transform: uppercase; }
.brief__cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  font-weight: 500;
  padding: 10px 14px;
  background: var(--ink);
  color: var(--page-0);
  border-radius: 999px;
  cursor: pointer;
}
.brief__cta svg { stroke: currentColor; }

/* =========================================================
   Tab bar
   ========================================================= */
.tabbar {
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 14px;
  z-index: 6;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 4px;
  padding: 8px;
  background: rgba(255,255,255,0.78);
  border: 1px solid var(--glass-stroke);
  border-radius: 24px;
  backdrop-filter: blur(18px) saturate(1.4);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.9) inset,
    0 10px 30px rgba(10,10,10,0.12);
}

/* =========================================================
   Dark-mode surface overrides
   Components that had hardcoded white backgrounds need
   theme-aware ones so text contrast doesn't collapse.
   ========================================================= */

/* Map chips — light pill on the dark field → keep dark ink for contrast */
[data-theme="dark"] .chip {
  background: rgba(36, 38, 42, 0.92);
  color: var(--ink);
  border-color: rgba(255, 255, 255, 0.10);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
}
[data-theme="dark"] .chip--tap:hover { background: rgba(46, 48, 54, 0.95); }

/* Event cards (Radar) */
[data-theme="dark"] .event {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.08);
}
[data-theme="dark"] .event--high {
  background: linear-gradient(180deg, rgba(255,255,255,0.07), rgba(255,255,255,0.04));
  border-color: rgba(255, 255, 255, 0.14);
}

/* Signals — lead quote card + impact chips */
[data-theme="dark"] .signal-card {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.08);
}
[data-theme="dark"] .impact {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.12);
  color: var(--ink);
}
[data-theme="dark"] .signal-list__icon {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.08);
}

/* Brief — the cream gradient background is the worst offender;
   replace with a warm-toned dark gradient that still reads editorial. */
[data-theme="dark"] [data-screen="brief"] {
  background:
    radial-gradient(120% 60% at 100% 0%, rgba(60, 48, 36, 0.55) 0%, transparent 60%),
    radial-gradient(120% 60% at 0% 100%, rgba(30, 42, 55, 0.55) 0%, transparent 60%),
    var(--page-0);
}

/* Climate halo overlays were hardcoded light — soften in dark */
[data-theme="dark"] .climate__halo--a {
  background: radial-gradient(circle at 40% 40%, rgba(199, 163, 125, 0.20), transparent 65%);
}
[data-theme="dark"] .climate__halo--b {
  background: radial-gradient(circle at 60% 50%, rgba(143, 163, 183, 0.20), transparent 65%);
}
[data-theme="dark"] .climate__halo--c {
  background: radial-gradient(circle at 50% 50%, rgba(180, 165, 145, 0.18), transparent 65%);
}

/* Map field gradient stops for dark theme */
[data-theme="dark"] .mapviz--v2 {
  background: var(--page-0);
}

/* Settings profile/avatar inset highlight tweak for dark */
[data-theme="dark"] .profile-card__avatar {
  background: radial-gradient(circle at 30% 30%, #C7A37D, #5C6B7A 75%);
}

/* Apply the same overrides under prefers-color-scheme:dark when no explicit choice */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="dark"]) .chip {
    background: rgba(36, 38, 42, 0.92);
    color: var(--ink);
    border-color: rgba(255, 255, 255, 0.10);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
  }
  :root:not([data-theme="light"]):not([data-theme="dark"]) .chip--tap:hover { background: rgba(46, 48, 54, 0.95); }
  :root:not([data-theme="light"]):not([data-theme="dark"]) .event {
    background: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.08);
  }
  :root:not([data-theme="light"]):not([data-theme="dark"]) .event--high {
    background: linear-gradient(180deg, rgba(255,255,255,0.07), rgba(255,255,255,0.04));
    border-color: rgba(255, 255, 255, 0.14);
  }
  :root:not([data-theme="light"]):not([data-theme="dark"]) .signal-card {
    background: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.08);
  }
  :root:not([data-theme="light"]):not([data-theme="dark"]) .impact {
    background: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.12);
    color: var(--ink);
  }
  :root:not([data-theme="light"]):not([data-theme="dark"]) .signal-list__icon {
    background: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.08);
  }
  :root:not([data-theme="light"]):not([data-theme="dark"]) [data-screen="brief"] {
    background:
      radial-gradient(120% 60% at 100% 0%, rgba(60, 48, 36, 0.55) 0%, transparent 60%),
      radial-gradient(120% 60% at 0% 100%, rgba(30, 42, 55, 0.55) 0%, transparent 60%),
      var(--page-0);
  }
  :root:not([data-theme="light"]):not([data-theme="dark"]) .climate__halo--a {
    background: radial-gradient(circle at 40% 40%, rgba(199, 163, 125, 0.20), transparent 65%);
  }
  :root:not([data-theme="light"]):not([data-theme="dark"]) .climate__halo--b {
    background: radial-gradient(circle at 60% 50%, rgba(143, 163, 183, 0.20), transparent 65%);
  }
  :root:not([data-theme="light"]):not([data-theme="dark"]) .climate__halo--c {
    background: radial-gradient(circle at 50% 50%, rgba(180, 165, 145, 0.18), transparent 65%);
  }
  :root:not([data-theme="light"]):not([data-theme="dark"]) .mapviz--v2 {
    background: var(--page-0);
  }
  :root:not([data-theme="light"]):not([data-theme="dark"]) .profile-card__avatar {
    background: radial-gradient(circle at 30% 30%, #C7A37D, #5C6B7A 75%);
  }
}

/* SVG colors inside the radar viz and map viz need to follow theme.
   We override any hardcoded #0A0A0A so they stay visible on dark page. */
.radar__viz, .mapviz__svg { color: var(--ink); }
.radar__viz svg [stroke="#0A0A0A"],
.mapviz__svg [stroke="#0A0A0A"] { stroke: currentColor; }
.radar__viz svg [fill="#0A0A0A"],
.mapviz__svg [fill="#0A0A0A"] { fill: currentColor; }

/* Tabbar — dark theme needs more presence + contrast */
[data-theme="dark"] .tabbar {
  background: rgba(30, 32, 36, 0.85);
  border-color: rgba(255, 255, 255, 0.10);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.06) inset,
    0 10px 30px rgba(0, 0, 0, 0.55);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="dark"]) .tabbar {
    background: rgba(30, 32, 36, 0.85);
    border-color: rgba(255, 255, 255, 0.10);
    box-shadow:
      0 1px 0 rgba(255, 255, 255, 0.06) inset,
      0 10px 30px rgba(0, 0, 0, 0.55);
  }
}

.tabbar__btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  height: 52px;
  border-radius: 16px;
  color: var(--ink-55);
  transition: all 240ms var(--ease);
}
.tabbar__btn svg { stroke: currentColor; }
.tabbar__btn span {
  font-size: 9px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.tabbar__btn:hover { color: var(--ink-70); }
.tabbar__btn.is-active {
  background: var(--ink);
  color: var(--page-0);
}

/* =========================================================
   Responsive
   ========================================================= */
@media (max-width: 1180px) {
  .stage { grid-template-columns: 1fr; gap: 32px; padding: 90px 24px 40px; }
  .stage__hint { justify-self: center; text-align: center; max-width: 360px; }
  .stage__hint--right { display: none; }
  .stage__hint h2 { font-size: 28px; }
}
@media (max-width: 480px) {
  /* Mobile: hide page chrome — the app takes over the whole viewport */
  html, body {
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
  }
  .stage-nav { display: none; }
  .stage {
    padding: 0;
    gap: 0;
    height: 100dvh;
    min-height: 0;
  }
  .stage__hint { display: none; }
  .phone {
    --phone-w: 100vw;
    --phone-h: 100vh;
    --phone-h: 100dvh;
    filter: none;
  }
  .phone__bezel {
    border-radius: 0;
    padding: 0;
    background: var(--page-0);
    box-shadow: none;
  }
  .phone__bezel::before { display: none; }
  .phone__notch { display: none; }
  .phone__screen { border-radius: 0; }
  .status { display: none; } /* OS draws the real status bar */
  .screen__body { padding-top: calc(env(safe-area-inset-top, 0px) + 14px); }
  .tabbar {
    position: fixed;
    left: 14px;
    right: 14px;
    bottom: max(14px, env(safe-area-inset-bottom));
  }
}

/* Standalone (installed PWA): hide page chrome + fake status bar, lock to viewport */
@media (display-mode: standalone) {
  html, body {
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
  }
  .stage-nav { display: none; }
  .stage {
    padding: 0;
    gap: 0;
    height: 100dvh;
    min-height: 0;
  }
  .stage__hint { display: none; }
  .status { display: none; }
  .phone {
    --phone-w: 100vw;
    --phone-h: 100vh;
    --phone-h: 100dvh;
    filter: none;
  }
  .phone__bezel {
    border-radius: 0;
    padding: 0;
    background: var(--page-0);
    box-shadow: none;
  }
  .phone__bezel::before { display: none; }
  .phone__notch { display: none; }
  .phone__screen { border-radius: 0; }
  .screen__body { padding-top: calc(env(safe-area-inset-top, 0px) + 14px); }
  .tabbar {
    position: fixed;
    left: 14px;
    right: 14px;
    bottom: max(14px, env(safe-area-inset-bottom));
  }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* =========================================================
   Scenario switcher (Settings → Demo · Scenario)
   Tappable tiles that flip the entire app between three
   day-state mockups. Same vocabulary as posture switcher
   but with three tiles instead of six.
   ========================================================= */
.scenario-seg {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
  margin-top: 4px;
}
.scenario-seg__btn {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  background: var(--page-1);
  border: 1px solid var(--ink-12);
  border-radius: 12px;
  padding: 14px 14px 13px;
  text-align: left;
  color: var(--ink);
  font-family: var(--ui);
  cursor: pointer;
  transition: border-color 180ms var(--ease), background 180ms var(--ease), transform 120ms var(--ease);
}
.scenario-seg__btn:hover { border-color: var(--ink-25); }
.scenario-seg__btn:active { transform: scale(0.985); }
.scenario-seg__btn strong {
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.005em;
}
.scenario-seg__btn small {
  font-size: 11.5px;
  color: var(--ink-55);
  letter-spacing: 0;
  line-height: 1.35;
}
.scenario-seg__btn.is-on {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--page-0);
}
.scenario-seg__btn.is-on small {
  color: color-mix(in oklab, var(--page-0) 70%, transparent);
}

/* =========================================================
   Per-scenario atmosphere mood (data-condition on screens
   and data-scenario on html). Subtle layer treatments so
   each day-state feels different even before you read it.
   ========================================================= */

/* =========================================================
   Per-condition atmosphere — literal weather effects, not
   abstract color washes. Four scenarios get a treatment;
   three (calm, choppy, turning) stay completely clean so the
   content reads without ambient interference.
   ========================================================= */

/* STORMY — distant lightning. Two soft white-gray bursts at
   different positions, flashing on random offsets so the rhythm
   feels like a real storm rather than a metronome. */
.screen[data-condition="stormy"] .climate__halo--a {
  display: block;
  position: absolute;
  width: 280px; height: 280px;
  top: 6%; left: 8%;
  right: auto; bottom: auto;
  background: radial-gradient(circle at 50% 50%,
    rgba(220, 220, 220, 0.55), transparent 60%);
  border-radius: 50%;
  opacity: 0;
  filter: blur(18px);
  animation: lightning-flash-1 11s linear infinite;
  transform: none;
}
.screen[data-condition="stormy"] .climate__halo--b {
  display: block;
  position: absolute;
  width: 240px; height: 240px;
  top: 28%; right: 6%;
  left: auto; bottom: auto;
  background: radial-gradient(circle at 50% 50%,
    rgba(210, 210, 210, 0.50), transparent 65%);
  border-radius: 50%;
  opacity: 0;
  filter: blur(22px);
  animation: lightning-flash-2 17s linear infinite;
  transform: none;
}
.screen[data-condition="stormy"] .climate__halo--c { display: none; }
.screen[data-condition="stormy"] .climate__grain { opacity: 0.05; }
@keyframes lightning-flash-1 {
  0%, 100%        { opacity: 0; }
  28%             { opacity: 0; }
  29%             { opacity: 0.70; }
  30%             { opacity: 0.15; }
  31%             { opacity: 0.55; }
  32%             { opacity: 0; }
  67%             { opacity: 0; }
  68%             { opacity: 0.35; }
  69%             { opacity: 0; }
  70%             { opacity: 0.55; }
  71%             { opacity: 0; }
}
@keyframes lightning-flash-2 {
  0%, 100%        { opacity: 0; }
  44%             { opacity: 0; }
  45%             { opacity: 0.60; }
  46%             { opacity: 0.10; }
  47%             { opacity: 0.40; }
  48%             { opacity: 0; }
  84%             { opacity: 0; }
  85%             { opacity: 0.45; }
  86%             { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .screen[data-condition="stormy"] .climate__halo--a,
  .screen[data-condition="stormy"] .climate__halo--b {
    animation: none !important;
    opacity: 0;
  }
}

/* FOGGY — soft gray spotlight that follows the pen as it moves.
   Simulates the pen being a beacon in fog. JS sets --pen-x-atm
   and --pen-y-atm in setPen so the gradient center tracks the pen. */
.screen[data-condition="foggy"] .climate__halo--a {
  display: block;
  position: absolute;
  inset: 0;
  top: 0; left: 0; right: 0; bottom: 0;
  width: auto; height: auto;
  /* Spotlight in fog: a bright halo around the pen that softens out
     into the surrounding mist. Stops widened (was 12% / 26%) so the
     glow is actually noticeable when the pen moves, instead of reading
     as a small static smudge. Smooth multi-stop falloff prevents a
     hard ring edge. */
  background: radial-gradient(
    circle at var(--pen-x-atm, 50%) var(--pen-y-atm, 50%),
    rgba(220, 222, 226, 0.42) 0%,
    rgba(220, 222, 226, 0.28) 8%,
    rgba(220, 222, 226, 0.14) 22%,
    rgba(220, 222, 226, 0.05) 38%,
    transparent 52%
  );
  opacity: 1;
  filter: blur(10px);
  animation: none;
  transform: none;
  /* Smooth the spotlight as the pen moves so the fog drifts to follow,
     rather than snapping every frame. Easing matches the pen's gentle
     per-minute updates and feels natural during scenario switches too. */
  transition: background 600ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.screen[data-condition="foggy"] .climate__halo--b,
.screen[data-condition="foggy"] .climate__halo--c { display: none; }
/* Keep the existing fog wash + dim barograph that simulate low visibility */
.screen[data-condition="foggy"] .climate__atmosphere::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(160, 165, 170, 0.08) 0%,
    rgba(160, 165, 170, 0.04) 50%,
    rgba(160, 165, 170, 0.08) 100%);
  pointer-events: none;
  z-index: 1;
}
[data-theme="dark"] .screen[data-condition="foggy"] .climate__atmosphere::after {
  background: linear-gradient(180deg,
    rgba(244, 242, 236, 0.03) 0%,
    rgba(244, 242, 236, 0.015) 50%,
    rgba(244, 242, 236, 0.03) 100%);
}
.screen[data-condition="foggy"] .climate__barograph { opacity: 0.42; }
[data-theme="dark"] .screen[data-condition="foggy"] .climate__barograph { opacity: 0.55; }

/* CALM — no atmosphere. Quiet content speaks for itself. */
.screen[data-condition="calm"] .climate__halo--a,
.screen[data-condition="calm"] .climate__halo--b,
.screen[data-condition="calm"] .climate__halo--c { display: none; }
.screen[data-condition="calm"] .climate__grain { opacity: 0; }

/* Scenario-seg URL-hint footnote */
.scenario-seg__hint {
  margin: 10px 4px 0;
  font-size: 11px;
  letter-spacing: 0.02em;
  color: var(--ink-55);
}
.scenario-seg__hint code {
  font-family: var(--display);
  font-size: 11px;
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--ink-06);
  color: var(--ink);
}

/* SUNNY — a warm amber sun centered behind the settings icon in the
   top-right of the header. The icon literally becomes the sun. Static
   (no drift) so it stays anchored on the icon. Soft enough to not
   compete with the title. */
.screen[data-condition="sunny"] .climate__halo--a {
  display: block;
  position: absolute;
  width: 360px; height: 360px;
  top: -150px;
  right: -150px;
  left: auto; bottom: auto;
  background: radial-gradient(circle at 50% 50%,
    rgba(232, 181, 122, 0.55) 0%,
    rgba(232, 181, 122, 0.20) 30%,
    transparent 60%);
  border-radius: 50%;
  opacity: 0.55;
  filter: blur(4px);
  animation: none;
  transform: none;
}
.screen[data-condition="sunny"] .climate__halo--b,
.screen[data-condition="sunny"] .climate__halo--c { display: none; }
.screen[data-condition="sunny"] .climate__grain { opacity: 0.04; }

/* CHOPPY, TURNING — no atmosphere. The chart and copy carry the meaning. */
.screen[data-condition="choppy"] .climate__halo--a,
.screen[data-condition="choppy"] .climate__halo--b,
.screen[data-condition="choppy"] .climate__halo--c { display: none; }
.screen[data-condition="choppy"] .climate__grain { opacity: 0; }
.screen[data-condition="turning"] .climate__halo--a,
.screen[data-condition="turning"] .climate__halo--b,
.screen[data-condition="turning"] .climate__halo--c { display: none; }
.screen[data-condition="turning"] .climate__grain { opacity: 0; }

/* Barograph time axis (HTML version).
   Rendered as a flex row just above the readings cluster. Padding: 0 so
   09:30 / 16:00 sit flush with the screen body's content edges (matching
   the readings cluster's left/right margins). Sits IN FLOW so the gap
   to the readings is consistent at any chart band height. */
.barograph__times {
  display: flex;
  justify-content: space-between;
  padding: 0;
  margin: 0 0 8px;
  font-family: var(--display);
  font-size: 10px;
  letter-spacing: 0.12em;
  color: var(--ink-55);
  opacity: 0.7;
  position: relative;
  z-index: 1;
  pointer-events: none;
}

/* =========================================================
   Map: migration trails (ghost + line + arrow per sector)
   ========================================================= */
.mapviz__svg .mapviz__ghosts circle {
  stroke: #0A0A0A;
  stroke-opacity: 0.32;
  stroke-width: 1.1;
  fill: none;
}
.mapviz__svg .mapviz__trails path {
  stroke: #0A0A0A;
  stroke-opacity: 0.42;
  stroke-width: 0.9;
  color: #0A0A0A;       /* feeds the marker via currentColor */
}
/* Dark map (used on the prototype's default theme) — light strokes
   so trails and ghost rings read cleanly on the dark field. */
.phone[data-theme="dark"] .mapviz__svg .mapviz__ghosts circle {
  stroke: #F4F2EC;
  stroke-opacity: 0.40;
}
.phone[data-theme="dark"] .mapviz__svg .mapviz__trails path {
  stroke: #F4F2EC;
  stroke-opacity: 0.50;
  color: #F4F2EC;
}


/* =========================================================
   Map chip positioning (static, no animation).
   Chips read their --x / --y custom properties from JS;
   no transitions, no replay logic. The quadrant grid is the
   whole story — defensive ↔ cyclical on X, leading ↔ lagging
   on Y, with sectors and watchlist contracts plotted together.
   ========================================================= */
@property --x { syntax: '<percentage>'; inherits: false; initial-value: 50%; }
@property --y { syntax: '<percentage>'; inherits: false; initial-value: 50%; }

/* =========================================================
   Narrative layer
   ---------------------------------------------------------
   Driver chip glow: marks the sector that's the center of
   gravity for today's regime. Soft pulsing halo + a tiny
   leadership tag (★). Tap to open the structured story.
   ========================================================= */
.mapviz .chip.is-driver {
  /* Halo + outline that read as "this is the one" without
     dominating the map. Two box-shadow layers: a tight inner
     ring + a wide soft glow. Tuned for dark mode (the
     default theme). */
  box-shadow:
    0 0 0 1.5px rgba(255, 206, 130, 0.65),
    0 0 22px   rgba(255, 188, 110, 0.45),
    0 4px 14px rgba(10, 10, 10, 0.25);
  z-index: 6;
  animation: driver-pulse 3.6s ease-in-out infinite;
}
.mapviz .chip.is-driver::after {
  /* Leadership tag — small star pinned to the top-right of
     the chip. Pure CSS, no extra DOM. */
  content: "\2605"; /* ★ */
  position: absolute;
  top: -6px; right: -6px;
  font-size: 10px;
  line-height: 12px;
  width: 14px; height: 14px;
  border-radius: 50%;
  background: rgba(255, 206, 130, 0.95);
  color: #0A0A0A;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  box-shadow: 0 1px 4px rgba(10, 10, 10, 0.35);
  pointer-events: none;
}
@keyframes driver-pulse {
  0%, 100% { box-shadow:
    0 0 0 1.5px rgba(255, 206, 130, 0.65),
    0 0 18px   rgba(255, 188, 110, 0.35),
    0 4px 14px rgba(10, 10, 10, 0.25); }
  50%      { box-shadow:
    0 0 0 1.5px rgba(255, 206, 130, 0.80),
    0 0 28px   rgba(255, 188, 110, 0.55),
    0 4px 14px rgba(10, 10, 10, 0.25); }
}
[data-theme="light"] .mapviz .chip.is-driver {
  box-shadow:
    0 0 0 1.5px rgba(217, 138, 63, 0.55),
    0 0 22px   rgba(217, 138, 63, 0.30),
    0 4px 14px rgba(10, 10, 10, 0.10);
}
@media (prefers-reduced-motion: reduce) {
  .mapviz .chip.is-driver { animation: none; }
}

/* Supporting tier: chips that confirm or modify the story. Default
   visual — full color, full opacity. No special class needed for
   appearance; the class is added only so JS / future styling has a
   hook. (Today it's a no-op visually; deliberately.) */
.mapviz .chip.is-evidence-supporting {
  /* reserved */
}

/* Background tier: chips that are NOT contributing to today's story.
   Dimmed so the eye skips past them. Their tone dot is muted to a
   neutral gray regardless of authored tone — colored dots imply a
   story-relevant role, which background chips by definition don't
   have. Still tappable; the detail sheet acknowledges and moves on. */
.mapviz .chip.is-evidence-background {
  opacity: 0.42;
  transition: opacity 240ms ease;
}
.mapviz .chip.is-evidence-background:hover,
.mapviz .chip.is-evidence-background:focus-visible {
  opacity: 0.78;
}
.mapviz .chip.is-evidence-background .chip__dot {
  background: var(--ink-40) !important;
  opacity: 0.7;
}

/* =========================================================
   Coherence band
   ---------------------------------------------------------
   Verdict line + four pills. Sits between the map's
   interpretation paragraph and the .mapviz viz container.
   ========================================================= */
.mapviz__coherence {
  margin: 14px 0 12px;
  padding: 12px 14px;
  border-radius: 16px;
  background: var(--ink-06);
  border: 1px solid var(--glass-stroke, var(--ink-12));
}
.mapviz__coherence[hidden] { display: none; }
.mapviz__coherence-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 6px;
}
.mapviz__coherence-eyebrow {
  font-family: var(--display, "JetBrains Mono", monospace);
  font-size: 9.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-55);
  flex-shrink: 0;
}
.mapviz__coherence-verdict {
  display: block;
  margin: 0 0 10px;
  font-size: 12.5px;
  color: var(--ink-90);
  letter-spacing: 0.005em;
  line-height: 1.4;
}

/* Confidence chip on the right side of the head row. Pairs the word
   ("HIGH CONFIDENCE") with a three-dot meter — fastest possible
   read at a glance. Tone is encoded by the is-confidence-* class
   on the wrapper, which lights the appropriate number of dots and
   colors the label. */
.mapviz__coherence-confidence {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
.mapviz__coherence-confidence[hidden] { display: none; }
.mapviz__confidence-label {
  font-family: var(--display, "JetBrains Mono", monospace);
  font-size: 9.5px;
  letter-spacing: 0.14em;
  color: var(--ink-70);
}
.mapviz__confidence-meter {
  display: inline-flex;
  gap: 3px;
}
.mapviz__confidence-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ink-25);
  transition: background 200ms ease;
}
/* HIGH: three dots lit, label and dots in positive tint */
.is-confidence-high .mapviz__confidence-dot:nth-child(1),
.is-confidence-high .mapviz__confidence-dot:nth-child(2),
.is-confidence-high .mapviz__confidence-dot:nth-child(3) {
  background: #7fb88a;
}
.is-confidence-high .mapviz__confidence-label { color: #7fb88a; }

/* MODERATE: two dots lit, neutral tint */
.is-confidence-moderate .mapviz__confidence-dot:nth-child(1),
.is-confidence-moderate .mapviz__confidence-dot:nth-child(2) {
  background: var(--ink-70);
}
.is-confidence-moderate .mapviz__confidence-label { color: var(--ink-70); }

/* LOW: one dot lit, amber/warning tint */
.is-confidence-low .mapviz__confidence-dot:nth-child(1) {
  background: #d88860;
}
.is-confidence-low .mapviz__confidence-label { color: #d88860; }

[data-theme="light"] .is-confidence-high .mapviz__confidence-dot:nth-child(1),
[data-theme="light"] .is-confidence-high .mapviz__confidence-dot:nth-child(2),
[data-theme="light"] .is-confidence-high .mapviz__confidence-dot:nth-child(3) {
  background: #4a8c5a;
}
[data-theme="light"] .is-confidence-high .mapviz__confidence-label { color: #4a8c5a; }
[data-theme="light"] .is-confidence-low  .mapviz__confidence-dot:nth-child(1) {
  background: #b56a3f;
}
[data-theme="light"] .is-confidence-low .mapviz__confidence-label { color: #b56a3f; }
.mapviz__coherence.is-coherent .mapviz__coherence-verdict {
  /* Verdict line gets a quiet positive tint when the regime
     is internally consistent. Not loud — the pills carry the
     color signal. */
  color: var(--ink-90);
}
.mapviz__coherence.is-conflicted .mapviz__coherence-verdict {
  /* Warning tint for conflicted regimes. Amber, not red —
     the read is "watch this," not "broken." */
  color: #d88860;
}

.mapviz__coherence-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.coherence-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 9px 5px 8px;
  border-radius: 999px;
  font-size: 10.5px;
  letter-spacing: 0.01em;
  border: 1px solid var(--ink-12);
  background: rgba(244, 242, 236, 0.04);
}
.coherence-pill__label {
  font-weight: 600;
  color: var(--ink-90);
  font-family: var(--display, "JetBrains Mono", monospace);
  letter-spacing: 0.04em;
}
.coherence-pill__status {
  color: var(--ink-70);
  font-weight: 500;
}
/* Tone variants — color the status text so the eye picks up
   the pattern across pills without needing to read each one. */
.coherence-pill--positive .coherence-pill__status { color: #7fb88a; }
.coherence-pill--positive { border-color: rgba(127, 184, 138, 0.32); }
.coherence-pill--neutral  .coherence-pill__status { color: var(--ink-55); }
.coherence-pill--warning  .coherence-pill__status { color: #d88860; }
.coherence-pill--warning  { border-color: rgba(216, 136, 96, 0.40); }
[data-theme="light"] .mapviz__coherence {
  background: rgba(10, 10, 10, 0.03);
  border-color: rgba(10, 10, 10, 0.08);
}
[data-theme="light"] .coherence-pill {
  background: rgba(255, 255, 255, 0.7);
  border-color: rgba(10, 10, 10, 0.08);
}
[data-theme="light"] .coherence-pill--positive .coherence-pill__status { color: #4a8c5a; }
[data-theme="light"] .coherence-pill--warning  .coherence-pill__status { color: #b56a3f; }

/* =========================================================
   Sector detail · Magnitude + Takeaway block
   ---------------------------------------------------------
   Sits high in the slide-over so the trader gets the
   priority read first: two qualitative indicator cards
   ("Market magnitude / Dominant ↑ Strengthening") + a
   one-line takeaway ("If you remember one thing…").
   Intentionally no numeric scores — labels only.
   ========================================================= */
.ss-block--magnitude {
  margin: 4px 0 22px;
}
.ss-magnitude__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin: 0 0 14px;
}
.ss-magnitude__row[hidden] { display: none; }
.ss-magnitude__row:has(.ss-mag-card:only-child) {
  /* When only one indicator is authored, let it span full width
     rather than sit awkwardly in a half-column. */
  grid-template-columns: 1fr;
}
.ss-mag-card {
  border: 1px solid var(--ink-12);
  border-radius: 12px;
  padding: 10px 12px;
  background: rgba(244, 242, 236, 0.03);
}
.ss-mag-card__label {
  font-family: var(--display, "JetBrains Mono", monospace);
  font-size: 9px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-55);
  margin-bottom: 6px;
}
.ss-mag-card__value {
  font-size: 17px;
  font-weight: 600;
  color: var(--ink-90);
  letter-spacing: -0.005em;
  line-height: 1.2;
}
.ss-mag-card__dir {
  display: inline-block;
  margin-top: 4px;
  font-size: 11px;
  letter-spacing: 0.01em;
  color: var(--ink-70);
}
.ss-mag-card__dir--strengthening { color: #7fb88a; }
.ss-mag-card__dir--fading        { color: #d88860; }
.ss-mag-card__dir--inflecting    { color: #d8b860; }
.ss-mag-card__dir--stable        { color: var(--ink-55); }

[data-theme="light"] .ss-mag-card {
  background: rgba(255, 255, 255, 0.6);
  border-color: rgba(10, 10, 10, 0.08);
}
[data-theme="light"] .ss-mag-card__dir--strengthening { color: #4a8c5a; }
[data-theme="light"] .ss-mag-card__dir--fading        { color: #b56a3f; }

.ss-takeaway[hidden] { display: none; }
.ss-takeaway {
  border-left: 2px solid rgba(255, 206, 130, 0.55);
  padding: 2px 0 2px 12px;
  margin: 4px 0 0;
}
.ss-takeaway__eyebrow {
  display: block;
  font-family: var(--display, "JetBrains Mono", monospace);
  font-size: 9px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-55);
  margin-bottom: 4px;
}
.ss-takeaway__body {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.45;
  color: var(--ink-90);
  letter-spacing: 0.005em;
}
[data-theme="light"] .ss-takeaway {
  border-left-color: rgba(217, 138, 63, 0.55);
}

/* =========================================================
   Preferences · two-level navigation
   ---------------------------------------------------------
   Root page = compact list of section rows. Tap a row to
   push a sub-page in from the right (chevron-back navigation
   pattern). Tap the back chevron to slide it back off-screen
   right. Follows the project-wide rule:
     <  top-left  → push / slide horizontally
     X  top-left  → modal / slide vertically
   ========================================================= */
.pref-pages {
  position: relative;
  /* Clip on both axes:
     - X clips the off-screen sub-pages during slide
     - Y clips the (much-taller) list page when a sub-page is active
       and JS has set an explicit shorter height on the wrap */
  overflow: hidden;
}
/* List page (root). Always at translateX(0); the base layer
   that sub-pages slide over. */
.pref-page--list {
  position: relative;
  z-index: 1;
}
/* Sub-pages. Absolutely positioned so they overlay the list,
   off-screen to the right by default. Adding .is-active slides
   them in. The container's overflow-x clips the off-state, but
   we also flip visibility (with a delayed transition matching
   the slide-out) as belt-and-suspenders against sub-pixel leak
   into the parent's padding gutter. */
.pref-page:not(.pref-page--list) {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  /* No min-height — let content determine natural height so
     JS can measure scrollHeight to size the parent wrap. */
  /* Pure black / white to match the parent settings surface
     (the rest of the app uses off-tones via --page-0, but
     Preferences is intentionally pure per design review). */
  background: #FFFFFF;
  transform: translate3d(100%, 0, 0);
  visibility: hidden;
  transition:
    transform  360ms cubic-bezier(0.22, 0.61, 0.36, 1),
    visibility 0s    linear 360ms;
  z-index: 2;
}
.pref-page:not(.pref-page--list).is-active {
  transform: translate3d(0, 0, 0);
  visibility: visible;
  transition:
    transform  360ms cubic-bezier(0.22, 0.61, 0.36, 1),
    visibility 0s    linear 0s;
}
[data-theme="dark"] .pref-page:not(.pref-page--list) {
  background: #000000;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .pref-page:not(.pref-page--list) {
    background: #000000;
  }
}
@media (prefers-reduced-motion: reduce) {
  .pref-page:not(.pref-page--list) {
    transition:
      transform  0s,
      visibility 0s;
  }
}

/* List of section rows (root preferences page). Each row is
   a button so it's tappable + keyboard-focusable. Label on
   the left, current value on the right, chevron at the end. */
.pref-list {
  list-style: none;
  padding: 0;
  margin: 8px 0 24px;
  border-top: 1px solid var(--ink-12);
}
.pref-list li {
  border-bottom: 1px solid var(--ink-12);
}
.pref-list__row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 16px 4px;
  background: transparent;
  border: 0;
  cursor: pointer;
  color: var(--ink);
  font: inherit;
  text-align: left;
  transition: background 140ms var(--ease);
}
.pref-list__row:hover { background: var(--ink-06); }
.pref-list__row:active { background: var(--ink-12); }
.pref-list__label {
  flex: 1;
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.005em;
  color: var(--ink-90);
}
.pref-list__value {
  font-size: 13px;
  color: var(--ink-55);
  letter-spacing: 0.005em;
  text-align: right;
  max-width: 50%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pref-list__chev {
  font-size: 18px;
  color: var(--ink-40);
  line-height: 1;
  margin-left: 2px;
  font-weight: 300;
}
[data-theme="light"] .pref-list { border-top-color: rgba(10,10,10,0.08); }
[data-theme="light"] .pref-list li { border-bottom-color: rgba(10,10,10,0.08); }

/* Hide the "Scenario · demo" row when the app was opened with a
   URL-bound scenario (?scenario=stormy / foggy / turning etc.).
   Testers shouldn't see — or be able to switch — out of their
   assigned scenario. Body.is-demo-locked is set by JS in
   applySavedScenario when the URL specifies a scenario. */
body.is-demo-locked .pref-list li:has(button[data-pref-open="scenario"]) {
  display: none;
}

/* =========================================================
   Floating dismiss
   ---------------------------------------------------------
   Appears in the top-left corner when a scrollable modal /
   slide-in screen has been scrolled past ~40px. The in-flow
   header button is the primary affordance at rest; this
   floating mirror exists so the user never has to scroll
   back up to dismiss. Two icons inside (X for modal-close,
   ‹ for nav-back) — JS toggles which one is shown via
   .floating-dismiss--show-back. Hidden via opacity (animated)
   when the parent isn't .is-scrolled.
   ========================================================= */
.floating-dismiss {
  position: absolute;
  top: 18px;
  left: 18px;
  z-index: 20;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.70);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  backdrop-filter: blur(20px) saturate(1.4);
  border: 1px solid rgba(10, 10, 10, 0.10);
  box-shadow: 0 4px 14px rgba(10, 10, 10, 0.08);
  color: var(--ink);
  cursor: pointer;
  /* Hidden at rest. The .is-scrolled toggle on the parent
     screen fades it in. */
  opacity: 0;
  pointer-events: none;
  transform: translateY(-4px);
  transition: opacity 220ms cubic-bezier(0.22, 0.61, 0.36, 1),
              transform 220ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
[data-theme="dark"] .floating-dismiss {
  background: rgba(20, 22, 26, 0.72);
  border-color: rgba(255, 255, 255, 0.10);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
}
.floating-dismiss__icon {
  width: 18px;
  height: 18px;
  display: block;
}
.floating-dismiss__icon--back { display: none; }
.floating-dismiss--show-back .floating-dismiss__icon--close { display: none; }
.floating-dismiss--show-back .floating-dismiss__icon--back  { display: block; }

/* Show the floating dismiss when the parent screen is scrolled
   past the threshold. */
.screen.is-scrolled > .floating-dismiss,
.detail-screen.is-scrolled > .floating-dismiss {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

/* Active press feedback. */
.floating-dismiss:active {
  transform: translateY(0) scale(0.94);
}

/* =========================================================
   Vantage Point selector (Map lens)
   ---------------------------------------------------------
   Minimal text + chevron control. Tap to drop a frosted-glass
   menu of ecosystems. Selecting a lens applies fade + pan +
   scale to the map without leaving the page.
   ========================================================= */
.lens-selector {
  position: relative;
  margin: 0 0 14px;
  z-index: 4;
}
.lens-selector__trigger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: 0;
  padding: 4px 0;
  color: var(--ink-90);
  font: inherit;
  font-size: 13.5px;
  letter-spacing: 0.005em;
  cursor: pointer;
  transition: opacity 140ms ease;
}
.lens-selector__trigger:hover { opacity: 0.85; }
.lens-selector__trigger:active { opacity: 0.7; }
.lens-selector__prefix {
  color: var(--ink-55);
  font-weight: 400;
}
.lens-selector__value {
  font-weight: 600;
  letter-spacing: -0.005em;
}
.lens-selector__chev {
  width: 12px;
  height: 12px;
  margin-left: 2px;
  transition: transform 200ms ease;
  color: var(--ink-70);
}
.lens-selector[aria-expanded="true"] .lens-selector__chev,
.lens-selector__trigger[aria-expanded="true"] .lens-selector__chev {
  transform: rotate(180deg);
}

/* Dropdown menu — frosted glass card, low profile.
   Important: `display: none` when hidden so the expensive
   backdrop-filter doesn't keep blurring the area behind it
   while invisible. JS toggles `hidden` and adds .is-open on
   the next frame so the fade-in still animates. */
.lens-selector__menu {
  position: absolute;
  top: calc(100% + 6px);
  left: -4px;
  min-width: 220px;
  padding: 4px;
  border-radius: 14px;
  background: rgba(20, 22, 26, 0.85);
  /* backdrop-filter is genuinely expensive — keep this modest
     (12px instead of 20px) so the GPU isn't blurring a huge
     area behind a small menu. */
  -webkit-backdrop-filter: blur(12px) saturate(1.3);
  backdrop-filter: blur(12px) saturate(1.3);
  border: 1px solid rgba(255, 255, 255, 0.10);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.40);
  display: flex;
  flex-direction: column;
  gap: 1px;
  opacity: 0;
  transform: translateY(-4px) scale(0.98);
  transition:
    opacity 180ms cubic-bezier(0.22, 0.61, 0.36, 1),
    transform 180ms cubic-bezier(0.22, 0.61, 0.36, 1);
  pointer-events: none;
}
.lens-selector__menu[hidden] { display: none; }
.lens-selector__menu.is-open {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}
[data-theme="light"] .lens-selector__menu {
  background: rgba(255, 255, 255, 0.92);
  border-color: rgba(10, 10, 10, 0.08);
  box-shadow: 0 12px 40px rgba(10, 10, 10, 0.12);
}
.lens-selector__option {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 10px 14px;
  border-radius: 10px;
  color: var(--ink-90);
  font: inherit;
  font-size: 13.5px;
  text-align: left;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.lens-selector__option:hover { background: rgba(255, 255, 255, 0.06); }
[data-theme="light"] .lens-selector__option:hover { background: rgba(10, 10, 10, 0.04); }
.lens-selector__option.is-active {
  background: rgba(255, 255, 255, 0.10);
  color: var(--ink-90);
  font-weight: 600;
}
[data-theme="light"] .lens-selector__option.is-active { background: rgba(10, 10, 10, 0.06); }

/* =========================================================
   Lens advisories — small qualitative call-outs that appear
   only when an ecosystem lens is active. Glass card row.
   ========================================================= */
.lens-advisories {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0 0 14px;
}
.lens-advisories[hidden] { display: none; }
.lens-advisory {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px 11px;
  border-radius: 12px;
  /* Slightly more opaque background since we removed the backdrop-filter
     (it was costly and multiple advisories compounded the cost). */
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--ink-12);
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--ink-90);
  letter-spacing: 0.005em;
}
[data-theme="light"] .lens-advisory {
  background: rgba(255, 255, 255, 0.65);
  border-color: rgba(10, 10, 10, 0.08);
}
.lens-advisory__icon {
  flex-shrink: 0;
  font-size: 13px;
  line-height: 1.4;
  filter: saturate(1.2);
}
.lens-advisory__text {
  flex: 1;
}

/* =========================================================
   Map · lens fade + camera transform
   ---------------------------------------------------------
   .mapviz transforms (scale + pan) per active lens.
   Individual chips fade to a quiet 22% opacity + 1px blur
   when they're NOT primary for the active lens — "distant
   weather systems on the horizon" per the brief.
   ========================================================= */
.mapviz {
  /* Single transition for the camera move. Slight overshoot
     on the cubic-bezier gives a "settling" spring feel without
     pulling in a physics library. */
  transition: transform 520ms cubic-bezier(0.34, 1.32, 0.50, 1);
  transform-origin: center center;
  will-change: transform;
}

/* Chip fade on lens. Excludes the driver chip — it stays
   prominent regardless of lens (the regime's main story is
   still the regime's main story). Animates smoothly so the
   lens swap reads as a single fluid moment. */
.mapviz .chip {
  transition:
    opacity 380ms cubic-bezier(0.22, 0.61, 0.36, 1),
    filter  380ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.mapviz .chip.is-lens-secondary:not(.is-driver) {
  /* Opacity drop alone carries the "distant weather" read.
     Dropped the original filter: blur(1px) — each blurred chip
     promoted to its own GPU compositor layer, and toggling the
     lens repeatedly compounded layer pressure (visible as
     progressive lag on desktop). The 22% opacity is enough
     focus signal without the perf cost. */
  opacity: 0.22;
}
.mapviz .chip.is-lens-secondary:not(.is-driver) .chip__dot {
  /* Mute tone color on faded chips — they shouldn't carry
     the "warm / cool" signal when they're context, not story. */
  opacity: 0.5;
}

/* =========================================================
   App splash screen
   ---------------------------------------------------------
   Covers the prototype on first load. Always-dark backdrop
   regardless of theme (loading state doesn't need to honor
   user preference). Dismissed by JS on window-load OR after
   a 3s ceiling, whichever fires first.
   ========================================================= */
.app-splash {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: #0A0B0D;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 1;
  transition: opacity 420ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.app-splash.is-leaving {
  opacity: 0;
  pointer-events: none;
}
.app-splash__panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  animation: app-splash-rise 720ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
.app-splash__logo {
  width: 92px;
  height: 92px;
  border-radius: 22px;
  object-fit: cover;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
  /* Slow breathing so the screen reads as "alive / loading" without
     a spinner. Disabled under reduced-motion. */
  animation: app-splash-breathe 3.4s ease-in-out infinite;
}
.app-splash__title {
  font-family: "JetBrains Mono", monospace;
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: 0.30em;
  text-transform: uppercase;
  color: rgba(244, 242, 236, 0.78);
}
@keyframes app-splash-rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes app-splash-breathe {
  0%, 100% { transform: scale(1);    }
  50%      { transform: scale(1.045); }
}
@media (prefers-reduced-motion: reduce) {
  .app-splash__panel,
  .app-splash__logo { animation: none; }
}

/* ======================================================================
   Feedback pill — appears for visitors arriving from the landing page
   (?from=landing) after they've engaged with the prototype (45s OR
   3+ screens visited). Sits above the tab bar so it doesn't block
   primary navigation. Dismissible via the × button.
   ====================================================================== */
.feedback-pill {
  position: fixed;
  left: 16px;
  right: 16px;
  bottom: 96px; /* clears the ~80px tab bar with some breathing room */
  z-index: 1000;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 6px 8px 18px;
  background: rgba(20, 20, 20, 0.96);
  color: #fff;
  border-radius: 999px;
  box-shadow:
    0 12px 32px rgba(0, 0, 0, 0.45),
    0 2px 6px rgba(0, 0, 0, 0.25);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.005em;
  transform: translateY(140%);
  opacity: 0;
  transition:
    transform 360ms cubic-bezier(0.2, 0.7, 0.2, 1),
    opacity 280ms;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
.feedback-pill.is-shown {
  transform: translateY(0);
  opacity: 1;
}
.feedback-pill__link {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 36px;
  padding: 0 4px;
  color: inherit;
  text-decoration: none;
}
.feedback-pill__link span {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.feedback-pill__close {
  flex: 0 0 auto;
  background: transparent;
  border: 0;
  color: #fff;
  font-size: 22px;
  line-height: 1;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0.65;
  border-radius: 999px;
  transition: opacity 160ms, background-color 160ms;
}
.feedback-pill__close:hover,
.feedback-pill__close:focus-visible {
  opacity: 1;
  background: rgba(255, 255, 255, 0.08);
  outline: none;
}
/* On wider viewports (e.g., the iframe-embedded desktop preview), the
   pill would be visually odd. We only render it for ?from=landing
   visitors anyway, and that flow is mobile-only — so this is mostly
   defensive. Keep it tightly sized on larger screens. */
@media (min-width: 600px) {
  .feedback-pill {
    left: auto;
    right: 24px;
    bottom: 24px;
    max-width: 360px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .feedback-pill {
    transition: opacity 200ms;
    transform: translateY(0);
  }
}

/* ======================================================================
   Focused mode — when visitors arrive from the V2 landing page
   (?from=landing) the prototype strips its marketing wrapper. No
   header, no "Tap through" intro, no Add-to-Home-Screen button.
   The phone takes center stage. Feedback pill still fires as built.
   Direct prototype visits show the full marketing chrome.
   ====================================================================== */
html.is-focused .stage-nav,
html.is-focused .stage__hint {
  display: none;
}
html.is-focused .stage {
  grid-template-columns: 1fr;
  justify-items: center;
  padding: 56px 24px 60px;
}
@media (max-width: 720px) {
  html.is-focused .stage {
    padding: 32px 16px 60px;
  }
}

/* =========================================================
   ALPHA MODAL — opens on hero CTA click.
   Dark dialog on dark backdrop. Two fields (open question +
   email) submit to Netlify Forms under the "feedback" name.
   ========================================================= */
.alpha-modal {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  /* When hidden via [hidden], display:none is set by user-agent.
     When shown via .is-open we use this flex layout. */
}
.alpha-modal[hidden] { display: none; }
.alpha-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.7);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  opacity: 0;
  transition: opacity 240ms;
}
.alpha-modal.is-open .alpha-modal__backdrop {
  opacity: 1;
}
.alpha-modal__panel {
  position: relative;
  z-index: 1;
  max-width: 480px;
  width: 100%;
  background: #131316;
  color: #fff;
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 22px;
  padding: 32px;
  box-shadow:
    0 40px 100px rgba(0,0,0,0.6),
    0 12px 30px rgba(0,0,0,0.4);
  transform: translateY(16px) scale(0.98);
  opacity: 0;
  transition:
    transform 280ms cubic-bezier(0.2, 0.7, 0.2, 1),
    opacity 220ms;
}
.alpha-modal.is-open .alpha-modal__panel {
  transform: translateY(0) scale(1);
  opacity: 1;
}
.alpha-modal__close {
  position: absolute;
  top: 16px;
  right: 16px;
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  color: rgba(255,255,255,0.6);
  cursor: pointer;
  border-radius: 999px;
  transition: color 160ms, background-color 160ms;
}
.alpha-modal__close:hover {
  color: #fff;
  background: rgba(255,255,255,0.06);
}
.alpha-modal__title {
  font-family: var(--display);
  font-size: 28px;
  font-weight: 600;
  letter-spacing: -0.02em;
  margin: 0 0 10px;
  color: #fff;
}
.alpha-modal__lede {
  font-size: 14px;
  line-height: 1.5;
  color: rgba(255,255,255,0.65);
  margin: 0 0 24px;
}

/* The form itself */
.alpha-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
  position: relative;
}
.alpha-form__hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.alpha-form__field {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.alpha-form__label {
  font-size: 13px;
  font-weight: 500;
  color: rgba(255,255,255,0.85);
  letter-spacing: 0.005em;
}
.alpha-form textarea,
.alpha-form input[type="email"] {
  width: 100%;
  padding: 12px 14px;
  font-family: inherit;
  font-size: 15px;
  line-height: 1.4;
  color: #fff;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 12px;
  outline: none;
  transition: border-color 160ms, background-color 160ms;
}
.alpha-form input[type="email"] {
  border-radius: 999px;
}
.alpha-form textarea {
  resize: vertical;
  min-height: 80px;
}
.alpha-form textarea::placeholder,
.alpha-form input[type="email"]::placeholder {
  color: rgba(255,255,255,0.35);
}
.alpha-form textarea:focus,
.alpha-form input[type="email"]:focus {
  border-color: rgba(255,255,255,0.4);
  background: rgba(255,255,255,0.08);
}
.alpha-form__submit {
  margin-top: 4px;
  padding: 14px 22px;
  background: #fff;
  color: #0a0a0a;
  border: 0;
  border-radius: 999px;
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.005em;
  cursor: pointer;
  transition: transform 140ms, box-shadow 140ms;
}
.alpha-form__submit:hover {
  transform: translateY(-1px);
  box-shadow: 0 8px 24px rgba(255,255,255,0.12);
}
.alpha-form__submit:active {
  transform: translateY(0);
}
.alpha-form__submit:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
.alpha-form__thanks {
  padding: 16px 18px;
  border-radius: 14px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.12);
  font-size: 14px;
  color: rgba(255,255,255,0.9);
  line-height: 1.5;
}
.alpha-form__thanks strong {
  display: block;
  font-weight: 600;
  margin-bottom: 4px;
  color: #fff;
}
.alpha-form.is-submitted .alpha-form__field,
.alpha-form.is-submitted .alpha-form__submit {
  display: none;
}
.alpha-form.is-submitted .alpha-form__thanks {
  display: block !important;
}

@media (max-width: 520px) {
  .alpha-modal__panel {
    padding: 24px 20px;
    border-radius: 18px;
  }
  .alpha-modal__title {
    font-size: 24px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .alpha-modal__backdrop,
  .alpha-modal__panel { transition: none; }
}


