/* =============================================================
   Nerd Page — dark canvas with jewel-tone accents.
   Lighter than Today on purpose: no backdrop-filter, no atmosphere
   layer, no @property color transitions. iPad WebKit constraint is
   the reason this aesthetic was designed.
   ============================================================= */

:root {
  /* Dark canvas */
  --nerd-bg-top:    #07090f;
  --nerd-bg-bottom: #0e131c;
  --nerd-panel:     #11151e;
  --nerd-divider:   #1e2433;

  /* Text scale */
  --nerd-text:    #f0f4fa;
  --nerd-text-2:  #a5afc0;
  --nerd-text-3:  #64707c;
  --nerd-text-4:  #3e4855;

  /* Jewel-tone accents — used consistently per metric */
  --nerd-temp:      #f59e0b;  /* amber       */
  --nerd-pressure:  #a78bfa;  /* lavender    */
  --nerd-humid:     #22d3ee;  /* cyan        */
  --nerd-wind:      #84cc16;  /* lime        */
  --nerd-uv:        #fb7185;  /* rose        */
  --nerd-lightning: #60a5fa;  /* electric    */
  --nerd-astro:     #fbbf24;  /* gold        */
  --nerd-dew:       #6eb4dc;  /* light blue  */
  --nerd-rain:      #6cc4ff;  /* sky blue    */
}

/* —— Long-press feedback on hero (lives on Today, fires when user holds) —— */
.hero {
  /* Tracking origin for the radial fill animation. */
  --press-x: 50%;
  --press-y: 50%;
  isolation: isolate;
}
.hero.long-pressing {
  transform: scale(0.98);
  transition: transform 240ms cubic-bezier(0.25, 0.8, 0.25, 1);
}
.hero.long-pressing::after {
  content: "";
  position: absolute;
  left: var(--press-x);
  top:  var(--press-y);
  width: 0; height: 0;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0.08) 45%, transparent 70%);
  transform: translate(-50%, -50%);
  animation: nerd-press-grow 700ms ease-out forwards;
  pointer-events: none;
  z-index: 3;
}
@keyframes nerd-press-grow {
  0%   { width: 0;     height: 0;     opacity: 0.85; }
  100% { width: 640px; height: 640px; opacity: 0;    }
}
/* iPad Safari defeats custom long-press handlers by firing its native
   text-selection / loupe gesture before our 700 ms timer completes. We
   suppress user-select on the hero AND every descendant so WebKit can't
   latch onto inner text nodes. touch-action: manipulation also blocks
   double-tap-zoom interference. Combined with preventDefault() in the
   pointerdown handler (passive: false), this is what makes the long-press
   open the Nerd Page on iPad. iPhone was working already; this is a no-op
   there. The rule is scoped to .hero so the rest of the page keeps normal
   text selection. */
.hero,
.hero * {
  -webkit-touch-callout: none;   /* suppress iOS "copy" menu / loupe */
  -webkit-user-select: none;
  user-select: none;
  touch-action: manipulation;
}

/* —— Nerd page overlay + crossfade —— */
.nerd-page {
  position: fixed;
  inset: 0;
  z-index: 3000;
  background:
    radial-gradient(ellipse at 50% -10%, #0e1424 0%, transparent 60%),
    linear-gradient(180deg, var(--nerd-bg-top) 0%, var(--nerd-bg-bottom) 100%);
  color: var(--nerd-text);
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  opacity: 0;
  pointer-events: none;
  transition: opacity 250ms ease-out;
  /* Honor iPhone safe-area for the close button and pull handle. */
  padding-top:    env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
  padding-left:   env(safe-area-inset-left);
  padding-right:  env(safe-area-inset-right);
  overflow: hidden;
}
body.nerd-open .nerd-page {
  opacity: 1;
  pointer-events: auto;
}
body.nerd-open .app {
  opacity: 0;
  pointer-events: none;
}
.app {
  transition: opacity 250ms ease-out;
}
/* Hide app entirely when the nerd page is fully crossfaded in — saves
   compositor work on the atmosphere layer + glass panels behind us. */
body.nerd-open.nerd-settled .app { visibility: hidden; }

/* —— Pull-down handle (subtle visual cue for the gesture) —— */
.nerd-pull-handle {
  position: absolute;
  top: max(8px, env(safe-area-inset-top));
  left: 50%;
  transform: translateX(-50%);
  width: 36px;
  height: 4px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.12);
  pointer-events: none;
}

/* —— Close button (top-LEFT — iOS convention; the top-right corner is
   reserved for the chip rail's ALL pill) ——
   The .nerd-page parent already pads by env(safe-area-inset-*), so 16px
   here is from the safe-area edge, not from the screen edge. Background
   is dark + opaque enough that the contrail (which can pass through the
   upper-left of the portrait at northern sun azimuths) can't read
   through and confuse the silhouette. */
.nerd-close {
  position: absolute;
  top:  16px;
  left: 16px;
  z-index: 10;
  width: 38px; height: 38px;
  border-radius: 50%;
  background: rgba(7, 9, 15, 0.62);
  border: 1px solid rgba(255, 255, 255, 0.18);
  color: var(--nerd-text);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s, transform 0.1s;
  display: flex; align-items: center; justify-content: center;
  -webkit-tap-highlight-color: transparent;
}
.nerd-close:hover  { background: rgba(7, 9, 15, 0.78); }
.nerd-close:active { transform: scale(0.94); }

/* —— Stage (where the portrait + chip rail live) ——
   --rail-w is the width budget given to the right-edge chip rail. The
   portrait + wind canvas are inset by this on the right so the rail
   isn't sitting on top of the picture. 70 px at >= 600 px, 60 px below. */
.nerd-stage {
  position: absolute;
  inset: 0;
  overflow: hidden;
  --rail-w: 70px;
}
@media (max-width: 599px) {
  .nerd-stage { --rail-w: 60px; }
}

/* —— Atmospheric Portrait SVG ——
   SVG is a *replaced* element: with `width:auto` the browser falls back
   to the intrinsic aspect ratio derived from its own viewBox, which
   becomes a self-referencing loop (next render reads the wrong rect and
   re-bakes the bad viewBox). Setting BOTH width and height explicitly
   defeats the replaced-element sizing rules so the SVG fills its box. */
.nerd-portrait {
  position: absolute;
  top: 0;
  left: 0;
  width: calc(100% - var(--rail-w));
  height: 100%;
  display: block;
  z-index: 0;
}
.nerd-portrait text {
  /* Keep glyph rendering sharp on retina */
  text-rendering: geometricPrecision;
  font-feature-settings: 'tnum';
}
/* —— Cloud band drift — slow CSS animation over the SVG cloud group —— */
.nerd-portrait .cloud-band {
  animation: cloud-drift 110s linear infinite;
  transform-origin: center center;
}
@keyframes cloud-drift {
  0%   { transform: translateX(-2.4%); }
  50%  { transform: translateX(2.4%); }
  100% { transform: translateX(-2.4%); }
}
/* Hard pause when the nerd page isn't visible. Browsers will pause animations
   on display:none elements, but during the 250 ms crossfade the page is still
   display:block at opacity 0 — we don't want a CSS animation burning GPU
   cycles invisibly. The body class flips synchronously with open/close. */
body:not(.nerd-open) .nerd-portrait .cloud-band {
  animation-play-state: paused;
}
@media (prefers-reduced-motion: reduce) {
  .nerd-portrait .cloud-band { animation: none; }
}

/* —— Wind streaks Canvas overlay —— */
.nerd-wind {
  position: absolute;
  top: 0;
  left: 0;
  width: calc(100% - var(--rail-w));
  height: 100%;
  display: block;
  z-index: 1;
  pointer-events: none;
}

/* ──────────────────────────────────────────────────────────────────────
   Chip rail — vertical, right edge
   ────────────────────────────────────────────────────────────────────── */

.nerd-rail {
  /* Pinned to the right edge of the stage. The .nerd-page parent ALREADY
     adds padding-top: env(safe-area-inset-top) and padding-bottom for the
     status bar / home indicator, so the stage (and therefore this rail)
     is already inside the safe area. Do NOT add another env() offset
     here — that double-stacks and pushes the ALL pill down. */
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: var(--rail-w);
  z-index: 2;
  /* Solid-enough background so the ALL pill + chips read as a unified
     container, not floating overlays. 0.55 alpha was too see-through. */
  background: linear-gradient(180deg,
    rgba(7, 9, 15, 0.92) 0%,
    rgba(14, 19, 28, 0.92) 100%);
  border-left: 1px solid rgba(255, 255, 255, 0.10);
  display: flex;
  flex-direction: column;
  /* No backdrop-filter — that was the Today iPad memory issue. The
     near-opaque background above is just an alpha-blend. */
}

/* —— ALL pill — fixed at the top of the rail —— */
.nerd-rail-all {
  flex: 0 0 auto;
  margin: 8px 6px 6px;
  padding: 8px 4px 8px 4px;
  background: rgba(251, 191, 36, 0.06);
  border: 1px solid rgba(251, 191, 36, 0.42);
  border-radius: 10px;
  color: var(--nerd-text);
  cursor: pointer;
  font-family: 'Inter', sans-serif;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  transition: background 0.15s, transform 0.1s;
  -webkit-tap-highlight-color: transparent;
}
.nerd-rail-all:hover  { background: rgba(251, 191, 36, 0.12); }
.nerd-rail-all:active { transform: scale(0.96); }
.rail-all-dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--nerd-astro);
  box-shadow: 0 0 6px rgba(251, 191, 36, 0.65);
  margin-bottom: 2px;
}
.rail-all-title {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.10em;
  color: var(--nerd-astro);
}
.rail-all-caret  { color: var(--nerd-astro); margin-left: 2px; }
.rail-all-sub {
  font-size: 9px;
  letter-spacing: 0.06em;
  color: var(--nerd-text-3);
  text-transform: uppercase;
}

/* —— Scrollable list of chips —— */
.nerd-rail-scroll {
  position: relative;                /* anchor for chip offsetTop math */
  flex: 1 1 auto;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 4px 6px 22px;          /* bottom pad clears the fade gradient */
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.18) transparent;
  scroll-behavior: smooth;
}
.nerd-rail-scroll::-webkit-scrollbar          { width: 4px; }
.nerd-rail-scroll::-webkit-scrollbar-track    { background: transparent; }
.nerd-rail-scroll::-webkit-scrollbar-thumb    {
  background: rgba(255, 255, 255, 0.16);
  border-radius: 2px;
}
.nerd-rail-scroll::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.30); }

/* —— Section header inside the rail —— label + hairline to the right.
   Same component reused in the phone bottom sheet (where it shows above
   each section's chip grid). The label inherits its color from the
   section's --accent CSS var (set inline on the header element). */
.nerd-section-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 10px 2px 4px;
  font-family: 'JetBrains Mono', monospace;
}
.nerd-section-header:first-child { margin-top: 2px; }
.nerd-section-label {
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--accent, var(--nerd-text-3));
  text-transform: uppercase;
  flex: 0 0 auto;
}
.nerd-section-rule {
  flex: 1 1 auto;
  height: 1px;
  background: linear-gradient(90deg,
              color-mix(in srgb, var(--accent, #ffffff) 28%, transparent),
              transparent);
}

/* —— Individual chip — single shared template, no per-chip filters ——
   Layout: 4 px accent stripe on the left + content (label / value / sub). */
.nerd-chip {
  position: relative;
  display: block;
  width: 100%;
  margin-bottom: 4px;
  padding: 6px 4px 6px 9px;       /* extra left for accent stripe */
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 8px;
  color: var(--nerd-text);
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.12s, transform 0.08s;
  overflow: hidden;
}
.nerd-chip:hover  { background: rgba(255, 255, 255, 0.06); }
.nerd-chip:active { transform: scale(0.97); }
.nerd-chip::before {
  /* Accent stripe — color pulled from --accent CSS var set per chip */
  content: "";
  position: absolute;
  left: 0; top: 6px; bottom: 6px;
  width: 3px;
  border-radius: 2px;
  background: var(--accent, var(--nerd-text-3));
}
.nerd-chip-label {
  display: block;
  font-family: 'JetBrains Mono', monospace;
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  /* Bumped from --nerd-text-3 (#64707c) for WCAG AA — at 9.5 px on the
     0.92-opaque rail bg, the lighter color #a5afc0 gives ~9.7:1 contrast
     vs the previous ~3.9:1 (below AA threshold of 4.5:1 for body text). */
  color: var(--nerd-text-2);
  text-transform: uppercase;
  line-height: 1.2;
}
.nerd-chip-value {
  display: block;
  font-family: 'JetBrains Mono', monospace;
  font-size: 15px;
  font-weight: 500;
  color: var(--nerd-text);
  line-height: 1.15;
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-feature-settings: 'tnum';
}
.nerd-chip-sub {
  display: block;
  font-family: 'JetBrains Mono', monospace;
  font-size: 9.5px;
  color: var(--nerd-text-2);
  letter-spacing: 0.04em;
  line-height: 1.2;
  margin-top: 1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nerd-chip[data-missing="1"] .nerd-chip-value { color: var(--nerd-text-4); }

/* —— Fade-out gradient + "↓ N more" indicator at bottom ——
   Both ignore pointer events so they don't block the last chip. */
.nerd-rail-fade {
  position: absolute;
  left: 1px; right: 4px; bottom: 0;
  height: 36px;
  background: linear-gradient(180deg, transparent 0%,
              rgba(10, 13, 22, 0.85) 70%, rgba(10, 13, 22, 1) 100%);
  pointer-events: none;
  border-bottom-left-radius: 8px;
}
.nerd-rail-more {
  position: absolute;
  left: 0; right: 4px; bottom: 4px;
  text-align: center;
  font-family: 'JetBrains Mono', monospace;
  font-size: 9px;
  letter-spacing: 0.06em;
  color: var(--nerd-text-2);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.18s ease-out;
}
.nerd-rail-more.visible { opacity: 0.85; }

/* —— Reduced-motion: kill chip transitions —— */
@media (prefers-reduced-motion: reduce) {
  .nerd-rail-all,
  .nerd-chip,
  .nerd-rail-more,
  .nerd-rail-scroll { transition: none; scroll-behavior: auto; }
}

/* ──────────────────────────────────────────────────────────────────────
   Phone bottom sheet — used at viewport < 700 px instead of the rail.
   Three snap positions: collapsed (~80 px, just affordance), peeking
   (~50 vh), expanded (~88 vh). JS toggles the .peeking / .expanded
   classes; CSS animates between them via height + transform.
   ────────────────────────────────────────────────────────────────────── */

.nerd-sheet {
  /* Hidden by default — only the @media (max-width: 699px) rule below
     promotes it to display: flex. Keeps the rail authoritative on iPad. */
  display: none;
}
/* Same [hidden]-defeated-by-author-display class as .local-strip: the phone
   @media rule sets `display: flex`, which beats the UA `[hidden]` rule, so the
   initial `hidden` attr would flash the sheet on phone before sheet.js clears
   it. Guard (0,2,0) wins over the media rule regardless of order. */
.nerd-sheet[hidden] { display: none; }

@media (max-width: 699px) {
  /* Swap the rail for the sheet, and let the portrait fill full width. */
  .nerd-rail   { display: none; }
  .nerd-stage  { --rail-w: 0px; }

  .nerd-sheet {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 3;
    height: calc(88px + env(safe-area-inset-bottom));
    background:
      linear-gradient(180deg, rgba(7, 9, 15, 0.94) 0%, rgba(14, 19, 28, 0.96) 100%);
    border-top: 1px solid rgba(255, 255, 255, 0.10);
    border-top-left-radius: 14px;
    border-top-right-radius: 14px;
    box-shadow: 0 -10px 32px rgba(0, 0, 0, 0.45);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    transition: height 250ms cubic-bezier(0.25, 0.8, 0.25, 1);
    /* Phone safe-area: home indicator clearance on the bottom */
    padding-bottom: env(safe-area-inset-bottom);
    padding-left:   env(safe-area-inset-left);
    padding-right:  env(safe-area-inset-right);
  }
  .nerd-sheet.peeking  { height: 50vh; }
  .nerd-sheet.expanded { height: 88vh; }
  /* Backdrop tap-to-collapse — a transparent overlay over the visible
     portrait area whenever the sheet is peeking or expanded. */
  .nerd-sheet.peeking::before,
  .nerd-sheet.expanded::before {
    content: '';
    position: fixed;
    inset: 0 0 var(--sheet-h, 50vh) 0;
    background: rgba(0, 0, 0, 0.25);
    pointer-events: auto;
  }
}

/* —— Pull handle — visible bar with a generous invisible hit zone ——
   The visible bar is 44 × 5 px; the actual touch target is the whole
   top 64 px of the sheet (handled in sheet.js), so users don't have to
   precisely target the small bar to start dragging. */
.nerd-sheet-handle {
  flex: 0 0 auto;
  width: 44px;
  height: 5px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.45);
  margin: 10px auto 6px;
  cursor: grab;
}
.nerd-sheet-handle:active { cursor: grabbing; }
/* Disable iOS native gestures (scroll, pull-to-refresh, magnify) inside
   the whole sheet so the JS drag handler owns vertical motion in the
   handle zone. The chip grid still scrolls because we toggle
   touch-action back to auto on it. */
.nerd-sheet { touch-action: none; }
.nerd-sheet-grid { touch-action: pan-y; }

/* —— Collapsed content (visible while .nerd-sheet has no state class) —— */
.nerd-sheet-collapsed {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 0 12px 8px;
}
.nerd-sheet.peeking .nerd-sheet-collapsed,
.nerd-sheet.expanded .nerd-sheet-collapsed {
  /* Hide the pills + hint when the sheet is open — the expanded
     content takes over. */
  display: none;
}
.nerd-sheet-pills {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.10em;
}
.nerd-sheet-pill {
  color: var(--accent, var(--nerd-text));
}
.nerd-sheet-pill-sep {
  color: var(--nerd-text-3);
  font-weight: 400;
}
.nerd-sheet-hint {
  font-family: 'Inter', sans-serif;
  font-size: 10.5px;
  letter-spacing: 0.04em;
  color: var(--nerd-text-3);
  font-style: italic;
}

/* —— Expanded content (hidden until .peeking or .expanded class) —— */
.nerd-sheet-expanded {
  flex: 1 1 auto;
  display: none;
  flex-direction: column;
  min-height: 0;       /* allow flex child to shrink so inner can scroll */
  padding: 0 14px 8px;
}
.nerd-sheet.peeking  .nerd-sheet-expanded,
.nerd-sheet.expanded .nerd-sheet-expanded { display: flex; }

.nerd-sheet-header {
  flex: 0 0 auto;
  padding: 4px 0 10px;
}
.nerd-sheet-title {
  font-family: 'Inter', sans-serif;
  font-size: 18px;
  font-weight: 600;
  color: var(--nerd-text);
  margin: 0;
}
.nerd-sheet-sub {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10.5px;
  color: var(--nerd-text-3);
  letter-spacing: 0.05em;
  margin: 2px 0 10px;
}
.nerd-sheet-search {
  width: 100%;
  padding: 9px 12px;
  font-family: 'Inter', sans-serif;
  font-size: 14px;
  color: var(--nerd-text);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 9px;
  -webkit-appearance: none;
  appearance: none;
  outline: none;
}
.nerd-sheet-search:focus { border-color: var(--nerd-astro); }
.nerd-sheet-search::placeholder { color: var(--nerd-text-3); }

/* —— Scrolling chip grid inside the expanded sheet —— */
.nerd-sheet-grid {
  flex: 1 1 auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.18) transparent;
  padding-bottom: 14px;
}
.nerd-sheet-grid::-webkit-scrollbar       { width: 4px; }
.nerd-sheet-grid::-webkit-scrollbar-track { background: transparent; }
.nerd-sheet-grid::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.16);
  border-radius: 2px;
}
.nerd-sheet-section-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 8px;
}
/* Chip card inside the sheet — wider/shorter than the rail variant,
   accent stripe on TOP instead of LEFT, horizontal value/unit layout. */
.nerd-sheet-section-grid .nerd-chip {
  margin-bottom: 0;
  padding: 10px 12px 9px 12px;
  min-height: 60px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  border-radius: 10px;
}
.nerd-sheet-section-grid .nerd-chip::before {
  /* Accent stripe across the TOP of the card */
  top: 0;
  left: 8px;
  right: 8px;
  bottom: auto;
  width: auto;
  height: 3px;
  border-radius: 0 0 2px 2px;
}
.nerd-sheet-section-grid .nerd-chip-label {
  font-size: 10px;
  color: var(--accent, var(--nerd-text-2));
  letter-spacing: 0.10em;
}
.nerd-sheet-section-grid .nerd-chip-value {
  font-size: 22px;
  font-weight: 600;
  line-height: 1.05;
}
.nerd-sheet-section-grid .nerd-chip-sub {
  font-size: 10px;
  color: var(--nerd-text-3);
  letter-spacing: 0.04em;
}
.nerd-sheet-section-grid .nerd-chip[data-hidden="1"] { display: none; }

/* —— Reduced-motion: snap, don't slide —— */
@media (prefers-reduced-motion: reduce) {
  .nerd-sheet { transition: none; }
}

/* ──────────────────────────────────────────────────────────────────────
   Drilldown — modal card overlaying the portrait+rail.
   Centered on desktop/iPad; full-width sheet on phone, sliding up from
   the bottom. Backdrop darkens the rest of the page. No backdrop-filter
   (iPad memory budget); a plain rgba dim handles it. Lifecycle (open /
   close / Escape / backdrop tap) lives in drilldown.js.
   ────────────────────────────────────────────────────────────────────── */

.nerd-drill {
  position: absolute;
  inset: 0;
  z-index: 20;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.nerd-drill.open { display: flex; }

.nerd-drill-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  opacity: 0;
  transition: opacity 200ms ease-out;
}
.nerd-drill.open .nerd-drill-backdrop { opacity: 1; }

.nerd-drill-card {
  position: relative;
  z-index: 1;
  width: min(100%, 640px);
  max-height: calc(100% - 24px);
  overflow-y: auto;
  background: linear-gradient(180deg,
    rgba(17, 22, 32, 0.97) 0%,
    rgba(10, 14, 22, 0.97) 100%);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 16px;
  padding: 22px 22px 18px;
  color: var(--nerd-text);
  font-family: 'Inter', sans-serif;
  transform: translateY(14px);
  opacity: 0;
  transition: transform 220ms cubic-bezier(0.25, 0.8, 0.25, 1),
              opacity   200ms ease-out;
  /* Accent stripe at the top-left of the card pulls in the chip's color */
  box-shadow:
    inset 4px 0 0 0 var(--accent, var(--nerd-text-3)),
    0 14px 40px rgba(0, 0, 0, 0.55);
}
.nerd-drill.open .nerd-drill-card {
  transform: translateY(0);
  opacity: 1;
}

/* —— Close (top-right of card) —— */
.nerd-drill-close {
  position: absolute;
  top: 10px; right: 12px;
  width: 32px; height: 32px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: var(--nerd-text);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.15s, transform 0.1s;
  -webkit-tap-highlight-color: transparent;
}
.nerd-drill-close:hover  { background: rgba(255, 255, 255, 0.12); }
.nerd-drill-close:active { transform: scale(0.94); }

/* —— Header — label + current value —— */
.nerd-drill-head { margin-bottom: 14px; padding-right: 40px; }
.nerd-drill-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.18em;
  color: var(--nerd-text-3);
  text-transform: uppercase;
  margin-bottom: 6px;
}
.nerd-drill-current {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-feature-settings: 'tnum';
}
.nerd-drill-value {
  font-family: 'JetBrains Mono', monospace;
  font-size: 38px;
  font-weight: 500;
  color: var(--nerd-text);
  line-height: 1;
}
.nerd-drill-unit {
  font-family: 'JetBrains Mono', monospace;
  font-size: 15px;
  color: var(--nerd-text-2);
}
.nerd-drill-trend {
  font-family: 'JetBrains Mono', monospace;
  font-size: 18px;
  color: var(--accent, var(--nerd-text-2));
  margin-left: 4px;
}

/* —— Chart —— */
.nerd-drill-chartwrap {
  position: relative;
  width: 100%;
  height: 160px;
  background: rgba(255, 255, 255, 0.02);
  border-radius: 10px;
  padding: 8px;
  margin-bottom: 10px;
}
.nerd-drill-chart {
  display: block;
  width: 100%;
  height: 100%;
}
.nerd-drill-axis {
  display: flex;
  justify-content: space-between;
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  color: var(--nerd-text-3);
  padding: 0 4px;
  margin-bottom: 14px;
  letter-spacing: 0.05em;
}

/* —— 24h min/max/avg row —— */
.nerd-drill-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  margin-bottom: 14px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 13px;
  font-feature-settings: 'tnum';
}
.nerd-drill-stats > div { display: flex; flex-direction: column; gap: 2px; }
.nerd-drill-stats .muted {
  font-size: 9.5px;
  letter-spacing: 0.10em;
  color: var(--nerd-text-3);
  text-transform: uppercase;
}

/* —— Plain-English readout + methodology —— */
.nerd-drill-readout {
  background: rgba(255, 255, 255, 0.03);
  border-left: 2px solid var(--accent, var(--nerd-text-3));
  padding: 10px 12px;
  margin-bottom: 12px;
  font-size: 14px;
  color: var(--nerd-text);
  border-radius: 6px;
  line-height: 1.45;
}
.nerd-drill-footer {
  font-size: 11px;
  color: var(--nerd-text-3);
  font-style: italic;
  line-height: 1.5;
  letter-spacing: 0.02em;
}

/* —— Phone: card slides up from the bottom edge instead of centering ——
   Keeps the portrait visible above the sheet so the user has context. */
@media (max-width: 599px) {
  .nerd-drill { padding: 0; align-items: flex-end; }
  .nerd-drill-card {
    width: 100%;
    max-height: 88%;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
    transform: translateY(100%);
    transition: transform 240ms cubic-bezier(0.25, 0.8, 0.25, 1),
                opacity   200ms ease-out;
  }
  .nerd-drill.open .nerd-drill-card { transform: translateY(0); }
}

/* —— No-history mode (derived/ephemeris metrics) ——
   Some metrics (sun, moon, freezing level, derived thermo) don't have a
   stored time series. The card hides the sparkline + axis + 24h stats
   row and just shows label / value / readout / methodology. */
.nerd-drill-card.no-history .nerd-drill-chartwrap,
.nerd-drill-card.no-history .nerd-drill-axis,
.nerd-drill-card.no-history .nerd-drill-stats { display: none; }

@media (prefers-reduced-motion: reduce) {
  .nerd-drill-backdrop,
  .nerd-drill-card,
  .nerd-drill-close { transition: none; }
  .nerd-drill-card  { transform: none; }
}

/* —— Reduced-motion respect —— */
@media (prefers-reduced-motion: reduce) {
  .nerd-page, .app { transition: none; }
  .hero.long-pressing::after { animation: none; }
  .hero.long-pressing { transition: none; transform: none; }
}

/* ──────────────────────────────────────────────────────────────────────
   Focus styles — visible ring on keyboard nav, hidden on pointer.
   :focus-visible is the modern bifurcation (matches keyboard focus and
   :focus-within for screen readers, but not pointer focus). Outline +
   offset gives a clean ring without thrashing the element's box model. */
.nerd-close:focus-visible,
.nerd-rail-all:focus-visible,
.nerd-chip:focus-visible,
.nerd-drill-close:focus-visible {
  outline: 2px solid var(--nerd-astro);
  outline-offset: 2px;
}
/* When a chip has a per-metric accent, prefer that color for the ring */
.nerd-chip:focus-visible { outline-color: var(--accent, var(--nerd-astro)); }
.nerd-drill-card:focus-visible { outline: none; }   /* dialog itself doesn't need a ring */

/* ──────────────────────────────────────────────────────────────────────
   Drilldown on iPad-landscape — 60% width per brief.
   < 600 px  → full-width sheet (already handled above)
   600–899   → centered modal min(640, 90%)
   ≥ 900 + landscape → 60% (max 760) — matches iPad-landscape "60%" spec */
@media (min-width: 900px) and (orientation: landscape) {
  /* Use vw, not % — % computes against the .nerd-drill content box (which
     subtracts the 24 px padding on each side), so a literal "60%" came out
     at ~58 % of the viewport. vw locks the card to exactly 60 % of viewport
     width per the brief, capped at 760 px on ultra-wide displays. */
  .nerd-drill-card { width: min(60vw, 760px); }
}
