/*
 * Signal page styles — Wearables Phase G.
 *
 * Reuses the design tokens from style.css (--bg-deep, --bg-card, --accent,
 * --text-primary, --text-secondary, --text-muted, --border, etc.). Only
 * Signal-specific layout / atoms live here.
 */

/* ─── Layout ─────────────────────────────────────────────── */
.signal-main {
  max-width: 1080px;
  margin: 0 auto;
  padding: calc(var(--nav-height) + 2rem) 1.5rem 6rem;
  min-height: 100vh;
  /* Chrome offsets used by the Mandala no-scroll layout. The top
     value mirrors signal-main padding-top (nav + 2rem). The bottom
     tab bar only exists on mobile (≤640px) — desktop keeps it 0. */
  --sn-chrome-top: calc(var(--nav-height, 72px) + 2rem);
  --sn-tabbar-bottom: 0px;
}
/* Data view (state-3): height-bounded. Drop the hero's 6rem bottom
   padding and tighten the top so the Mandala panel actually fits
   inside one viewport without spawning a vertical scrollbar.
   The bottom tab bar (.signal-tabbar-bottom) is fixed at the bottom
   on all viewports, so reserve --sn-tabbar-bottom for it here. */
.signal-main.signal-main-data {
  padding-top: calc(var(--nav-height, 72px) + 0.75rem);
  padding-bottom: 0;
  min-height: 0;
  --sn-chrome-top: calc(var(--nav-height, 72px) + 0.75rem);
  --sn-tabbar-bottom: 64px;
}
/* When the data view is showing AND Mandala is the active panel,
   pin the page so it never scrolls. Bodygraph/Settings panels
   may still scroll — they don't match this `:has` selector. */
.signal-main.signal-main-data:has(.sn-mandala-view:not([hidden])) {
  height: 100vh;
  overflow: hidden;
}
/* Tuck the global footer out of the page on the Mandala tab so the
   viewport stays exactly 100vh and the page never scrolls. */
body:has(.signal-main.signal-main-data .sn-mandala-view:not([hidden])) > footer {
  display: none;
}
/* Lock the document scroll on the Mandala tab so background content
   underneath the fold can't be reached by the page. */
body:has(.signal-main.signal-main-data .sn-mandala-view:not([hidden])) {
  overflow: hidden;
}

.signal-state[hidden] { display: none; }

/* ─── Hero ───────────────────────────────────────────────── */
.signal-hero {
  text-align: center;
  margin: 1.5rem auto 4rem;
  max-width: 820px;
}

.signal-hero-title {
  font-family: 'Playfair Display', 'DM Sans', serif;
  font-size: clamp(1.9rem, 4.2vw, 3rem);
  line-height: 1.15;
  color: var(--text-primary);
  margin: 0 0 1.25rem;
  letter-spacing: -0.01em;
}

.signal-hero-sub {
  font-size: 1.125rem;
  color: var(--text-secondary);
  line-height: 1.6;
  margin: 0 auto 2.5rem;
  max-width: 620px;
}

.signal-hero-art {
  margin: 0 auto 2.5rem;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--bg-card);
  overflow: hidden;
  max-width: 720px;
}

.signal-hero-art svg {
  display: block;
  width: 100%;
  height: auto;
}

/* ─── CTAs / Buttons ─────────────────────────────────────── */
.signal-cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  justify-content: center;
  align-items: center;
}

.signal-main .signal-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.6rem 1.1rem;
  border-radius: 10px;
  border: 1px solid transparent;
  font-family: var(--sn-body);
  font-size: 0.85rem;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
  background: var(--sn-violet-2);
  color: var(--sn-text);
  border-color: var(--sn-hairline-2);
  line-height: 1.2;
  letter-spacing: 0.01em;
}
.signal-main .signal-btn:hover {
  background: var(--sn-violet-3);
}

.signal-main .signal-btn-primary {
  background: var(--sn-gold);
  color: var(--sn-night);
  border-color: var(--sn-gold);
}
.signal-main .signal-btn-primary:hover {
  background: var(--sn-amber);
  border-color: var(--sn-amber);
}

.signal-main .signal-btn-secondary {
  background: var(--sn-violet-2);
  color: var(--sn-text);
  border-color: var(--sn-hairline-2);
}

.signal-main .signal-btn-ghost {
  background: transparent;
  color: var(--sn-text-2);
  border-color: var(--sn-hairline);
}
.signal-main .signal-btn-ghost:hover {
  color: var(--sn-text);
  border-color: var(--sn-hairline-2);
}

/* ─── How it works ───────────────────────────────────────── */
.signal-section-title {
  font-family: 'Playfair Display', 'DM Sans', serif;
  font-size: 1.75rem;
  color: var(--text-primary);
  margin: 0 0 2rem;
  text-align: center;
  letter-spacing: -0.005em;
}

.signal-howitworks {
  margin: 4rem 0;
}

/* ─── Marketing feature rail (Cosmic Clock + Forecast previews) ───────
   Two-up rows: copy on one side, phone-style screenshot on the other.
   Alternates left/right on wide viewports via .sn-feature--flip. */
.sn-feature-rail {
  margin: 4rem auto;
  max-width: 1100px;
  padding: 0 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 3rem;
}
.sn-feature {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  align-items: center;
}
@media (min-width: 720px) {
  .sn-feature {
    grid-template-columns: 1fr 1fr;
    gap: 3rem;
  }
  .sn-feature--flip .sn-feature-copy { order: 2; }
  .sn-feature--flip .sn-feature-shot { order: 1; }
}
.sn-feature-copy {
  text-align: center;
}
@media (min-width: 720px) {
  .sn-feature-copy { text-align: left; }
}
.sn-feature-eyebrow {
  margin: 0 0 0.5rem;
  font-family: var(--sn-mono);
  font-size: 0.75rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sn-gold);
}
.sn-feature-title {
  margin: 0 0 0.85rem;
  font-family: 'Playfair Display', 'DM Sans', serif;
  font-size: clamp(1.5rem, 3vw, 2rem);
  line-height: 1.15;
  color: var(--sn-text, #ece6ff);
  font-weight: 500;
}
.sn-feature-body {
  margin: 0;
  font-family: var(--sn-body);
  font-size: 1rem;
  line-height: 1.55;
  color: var(--sn-text-2, #b8aee0);
  max-width: 36rem;
}
@media (min-width: 720px) {
  .sn-feature-body { margin-left: 0; }
}
.sn-feature-shot {
  display: flex;
  justify-content: center;
  align-items: center;
}
.sn-feature-shot img {
  display: block;
  width: 100%;
  max-width: 360px;
  height: auto;
  border-radius: 18px;
  border: 1px solid rgba(214, 198, 255, 0.12);
  background: #0c0917;
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.4);
}

.signal-steps {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
  max-width: 920px;
  margin: 0 auto;
}

.signal-step {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1.5rem 1.25rem;
  position: relative;
}

.signal-step h3 {
  margin: 0.5rem 0 0.5rem;
  font-size: 1.1rem;
  color: var(--text-primary);
}

.signal-step p {
  margin: 0;
  color: var(--text-secondary);
  font-size: 0.95rem;
  line-height: 1.55;
}

.signal-step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--accent-glow);
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 0.9rem;
  font-weight: 600;
}

/* ─── Provider footer (state 1) ──────────────────────────── */
.signal-providers {
  text-align: center;
  margin-top: 4rem;
  padding-top: 2rem;
  border-top: 1px solid var(--border);
}

.signal-providers-line {
  color: var(--text-muted);
  font-size: 0.85rem;
  margin: 0 0 1rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.signal-providers-row {
  display: flex;
  gap: 2rem;
  justify-content: center;
  align-items: center;
  opacity: 0.65;
}

.signal-providers-row img {
  filter: grayscale(0.3);
}

/* ─── Senary iOS design tokens (scoped to /signal page) ─────
   Matches the Claude Design Senary iOS handoff bundle. Cosmic dark
   violet surface, warm gold for positive emphasis, oxblood for
   negative, mauve/pearl for cosmic accents. Outfit for display
   headings, Plus Jakarta Sans for body, JetBrains Mono for data
   captions and the eyebrow-tracked labels. */
@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&family=Plus+Jakarta+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');

.signal-main {
  --sn-void:        #07050d;
  --sn-night:       #0c0917;
  --sn-violet:      #14102a;
  --sn-violet-2:    #1c1740;
  --sn-violet-3:    #2a2356;
  --sn-hairline:    rgba(214, 198, 255, 0.10);
  --sn-hairline-2:  rgba(214, 198, 255, 0.18);
  --sn-text:        #ece6ff;
  --sn-text-2:      #b8aee0;
  --sn-text-3:      #7a6ea3;
  --sn-text-4:      #4d4470;
  --sn-gold:        #e9b96a;
  --sn-gold-soft:   #c79a4d;
  --sn-amber:       #f3c876;
  --sn-red:         #c4504c;
  --sn-mauve:       #a489d4;
  --sn-pearl:       #d8d2ee;
  --sn-display:     'Outfit', 'DM Sans', system-ui, sans-serif;
  --sn-body:        'Plus Jakarta Sans', 'Inter', system-ui, sans-serif;
  --sn-mono:        'JetBrains Mono', 'Fira Code', ui-monospace, monospace;
  background:
    radial-gradient(ellipse at 20% 0%, rgba(122, 76, 178, 0.12), transparent 55%),
    radial-gradient(ellipse at 80% 100%, rgba(60, 30, 120, 0.16), transparent 55%),
    var(--sn-night);
  color: var(--sn-text);
  font-family: var(--sn-body);
  min-height: 100vh;
}

/* ─── Eyebrow ───────────────────────────────────────────── */
.signal-main .sn-eyebrow,
.signal-main .signal-h3 {
  font-family: var(--sn-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sn-text-3);
  margin: 0 0 0.75rem;
  font-weight: 500;
}

/* ─── Connected state header ─────────────────────────────── */
.signal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.5rem;
  margin-bottom: 2rem;
  flex-wrap: wrap;
}

.signal-page-title {
  font-family: var(--sn-display);
  font-size: clamp(2rem, 4vw, 3rem);
  font-weight: 300;
  margin: 0 0 0.4rem;
  color: var(--sn-text);
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.signal-summary {
  margin: 0;
  color: var(--sn-text-3);
  font-size: 0.85rem;
  font-family: var(--sn-mono);
  letter-spacing: 0.02em;
}

.signal-header-actions {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* ─── Inventory ("YOUR DATA") panel ────────────────────────
   Per-data-type breakdown: name on the left, days + coverage % +
   "since DATE" right-aligned in mono. Deliberately no totals row —
   the user wants to see "is sleep data complete? is activity complete?"
   not a single rolled-up number. */
.signal-inventory {
  background: var(--sn-violet);
  border: 1px solid var(--sn-hairline);
  border-radius: 14px;
  padding: 1.5rem 1.75rem;
  margin-bottom: 2rem;
}

.signal-inventory-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
}

.signal-inventory-row {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  gap: 1.25rem;
  align-items: baseline;
  font-size: 0.95rem;
  padding: 0.7rem 0;
  border-bottom: 1px dashed var(--sn-hairline);
}
.signal-inventory-row:last-child { border-bottom: 0; }

.signal-inventory-type {
  font-family: var(--sn-display);
  font-weight: 400;
  font-size: 1rem;
  color: var(--sn-text);
  text-transform: capitalize;
  letter-spacing: -0.01em;
}
.signal-inventory-meta {
  color: var(--sn-text-2);
  font-family: var(--sn-mono);
  font-size: 0.8rem;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

@media (max-width: 600px) {
  .signal-inventory-row {
    grid-template-columns: 1fr;
    gap: 0.1rem;
  }
}

/* ─── Controls ───────────────────────────────────────────── */
.signal-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 1.5rem;
  margin-bottom: 1rem;
}

.signal-control-group {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.signal-main .signal-control-group label {
  font-family: var(--sn-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sn-text-3);
  font-weight: 500;
}

.signal-main .signal-control-group select {
  background: var(--sn-violet);
  color: var(--sn-text);
  border: 1px solid var(--sn-hairline-2);
  border-radius: 8px;
  padding: 0.5rem 0.75rem;
  font-family: var(--sn-body);
  font-size: 0.9rem;
  min-width: 160px;
}

.signal-main .signal-segment {
  display: inline-flex;
  background: var(--sn-violet);
  border: 1px solid var(--sn-hairline);
  border-radius: 10px;
  overflow: hidden;
}

.signal-main .signal-seg-btn {
  background: transparent;
  color: var(--sn-text-2);
  border: 0;
  padding: 0.55rem 1rem;
  cursor: pointer;
  font-family: var(--sn-body);
  font-size: 0.85rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  border-right: 1px solid var(--sn-hairline);
  transition: background 0.12s ease, color 0.12s ease;
}
.signal-main .signal-seg-btn:last-child { border-right: 0; }
.signal-main .signal-seg-btn:hover { background: var(--sn-violet-2); color: var(--sn-text); }
.signal-main .signal-seg-btn.active {
  background: var(--sn-gold);
  color: var(--sn-night);
}

.signal-main .signal-overlay-chips {
  margin-left: auto;
}

.signal-main .signal-chips {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}

.signal-main .signal-chip {
  background: rgba(184, 174, 224, 0.06);
  border: 1px solid var(--sn-hairline);
  color: var(--sn-text-2);
  border-radius: 999px;
  padding: 0.35rem 0.85rem;
  font-size: 0.78rem;
  cursor: pointer;
  font-family: var(--sn-body);
  font-weight: 500;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.signal-main .signal-chip:hover {
  color: var(--sn-text);
  border-color: var(--sn-hairline-2);
}
.signal-main .signal-chip.active {
  background: rgba(233, 185, 106, 0.12);
  color: var(--sn-gold);
  border-color: var(--sn-gold);
}

/* ─── Chart host ─────────────────────────────────────────── */
.signal-chart-host {
  position: relative;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1rem;
  min-height: 360px;
  overflow: hidden;
}

.signal-chart-svg {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  cursor: grab;
}
.signal-chart-svg.dragging { cursor: grabbing; }

.signal-chart-svg svg {
  display: block;
  background: transparent;
}

.signal-chart-empty {
  position: absolute;
  inset: 1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  font-size: 0.95rem;
  text-align: center;
  pointer-events: none;
}
.signal-chart-empty[hidden] { display: none; }
.signal-state[hidden] { display: none; }
.signal-data[hidden],
.signal-backfill[hidden],
.signal-empty[hidden],
.signal-loading[hidden] { display: none; }

/* ─── Backfill progress ──────────────────────────────────── */
.signal-backfill {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 3rem 2rem 2.5rem;
  max-width: 540px;
  margin: 4rem auto;
  text-align: center;
}

.signal-backfill-icon {
  position: relative;
  width: 64px;
  height: 64px;
  margin: 0 auto 1.5rem;
}
.signal-backfill-orbit {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 1px solid rgba(196, 154, 108, 0.25);
  border-top-color: var(--accent);
  animation: signal-orbit 1.6s linear infinite;
}
.signal-backfill-core {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 18px rgba(196, 154, 108, 0.55);
  animation: signal-pulse 2s ease-in-out infinite;
}
@keyframes signal-orbit {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

.signal-backfill-line {
  color: var(--text-secondary);
  font-family: var(--font-mono);
  font-size: 0.92rem;
  margin: 0.5rem 0 1.5rem;
  line-height: 1.5;
}
.signal-backfill-line [data-bf-fetched],
.signal-backfill-line [data-bf-type] {
  color: var(--text-primary);
  font-weight: 500;
}
.signal-backfill-sep {
  color: var(--text-muted);
  margin: 0 0.5em;
}

.signal-backfill-pct {
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 0.85rem;
  margin: 0.5rem 0 0;
  letter-spacing: 0.05em;
}

.signal-progress-bar {
  position: relative;
  height: 4px;
  background: var(--bg-surface);
  border-radius: 999px;
  overflow: hidden;
  margin: 1rem auto 0.5rem;
  max-width: 320px;
}
.signal-progress-bar > span {
  display: block;
  height: 100%;
  background: var(--accent);
  transition: width 0.4s ease;
  border-radius: 999px;
}

/* Indeterminate variant for the compute substate (no measurable %). */
.signal-progress-bar--indeterminate {
  background: var(--bg-surface);
}
.signal-progress-shimmer {
  position: absolute;
  top: 0;
  left: -40%;
  width: 40%;
  height: 100%;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(196, 154, 108, 0.85) 50%,
    transparent 100%
  );
  border-radius: 999px;
  animation: signal-shimmer 1.5s ease-in-out infinite;
}
@keyframes signal-shimmer {
  0%   { left: -40%; }
  100% { left: 100%; }
}

/* Compute substate icon: nested pulse rings */
.signal-compute-icon {
  width: 72px;
  height: 72px;
}
.signal-compute-pulse {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  border-radius: 50%;
  border: 1px solid var(--accent);
  opacity: 0;
  animation: signal-compute-pulse 2.4s ease-out infinite;
}
.signal-compute-pulse--1 { animation-delay: 0s; }
.signal-compute-pulse--2 { animation-delay: 0.8s; }
.signal-compute-pulse--3 { animation-delay: 1.6s; }
@keyframes signal-compute-pulse {
  0%   { transform: scale(1);   opacity: 0.85; }
  100% { transform: scale(4.5); opacity: 0;    }
}

/* iOS-style activity spinner (12 rotating spokes). Used for the
   "Calculating your insights" gate that blocks the first card draw
   until the candidate pool has ≥3 insights. Warm-gold accent matches
   the rest of the Cosmic Pulse palette. */
.signal-ios-spinner {
  position: relative;
  width: 56px;
  height: 56px;
  margin: 0 auto 1.75rem;
  color: var(--accent, #c49a6c);
}
.signal-ios-spinner-spoke {
  position: absolute;
  top: 0;
  left: 50%;
  width: 4px;
  height: 14px;
  margin-left: -2px;
  border-radius: 2px;
  background: currentColor;
  transform-origin: 50% 28px;
  opacity: 0.15;
  animation: signal-ios-spinner-fade 1s linear infinite;
}
/* 12 spokes, 30° apart. Staggered animation delays so the brightest
   spoke walks around the wheel. Visually identical to UIActivityIndicator. */
.signal-ios-spinner-spoke:nth-child(1)  { transform: rotate(0deg);   animation-delay: -1.0000s; }
.signal-ios-spinner-spoke:nth-child(2)  { transform: rotate(30deg);  animation-delay: -0.9167s; }
.signal-ios-spinner-spoke:nth-child(3)  { transform: rotate(60deg);  animation-delay: -0.8333s; }
.signal-ios-spinner-spoke:nth-child(4)  { transform: rotate(90deg);  animation-delay: -0.7500s; }
.signal-ios-spinner-spoke:nth-child(5)  { transform: rotate(120deg); animation-delay: -0.6667s; }
.signal-ios-spinner-spoke:nth-child(6)  { transform: rotate(150deg); animation-delay: -0.5833s; }
.signal-ios-spinner-spoke:nth-child(7)  { transform: rotate(180deg); animation-delay: -0.5000s; }
.signal-ios-spinner-spoke:nth-child(8)  { transform: rotate(210deg); animation-delay: -0.4167s; }
.signal-ios-spinner-spoke:nth-child(9)  { transform: rotate(240deg); animation-delay: -0.3333s; }
.signal-ios-spinner-spoke:nth-child(10) { transform: rotate(270deg); animation-delay: -0.2500s; }
.signal-ios-spinner-spoke:nth-child(11) { transform: rotate(300deg); animation-delay: -0.1667s; }
.signal-ios-spinner-spoke:nth-child(12) { transform: rotate(330deg); animation-delay: -0.0833s; }
@keyframes signal-ios-spinner-fade {
  0%   { opacity: 1; }
  100% { opacity: 0.15; }
}

/* Smooth fade between compute substate and the deck UI once the pool
   reaches the 3-insight threshold. Both share #signal-state-3 so the
   transition is just opacity. */
#signal-compute {
  transition: opacity 0.35s ease-out;
}
#signal-compute.is-fading-out {
  opacity: 0;
  pointer-events: none;
}
#signal-data {
  transition: opacity 0.35s ease-in;
}
#signal-data.is-fading-in {
  opacity: 0;
}
#signal-data.is-fading-in.is-visible {
  opacity: 1;
}

/* ─── Empty state (3c) ───────────────────────────────────── */
.signal-empty {
  text-align: center;
  padding: 4rem 2rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 12px;
  margin-top: 2rem;
}
.signal-empty h2 {
  font-family: 'Playfair Display', 'DM Sans', serif;
  font-size: 1.6rem;
  color: var(--text-primary);
  margin: 0 0 0.75rem;
}
.signal-empty p {
  color: var(--text-secondary);
  margin: 0 auto 1.5rem;
  max-width: 480px;
}

/* ─── Loading splash ─────────────────────────────────────── */
.signal-loading {
  text-align: center;
  padding: 6rem 1rem;
}
.signal-loading-pulse {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--accent);
  margin: 0 auto 1rem;
  opacity: 0.6;
  animation: signal-pulse 1.4s ease-in-out infinite;
}
@keyframes signal-pulse {
  0%, 100% { transform: scale(0.85); opacity: 0.4; }
  50%      { transform: scale(1.05); opacity: 0.85; }
}

.signal-muted { color: var(--text-muted); font-size: 0.9rem; }

.signal-footnote {
  margin: 3rem 0 0;
  text-align: center;
  color: var(--text-muted);
  font-size: 0.85rem;
}
.signal-footnote a { color: var(--accent); text-decoration: none; }
.signal-footnote a:hover { text-decoration: underline; }

/* ─── Chart overlay element styles ───────────────────────── */
.sg-curve { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.sg-area  { fill: var(--accent-glow); stroke: none; opacity: 0.55; }
.sg-dot   { fill: var(--accent); }
.sg-axis  { stroke: var(--border); stroke-width: 0.5; }
.sg-axis-text { fill: var(--text-muted); font-size: 10px; font-family: 'JetBrains Mono', monospace; }
.sg-grid  { stroke: var(--border); stroke-width: 0.4; opacity: 0.6; }

.sg-moon-marker  { fill: var(--text-secondary); }
.sg-moon-full    { fill: var(--text-primary); stroke: var(--text-primary); }
.sg-moon-new     { fill: var(--bg-deep); stroke: var(--text-secondary); }
.sg-moon-quarter { stroke: var(--text-muted); stroke-width: 0.6; }
.sg-moon-label   { fill: var(--text-muted); font-size: 9px; font-family: 'JetBrains Mono', monospace; }

.sg-retro-bar    { opacity: 0.7; rx: 1; }
.sg-retro-label  { font-size: 9px; font-family: 'JetBrains Mono', monospace; }

.sg-sign-band    { opacity: 0.45; }
.sg-sign-glyph   { fill: var(--text-primary); font-size: 11px; text-anchor: middle; font-family: serif; }

/* Provider color palette (used for retrograde rows + tooltips) */
.sg-planet-mercury { fill: #b08bc8; color: #b08bc8; }
.sg-planet-venus   { fill: #e8a838; color: #e8a838; }
.sg-planet-mars    { fill: #c83838; color: #c83838; }
.sg-planet-jupiter { fill: #c49a6c; color: #c49a6c; }
.sg-planet-saturn  { fill: #88c888; color: #88c888; }
.sg-planet-uranus  { fill: #3888c8; color: #3888c8; }
.sg-planet-neptune { fill: #5a8ad9; color: #5a8ad9; }
.sg-planet-pluto   { fill: #8a6d4d; color: #8a6d4d; }

/* ─── Phase H: View switcher + new view panels ───────────── */
.signal-view-switcher {
  display: flex;
  gap: 1rem;
  align-items: flex-end;
  flex-wrap: wrap;
  justify-content: space-between;
  margin: 0.5rem 0 1.25rem;
}

.signal-view-tabs .signal-seg-btn {
  font-family: 'Playfair Display', 'DM Sans', serif;
  font-size: 0.95rem;
  letter-spacing: 0;
  padding: 0.55rem 1rem;
}

.signal-metric-picker {
  margin-left: auto;
}

/* Force-hide non-active view panels. The `!important` defeats any
   layout rule (flex, grid, or `display:` on a more specific selector)
   that might otherwise keep the Bodygraph SVG / Settings list / etc.
   visible after the Transit tab has been switched in. */
.signal-view[hidden] { display: none !important; }

/* ─── Aggregate view ─────────────────────────────────────── */
.signal-aggregate-host { min-height: 360px; }

.signal-aggregate-note {
  margin: 0.75rem 0 0;
  color: var(--text-muted);
  font-size: 0.85rem;
  font-family: var(--font-mono);
}

.signal-aggregate-svg {
  width: 100%;
  display: block;
}

.sg-bar       { fill: var(--accent); transition: opacity 0.15s; }
.sg-bar:hover { opacity: 0.85; }
.sg-bar-low   { fill: var(--text-muted); opacity: 0.45; }
.sg-bar-track { fill: var(--bg-surface); }
.sg-bar-label { fill: var(--text-secondary); font-size: 11px; font-family: var(--font-mono); }
.sg-bar-value { fill: var(--text-primary); font-size: 11px; font-family: var(--font-mono); }
.sg-bar-baseline { stroke: var(--text-muted); stroke-dasharray: 3 3; stroke-width: 0.8; }

/* Radial spokes for moon-sign / sun-sign axes */
.sg-spoke      { stroke: var(--accent); stroke-linecap: round; }
.sg-spoke-low  { stroke: var(--text-muted); stroke-linecap: round; opacity: 0.5; }
.sg-spoke-rim  { fill: none; stroke: var(--border); stroke-width: 0.6; }
.sg-spoke-tick { stroke: var(--border); stroke-width: 0.4; }
.sg-spoke-label { fill: var(--text-secondary); font-size: 11px; font-family: var(--font-mono); text-anchor: middle; }
.sg-spoke-mean { fill: var(--text-primary); font-size: 10px; font-family: var(--font-mono); text-anchor: middle; }

/* ─── Outliers (constellation) view ──────────────────────── */
.signal-outliers-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
  margin: 1rem 0;
}
@media (max-width: 720px) {
  .signal-outliers-grid { grid-template-columns: 1fr; }
}

.signal-wheel-host { padding: 1.25rem; }
.signal-wheel-host h3 { margin: 0 0 0.75rem; }
.signal-wheel-svg svg { width: 100%; height: auto; }

.sg-wheel-rim   { fill: none; stroke: var(--border); stroke-width: 0.8; }
.sg-wheel-zod   { fill: none; stroke: var(--border-light); stroke-width: 0.5; }
.sg-wheel-gate  { fill: none; stroke: var(--border); stroke-width: 0.4; opacity: 0.6; }
.sg-wheel-label { fill: var(--text-secondary); font-size: 11px; font-family: var(--font-mono); text-anchor: middle; }
.sg-wheel-marker        { fill: var(--accent); stroke: var(--bg-deep); stroke-width: 1; }
.sg-wheel-marker-trans  { fill: var(--accent-dim, var(--accent)); stroke: var(--bg-deep); stroke-width: 1; opacity: 0.85; }
.sg-wheel-badge {
  fill: var(--text-primary);
  font-size: 9px;
  font-family: var(--font-mono);
  text-anchor: middle;
}
.sg-wheel-trans-line { stroke: var(--text-muted); stroke-width: 0.6; opacity: 0.7; stroke-dasharray: 2 2; }

.signal-outliers-tables {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
  margin-top: 0.5rem;
}
@media (max-width: 720px) {
  .signal-outliers-tables { grid-template-columns: 1fr; }
}

.signal-outliers-table {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1rem 1.25rem;
}
.signal-outliers-table h4 {
  margin: 0 0 0.5rem;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  font-family: var(--font-mono);
}
.signal-outliers-table table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}
.signal-outliers-table th,
.signal-outliers-table td {
  text-align: left;
  padding: 0.3rem 0.5rem;
  border-bottom: 1px dashed var(--border);
  color: var(--text-secondary);
  font-family: var(--font-mono);
}
.signal-outliers-table th {
  color: var(--text-muted);
  font-weight: 500;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* ─── Outlier Bodygraph view ─────────────────────────────── */
.signal-bg-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.25rem;
  margin: 1rem 0;
}
@media (max-width: 900px) {
  .signal-bg-grid { grid-template-columns: 1fr; }
}

.signal-bg-host { padding: 1rem; }
.signal-bg-host h3 { margin: 0 0 0.5rem; }
.signal-bg-svg svg { width: 100%; height: auto; max-height: 540px; }

.signal-bg-cta {
  text-align: center;
  margin: 1rem 0 0;
  color: var(--text-muted);
  font-size: 0.9rem;
}
.signal-bg-cta a { color: var(--accent); text-decoration: none; }
.signal-bg-cta a:hover { text-decoration: underline; }

/* Bodygraph gate-shading layer */
.sg-bg-gate         { fill: var(--bg-surface); transition: fill 0.15s; }
.sg-bg-gate-h1      { fill: rgba(196, 154, 108, 0.25); }
.sg-bg-gate-h2      { fill: rgba(196, 154, 108, 0.50); }
.sg-bg-gate-h3      { fill: rgba(196, 154, 108, 0.75); }
.sg-bg-gate-h4      { fill: rgba(196, 154, 108, 1.00); }
.sg-bg-channel-line { stroke: var(--text-muted); stroke-width: 1.5; opacity: 0.45; }
.sg-bg-channel-active {
  stroke: var(--accent);
  stroke-width: 3;
  opacity: 0.95;
  filter: drop-shadow(0 0 3px var(--accent));
}
.sg-bg-channel-natal {
  stroke: #88c888;
  stroke-width: 3;
  opacity: 0.95;
  filter: drop-shadow(0 0 3px #88c888);
}

/* ──────────────────────────────────────────────────────────
   Senary iOS — Mandala tab
   Cosmic dark-violet palette, ported from the Senary iOS
   design package (claude.ai/design). Scoped so it doesn't
   bleed into the rest of the Signal page.
   ────────────────────────────────────────────────────────── */
@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&family=Plus+Jakarta+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');

.sn-mandala-view {
  /* Senary tokens scoped to the Mandala view */
  --sn-void:       #07050d;
  --sn-night:      #0c0917;
  --sn-violet:     #14102a;
  --sn-violet-2:   #1c1740;
  --sn-violet-3:   #2a2356;
  --sn-hairline:   rgba(214, 198, 255, 0.10);
  --sn-hairline-2: rgba(214, 198, 255, 0.18);
  --sn-text:       #ece6ff;
  --sn-text-2:     #b8aee0;
  --sn-text-3:     #7a6ea3;
  --sn-text-4:     #4d4470;
  --sn-gold:       #e9b96a;
  --sn-gold-soft:  #c79a4d;
  --sn-gold-glow:  rgba(233, 185, 106, 0.55);
  --sn-amber:      #f3c876;
  --sn-red:        #c4504c;
  --sn-red-glow:   rgba(196, 80, 76, 0.5);
  --sn-mauve:      #a489d4;
  --sn-pearl:      #d8d2ee;

  --sn-display: 'Outfit', 'Playfair Display', system-ui, sans-serif;
  --sn-body:    'Plus Jakarta Sans', 'Inter', system-ui, sans-serif;
  --sn-mono:    'JetBrains Mono', ui-monospace, monospace;

  position: relative;
  background:
    radial-gradient(ellipse at 20% 0%, rgba(122, 76, 178, 0.22), transparent 55%),
    radial-gradient(ellipse at 80% 100%, rgba(60, 30, 120, 0.28), transparent 55%),
    linear-gradient(180deg, #0c0917 0%, #07050d 100%);
  border-radius: 18px;
  padding: 0;
  overflow: hidden;
  isolation: isolate;
}

.sn-mandala-view .sn-mandala-stars {
  position: absolute; inset: 0; opacity: 0.32; pointer-events: none;
  background-image:
    radial-gradient(1px 1px at 12% 18%, rgba(255,255,255,0.5), transparent 60%),
    radial-gradient(1px 1px at 28% 64%, rgba(255,255,255,0.35), transparent 60%),
    radial-gradient(1.2px 1.2px at 44% 22%, rgba(233,185,106,0.5), transparent 60%),
    radial-gradient(1px 1px at 62% 80%, rgba(255,255,255,0.4), transparent 60%),
    radial-gradient(1px 1px at 76% 36%, rgba(255,255,255,0.3), transparent 60%),
    radial-gradient(1px 1px at 88% 12%, rgba(255,255,255,0.45), transparent 60%),
    radial-gradient(1px 1px at 8% 88%, rgba(255,255,255,0.3), transparent 60%),
    radial-gradient(1px 1px at 52% 50%, rgba(184,174,224,0.35), transparent 60%);
}

.sn-mandala-card {
  position: relative;
  z-index: 1;
  padding: 1.5rem 1.75rem 1.75rem;
  max-width: 560px;
  margin: 0 auto;
}

.sn-mandala-view .sn-eyebrow {
  display: block;
  font-family: var(--sn-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sn-text-3);
  margin: 0 0 0.75rem;
}
.sn-mandala-view .sn-eyebrow-section { margin-top: 1.5rem; margin-bottom: 0.5rem; }

/* Pole toggle (Your highs / Your lows) */
.sn-mandala-view .sn-pole-toggle {
  display: flex;
  padding: 4px;
  border-radius: 14px;
  background: rgba(20,16,42,0.55);
  border: 1px solid var(--sn-hairline-2);
  margin-bottom: 1.4rem;
}
.sn-mandala-view .sn-pole-btn {
  flex: 1;
  text-align: center;
  padding: 9px 0;
  border-radius: 10px;
  background: transparent;
  border: none;
  font-family: var(--sn-display);
  font-weight: 500;
  font-size: 13px;
  color: var(--sn-text-2);
  letter-spacing: 0.2px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, box-shadow 0.15s;
}
.sn-mandala-view .sn-pole-btn[data-pole="positive"].active {
  background: rgba(233,185,106,0.18);
  color: var(--sn-gold);
  box-shadow: inset 0 0 0 1px var(--sn-gold);
}
.sn-mandala-view .sn-pole-btn[data-pole="negative"].active {
  background: rgba(196,80,76,0.18);
  color: var(--sn-red);
  box-shadow: inset 0 0 0 1px var(--sn-red);
}

/* Headline */
.sn-mandala-view .sn-headline {
  font-family: var(--sn-display);
  font-size: 22px;
  font-weight: 300;
  color: var(--sn-text);
  line-height: 1.25;
  letter-spacing: -0.3px;
  text-wrap: balance;
  margin: 0 0 0.65rem;
}
.sn-mandala-view .sn-headline .sn-sign-pos { color: var(--sn-gold); font-weight: 700; }
.sn-mandala-view .sn-headline .sn-sign-neg { color: var(--sn-red);  font-weight: 700; }

/* Pattern strength pill + readout link */
.sn-mandala-view .sn-pattern-meta {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 0.5rem;
  flex-wrap: wrap;
}
.sn-mandala-view .sn-pattern-pill {
  padding: 3px 9px;
  border-radius: 10px;
  font-family: var(--sn-mono);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 1.4px;
  text-transform: uppercase;
}
.sn-mandala-view[data-active-pole="positive"] .sn-pattern-pill {
  background: rgba(233,185,106,0.15);
  border: 1px solid var(--sn-gold);
  color: var(--sn-gold);
}
.sn-mandala-view[data-active-pole="negative"] .sn-pattern-pill {
  background: rgba(196,80,76,0.18);
  border: 1px solid var(--sn-red);
  color: var(--sn-red);
}
.sn-mandala-view .sn-pattern-readout {
  font-family: var(--sn-mono);
  font-size: 10px;
  color: var(--sn-text-3);
}

/* Mandala stage */
.sn-mandala-view .sn-mandala-stage {
  display: flex; justify-content: center;
  padding: 1rem 0 0.5rem;
}
.sn-mandala-view .sn-mandala-stage svg { display: block; overflow: visible; max-width: 100%; }

/* Chip row */
.sn-mandala-view .sn-chip-row {
  display: block;
  padding: 0.75rem 0 1rem;
}
.sn-mandala-view .sn-chip-label {
  margin: 0 0 0.5rem;
}
.sn-mandala-view .sn-chip-list {
  display: flex; gap: 8px;
  flex-wrap: wrap;
}
.sn-mandala-view .sn-chip {
  padding: 7px 13px;
  border-radius: 18px;
  background: rgba(20,16,42,0.5);
  border: 1px solid var(--sn-hairline-2);
  font-family: var(--sn-display);
  font-size: 12px;
  font-weight: 500;
  color: var(--sn-text-2);
  white-space: nowrap;
  cursor: default;
}
.sn-mandala-view .sn-chip.muted {
  opacity: 0.45;
}
.sn-mandala-view[data-active-pole="positive"] .sn-chip.active {
  background: rgba(233,185,106,0.16);
  border-color: var(--sn-gold);
  color: var(--sn-gold);
}
.sn-mandala-view[data-active-pole="negative"] .sn-chip.active {
  background: rgba(196,80,76,0.16);
  border-color: var(--sn-red);
  color: var(--sn-red);
}

/* Narrative */
.sn-mandala-view .sn-narrative {
  font-family: var(--sn-body);
  font-size: 14px;
  color: var(--sn-text-2);
  line-height: 1.55;
  margin: 0;
}

/* Natal placements card */
.sn-mandala-view .sn-natal-card {
  margin-top: 1rem;
  padding: 14px;
  background: rgba(20,16,42,0.5);
  border: 1px solid var(--sn-hairline-2);
  border-radius: 14px;
}
.sn-mandala-view .sn-natal-head { margin-bottom: 8px; }
.sn-mandala-view .sn-natal-row {
  display: flex; gap: 10px;
  padding: 7px 0;
  border-top: 0.5px solid var(--sn-hairline);
}
.sn-mandala-view .sn-natal-row:first-child { border-top: 0.5px solid var(--sn-hairline-2); }
.sn-mandala-view .sn-natal-glyph {
  font-family: var(--sn-mono);
  font-size: 12px;
  width: 16px;
}
.sn-mandala-view[data-active-pole="positive"] .sn-natal-glyph { color: var(--sn-gold); }
.sn-mandala-view[data-active-pole="negative"] .sn-natal-glyph { color: var(--sn-red); }
.sn-mandala-view .sn-natal-tag {
  font-family: var(--sn-mono);
  font-size: 9px;
  color: var(--sn-text-3);
  letter-spacing: 1.2px;
  width: 50px;
  padding-top: 2px;
}
.sn-mandala-view .sn-natal-detail {
  font-family: var(--sn-mono);
  font-size: 11px;
  color: var(--sn-text-2);
}

/* Mandala SVG strokes / styles */
.sn-mandala-view .sn-spoke   { stroke: var(--sn-hairline-2); stroke-width: 0.5; }
.sn-mandala-view .sn-rim     { stroke: var(--sn-hairline-2); stroke-width: 0.6; fill: none; }
.sn-mandala-view .sn-rim-2   { stroke: var(--sn-hairline);   stroke-width: 0.5; fill: none; }
.sn-mandala-view .sn-tick    { stroke: var(--sn-hairline);   stroke-width: 0.4; }
.sn-mandala-view .sn-tick-major { stroke: var(--sn-text-3);  stroke-width: 0.6; }
.sn-mandala-view .sn-glyph   { font-family: 'Apple Color Emoji', 'Segoe UI Symbol', sans-serif; font-size: 16px; }
.sn-mandala-view .sn-center-label-top {
  font-family: var(--sn-mono);
  font-size: 9px;
  fill: var(--sn-text-3);
  letter-spacing: 2px;
}
.sn-mandala-view .sn-center-label-bottom {
  font-family: var(--sn-display);
  font-size: 14px;
  font-weight: 500;
  /* Default readable fill. The pole toggle on the legacy .sn-mandala-view
     used [data-active-pole] to tint these; the deck-view dropped that
     attribute, so without this default the SVG <text> falls back to
     black. Inline `fill` in drawSenaryMandala overrides per pole. */
  fill: var(--sn-text);
}
/* [Eva 2026-05-26 — iOS card port] Dominant-sign glyph above the
   center sign name. Slightly bigger than the rim glyphs so it reads
   as the focal point of the wheel. Filled by inline style in
   drawSenaryMandala so it tracks the cluster / pole color.
   `Segoe UI Symbol` + `sans-serif` are listed BEFORE color-emoji
   fonts so the glyph renders as a monochrome shape that honors the
   `fill` inline style (color-emoji fonts ignore fill on macOS). */
.sn-mandala-view .sn-center-glyph {
  font-family: 'Segoe UI Symbol', 'Noto Sans Symbols', sans-serif;
  font-size: 20px;
  font-weight: 400;
  fill: var(--sn-text);
}
.sn-mandala-view[data-active-pole="positive"] .sn-center-label-bottom { fill: var(--sn-gold); }
.sn-mandala-view[data-active-pole="negative"] .sn-center-label-bottom { fill: var(--sn-red); }

/* ─────────────────────────────────────────────────────────────────────
   DECK / CARD-DRAW UX (Mandala tab) — ported from iOS:
     ios/HumanDesign/Views/Mandala/Card/*
   Shapes: cusp-cornered card frames (CSS clip-path), gold double strokes,
   mauve halo behind hero card, dark violet weave on backs.
   ──────────────────────────────────────────────────────────────────── */

.signal-main {
  /* Oxblood for the negative-pole accent (mirrors iOS Color.oxblood). */
  --sn-oxblood: #c4504c;
  /* Deeper violet card fill, matches iOS RevealedCardView fillColor. */
  --sn-card-fill: #1a1232;

  /* v5 three-cluster colour tokens. Used by the cluster sliver, polarity
     arrow tint, planet glyph tint, mandala wheel sign-segment fill, and
     the metric-names footer pill. */
  --sn-cluster-activity:  #f0735a;   /* warm coral */
  --sn-cluster-sleep:     #3fc9d6;   /* cyan / turquoise */
  --sn-cluster-recovery:  #b07cff;   /* luminous violet */
}

/* v5 cluster tab: a protruding folder-tab silhouette sitting ABOVE the
   card frame, centered, ~70% of card width. Mirrors the iOS
   RevealedCardView cluster tab — the tab IS the cluster identity surface
   (hero icon + cluster name caption live on top of it). Bottom edge sits
   flush with the card top edge so it reads as one continuous shape; top
   corners are rounded to give it a folder-tab silhouette.

   The card frame uses `overflow:visible` (see `.sn-revealed-card.sn-rc-rich`)
   so the tab can protrude above the frame without being clipped. The tab
   itself has `pointer-events:none` so it doesn't intercept taps on the
   hero icon / cluster label that sit on top of it. */
.sn-revealed-card[data-card-cluster] .sn-rc-cluster-sliver {
  position: absolute;
  top: -18px;
  left: 50%;
  transform: translateX(-50%);
  width: 70%;
  max-width: 224px;
  height: 28px;
  border-radius: 10px 10px 0 0;
  z-index: 4;
  pointer-events: none;
  box-shadow: 0 -2px 6px rgba(0, 0, 0, 0.35),
              inset 0 -1px 0 rgba(0, 0, 0, 0.18);
}
.sn-revealed-card[data-card-cluster="activity"] .sn-rc-cluster-sliver { background: var(--sn-cluster-activity); }
.sn-revealed-card[data-card-cluster="sleep"]    .sn-rc-cluster-sliver { background: var(--sn-cluster-sleep); }
.sn-revealed-card[data-card-cluster="recovery"] .sn-rc-cluster-sliver { background: var(--sn-cluster-recovery); }

/* v5 polarity arrow tint. The arrow glyph (↑ or ↓) inherits the cluster
   colour so direction reads at a glance without text labels. */
.sn-revealed-card[data-card-cluster="activity"] .sn-rc-polarity-arrow { color: var(--sn-cluster-activity); }
.sn-revealed-card[data-card-cluster="sleep"]    .sn-rc-polarity-arrow { color: var(--sn-cluster-sleep); }
.sn-revealed-card[data-card-cluster="recovery"] .sn-rc-polarity-arrow { color: var(--sn-cluster-recovery); }

.sn-rc-polarity-arrow {
  /* [Fix 2026-05-25 Bug 4] Shrunk from 2.4rem to 1.4rem (~19px at the
     16px base) so the glyph sits cleanly inside the 20px-tall eyebrow
     row instead of overflowing into the cluster sliver above. */
  font-size: 1.4rem;
  line-height: 1;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  margin-right: 0.4rem;
}
.sn-rc-cluster-icon {
  /* [Fix 2026-05-25 Bug 4] Shrunk from 28px to 18px so the icon fits
     the 20px-tall eyebrow row. */
  width: 18px;
  height: 18px;
  object-fit: contain;
  display: inline-block;
  vertical-align: middle;
}
/* [Fix 2026-05-25 Bug 1] Hero cluster icon — absolutely positioned over
   the cluster sliver at the top of the card. Centered horizontally,
   pulled up so the icon visually overlaps and dominates the sliver.
   Eva's directive: cluster identity must be the boldest glyph on the
   card; the planet glyph moved to the meta-line below the headline.

   Source PNGs are solid-black silhouettes. The CSS filter stack
   `brightness(0) invert(1)` paints them white so they read on the
   dark card body. Per-cluster colour overrides land below to retint
   the silhouette in the cluster hue. */
.sn-rc-cluster-icon--hero {
  /* Sits centered ON the protruding cluster tab (which spans top:-18px
     to top:+10px). Icon centered within the tab so it reads as the
     dominant glyph anchored to the tab. Tinted to deep navy by the
     per-cluster filter rules below so it pops on the saturated tab
     background. */
  position: absolute;
  top: -14px;
  left: calc(50% - 60px);
  transform: translateX(-50%);
  width: 22px;
  height: 22px;
  z-index: 6;
  pointer-events: none;
  filter:
    drop-shadow(0 1px 2px rgba(0, 0, 0, 0.45))
    brightness(0);
}
/* Per-cluster tint. With the cluster tab redesign the hero icon sits
   ON the saturated tab background — so the silhouette renders in deep
   navy (the tab's text color) instead of the cluster hue, mirroring
   iOS RevealedCardView where the cluster sliver icon is painted in
   bgDeep. The per-cluster filters become identical (all → deep navy);
   we keep the selectors so any future per-cluster tint variation has
   an existing hook to land on. */
.sn-revealed-card[data-card-cluster="activity"] .sn-rc-cluster-icon--hero,
.sn-revealed-card[data-card-cluster="sleep"] .sn-rc-cluster-icon--hero,
.sn-revealed-card[data-card-cluster="recovery"] .sn-rc-cluster-icon--hero {
  filter:
    drop-shadow(0 1px 2px rgba(0, 0, 0, 0.35))
    brightness(0);
}

/* [Fix 2026-05-25 Bug 2] Cluster name caption sitting directly below the
   hero icon. Letter-spaced caps in the cluster colour. Eva's directive:
   the card must identify its cluster at a glance without reading body
   copy, so the cluster name rides next to the icon as a visible label.
   The icon hovers at top:-12 with height:32 (bottom edge ~y=20). The
   label sits below the icon, centred over the sliver region, occupying
   the gap between the icon and the headline at y=42. */
.sn-rc-cluster-label {
  /* Cluster name caption sitting on the protruding tab, next to the
     hero icon. Painted in deep navy (the tab's text color) so it pops
     on the saturated cluster-color tab background. Mirrors iOS where
     the cluster sliver shows the name in bgDeep. */
  position: absolute;
  top: -12px;
  left: calc(50% + 6px);
  z-index: 6;
  pointer-events: none;
  font-family: var(--sn-mono, monospace);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  white-space: nowrap;
  color: #0a0a17;
}
/* Override the previous per-cluster colour rules — the label is always
   deep navy on the tab now. Keeping explicit selectors so any future
   per-cluster tint experiment has a hook. */
.sn-revealed-card[data-card-cluster="activity"] .sn-rc-cluster-label,
.sn-revealed-card[data-card-cluster="sleep"] .sn-rc-cluster-label,
.sn-revealed-card[data-card-cluster="recovery"] .sn-rc-cluster-label {
  color: #0a0a17;
}
/* Legacy planet glyph (eyebrow row) — kept for any non-v5 layout that
   still inserts it. v5 card render no longer appends this element. */
.sn-rc-planet-glyph {
  font-size: 1.2rem;
  line-height: 1;
}
.sn-revealed-card[data-card-cluster="activity"] .sn-rc-planet-glyph { color: var(--sn-cluster-activity); }
.sn-revealed-card[data-card-cluster="sleep"]    .sn-rc-planet-glyph { color: var(--sn-cluster-sleep); }
.sn-revealed-card[data-card-cluster="recovery"] .sn-rc-planet-glyph { color: var(--sn-cluster-recovery); }

/* [Fix 2026-05-25 Bug 1] Meta-line planet glyph (♀, ♂, ☿, etc.) sitting
   just before the bold planet name. Tuned smaller than the eyebrow
   version because it lives next to running text. */
.sn-meta-planet-glyph {
  font-size: 1.1em;
  line-height: 1;
  margin-right: 1px;
  opacity: 0.95;
}
.sn-revealed-card[data-card-cluster="activity"] .sn-meta-planet-glyph { color: var(--sn-cluster-activity); }
.sn-revealed-card[data-card-cluster="sleep"]    .sn-meta-planet-glyph { color: var(--sn-cluster-sleep); }
.sn-revealed-card[data-card-cluster="recovery"] .sn-meta-planet-glyph { color: var(--sn-cluster-recovery); }

/* Bottom metric-names pill, tinted by cluster. Sits at the foot of the
   card, INSIDE the frame, no text "ACTIVITY / SLEEP / RECOVERY" label. */
.sn-rc-metric-pill {
  display: inline-block;
  /* [Fix 2026-05-25 Bug 4] Tighter padding + smaller font + no vertical
     margin so the pill + window-range line fit inside the 34px footer
     box. Previously 0.35rem/0.78rem/0.5rem auto blew the footer height
     and clipped the range underneath. */
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 9px;
  line-height: 1.35;
  letter-spacing: 0.05em;
  text-transform: lowercase;
  border: 1px solid currentColor;
  background: rgba(255,255,255,0.04);
  margin: 0;
}
.sn-revealed-card[data-card-cluster="activity"] .sn-rc-metric-pill { color: var(--sn-cluster-activity); }
.sn-revealed-card[data-card-cluster="sleep"]    .sn-rc-metric-pill { color: var(--sn-cluster-sleep); }
.sn-revealed-card[data-card-cluster="recovery"] .sn-rc-metric-pill { color: var(--sn-cluster-recovery); }

/* [Fix 2026-05-25 Bug 3] Strength pill (top-right eyebrow) follows
   cluster colour when the card carries one. Beat / shift / pole rules
   live in the base section below; the more-specific [data-card-cluster]
   selector here overrides them on v5 cards so the pill never reads gold
   on a Sleep card. */
.sn-revealed-card.sn-rc-rich[data-card-cluster="activity"] .sn-pattern-pill {
  color: var(--sn-cluster-activity);
  border-color: var(--sn-cluster-activity);
  background: rgba(240, 115, 90, 0.15);
}
.sn-revealed-card.sn-rc-rich[data-card-cluster="sleep"] .sn-pattern-pill {
  color: var(--sn-cluster-sleep);
  border-color: var(--sn-cluster-sleep);
  background: rgba(63, 201, 214, 0.15);
}
.sn-revealed-card.sn-rc-rich[data-card-cluster="recovery"] .sn-pattern-pill {
  color: var(--sn-cluster-recovery);
  border-color: var(--sn-cluster-recovery);
  background: rgba(176, 124, 255, 0.15);
}

/* [Eva 2026-05-26 — iOS card port] Stacked stat-chip column on the
   eyebrow-right. Replaces the single "Strong signal" text pill with
   two cluster-bordered chips: |z|=X.Y on top and n=N on the bottom.
   Mirrors RevealedCardView.eyebrowRowWithSliver in iOS where the
   |z| pill is the right counterweight to the polarity arrow on the
   left, and n=N sits below in the same column.

   Chips inherit per-cluster color + border from the .sn-pattern-pill
   rules above; only layout + sizing changes here. text-transform:none
   + letter-spacing reset preserves the literal "|z|=" / "n=" glyphs
   instead of uppercasing + tracking them like the legacy text pill. */
.sn-revealed-card.sn-rc-rich .sn-rc-stat-stack {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  line-height: 1;
}
.sn-revealed-card.sn-rc-rich .sn-rc-stat-stack .sn-pattern-pill {
  text-transform: none;
  letter-spacing: 0.02em;
  font-family: var(--sn-mono);
  font-size: 8.5px;
  font-weight: 600;
  padding: 1px 6px;
  line-height: 1.25;
}
/* Card frame border + side tone strip follow cluster on v5 cards too.
   Mirrors the existing pole rules but takes precedence via
   [data-card-cluster]. Keeps the four visual signals (sliver, wheel,
   pill, frame) in agreement. */
.sn-revealed-card[data-card-cluster="activity"]::before { border-color: rgba(240, 115, 90, 0.85); }
.sn-revealed-card[data-card-cluster="activity"]::after  { border-color: rgba(240, 115, 90, 0.55); }
.sn-revealed-card[data-card-cluster="sleep"]::before    { border-color: rgba(63, 201, 214, 0.85); }
.sn-revealed-card[data-card-cluster="sleep"]::after     { border-color: rgba(63, 201, 214, 0.55); }
.sn-revealed-card[data-card-cluster="recovery"]::before { border-color: rgba(176, 124, 255, 0.85); }
.sn-revealed-card[data-card-cluster="recovery"]::after  { border-color: rgba(176, 124, 255, 0.55); }
.sn-revealed-card.sn-rc-rich[data-card-cluster="activity"] .sn-rc-tone-strip { background: var(--sn-cluster-activity); }
.sn-revealed-card.sn-rc-rich[data-card-cluster="sleep"]    .sn-rc-tone-strip { background: var(--sn-cluster-sleep); }
.sn-revealed-card.sn-rc-rich[data-card-cluster="recovery"] .sn-rc-tone-strip { background: var(--sn-cluster-recovery); }

/* Mandala wheel sign-segment tint by cluster. The wheel renders the same
   shape no matter the cluster; only the highlight colour changes. */
.sn-revealed-card[data-card-cluster="activity"] .sn-mandala-stage .sn-cluster-tint { fill: var(--sn-cluster-activity); }
.sn-revealed-card[data-card-cluster="sleep"]    .sn-mandala-stage .sn-cluster-tint { fill: var(--sn-cluster-sleep); }
.sn-revealed-card[data-card-cluster="recovery"] .sn-mandala-stage .sn-cluster-tint { fill: var(--sn-cluster-recovery); }

/* Top tab bar — full width segmented control above the panels. */
.signal-view-switcher-top {
  display: flex;
  justify-content: center;
  margin: 0 0 1.5rem;
}
.signal-view-switcher-top .signal-segment {
  width: 100%;
  max-width: 480px;
  display: flex;
}
.signal-view-switcher-top .signal-seg-btn {
  flex: 1;
}

/* ─── Mandala deck stage ──────────────────────────────────── */
/* Mandala tab is a fixed-height flex column that NEVER scrolls
   vertically. The revealed-card host flexes to fill the gap and
   the bottom row (history + draw deck) parks at the bottom. The
   card frame keeps its 5:7 aspect ratio via min(width,height)
   constraints so it shrinks gracefully on short viewports. */
.sn-deck-view {
  position: relative;
  /* Subtract the page chrome (nav + signal-main top padding), the
     top view-switcher row, and the mobile tab bar (0 on desktop). */
  height: calc(
    100vh
    - var(--sn-chrome-top)
    - 4.25rem    /* top view-switcher row + its 1.5rem margin */
    - var(--sn-tabbar-bottom)
    - 1rem       /* breathing room */
  );
  min-height: 0;
  border-radius: 16px;
  background: transparent;
  /* No bottom padding — the card claims that space; deck/column sit
     flush against the bottom edge of the stage. */
  padding: 0.25rem 0 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.sn-deck-stage {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  align-items: center;
  width: 100%;
  flex: 1 1 auto;
  min-height: 0;
}

.sn-deck-eyebrow-row {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 0.25rem 1rem 0.1rem;
  flex: 0 0 auto;
  min-height: 1.6rem;
}

/* ── F3 eligibility banner (web addendum F § 6.1) ────────────
   Bug C (Option 2): banner only renders when at least one cluster is
   in seed/standard/none tier (visibility gating lives in signal.js
   renderEligibilityBanner). When it does render, keep it a subtle
   status line — no heavy border, no shadow, no boxed background. */
.sn-eligibility-banner {
  width: 100%;
  max-width: 36rem;
  margin: 0.3rem auto 0.1rem;
  padding: 0.2rem 1.6rem 0.2rem 0.4rem;
  background: transparent;
  border: 0;
  border-radius: 0;
  color: var(--sn-text-3, var(--sn-text-2));
  font-size: 0.76rem;
  line-height: 1.35;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  opacity: 0.78;
}
.sn-eligibility-text {
  flex: 1 1 auto;
  letter-spacing: 0.01em;
}
.sn-eligibility-dismiss {
  position: absolute;
  right: 0.25rem;
  top: 50%;
  transform: translateY(-50%);
  background: transparent;
  border: 0;
  color: var(--sn-text-3, var(--sn-text-2));
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  padding: 0.1rem 0.3rem;
  opacity: 0.45;
}
.sn-eligibility-dismiss:hover {
  opacity: 0.85;
}
.sn-eligibility-banner[hidden] {
  display: none !important;
}
@media (max-width: 480px) {
  .sn-eligibility-banner {
    font-size: 0.72rem;
    padding: 0.18rem 1.4rem 0.18rem 0.3rem;
  }
}
.sn-deck-header-copy {
  font-family: var(--sn-display);
  font-weight: 300;
  font-style: italic;
  font-size: 1rem;
  line-height: 1.35;
  color: var(--sn-text-2);
  text-align: center;
  letter-spacing: 0.01em;
  max-width: 32ch;
  opacity: 0;
  transition: opacity 0.6s ease;
}
.sn-deck-header-copy.is-visible {
  opacity: 1;
}
@media (max-width: 640px) {
  .sn-deck-header-copy {
    font-size: 0.88rem;
    max-width: 28ch;
  }
}

.sn-deck-view .sn-pole-toggle {
  display: inline-flex;
  background: rgba(20, 16, 42, 0.55);
  border: 1px solid var(--sn-hairline);
  border-radius: 12px;
  padding: 3px;
  align-self: center;
}
.sn-deck-view .sn-pole-btn {
  background: transparent;
  color: var(--sn-text-2);
  border: 0;
  padding: 0.32rem 0.85rem;
  cursor: pointer;
  font-family: var(--sn-display);
  font-size: 0.78rem;
  font-weight: 500;
  border-radius: 9px;
  transition: background 0.16s, color 0.16s, border-color 0.16s;
  border: 1px solid transparent;
  white-space: nowrap;
  line-height: 1.2;
}
.sn-deck-view .sn-pole-btn[data-pole="positive"].active {
  background: rgba(233, 185, 106, 0.18);
  color: var(--sn-gold);
  border-color: var(--sn-gold);
}
.sn-deck-view .sn-pole-btn[data-pole="negative"].active {
  background: rgba(196, 80, 76, 0.18);
  color: var(--sn-oxblood);
  border-color: var(--sn-oxblood);
}

/* ─── Hero card area ─────────────────────────────────────── */
.sn-deck-hero {
  position: absolute;
  inset: 0;
  /* History strip sits at bottom:16, height:72 → occupies bottom 88px.
     Reserve 144px below the card so there's a clear ~56px breathing
     gap between the card's bottom edge and the thumbnails. */
  padding: 0.25rem 16px 144px 16px;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* When revealed, the host fills the hero so the inner card can size
   against it. When idle (data-state != revealed), the host stays
   hidden so only the placeholder card shows. */
.sn-deck-hero[data-state="revealed"] .sn-revealed-card-host {
  display: flex;
  width: 100%;
  height: 100%;
  align-items: center;
  justify-content: center;
}

.sn-deck-hero[data-state="revealed"] .sn-card-placeholder {
  display: none;
}
.sn-deck-hero[data-state="revealed"] .sn-revealed-card-host {
  display: flex;
}

/* ─── Card frame (cusp-cornered, gold double stroke, mauve halo) ─── */
.sn-card {
  position: relative;
  display: block;
  width: 240px;
  aspect-ratio: 240 / 340;
  background: var(--sn-card-fill);
  /* CSS clip-path approximation of iOS CuspRect: gentle inward notches. */
  clip-path: polygon(
    14px 0,
    calc(100% - 14px) 0,
    100% 14px,
    100% calc(100% - 14px),
    calc(100% - 14px) 100%,
    14px 100%,
    0 calc(100% - 14px),
    0 14px
  );
  cursor: pointer;
  border: 0;
  padding: 0;
  font-family: var(--sn-body);
  color: var(--sn-text);
  text-align: center;
  transition: transform 0.18s ease, filter 0.18s ease;
}
.sn-card:hover {
  filter: brightness(1.06);
}
.sn-card:active {
  transform: scale(0.98);
}

/* The double gold stroke is faked via a layered ::before+::after; clip-path
   strips visible borders, so we render two pseudo-element overlays with
   matching clip-paths and opacities. */
.sn-card::before,
.sn-card::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  clip-path: inherit;
  background: transparent;
  border: 1.2px solid rgba(233, 185, 106, 0.85);
  /* Use box-shadow inset to fake the inner stroke when we change inset. */
}
.sn-card::after {
  inset: 6px;
  border: 0.7px solid rgba(233, 185, 106, 0.55);
}

/* Mauve halo behind every card (the OrnateCardFrame radial gradient). */
.sn-card-halo,
.sn-revealed-card-host::before {
  position: absolute;
  inset: -28px;
  pointer-events: none;
  background: radial-gradient(
    ellipse at center,
    rgba(164, 137, 212, 0.32) 0%,
    rgba(164, 137, 212, 0.0) 65%
  );
  filter: blur(16px);
  z-index: -1;
}
.sn-revealed-card-host {
  position: relative;
  display: none;
}
.sn-revealed-card-host::before { content: ''; }

/* Pole-tinted strokes for the revealed card. */
.sn-deck-view[data-active-pole="negative"] .sn-revealed-card::before,
.sn-revealed-card[data-card-pole="negative"]::before {
  border-color: rgba(196, 80, 76, 0.85);
}
.sn-deck-view[data-active-pole="negative"] .sn-revealed-card::after,
.sn-revealed-card[data-card-pole="negative"]::after {
  border-color: rgba(196, 80, 76, 0.55);
}

/* ─── Card BACK pattern — diagonal weave + concentric rings ───────── */
.sn-card-back {
  background:
    /* 8px diagonal weave (dual-direction lattice) */
    repeating-linear-gradient(
      45deg,
      rgba(233, 185, 106, 0.08) 0,
      rgba(233, 185, 106, 0.08) 0.5px,
      transparent 0.5px,
      transparent 8px
    ),
    repeating-linear-gradient(
      -45deg,
      rgba(233, 185, 106, 0.08) 0,
      rgba(233, 185, 106, 0.08) 0.5px,
      transparent 0.5px,
      transparent 8px
    ),
    radial-gradient(circle at center, #1c1240 0%, #120a2a 100%);
}
.sn-card-back::before {
  border: 1.2px solid rgba(233, 185, 106, 0.55);
}
.sn-card-back::after {
  border: 0.7px solid rgba(233, 185, 106, 0.30);
}

.sn-card-glyph {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 44px;
  height: 44px;
  margin: -22px 0 0 -22px;
  border-radius: 50%;
  background:
    radial-gradient(circle, transparent 0 6%, rgba(233, 185, 106, 0.85) 6.5% 7.5%, transparent 8% 28%, rgba(233, 185, 106, 0.65) 28.5% 29.5%, transparent 30% 44%, rgba(233, 185, 106, 0.55) 44.5% 46%, transparent 47% 100%);
}

.sn-card-cta {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 28px;
  font-family: var(--sn-mono);
  font-size: 9px;
  letter-spacing: 0.22em;
  color: rgba(233, 185, 106, 0.7);
  text-transform: uppercase;
  font-weight: 600;
}

/* ─── Stage body: drawn-cards column (L), hero (C), draw deck (BR) ── */
.sn-deck-body {
  position: relative;
  width: 100%;
  flex: 1 1 auto;
  min-height: 0;
}

/* Drawn-cards strip — anchored along the BOTTOM, horizontal scroll-snap.
   Deck sits at bottom-LEFT (left: 16px, 50px wide), so the strip starts
   to its right (82px = 16+50+16 gap) and runs to the right edge. */
.sn-history-strip {
  position: absolute;
  left: 82px;
  right: 12px;
  bottom: 16px;
  height: 72px;            /* matches card aspect 50x72 */
  display: flex;
  flex-direction: row;
  z-index: 2;
  pointer-events: auto;
}
.sn-history-row {
  display: flex;
  flex-direction: row;
  gap: 8px;
  align-items: center;
  /* Horizontal scroll with snap-to-card. Newest is on the RIGHT. */
  overflow-x: auto;
  overflow-y: hidden;
  flex-wrap: nowrap;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  padding: 0 2px;
  width: 100%;
  height: 100%;
}
.sn-history-row::-webkit-scrollbar {
  display: none;
}

/* History thumbnail = small Senary deck cover. Same construction as
   .sn-deck-cover (gold inset frame, hex sigil) but at 50×72, with dust
   suppressed (radial gradients vanish at this scale anyway) and a
   smaller corner-bracket inset. The .sn-history-card-glyph element is
   no longer needed for the visual — the sigil is now in the background
   image — but we keep the JS appendChild call by styling the element
   to be invisible. */
.sn-history-card {
  position: relative;
  width: 50px;
  flex: 0 0 50px;
  aspect-ratio: 90 / 131;
  border-radius: 3px;
  overflow: hidden;
  border: 0;
  padding: 0;
  cursor: pointer;
  scroll-snap-align: end;
  transition: filter 0.16s ease, transform 0.16s ease;
  /* Body fill: same recipe as .sn-deck-cover, dimmed slightly so the
     newly-drawn hero card stays the focal point. */
  background:
    radial-gradient(ellipse 70% 60% at 50% 42%,
      rgba(96, 60, 168, 0.45) 0%, rgba(96, 60, 168, 0) 65%),
    radial-gradient(ellipse 80% 55% at 50% 90%,
      rgba(40, 22, 80, 0.5) 0%, rgba(40, 22, 80, 0) 70%),
    linear-gradient(180deg, #261248 0%, #1a0b34 50%, #120726 100%);
  box-shadow:
    inset 0 0 0 0.8px rgba(233, 185, 106, 0.85),
    inset 0 0 0 1.6px rgba(0, 0, 0, 0.55),
    inset 0 0 0 2.2px rgba(233, 185, 106, 0.45);
}
.sn-history-card::before {
  /* Hex sigil as a background image. Suppress dust at this size. */
  content: '';
  position: absolute;
  inset: 3px;
  pointer-events: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'>\
<g transform='translate(-284 -29)'>\
<path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='none' stroke='%23e9b96a' stroke-width='2.4' stroke-linejoin='miter'/>\
<g transform='translate(334 79) scale(0.78) translate(-334 -79)'><path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='none' stroke='%23e9b96a' stroke-opacity='0.55' stroke-width='1.0'/></g>\
<g transform='translate(334 79) scale(0.56) translate(-334 -79)'><path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='none' stroke='%23e9b96a' stroke-opacity='0.385' stroke-width='0.9'/></g>\
<g transform='translate(334 79) scale(0.34) translate(-334 -79)'><path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='none' stroke='%23e9b96a' stroke-opacity='0.275' stroke-width='0.8'/></g>\
<g transform='translate(334 79) scale(0.16) translate(-334 -79)'><path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='%23e9b96a' fill-opacity='0.85'/></g>\
</g></svg>");
  background-repeat: no-repeat;
  background-position: 50% 42%;
  background-size: 60% auto;
}
.sn-history-card-caption {
  position: absolute;
  inset: auto 0 4px 0;
  font-family: var(--sn-mono);
  font-size: 6px;
  letter-spacing: 0.18em;
  color: rgba(233, 185, 106, 0.85);
  text-align: center;
  font-weight: 600;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
  z-index: 1;
}
.sn-history-card-glyph {
  /* Hidden — sigil now comes from the ::before background image. The
     element is still appended by JS for backward compat; we just don't
     paint it. */
  display: none;
}
.sn-history-card:hover:not(:disabled) {
  filter: brightness(1.15);
}
.sn-history-card:active:not(:disabled) {
  transform: scale(0.96);
}
.sn-history-card[data-history-pole="negative"]::before {
  border-color: rgba(196, 80, 76, 0.55);
}
.sn-history-card[data-history-pole="negative"] .sn-history-card-caption {
  color: rgba(196, 80, 76, 0.7);
}
.sn-history-card[data-history-pole="negative"] .sn-history-card-glyph {
  background:
    radial-gradient(circle, transparent 0 6%, rgba(196, 80, 76, 0.7) 6.5% 8%, transparent 9% 32%, rgba(196, 80, 76, 0.5) 33% 35%, transparent 36% 100%);
}

/* Empty placeholder slot — marks the chronological position of the
   currently-displayed (hero) card within the history strip. Same
   footprint as a thumb, but with a dashed pole-tinted outline and no
   card-back fill. Non-interactive. */
.sn-history-card-empty {
  position: relative;
  width: 50px;
  flex: 0 0 50px;
  aspect-ratio: 50 / 72;
  background: transparent;
  background-image: none;
  clip-path: none;
  border: 1.2px dashed rgba(214, 198, 255, 0.35);
  border-radius: 6px;
  pointer-events: none;
  cursor: default;
}
.sn-history-card-empty::before {
  content: none;
}
.sn-history-card-empty[data-pole="positive"] {
  border-color: rgba(233, 185, 106, 0.55);
}
.sn-history-card-empty[data-pole="negative"] {
  border-color: rgba(196, 80, 76, 0.55);
}

/* FLIP-animation clones: fixed-positioned, animated via JS. */
.sn-flip-clone {
  position: fixed;
  z-index: 9999;
  pointer-events: none;
  transform-origin: top left;
  transform-style: preserve-3d;
  backface-visibility: hidden;
  will-change: transform, opacity;
  transition: transform 600ms cubic-bezier(0.22, 1, 0.36, 1), opacity 600ms ease;
}
.sn-flip-clone-back {
  /* Optional backface for the rotating thumbnail; not strictly required
     since we cross-fade clones, but keeps the half-flip readable. */
}

/* ─── Draw deck (bottom-LEFT corner, under the drawn-cards column,
   sized to match thumbs: 50x72). Conceptually the deck you draw FROM
   sits underneath the cards you've drawn — same column. ─── */
.sn-draw-deck-wrap {
  position: absolute;
  left: 16px;
  bottom: 16px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  z-index: 3;
}
.sn-draw-deck {
  position: relative;
  width: 50px;
  height: 72px;
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.sn-draw-deck:disabled,
.sn-draw-deck[aria-disabled="true"] {
  cursor: pointer;            /* tap still reveals the cooldown caption */
}
/* Dim only the inner card stack during cooldown so the ring + caption
   overlay stay fully visible above the sleepy-looking deck. */
.sn-draw-deck[aria-disabled="true"] .sn-deck-card {
  opacity: 0.45;
}
.sn-draw-deck[aria-disabled="true"] .sn-deck-card.sn-deck-card-3 { opacity: 0.22; }
.sn-draw-deck[aria-disabled="true"] .sn-deck-card.sn-deck-card-2 { opacity: 0.32; }

/* Bottom-LEFT draw deck — small (50×72) face-down Senary deck covers,
   stacked with subtle tilt. Same construction as .sn-deck-cover scaled
   down, dust suppressed (radial-gradient dust dots vanish at this size
   anyway, just like in the history thumbs). */
.sn-deck-card {
  position: absolute;
  inset: 0;
  border-radius: 3px;
  overflow: hidden;
  display: block;
  background:
    radial-gradient(ellipse 70% 60% at 50% 42%,
      rgba(96, 60, 168, 0.45) 0%, rgba(96, 60, 168, 0) 65%),
    radial-gradient(ellipse 80% 55% at 50% 90%,
      rgba(40, 22, 80, 0.5) 0%, rgba(40, 22, 80, 0) 70%),
    linear-gradient(180deg, #261248 0%, #1a0b34 50%, #120726 100%);
  box-shadow:
    inset 0 0 0 0.8px rgba(233, 185, 106, 0.85),
    inset 0 0 0 1.6px rgba(0, 0, 0, 0.55),
    inset 0 0 0 2.2px rgba(233, 185, 106, 0.45);
}
.sn-deck-card::before {
  /* Hex sigil at small scale. */
  content: '';
  position: absolute;
  inset: 3px;
  pointer-events: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'>\
<g transform='translate(-284 -29)'>\
<path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='none' stroke='%23e9b96a' stroke-width='2.4' stroke-linejoin='miter'/>\
<g transform='translate(334 79) scale(0.78) translate(-334 -79)'><path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='none' stroke='%23e9b96a' stroke-opacity='0.55' stroke-width='1.0'/></g>\
<g transform='translate(334 79) scale(0.56) translate(-334 -79)'><path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='none' stroke='%23e9b96a' stroke-opacity='0.385' stroke-width='0.9'/></g>\
<g transform='translate(334 79) scale(0.34) translate(-334 -79)'><path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='none' stroke='%23e9b96a' stroke-opacity='0.275' stroke-width='0.8'/></g>\
<g transform='translate(334 79) scale(0.16) translate(-334 -79)'><path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='%23e9b96a' fill-opacity='0.85'/></g>\
</g></svg>");
  background-repeat: no-repeat;
  background-position: 50% 50%;
  background-size: 60% auto;
}
/* Bottom-right draw deck: top card straight, backs fan outward so the
   small deck reads consistent with the hero deck stack. */
.sn-deck-card-3 { transform: rotate(3deg) translate(4px, 4px); opacity: 0.55; }
.sn-deck-card-2 { transform: rotate(1.5deg) translate(2px, 2px); opacity: 0.75; }
.sn-deck-card-1 { transform: rotate(0deg) translate(0, 0); opacity: 1; }

/* The old .sn-deck-card-glyph element (rendered as concentric rings) is
   no longer needed since the sigil is in the background. Hidden but kept
   for any inline-script paths that still query for it. */
.sn-deck-card-glyph { display: none; }

.sn-draw-caption {
  font-family: var(--sn-mono);
  font-size: 9px;
  letter-spacing: 0.12em;
  color: var(--sn-text-3);
  text-align: left;
  margin-top: 4px;
  min-height: 10px;
}

/* The old .sn-deck-cooldown / .sn-deck-cooldown-arc / .sn-deck-cooldown-fill /
 * .sn-deck-cooldown-caption styles (the small ring overlay + popover that
 * orbited the bottom-left draw deck) have been REMOVED. The new countdown
 * is the radial ring (.sn-countdown / .sn-countdown-ring) defined at the
 * bottom of this file and centered over the hero deck cover, per the
 * mockups in /ios/Reference_design/Cards/05 and /07. The orphaned circle
 * that "didn't serve the right function" was that ring + its tap-revealed
 * caption; both removed. */

/* Bug A: when no cards have been drawn yet, hide the bottom-left small
   draw deck and the (empty) history strip. The centered hero deck is the
   only deck visible until the first reveal — after which the hero hosts
   the revealed card and these auxiliary surfaces mount. */
.sn-deck-view.is-deck-empty .sn-draw-deck-wrap,
.sn-deck-view.is-deck-empty .sn-history-strip {
  display: none !important;
}

/* ─── Drawing animation overlay ──────────────────────────── */
.sn-deck-anim {
  position: fixed;
  inset: 0;
  z-index: 100;
  pointer-events: none;
  display: block;
}
.sn-deck-anim[hidden] { display: none; }
.sn-deck-anim-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(10, 8, 22, 0);
  transition: background 0.25s ease;
}
.sn-deck-anim.sn-deck-anim-mid .sn-deck-anim-backdrop {
  background: rgba(10, 8, 22, 0.35);
}

/* The flying card during the draw animation. Combines .sn-deck-cover
   (visual face — gold frame, hex sigil, dust) with the flight-specific
   geometry below. Starts at the bottom-left small deck position and
   transitions to hero center while flipping 180° on Y. */
.sn-deck-anim-card.sn-deck-cover {
  position: absolute;
  width: 50px;
  height: 72px;
  left: 20px;
  bottom: 20px;
  /* Keep the cover's box-shadow inset stack (gold double frame) but
     override aspect-ratio in favor of explicit dims so transitions
     animate width/height directly. */
  aspect-ratio: auto;
  transition:
    transform 0.55s cubic-bezier(0.32, 0.85, 0.45, 1.0),
    width 0.55s cubic-bezier(0.32, 0.85, 0.45, 1.0),
    height 0.55s cubic-bezier(0.32, 0.85, 0.45, 1.0),
    left 0.55s cubic-bezier(0.32, 0.85, 0.45, 1.0),
    top 0.55s cubic-bezier(0.32, 0.85, 0.45, 1.0),
    right 0.55s cubic-bezier(0.32, 0.85, 0.45, 1.0),
    bottom 0.55s cubic-bezier(0.32, 0.85, 0.45, 1.0),
    opacity 0.18s ease;
  transform-origin: center;
  transform-style: preserve-3d;
  perspective: 800px;
}

/* mid-flight: scale to hero size, position center-ish, flip 180°. */
.sn-deck-anim.sn-deck-anim-mid .sn-deck-anim-card.sn-deck-cover {
  width: 240px;
  height: 349px;
  right: auto;
  bottom: auto;
  left: calc(50% - 120px);
  top: calc(40% - 174px);
  transform: rotateY(180deg);
}
.sn-deck-anim.sn-deck-anim-settled .sn-deck-anim-card {
  opacity: 0;
}

/* ─── REVEALED card (hero) ───────────────────────────────── */
.sn-revealed-card {
  position: relative;
  width: 100%;
  max-width: 320px;
  aspect-ratio: 320 / 460;
  background: var(--sn-card-fill);
  /* Gently rounded corners. The old cusp-rect clip-path left dark
     diagonal cut-outs at each corner that exposed the page behind —
     visually unfinished. Rounded corners keep the card body solid all
     the way to the gold strokes. */
  border-radius: 14px;
  padding: 22px 22px 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  text-align: left;
  margin: 0 auto;
}

/* Rich variant: fixed-size 320×549 frame scaled via transform so the
   internal layout is pixel-identical across all viewports. Wrapped in
   a `.sn-card-slot` that reserves the bounding box at the scaled size,
   and JS sets `--card-scale` via ResizeObserver based on slot size.
   All children are absolutely positioned with PX coordinates. */
.sn-card-slot {
  position: relative;
  /* Fit the card inside whatever bounding box the parent (.sn-deck-hero)
     gives us while keeping the 7:12 tarot aspect ratio. The parent's
     padding already reserves room for the history strip + nav, so the
     slot just needs to honour the parent's height — NOT a viewport-
     relative clamp, which can be larger than the parent on tight
     screens (iPhone SE) and cause the card to bleed past the strip. */
  width: 100%;
  aspect-ratio: 320 / 549;
  max-width: 420px;
  max-height: 100%;
  min-height: 0;
  margin: 0 auto;
}
.sn-revealed-card.sn-rc-rich {
  position: absolute;
  /* Center the fixed 320×549 card inside the slot. Previously anchored
     to top-left + transform-origin:top-left, which left the scaled card
     hugging the slot's top-left corner whenever the height was the
     binding constraint (any tight viewport). Translate by half its own
     border-box before scaling so the box center lands at the slot's
     center regardless of scale factor. */
  top: 50%;
  left: 50%;
  width: 320px;
  height: 549px;
  transform-origin: center;
  transform: translate(-50%, -50%) scale(var(--card-scale, 1));
  display: block;
  margin: 0;
  padding: 14px 14px 12px;
  gap: 0;
  /* overflow:visible so the cluster tab + hero icon + cluster label can
     protrude above the card frame (top:-18px). Internal layout uses
     absolute children that respect the padding box, so clipping the card
     body isn't needed. */
  overflow: visible;
}
.sn-revealed-card.sn-rc-rich > * {
  margin: 0;
}
/* Eyebrow row: "PEAK · I" left, strength pill right */
.sn-revealed-card.sn-rc-rich .sn-rc-eyebrow-row {
  position: absolute;
  top: 14px;
  left: 14px;
  right: 14px;
  height: 20px;
}
/* Headline: ~4 lines of 13.5px / 1.25 = ~17px line ≈ 68px box */
.sn-revealed-card.sn-rc-rich .sn-headline {
  position: absolute;
  top: 42px;
  left: 14px;
  right: 14px;
  height: 72px;
  font-family: var(--sn-display);
  font-weight: 300;
  font-size: 13.5px;
  line-height: 1.25;
  letter-spacing: -0.15px;
  color: var(--sn-text);
  text-wrap: balance;
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.sn-revealed-card.sn-rc-rich .sn-headline .sn-sign-pos { color: var(--sn-gold); font-weight: 700; }
.sn-revealed-card.sn-rc-rich .sn-headline .sn-sign-neg { color: var(--sn-oxblood); font-weight: 700; }
.sn-revealed-card.sn-rc-rich .sn-headline .sn-sign-shift { color: #4FC3D9; font-weight: 700; }
.sn-revealed-card.sn-rc-rich .sn-headline .sn-sign-beat { color: #9b7cd4; font-weight: 700; }
/* Same cyan / purple tokens for shift / beat tokens that appear in the
   subline + body paragraph, mirroring how positive/negative tokens tint
   everywhere they appear on the card. */
.sn-revealed-card.sn-rc-rich .sn-sign-shift { color: #4FC3D9; font-weight: 700; }
.sn-revealed-card.sn-rc-rich .sn-sign-beat { color: #9b7cd4; font-weight: 700; }

/* Shift card variant: compact headline + subline sit above a vertically
   centered mandala wheel. Per-day metric-value dots overlay the wheel
   itself (no separate bodygraph, no separate ±7d line chart). The body
   paragraph the long narrative cards use is suppressed — the dots ARE
   the narrative for shift cards. 320×549 frame budget (top-down):
     14-34   eyebrow row (base rule)
     38-86   headline (4 lines max at 12px line-height)
     90-104  meta / subline (base rule overrides override)
     186-426 mandala wheel + scatter dots (sn-mandala-stage; 240px tall,
              vertically centered in the 104-509 content band)
     513-539 footer (base rule, bottom:10)                          */
.sn-revealed-card.sn-rc-rich[data-card-pole="shifts"] .sn-headline {
  position: absolute;
  top: 38px;
  left: 22px;
  right: 22px;
  height: auto;
  max-height: 50px;
  font-family: var(--sn-display);
  font-weight: 400;
  font-size: 13px;
  line-height: 1.25;
  letter-spacing: -0.1px;
  color: var(--sn-text);
  text-wrap: balance;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.sn-revealed-card.sn-rc-rich[data-card-pole="shifts"] .sn-pattern-meta {
  top: 92px;
}
.sn-revealed-card.sn-rc-rich[data-card-pole="shifts"] .sn-mandala-stage {
  /* Centered vertically in the available band between the subline
     (~104) and the footer (~509). Band = 405px; mandala = 240px →
     top = 104 + (405 - 240)/2 ≈ 186. Bumped from 130px/122px to
     240px/240px wheel on 2026-05-20 after removing the bodygraph +
     bottom line chart so the wheel fills the freed space and the
     scatter dots are legible. left/right reset clears the inherited
     14px gutters from the base rule that were starving justify-content
     of centering space and pushing the wheel off-axis. Bottom-cap
     prevents the wheel from overrunning the "Why this might matter"
     eyebrow text underneath. */
  top: 156px;
  height: 240px;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: visible;
}
.sn-revealed-card.sn-rc-rich[data-card-pole="shifts"] .sn-mandala-stage svg {
  width: 240px;
  height: 240px;
  max-width: 240px;
  overflow: visible;
}

/* Shift cards restore the "Why this might matter" body paragraph
   directly under the subline. The descriptor's buildShiftBody emits the
   narrative — anchor's transit + each amplifier with "Amplified by ..."
   framing + natal overlap. The metric-value dots on the wheel SHOW the
   crossing; the body paragraph EXPLAINS it. (Reinstated 2026-05-20
   after Eva: "First of all yes restore the body text".) */

/* Shift card metric-value dot overlay on the Mandala wheel.
   Replaced the standalone ±7d line chart on 2026-05-20 — dots now
   sit ON the wheel itself at the responsible planet's daily longitude
   so the user sees the regime change happen as the planet crosses
   a sign boundary. Renderer: overlayShiftDotsOnMandala() in signal.js. */
.sn-shift-dots {
  pointer-events: none;
}
.sn-shift-day-dot--before {
  /* Mauve, semi-transparent. Pre-shift days. */
}
.sn-shift-day-dot--after {
  /* Polarity cyan, full opacity. Post-shift days. */
}
.sn-shift-day-marker {
  /* Outlined cyan ring on the shift day itself. */
}

/* Beat card variant — mirrors shift layout (text-only card, same
   positioned headline + body bands). The polarity colour swaps cyan
   → lavender (#9b7cd4). */
.sn-revealed-card.sn-rc-rich[data-card-pole="beats"] .sn-headline {
  position: absolute;
  top: 56px;
  left: 22px;
  right: 22px;
  height: auto;
  max-height: 140px;
  font-family: var(--sn-display);
  font-weight: 400;
  font-size: 19px;
  line-height: 1.3;
  letter-spacing: -0.2px;
  color: var(--sn-text);
  text-wrap: balance;
  display: block;
  -webkit-line-clamp: initial;
  -webkit-box-orient: initial;
  overflow: hidden;
}
.sn-revealed-card.sn-rc-rich[data-card-pole="beats"] .sn-body {
  position: absolute;
  top: 212px;
  left: 22px;
  right: 22px;
  bottom: 24px;
  margin: 0;
  font-family: var(--sn-body);
  font-weight: 400;
  font-size: 14px;
  line-height: 1.5;
  letter-spacing: -0.05px;
  color: var(--sn-text-2);
  text-wrap: pretty;
  overflow: hidden;
}

.sn-revealed-card.sn-rc-rich .sn-pattern-meta {
  position: absolute;
  top: 118px;
  left: 14px;
  right: 14px;
  height: 14px;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: nowrap;
  overflow: hidden;
  white-space: nowrap;
}
.sn-revealed-card.sn-rc-rich .sn-pattern-meta > * {
  flex-shrink: 1;
  min-width: 0;
}
.sn-revealed-card.sn-rc-rich .sn-pattern-readout {
  font-family: var(--sn-mono);
  font-size: 9px;
  color: var(--sn-text-3);
  line-height: 1.35;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sn-revealed-card.sn-rc-rich .sn-pattern-readout strong {
  color: var(--sn-text-2);
  font-weight: 500;
}
/* Small inline color dot before the planet name in the meta line.
   Took over the role of the old `.sn-mandala-planet-legend` row that
   used to sit under the wheel — same swatch, now adjacent to the
   driving-planet label so the legend reads in one sweep. */
.sn-revealed-card.sn-rc-rich .sn-pattern-readout .sn-meta-planet-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  margin-right: 5px;
  vertical-align: 1px;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.5);
}
.sn-revealed-card.sn-rc-rich .sn-pattern-pill {
  padding: 1px 6px;
  border-radius: 8px;
  font-family: var(--sn-mono);
  font-size: 7px;
  font-weight: 600;
  letter-spacing: 0.9px;
  text-transform: uppercase;
  color: var(--sn-gold);
  border: 1px solid var(--sn-gold);
  background: rgba(233, 185, 106, 0.15);
}
.sn-deck-view[data-active-pole="negative"] .sn-revealed-card.sn-rc-rich .sn-pattern-pill,
.sn-revealed-card.sn-rc-rich[data-card-pole="negative"] .sn-pattern-pill {
  color: var(--sn-oxblood);
  border-color: var(--sn-oxblood);
  background: rgba(196, 80, 76, 0.15);
}
/* Shift pole: cyan eyebrow + strength pill, parallel to the
   positive (gold) and negative (oxblood) treatments above. */
.sn-revealed-card.sn-rc-rich[data-card-pole="shifts"] .sn-rc-eyebrow-row {
  color: #4FC3D9;
}
.sn-revealed-card.sn-rc-rich[data-card-pole="shifts"] .sn-pattern-pill {
  color: #4FC3D9;
  border-color: #4FC3D9;
  background: rgba(79, 195, 217, 0.15);
}
/* Pole-tinted strokes for the shift revealed card border. */
.sn-revealed-card[data-card-pole="shifts"]::before {
  border-color: rgba(79, 195, 217, 0.85);
}
.sn-revealed-card[data-card-pole="shifts"]::after {
  border-color: rgba(79, 195, 217, 0.55);
}
/* Beat pole: lavender (#9b7cd4) eyebrow + strength pill. */
.sn-revealed-card.sn-rc-rich[data-card-pole="beats"] .sn-rc-eyebrow-row {
  color: #9b7cd4;
}
.sn-revealed-card.sn-rc-rich[data-card-pole="beats"] .sn-pattern-pill {
  color: #9b7cd4;
  border-color: #9b7cd4;
  background: rgba(155, 124, 212, 0.15);
}
.sn-revealed-card[data-card-pole="beats"]::before {
  border-color: rgba(155, 124, 212, 0.85);
}
.sn-revealed-card[data-card-pole="beats"]::after {
  border-color: rgba(155, 124, 212, 0.55);
}
/* Mandala wheel: 170×170 SVG + small gap + "● MOON" caption.
   Total stage = svg(170) + gap(4) + caption(~22) = 196, fits 204 budget.
   overflow:visible so the wheel's outer ticks/glyphs render fully —
   the chip row below starts at top:354 so there's no collision. */
.sn-revealed-card.sn-rc-rich .sn-mandala-stage {
  position: absolute;
  top: 156px;            /* Pushed further down (144→156, +12) so the wheel
                            has clear breathing room below the meta line.
                            Height drops 200→188 to compensate, keeping the
                            chip row anchored at top:346. */
  left: 14px;
  right: 14px;
  height: 188px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 0;
  overflow: visible;
}
.sn-revealed-card.sn-rc-rich .sn-mandala-stage svg {
  display: block;
  overflow: visible;
  width: 170px;
  height: 170px;
  max-width: 170px;
  flex-shrink: 0;
}
.sn-revealed-card.sn-rc-rich .sn-mandala-planet-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  justify-content: center;
  margin: 0;
  padding: 0 4px;
}
.sn-revealed-card.sn-rc-rich .sn-planet-swatch {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--sn-mono);
  font-size: 9px;
  letter-spacing: 0.6px;
  color: var(--sn-text-3);
  text-transform: uppercase;
}
.sn-revealed-card.sn-rc-rich .sn-planet-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  display: inline-block;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.5);
}
.sn-revealed-card.sn-rc-rich .sn-chip-row {
  position: absolute;
  top: 346px;
  left: 14px;
  right: 14px;
  height: 24px;
  display: flex;
  align-items: center;
  padding: 0;
}
.sn-revealed-card.sn-rc-rich .sn-chip-label {
  display: block;
  margin: 0 0 4px;
  font-family: var(--sn-mono);
  font-size: 9px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sn-text-3);
}
.sn-revealed-card.sn-rc-rich .sn-chip-list {
  display: flex; gap: 6px;
  flex-wrap: wrap;
}
.sn-revealed-card.sn-rc-rich .sn-chip {
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(20,16,42,0.5);
  border: 1px solid var(--sn-hairline-2);
  font-family: var(--sn-display);
  font-size: 9.5px;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--sn-text-2);
  white-space: nowrap;
  line-height: 1.5;
}
.sn-deck-view[data-active-pole="positive"] .sn-revealed-card.sn-rc-rich .sn-chip.active,
.sn-revealed-card.sn-rc-rich[data-card-pole="positive"] .sn-chip.active {
  background: rgba(233,185,106,0.16);
  border-color: var(--sn-gold);
  color: var(--sn-gold);
}
.sn-deck-view[data-active-pole="negative"] .sn-revealed-card.sn-rc-rich .sn-chip.active,
.sn-revealed-card.sn-rc-rich[data-card-pole="negative"] .sn-chip.active {
  background: rgba(196,80,76,0.16);
  border-color: var(--sn-oxblood);
  color: var(--sn-oxblood);
}
.sn-revealed-card.sn-rc-rich .sn-eyebrow-section {
  position: absolute;
  top: 378px;
  left: 14px;
  right: 14px;
  height: 14px;
  display: block;
  margin: 0;
  font-family: var(--sn-mono);
  font-size: 8.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sn-text-3);
}
.sn-revealed-card.sn-rc-rich .sn-narrative {
  position: absolute;
  top: 396px;
  left: 14px;
  right: 14px;
  /* [Fix 2026-05-25 Bug 4] Trim height 116→102 + line clamp 8→7 so the
     narrative ends at ~498px and clears the bumped footer (now at
     bottom:8 height:40 → top edge ~501px). */
  height: 102px;
  font-family: var(--sn-body);
  font-size: 10px;
  color: var(--sn-text-2);
  line-height: 1.4;
  margin: 0;
  display: -webkit-box;
  -webkit-line-clamp: 7;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.sn-revealed-card.sn-rc-rich .sn-amp-strip {
  position: absolute;
  top: 118px;
  left: 14px;
  right: 14px;
  height: 16px;
  display: inline-flex;
  flex-wrap: nowrap;
  gap: 5px;
  margin: 0;
  overflow: hidden;
}
.sn-revealed-card.sn-rc-rich .sn-amp-chip {
  padding: 3px 7px;
  border-radius: 9px;
  background: rgba(20,16,42,0.55);
  border: 1px solid var(--sn-hairline-2);
  font-family: var(--sn-mono);
  font-size: 10px;
  color: var(--sn-text-2);
  white-space: nowrap;
}
.sn-revealed-card.sn-rc-rich .sn-natal-card {
  margin-top: 6px;
  padding: 10px 12px;
  background: rgba(20,16,42,0.5);
  border: 1px solid var(--sn-hairline-2);
  border-radius: 12px;
}
.sn-revealed-card.sn-rc-rich .sn-natal-head {
  margin-bottom: 4px;
}
.sn-revealed-card.sn-rc-rich .sn-natal-row {
  display: flex; gap: 8px;
  padding: 5px 0;
  border-top: 0.5px solid var(--sn-hairline);
}
.sn-revealed-card.sn-rc-rich .sn-natal-row:first-child {
  border-top: 0;
}
.sn-revealed-card.sn-rc-rich .sn-natal-glyph {
  font-family: var(--sn-mono);
  font-size: 12px;
  width: 16px;
  color: var(--sn-gold);
}
.sn-deck-view[data-active-pole="negative"] .sn-revealed-card.sn-rc-rich .sn-natal-glyph,
.sn-revealed-card.sn-rc-rich[data-card-pole="negative"] .sn-natal-glyph {
  color: var(--sn-oxblood);
}
.sn-revealed-card.sn-rc-rich .sn-natal-tag {
  font-family: var(--sn-mono);
  font-size: 9px;
  color: var(--sn-text-3);
  letter-spacing: 1.2px;
  width: 50px;
  padding-top: 2px;
}
.sn-revealed-card.sn-rc-rich .sn-natal-detail {
  font-family: var(--sn-mono);
  font-size: 10.5px;
  color: var(--sn-text-2);
}
.sn-revealed-card.sn-rc-rich .sn-natal-empty {
  font-family: var(--sn-body);
  font-size: 12.5px;
  color: var(--sn-text-2);
  padding: 4px 0;
}
.sn-revealed-card.sn-rc-rich .sn-natal-empty a {
  color: var(--sn-gold);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.sn-deck-view[data-active-pole="negative"] .sn-revealed-card.sn-rc-rich .sn-natal-empty a,
.sn-revealed-card.sn-rc-rich[data-card-pole="negative"] .sn-natal-empty a {
  color: var(--sn-oxblood);
}
.sn-revealed-card.sn-rc-rich .sn-card-footer {
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 8px;
  /* [Fix 2026-05-25 Bug 4] Bumped 34→40 + reduced bottom 10→8 to fit
     the metric pill (~14px including border) + 3px gap + the window-
     range line (~11px) + 6px top padding. Old 34px clipped the range
     line whenever the pill carried real content. */
  height: 40px;
  margin: 0;
  padding: 5px 0 0;
  border-top: 1px dashed rgba(214, 198, 255, 0.18);
  font-family: var(--sn-mono);
  font-size: 9px;
  letter-spacing: 0.4px;
  color: var(--sn-text-3);
  text-transform: lowercase;
  text-align: center;
  overflow: hidden;
  box-sizing: border-box;
  /* Stack the pill above the date line via flex so the two lines
     reliably honour the box's vertical budget. */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
}
.sn-revealed-card.sn-rc-rich .sn-card-footer .sn-cf-line {
  display: block;
  line-height: 1.25;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.sn-revealed-card.sn-rc-rich .sn-card-footer .sn-cf-range {
  color: var(--sn-text-2);
}
.sn-revealed-card.sn-rc-rich .sn-card-footer:empty {
  display: none;
}
.sn-revealed-card::before,
.sn-revealed-card::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  border: 1.2px solid rgba(233, 185, 106, 0.85);
}
.sn-revealed-card::after {
  inset: 6px;
  border-radius: 10px;          /* inset radius = outer 14 − inset 6 + tweak */
  border: 0.7px solid rgba(233, 185, 106, 0.55);
}

/* Side tone strip on the revealed card (4px left edge). Color depends
   on the card's pole: gold = highs, oxblood = lows, blue = future
   shifts. Pseudo-element pattern is already used by ::before/::after
   for the ornate frame, so we mount this on a dedicated span. */
.sn-revealed-card.sn-rc-rich .sn-rc-tone-strip {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 4px;
  border-radius: 1px;
  pointer-events: none;
  z-index: 2;
}
.sn-revealed-card.sn-rc-rich[data-card-pole="positive"] .sn-rc-tone-strip { background: var(--sn-gold); }
.sn-revealed-card.sn-rc-rich[data-card-pole="negative"] .sn-rc-tone-strip { background: var(--sn-oxblood); }
.sn-revealed-card.sn-rc-rich[data-card-pole="shifts"]   .sn-rc-tone-strip { background: #3a8fc8; }
.sn-revealed-card.sn-rc-rich[data-card-pole="beats"]    .sn-rc-tone-strip { background: #9b7cd4; }

.sn-rc-eyebrow-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-family: var(--sn-mono);
  font-size: 9.5px;
  letter-spacing: 0.16em;
  font-weight: 600;
  color: var(--sn-gold);
  text-transform: uppercase;
}
/* [Fix 2026-05-25 Bug 4] Right cluster of the eyebrow row holds the
   planet glyph + strength pill + (optional) double-signal chip in a
   single flex container. The wrapper guarantees the eyebrow row has
   exactly two direct children so `justify-content: space-between`
   anchors them at left + right edges. Without the wrapper each
   right-hand item became its own flex item and the middle one
   anchored to the row centre. */
.sn-rc-eyebrow-right {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
/* [Fix 2026-05-25 Bug 3] Extremes arrow glyph keeps the same shrunk
   size as ↑/↓ but tints with a neutral colour so it reads as a
   neither-direction swing. */
.sn-rc-polarity-arrow--extremes {
  opacity: 0.92;
}
/* Double Signal chip — small-caps badge next to the strength pill on
   shifts/beats that pair up within ±3 days on the same cluster. Sits
   inside .sn-rc-eyebrow-row alongside .sn-pattern-pill. */
.sn-rc-double-signal {
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 8px;
  font-family: var(--sn-mono);
  font-size: 7px;
  font-weight: 600;
  letter-spacing: 0.9px;
  text-transform: uppercase;
  color: var(--sn-text-3);
  border: 1px solid var(--sn-text-3);
  background: rgba(0, 0, 0, 0.15);
  opacity: 0.85;
}
/* Stylized Roman numeral inside the eyebrow (e.g. "↓ · IV"). Serif,
   italic, slightly larger, letter-spaced like a tarot card index. The
   eyebrow-left wraps arrow + sep + roman in a tight inline-flex so they
   read as one tarot-index token. */
.sn-rc-eyebrow-row .sn-rc-roman {
  font-family: var(--sn-display);
  font-style: italic;
  font-size: 13.5px;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: none;
  color: inherit;
  margin-left: 2px;
}
/* Dot separator between the polarity arrow and the Roman numeral. */
.sn-rc-eyebrow-row .sn-rc-sep {
  display: inline-block;
  margin: 0 4px;
  font-family: var(--sn-mono);
  font-size: 11px;
  font-weight: 700;
  color: var(--sn-text-3);
  opacity: 0.7;
  vertical-align: middle;
}
/* Roman numeral tinted in cluster color so the eyebrow-left reads as a
   single colored cluster-of-three token (arrow + dot + roman). Matches
   iOS where polarityArrow + middot + Roman all share the pole color. */
.sn-revealed-card[data-card-cluster="activity"] .sn-rc-eyebrow-row .sn-rc-roman {
  color: var(--sn-cluster-activity);
}
.sn-revealed-card[data-card-cluster="sleep"] .sn-rc-eyebrow-row .sn-rc-roman {
  color: var(--sn-cluster-sleep);
}
.sn-revealed-card[data-card-cluster="recovery"] .sn-rc-eyebrow-row .sn-rc-roman {
  color: var(--sn-cluster-recovery);
}
/* Natal-placement markers on the wheel — circle + glyph + tap target. */
.sn-natal-marker {
  cursor: pointer;
  transition: transform 0.12s ease;
}
.sn-natal-marker:hover {
  transform: scale(1.15);
  transform-origin: center;
}
/* Floating natal popover: small panel that anchors near the top of
   the revealed card whenever a natal marker is tapped. */
.sn-natal-popover {
  position: absolute;
  top: 36px;
  left: 50%;
  transform: translateX(-50%);
  width: 150px;
  padding: 0.55rem 0.65rem 0.65rem;
  background: var(--sn-violet-2);
  border: 1px solid var(--sn-hairline-2);
  border-radius: 10px;
  z-index: 12;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
  font-family: var(--sn-mono);
  color: var(--sn-text-2);
}
.sn-natal-popover[hidden] { display: none; }
.sn-natal-popover.is-personality {
  border-color: rgba(255, 255, 255, 0.55);
}
.sn-natal-popover.is-design {
  border-color: var(--sn-red);
}
.sn-natal-popover-close {
  position: absolute;
  top: 2px; right: 4px;
  background: transparent;
  border: 0;
  color: var(--sn-text-3);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 4px;
}
.sn-natal-popover-header {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 4px;
}
.sn-natal-popover-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  font-size: 11px;
  color: #fff;
  border: 1px solid #fff;
}
.sn-natal-popover.is-personality .sn-natal-popover-glyph {
  background: #000;
}
.sn-natal-popover.is-design .sn-natal-popover-glyph {
  background: var(--sn-red);
}
.sn-natal-popover-side {
  font-size: 8.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 600;
}
.sn-natal-popover.is-personality .sn-natal-popover-side {
  color: var(--sn-text);
}
.sn-natal-popover.is-design .sn-natal-popover-side {
  color: var(--sn-red);
}
.sn-natal-popover-title {
  font-size: 10.5px;
  color: var(--sn-text);
  line-height: 1.3;
}
.sn-natal-popover-gate {
  margin-top: 2px;
  font-size: 9.5px;
  color: var(--sn-text-3);
  letter-spacing: 0.04em;
}

/* Chip / strength-pill explanatory popover. Anchored inside the card,
   styled similarly to the natal-marker popover but wider (chip / pill
   copy is longer than a planet placement). Polarity-aware border tint. */
.sn-card-popover {
  position: absolute;
  /* Default centring; JS overrides with computed top/left from anchor. */
  top: 50%;
  left: 50%;
  transform: translateX(-50%);
  width: 220px;
  max-width: 90%;
  padding: 0.65rem 0.75rem 0.7rem;
  background: var(--sn-violet-2);
  border: 1px solid var(--sn-hairline-2);
  border-radius: 10px;
  z-index: 14;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
  font-family: var(--sn-mono);
  color: var(--sn-text-2);
}
.sn-card-popover[hidden] { display: none; }
.sn-card-popover.is-positive { border-color: var(--sn-gold); }
.sn-card-popover.is-negative { border-color: var(--sn-oxblood); }
.sn-card-popover.is-beat { border-color: rgba(155, 124, 212, 0.85); }
.sn-card-popover.is-shift { border-color: rgba(79, 195, 217, 0.85); }
.sn-card-popover-close {
  position: absolute;
  top: 2px; right: 4px;
  background: transparent;
  border: 0;
  color: var(--sn-text-3);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 4px;
}
.sn-card-popover-title {
  font-size: 9.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--sn-text);
  margin-bottom: 4px;
  padding-right: 14px;
}
.sn-card-popover.is-positive .sn-card-popover-title { color: var(--sn-gold); }
.sn-card-popover.is-negative .sn-card-popover-title { color: var(--sn-oxblood); }
.sn-card-popover-body {
  font-size: 10.5px;
  color: var(--sn-text);
  line-height: 1.45;
}
.sn-card-popover-body p {
  margin: 0;
}
.sn-card-popover-stat {
  margin-top: 6px;
  font-size: 9.5px;
  color: var(--sn-text-3);
  letter-spacing: 0.04em;
}
.sn-card-popover .sn-card-popover-body strong {
  color: inherit;
  font-weight: 600;
}
/* Chip / pill cursor affordance — the JS also adds these but having
   them in CSS keeps SSR / cached HTML happy. */
.sn-pattern-pill,
.sn-chip-row .sn-chip.active {
  cursor: pointer;
}
.sn-deck-view[data-active-pole="negative"] .sn-rc-eyebrow-row,
.sn-revealed-card.sn-rc-rich[data-card-pole="negative"] .sn-rc-eyebrow-row {
  color: var(--sn-oxblood);
}
.sn-rc-strength-pill {
  display: inline-flex;
  padding: 3px 10px;
  border-radius: 999px;
  font-family: var(--sn-mono);
  font-size: 9px;
  letter-spacing: 0.16em;
  font-weight: 600;
  color: var(--sn-gold);
  border: 1px solid var(--sn-gold);
  background: rgba(233, 185, 106, 0.15);
  text-transform: uppercase;
}
.sn-deck-view[data-active-pole="negative"] .sn-rc-strength-pill,
.sn-revealed-card.sn-rc-rich[data-card-pole="negative"] .sn-rc-strength-pill {
  color: var(--sn-oxblood);
  border-color: var(--sn-oxblood);
  background: rgba(196, 80, 76, 0.15);
}

.sn-rc-headline {
  font-family: var(--sn-display);
  font-weight: 300;
  font-size: 19px;
  line-height: 1.32;
  color: var(--sn-text);
  margin: 0;
}
.sn-rc-headline .sn-sign-pos { color: var(--sn-gold); font-weight: 700; }
.sn-rc-headline .sn-sign-neg { color: var(--sn-oxblood); font-weight: 700; }

.sn-rc-meta {
  font-family: var(--sn-mono);
  font-size: 10px;
  letter-spacing: 0.04em;
  color: var(--sn-text-3);
  margin: 0;
}

.sn-rc-wheel {
  width: 100%;
  display: flex;
  justify-content: center;
  margin: 4px 0 6px;
}
.sn-rc-wheel svg { display: block; max-width: 100%; }

.sn-rc-planet-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 2px 0 4px;
}
.sn-rc-planet-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 5px 9px;
  border-radius: 999px;
  border: 0.8px solid var(--sn-hairline-2);
  background: rgba(20, 16, 42, 0.55);
  color: var(--sn-text-3);
  font-family: var(--sn-mono);
  font-size: 10px;
  letter-spacing: 0.04em;
  font-weight: 500;
}
.sn-rc-planet-pill.active {
  color: var(--sn-gold);
  border-color: var(--sn-gold);
  background: rgba(233, 185, 106, 0.16);
}
.sn-deck-view[data-active-pole="negative"] .sn-rc-planet-pill.active,
.sn-revealed-card.sn-rc-rich[data-card-pole="negative"] .sn-rc-planet-pill.active {
  color: var(--sn-oxblood);
  border-color: var(--sn-oxblood);
  background: rgba(196, 80, 76, 0.16);
}
.sn-rc-planet-glyph { font-size: 11px; }

.sn-rc-narrative {
  font-family: var(--sn-body);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--sn-text-2);
  margin: 0;
}

/* ─── Settings panel cards ──────────────────────────────── */
.signal-settings-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  margin-bottom: 2rem;
}
@media (min-width: 720px) {
  .signal-settings-grid {
    grid-template-columns: 1fr 1fr;
  }
}

.signal-settings-card {
  background: var(--sn-violet);
  border: 1px solid var(--sn-hairline);
  border-radius: 14px;
  padding: 1.5rem 1.75rem;
}
.signal-settings-provider {
  font-family: var(--sn-display);
  font-size: 1.6rem;
  font-weight: 400;
  color: var(--sn-text);
  margin: 0.25rem 0 0.5rem;
  text-transform: capitalize;
  letter-spacing: -0.01em;
}
.signal-settings-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1rem;
}

/* ─── Empty / placeholder copy on the placeholder card ──── */
.sn-card-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
}
.sn-card-placeholder .sn-card-glyph {
  position: relative;
  left: auto;
  top: auto;
  margin: 0;
}
.sn-card-placeholder .sn-card-cta {
  position: relative;
  inset: auto;
}

/* ─── New Hero (state-1 / state-2 logged-out + connect-prompt) ───────
   Two-column layout: copy on the left, stylized iPhone with mandala
   wheel on the right. Cosmic backdrop with starfield + radial glow.
   Stacks on mobile.
*/
.signal-main .sn-hero {
  position: relative;
  margin: 0 auto 3.5rem;
  padding: 3.25rem 1.5rem 3rem;
  max-width: 1180px;
  border-radius: 24px;
  overflow: hidden;
  isolation: isolate;
}

/* Starfield: scattered radial-gradient dots layered with stagger. Pure
   CSS so we don't ship another image. */
.signal-main .sn-hero-stars {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background-image:
    radial-gradient(1px 1px at 12% 18%, rgba(255,255,255,0.55), transparent 50%),
    radial-gradient(1px 1px at 28% 62%, rgba(255,255,255,0.40), transparent 50%),
    radial-gradient(1.5px 1.5px at 41% 28%, rgba(233,185,106,0.65), transparent 50%),
    radial-gradient(1px 1px at 55% 76%, rgba(255,255,255,0.50), transparent 50%),
    radial-gradient(1px 1px at 68% 12%, rgba(255,255,255,0.55), transparent 50%),
    radial-gradient(1.2px 1.2px at 78% 48%, rgba(214,198,255,0.55), transparent 50%),
    radial-gradient(1px 1px at 88% 84%, rgba(255,255,255,0.45), transparent 50%),
    radial-gradient(1px 1px at 8% 88%, rgba(255,255,255,0.35), transparent 50%),
    radial-gradient(1.4px 1.4px at 33% 8%, rgba(233,185,106,0.5), transparent 50%),
    radial-gradient(1px 1px at 62% 38%, rgba(255,255,255,0.40), transparent 50%);
  opacity: 0.85;
}

/* Soft purple→gold glow behind copy column */
.signal-main .sn-hero-glow {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(ellipse 60% 70% at 18% 30%, rgba(122, 76, 178, 0.22), transparent 60%),
    radial-gradient(ellipse 45% 55% at 78% 65%, rgba(233, 185, 106, 0.12), transparent 60%);
}

.signal-main .sn-hero-grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: 3.5rem;
  align-items: center;
}

/* Copy column */
.signal-main .sn-hero-eyebrow {
  font-family: var(--sn-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--sn-gold);
  margin: 0 0 1.4rem;
}

.signal-main .sn-hero-headline {
  font-family: var(--sn-display);
  font-size: clamp(2rem, 4.4vw, 3.4rem);
  font-weight: 600;
  line-height: 1.06;
  letter-spacing: -0.018em;
  color: var(--sn-text);
  margin: 0 0 1.4rem;
  text-wrap: balance;
}

.signal-main .sn-hero-sub {
  font-family: var(--sn-body);
  font-size: clamp(1rem, 1.25vw, 1.125rem);
  line-height: 1.6;
  color: var(--sn-text-2);
  margin: 0 0 2rem;
  max-width: 36ch;
}

.signal-main .sn-hero-cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 0 0 2.4rem;
}

.signal-main .sn-hero-compat-label {
  font-family: var(--sn-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sn-text-3);
  margin: 0 0 0.7rem;
  font-weight: 500;
}

.signal-main .sn-hero-compat-row {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
}

.signal-main .sn-hero-compat-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.3rem 0.75rem 0.3rem 0.35rem;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--sn-text-2);
  background: var(--sn-violet-2);
  border: 1px solid var(--sn-hairline-2);
}

.signal-main .sn-hero-compat-chip-icon {
  width: 22px;
  height: 22px;
  border-radius: 5px;
  object-fit: cover;
  object-position: center;
  flex-shrink: 0;
  display: block;
}

.signal-main .sn-hero-compat-chip--more {
  background: transparent;
  border-color: transparent;
  color: var(--sn-text-3);
  padding: 0.45rem 0.25rem;
  font-style: italic;
}

/* ─── Device mockup (right column) ─────────────────────────── */
.signal-main .sn-hero-device {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  perspective: 1200px;
}

.signal-main .sn-hero-device-frame {
  position: relative;
  width: 280px;
  aspect-ratio: 280 / 580;
  border-radius: 38px;
  background: linear-gradient(165deg, #1f1936 0%, #0c0917 70%);
  padding: 10px;
  box-shadow:
    0 0 0 1.5px rgba(214, 198, 255, 0.18),
    0 0 0 4px rgba(20, 16, 42, 0.85),
    0 30px 60px -15px rgba(0, 0, 0, 0.7),
    0 0 90px rgba(122, 76, 178, 0.30);
  transform: rotate(2.5deg);
  transition: transform 0.5s ease;
}
.signal-main .sn-hero-device:hover .sn-hero-device-frame {
  transform: rotate(0deg);
}

.signal-main .sn-hero-device-notch {
  position: absolute;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  width: 90px;
  height: 22px;
  background: #050309;
  border-radius: 14px;
  z-index: 2;
}

.signal-main .sn-hero-device-screen {
  width: 100%;
  height: 100%;
  border-radius: 30px;
  background: radial-gradient(ellipse at top, #1c1740 0%, #0c0917 60%);
  padding: 44px 18px 22px;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* When the device screen hosts the literal Mandala-card screenshot,
   drop the inner padding so the image fills the bezel edge-to-edge. */
.signal-main .sn-hero-device-screen--image {
  padding: 0;
  background: #0c0917;
}
.signal-main .sn-hero-device-shot {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}

.signal-main .sn-hero-device-statusbar {
  position: absolute;
  top: 18px;
  left: 22px;
  right: 22px;
  display: flex;
  justify-content: space-between;
  font-family: var(--sn-mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--sn-text);
  letter-spacing: 0.02em;
  z-index: 1;
}
.signal-main .sn-hero-device-statusbar-icons {
  color: var(--sn-text-2);
}

.signal-main .sn-hero-device-eyebrow {
  font-family: var(--sn-mono);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--sn-text-3);
  text-align: center;
  margin: 0 0 0.6rem;
}

.signal-main .sn-hero-device-pole {
  display: flex;
  justify-content: center;
  gap: 0.25rem;
  margin: 0 auto 0.9rem;
  padding: 3px;
  border-radius: 999px;
  background: var(--sn-violet-2);
  border: 1px solid var(--sn-hairline);
  width: fit-content;
}
.signal-main .sn-hero-device-pole-btn {
  font-family: var(--sn-body);
  font-size: 9.5px;
  font-weight: 500;
  padding: 4px 9px;
  border-radius: 999px;
  color: var(--sn-text-3);
}
.signal-main .sn-hero-device-pole-btn.active {
  background: rgba(233, 185, 106, 0.18);
  color: var(--sn-gold);
}

.signal-main .sn-hero-device-wheel {
  width: 100%;
  aspect-ratio: 1;
  margin: 0.4rem 0 0.6rem;
}

.signal-main .sn-hero-device-caption {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.4rem;
  font-family: var(--sn-display);
  margin: 0 0 0.3rem;
}
.signal-main .sn-hero-device-glyph {
  font-size: 14px;
  color: var(--sn-gold);
}
.signal-main .sn-hero-device-sign {
  font-size: 13px;
  font-weight: 500;
  color: var(--sn-text);
  letter-spacing: 0.01em;
}

.signal-main .sn-hero-device-meta {
  font-family: var(--sn-mono);
  font-size: 9px;
  font-weight: 400;
  color: var(--sn-text-3);
  text-align: center;
  margin: 0 0 0.7rem;
}
.signal-main .sn-hero-device-meta-dot { margin: 0 0.3rem; }

.signal-main .sn-hero-device-pills {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.25rem;
}
.signal-main .sn-hero-device-pill {
  font-family: var(--sn-mono);
  font-size: 8.5px;
  font-weight: 500;
  padding: 3px 7px;
  border-radius: 999px;
  background: var(--sn-violet-2);
  border: 0.5px solid var(--sn-hairline);
  color: var(--sn-text-3);
  letter-spacing: 0.02em;
}
.signal-main .sn-hero-device-pill.active {
  background: rgba(233, 185, 106, 0.16);
  border-color: rgba(233, 185, 106, 0.5);
  color: var(--sn-gold);
}

/* ─── Hero Mandala-card preview ────────────────────────────────
   Replaces the legacy device-wheel mockup with a tarot-style card
   preview that mirrors the new Mandala draw screen Eva ships in the
   iOS reference designs. Lives inside the existing .sn-hero-device
   frame so the iPhone bezel + shadow + scale are unchanged. */
.signal-main .sn-hero-card-tagline {
  font-family: var(--sn-display);
  font-size: 11px;
  font-style: italic;
  line-height: 1.35;
  text-align: center;
  color: var(--sn-text-2);
  margin: 0.4rem 0.6rem 0.55rem;
}
.signal-main .sn-hero-card {
  position: relative;
  margin: 0 0.45rem 0.6rem;
  padding: 0.55rem 0.65rem 0.5rem;
  border-radius: 12px;
  border: 1px solid rgba(233, 185, 106, 0.5);
  background: linear-gradient(180deg, rgba(28, 23, 64, 0.85), rgba(12, 9, 23, 0.95));
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4), inset 0 0 0 1px rgba(233, 185, 106, 0.08);
}
.signal-main .sn-hero-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 0 0.45rem;
  gap: 0.4rem;
}
.signal-main .sn-hero-card-eyebrow {
  font-family: var(--sn-mono);
  font-size: 7px;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: var(--sn-gold);
  text-transform: uppercase;
}
.signal-main .sn-hero-card-eyebrow--mt {
  display: block;
  margin: 0.5rem 0 0.25rem;
  color: var(--sn-text-3);
  letter-spacing: 0.14em;
}
.signal-main .sn-hero-card-pill {
  font-family: var(--sn-mono);
  font-size: 6.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  padding: 3px 7px;
  border-radius: 999px;
  border: 1px solid rgba(233, 185, 106, 0.7);
  color: var(--sn-gold);
  text-transform: uppercase;
}
.signal-main .sn-hero-card-headline {
  font-family: var(--sn-body);
  font-size: 9.5px;
  line-height: 1.35;
  font-weight: 500;
  color: var(--sn-text);
  margin: 0 0 0.4rem;
}
.signal-main .sn-hero-card-meta {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  font-family: var(--sn-mono);
  font-size: 7px;
  letter-spacing: 0.05em;
  color: var(--sn-text-2);
  margin: 0 0 0.35rem;
}
.signal-main .sn-hero-card-dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--sn-text-2);
  display: inline-block;
}
.signal-main .sn-hero-card-wheel {
  width: 100%;
  aspect-ratio: 1;
  margin: 0.1rem 0 0.3rem;
}
.signal-main .sn-hero-card-wheel svg {
  width: 100%;
  height: 100%;
  display: block;
}
.signal-main .sn-hero-card-body {
  font-family: var(--sn-body);
  font-size: 8px;
  line-height: 1.45;
  color: var(--sn-text-2);
  margin: 0 0 0.4rem;
}
.signal-main .sn-hero-card-body strong { color: var(--sn-text); font-weight: 600; }
.signal-main .sn-hero-card-foot {
  border-top: 1px dashed rgba(184, 174, 224, 0.18);
  padding-top: 0.3rem;
  font-family: var(--sn-mono);
  font-size: 7px;
  letter-spacing: 0.08em;
  color: var(--sn-text-3);
  text-align: center;
}
.signal-main .sn-hero-card-strip {
  display: flex;
  gap: 0.25rem;
  padding: 0 0.45rem;
  overflow: hidden;
}
.signal-main .sn-hero-card-thumb {
  flex: 1 1 0;
  min-width: 0;
  aspect-ratio: 5 / 7;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 5px;
  border: 1px solid rgba(233, 185, 106, 0.35);
  background: linear-gradient(180deg, rgba(28, 23, 64, 0.85), rgba(12, 9, 23, 0.95));
  font-family: var(--sn-mono);
  font-size: 6.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--sn-text-2);
  text-transform: uppercase;
}
.signal-main .sn-hero-card-thumb--clock {
  background: linear-gradient(180deg, rgba(60, 50, 100, 0.85), rgba(20, 15, 50, 0.95));
  color: var(--sn-gold);
}
.signal-main .sn-hero-card-thumb--empty {
  border-style: dashed;
  background: transparent;
  color: transparent;
}

/* Soft floor shadow */
.signal-main .sn-hero-device-shadow {
  position: absolute;
  bottom: -20px;
  left: 50%;
  transform: translateX(-50%);
  width: 70%;
  height: 24px;
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(122, 76, 178, 0.32), transparent 70%);
  filter: blur(10px);
  z-index: -1;
}

/* ─── Responsive: stack on tablets/mobile ───────────────────── */
@media (max-width: 900px) {
  .signal-main .sn-hero {
    padding: 2.25rem 1rem 2rem;
    margin-bottom: 2.5rem;
  }
  .signal-main .sn-hero-grid {
    grid-template-columns: 1fr;
    gap: 2.5rem;
    text-align: center;
  }
  .signal-main .sn-hero-sub {
    margin-left: auto;
    margin-right: auto;
  }
  .signal-main .sn-hero-cta-row,
  .signal-main .sn-hero-compat-row {
    justify-content: center;
  }
  .signal-main .sn-hero-headline br { display: none; }
  .signal-main .sn-hero-device-frame {
    width: 240px;
    transform: rotate(0deg);
  }
}
@media (max-width: 480px) {
  .signal-main .sn-hero-device-frame { width: 210px; }
}

/* ─── Mobile: bottom tab bar (legacy — now replaced by .signal-tabbar-bottom) ─── */
/* The .signal-view-switcher-top markup is no longer emitted; these
   rules are kept inert to avoid breaking any cached references. The
   new fixed bottom nav lives in its own block at the end of this file. */
.signal-seg-btn-icon { display: none; }
.signal-seg-btn-label { display: inline; }

@media (max-width: 640px) {
  /* Legacy: previously pinned the old top-tab segmented control to the
     bottom on mobile. The HTML for that has been removed; rules below
     are dead-code retained as a safety net. */
  .signal-view-switcher-top {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 50;
    margin: 0;
    padding: 6px 12px calc(6px + env(safe-area-inset-bottom));
    background: var(--sn-violet, #14102a);
    border-top: 1px solid var(--sn-hairline-2, rgba(214, 198, 255, 0.18));
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
  }
  .signal-view-switcher-top .signal-segment {
    width: 100%;
    max-width: none;
    background: transparent;
    border: 0;
    border-radius: 0;
    display: flex;
    justify-content: space-around;
    gap: 4px;
    padding: 0;
  }
  .signal-view-switcher-top .signal-seg-btn {
    flex: 1 1 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 6px 4px 4px;
    min-height: 48px;
    background: transparent;
    border: 0;
    border-top: 2px solid transparent;
    border-radius: 0;
    color: var(--sn-text-3, #9a93b8);
    font-size: 10px;
    font-family: var(--sn-mono, 'JetBrains Mono', monospace);
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }
  .signal-view-switcher-top .signal-seg-btn .signal-seg-btn-icon {
    display: block;
    width: 22px;
    height: 22px;
  }
  .signal-view-switcher-top .signal-seg-btn .signal-seg-btn-label {
    display: block;
    font-size: 10px;
    line-height: 1;
  }
  .signal-view-switcher-top .signal-seg-btn:hover {
    background: transparent;
    color: var(--sn-text-2, #d6c6ff);
  }
  .signal-view-switcher-top .signal-seg-btn.active {
    color: var(--sn-gold, #e9b96a);
    border-top-color: var(--sn-gold, #e9b96a);
    background: rgba(233, 185, 106, 0.06);
  }
  /* Bodygraph and Settings panels keep their natural scroll, but
     reserve room for the bottom tab bar so the last content
     doesn't disappear under it. */
  .signal-view[data-view-panel="bodygraph"],
  .signal-view[data-view-panel="settings"] {
    padding-bottom: calc(var(--sn-tabbar-bottom) + 1rem);
  }
  /* Mandala stays no-scroll on mobile. The desktop height calc
     subtracts 4.25rem for the TOP tab pill row — but on mobile
     those tabs are pinned to the BOTTOM (position:fixed), so the
     top row contributes 0px. Override the height calc to remove
     that phantom 4.25rem reservation — that's the source of the
     gap Eva saw between the card/deck and the bottom tab bar. */
  .sn-deck-view {
    padding: 0.25rem 0 0;       /* no bottom pad — deck sits flush against tab bar */
    min-height: 0;
    height: calc(
      100vh
      - var(--sn-chrome-top)
      - var(--sn-tabbar-bottom)
      - 0.5rem    /* minimal breathing room */
    );
  }
  .sn-deck-view .sn-deck-stage {
    gap: 0.4rem;
  }
  .sn-deck-hero {
    /* History strip at bottom:12, height:72 → occupies bottom 84px on
       mobile. Reserve 140px so the card has ~56px of breathing room
       above the thumbnail row, matching the desktop ratio. */
    padding: 0.25rem 12px 140px 12px;
  }
  /* On mobile the bottom tab bar is pinned at the bottom — keep the
     draw deck at the bottom-left, and the drawn-cards row to its right. */
  .sn-draw-deck-wrap {
    left: 12px;
    bottom: 12px;
  }
  .sn-history-strip {
    left: 74px;            /* 12 + 50 + 12 gap */
    right: 8px;
    bottom: 12px;
    height: 72px;
  }
  .sn-history-row {
    padding: 0 2px;
  }
}

/* ──────────────────────────────────────────────────────────────────────
 * [v2] Window-date badge — small pill in the revealed card footer.
 * ────────────────────────────────────────────────────────────────────── */
.sn-card-window {
  display: inline-block;
  margin-top: 6px;
  padding: 3px 8px;
  border-radius: 999px;
  border: 1px solid rgba(196, 154, 108, 0.35);
  background: rgba(196, 154, 108, 0.06);
  font-family: 'JetBrains Mono', 'Menlo', monospace;
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-secondary, #9a9690);
  white-space: nowrap;
}
.sn-card-footer .sn-card-window {
  margin-left: 0;
}

/* ──────────────────────────────────────────────────────────────────────
 * Senary deck cover (mockup 02) — face-down card art used everywhere a
 * face-down card shows on the Signal page. Replaces the old
 * .sn-card-back diagonal-weave + concentric-rings treatment.
 *
 * Construction (per /ios/Reference_design/Cards/02 ...):
 *   - 90×131 proportions (keeps with iOS RevealedCard)
 *   - body fill: dual radial-gradient + linear-gradient (deep violet)
 *   - gold inset DOUBLE frame via inset-shadow + nested ::before/::after
 *   - 4 corner brackets (gold)
 *   - 8 gold dust dots (radial-gradient backgrounds at fixed positions)
 *   - central nested-hex sigil at 5 scales (1.0, 0.78, 0.56, 0.34, 0.16);
 *     outer 4 stroked, innermost filled — inlined as data-URI SVG so the
 *     same artwork scales on the hero, draw deck, and history thumbs.
 * ────────────────────────────────────────────────────────────────────── */

:root {
  --sn-deck-gold: #e9b96a;
  --sn-deck-oxblood: #c4504c;
}

.sn-deck-cover {
  position: relative;
  display: block;
  width: 240px;
  aspect-ratio: 90 / 131;
  /* Soft cusp/rounded rectangle. The mockup uses ~2px corner radius;
     keep it tight so the gold frame reads cleanly. */
  border-radius: 4px;
  overflow: hidden;
  /* Body fill: layered radial highlights + base linear gradient.
     The radial at center brightens the middle; the off-center radial
     gives subtle volume; the linear is the deep-violet base. */
  background:
    radial-gradient(ellipse 70% 60% at 50% 42%,
      rgba(96, 60, 168, 0.45) 0%, rgba(96, 60, 168, 0) 65%),
    radial-gradient(ellipse 80% 55% at 50% 90%,
      rgba(40, 22, 80, 0.5) 0%, rgba(40, 22, 80, 0) 70%),
    linear-gradient(180deg, #261248 0%, #1a0b34 50%, #120726 100%);
  /* The gold double frame: outer brighter, inner thinner. Implemented
     as a stack of inset box-shadows so we can keep the corner-bracket
     and dust dots as separate pseudo-elements without fighting borders. */
  box-shadow:
    inset 0 0 0 1px rgba(233, 185, 106, 0.85),   /* outer gold */
    inset 0 0 0 2px rgba(0, 0, 0, 0.6),          /* dark separator */
    inset 0 0 0 3px rgba(233, 185, 106, 0.55),   /* inner gold */
    0 12px 24px rgba(0, 0, 0, 0.45),             /* drop shadow */
    0 0 18px rgba(164, 137, 212, 0.18);          /* mauve halo */
}

/* The inner body that hosts the sigil + dust + corner brackets. We use
   a separate <span> child so we can layer pseudo-elements without
   conflicting with the parent's box-shadow stack. */
.sn-deck-cover-body {
  position: absolute;
  inset: 6px;
  display: block;
  pointer-events: none;
  /* central nested-hex sigil — inlined SVG as a background-image data URI.
     5 scales of the Senary mark hex (path from SenaryMark.swift), the
     outermost stroked thickly, descending opacity/width, innermost filled
     as a small dot. Position centered with no-repeat. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'>\
<g transform='translate(-284 -29)'>\
<path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='none' stroke='%23e9b96a' stroke-width='2.4' stroke-linejoin='miter'/>\
<g transform='translate(334 79) scale(0.78) translate(-334 -79)'><path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='none' stroke='%23e9b96a' stroke-opacity='0.55' stroke-width='1.0'/></g>\
<g transform='translate(334 79) scale(0.56) translate(-334 -79)'><path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='none' stroke='%23e9b96a' stroke-opacity='0.385' stroke-width='0.9'/></g>\
<g transform='translate(334 79) scale(0.34) translate(-334 -79)'><path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='none' stroke='%23e9b96a' stroke-opacity='0.275' stroke-width='0.8'/></g>\
<g transform='translate(334 79) scale(0.16) translate(-334 -79)'><path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='%23e9b96a' fill-opacity='0.85'/></g>\
</g></svg>");
  background-repeat: no-repeat;
  background-position: 50% 50%;
  /* The hex sigil reads cleanest at ~38% of the card width. */
  background-size: 42% auto;
}

/* Corner brackets — 4 small L-shapes at the inset corners, drawn as
   pseudo-elements via clipped borders. Using a single ::before/::after
   would only get us 2 corners; instead we use an extra pair on the body
   element for the bottom corners. */
.sn-deck-cover-body::before,
.sn-deck-cover-body::after {
  content: '';
  position: absolute;
  width: 14%;
  height: 10%;
  border: 1px solid rgba(233, 185, 106, 0.75);
  pointer-events: none;
}
.sn-deck-cover-body::before {
  /* top-left bracket */
  top: 6%;
  left: 6%;
  border-right: 0;
  border-bottom: 0;
}
.sn-deck-cover-body::after {
  /* top-right bracket */
  top: 6%;
  right: 6%;
  border-left: 0;
  border-bottom: 0;
}
.sn-deck-cover::before,
.sn-deck-cover::after {
  content: '';
  position: absolute;
  width: 14%;
  height: 10%;
  border: 1px solid rgba(233, 185, 106, 0.75);
  pointer-events: none;
  z-index: 2;
}
.sn-deck-cover::before {
  /* bottom-left bracket */
  bottom: 6%;
  left: 6%;
  border-right: 0;
  border-top: 0;
}
.sn-deck-cover::after {
  /* bottom-right bracket */
  bottom: 6%;
  right: 6%;
  border-left: 0;
  border-top: 0;
}

/* 8 gold dust dots — positioned per mockup 02. The dust SVG in the mockup
   places dots in normalized 90×131 coordinates; we map to percentages so
   the same composition scales with the card. Each dot is a small
   radial-gradient inside its own slot, scaled to card width. */
.sn-deck-cover .sn-deck-cover-body {
  /* override single background-image with sigil + 8 dots layered.
     First image = sigil; remaining 8 = dust dots. */
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'>\
<g transform='translate(-284 -29)'>\
<path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='none' stroke='%23e9b96a' stroke-width='2.4' stroke-linejoin='miter'/>\
<g transform='translate(334 79) scale(0.78) translate(-334 -79)'><path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='none' stroke='%23e9b96a' stroke-opacity='0.55' stroke-width='1.0'/></g>\
<g transform='translate(334 79) scale(0.56) translate(-334 -79)'><path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='none' stroke='%23e9b96a' stroke-opacity='0.385' stroke-width='0.9'/></g>\
<g transform='translate(334 79) scale(0.34) translate(-334 -79)'><path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='none' stroke='%23e9b96a' stroke-opacity='0.275' stroke-width='0.8'/></g>\
<g transform='translate(334 79) scale(0.16) translate(-334 -79)'><path d='m371.36 110.8l-46.08 16.45-37.28-31.67 8.79-48.13 46.07-16.45 37.29 31.68z' fill='%23e9b96a' fill-opacity='0.85'/></g>\
</g></svg>"),
    /* 8 dust dots — positions per mockup. radial-gradient simulates a
       tiny soft circle of gold. */
    radial-gradient(circle, rgba(233,185,106,0.30) 0 35%, transparent 60%),
    radial-gradient(circle, rgba(233,185,106,0.38) 0 35%, transparent 60%),
    radial-gradient(circle, rgba(233,185,106,0.46) 0 35%, transparent 60%),
    radial-gradient(circle, rgba(233,185,106,0.54) 0 35%, transparent 60%),
    radial-gradient(circle, rgba(233,185,106,0.30) 0 35%, transparent 60%),
    radial-gradient(circle, rgba(233,185,106,0.38) 0 35%, transparent 60%),
    radial-gradient(circle, rgba(233,185,106,0.46) 0 35%, transparent 60%),
    radial-gradient(circle, rgba(233,185,106,0.54) 0 35%, transparent 60%);
  background-repeat: no-repeat;
  /* Sigil first; then dust dots clockwise from top-left.
     Mockup coords (90×131): (16.2,28.8)=18%,22%; (70.2,26.2)=78%,20%;
     (19.8,96.9)=22%,74%; (75.6,94.3)=84%,72%; (10.8,60.3)=12%,46%;
     (82.8,55.0)=92%,42%; (45,13.1)=50%,10%; (45,123.1)=50%,94%. */
  background-position:
    50% 50%,
    18% 22%,
    78% 20%,
    22% 74%,
    84% 72%,
    12% 46%,
    92% 42%,
    50% 10%,
    50% 94%;
  background-size:
    42% auto,
    3px 3px,
    3px 3px,
    3px 3px,
    3px 3px,
    3px 3px,
    3px 3px,
    3px 3px,
    3px 3px;
}

/* Reset the body's ::before/::after corner brackets (they would otherwise
   inherit the multi-bg stack above). They're already declared with their
   own border, so nothing to do — but the bg-image cascade reset above
   strips the single-bg fallback. */

/* CTA label on the top card (only shown when interactive). */
.sn-deck-cover-cta {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 12%;
  z-index: 3;
  font-family: var(--sn-mono);
  font-size: 9px;
  letter-spacing: 0.22em;
  color: rgba(233, 185, 106, 0.85);
  text-transform: uppercase;
  font-weight: 600;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
}

/* The top card needs to be a real button so taps work. Reset native
   styles. */
button.sn-deck-cover {
  background-color: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  font: inherit;
  color: inherit;
}
button.sn-deck-cover:hover { filter: brightness(1.06); }
button.sn-deck-cover:active { transform: scale(0.98); }

/* Stack 4 deck covers with subtle tilts and offsets — back 3 get
   reduced brightness and pointer-events:none. */
.sn-deck-stack {
  position: relative;
  display: inline-block;
}
.sn-deck-stack .sn-deck-cover {
  position: absolute;
  top: 0;
  left: 0;
  transition: transform 0.18s ease;
}
/* Top card is the alignment reference — pinned straight at (0,0). Cards
   behind it fan outward in one direction so the user reads the top card
   as "the card" and the rest as "the deck underneath". */
.sn-deck-stack .sn-deck-cover--back-3 {
  transform: rotate(4.5deg) translate(9px, 9px);
  filter: brightness(0.85);
  pointer-events: none;
}
.sn-deck-stack .sn-deck-cover--back-2 {
  transform: rotate(3deg) translate(6px, 6px);
  filter: brightness(0.85);
  pointer-events: none;
}
.sn-deck-stack .sn-deck-cover--back-1 {
  transform: rotate(1.5deg) translate(3px, 3px);
  filter: brightness(0.85);
  pointer-events: none;
}
.sn-deck-stack .sn-deck-cover--top {
  transform: rotate(0deg) translate(0, 0);
  position: relative; /* sets the stack's bounding box */
}

/* Hero-scale deck stack — fills available height in the hero zone. */
.sn-deck-stack-hero {
  /* Match existing .sn-card 240×340 footprint; revealed card uses these
     dimensions so the stack feels comparable. The covers themselves are
     constrained by their 90/131 aspect ratio. */
  width: 240px;
  height: 349px;     /* 240 * 131/90 ≈ 349 */
}
.sn-deck-stack-hero .sn-deck-cover {
  width: 240px;
  height: 349px;
}

@media (max-width: 640px) {
  .sn-deck-stack-hero,
  .sn-deck-stack-hero .sn-deck-cover {
    width: 200px;
    height: 291px;  /* 200 * 131/90 */
  }
}

/* ──────────────────────────────────────────────────────────────────────
 * Radial countdown ring (mockups 05/07) — 117×117 SVG centered over the
 * hero deck cover when in cooldown. Tint switches gold → oxblood when
 * fractionRemaining < 25%; cross-fade between 30% and 25% via CSS
 * transition on the wrapper's color value (the ring uses currentColor).
 * ────────────────────────────────────────────────────────────────────── */
.sn-countdown {
  position: absolute;
  /* Anchored over the small bottom-left draw deck (50×72 at left:16,
     bottom:16; center = (41, 52) from body bottom-left). 64×64 ring
     centered on that point ⇒ left:9, bottom:20. The revealed card on
     the hero stays unobstructed. */
  left: 9px;
  bottom: 20px;
  width: 64px;
  height: 64px;
  /* Pointer-events were `none` historically so the ring stayed purely
     decorative, but Eva asked for tap-to-explain on the ring (#52).
     Enabling pointer-events here is safe because the [hidden] attribute
     fully unmounts the element when not in cooldown. */
  pointer-events: auto;
  cursor: pointer;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--sn-deck-gold);
  /* Smooth gold→oxblood crossfade for the ring (uses currentColor on
     strokes/fills inside the SVG) AND the digit text. */
  transition: color 0.4s ease-in-out;
}
@media (max-width: 640px) {
  /* Mobile deck is at left:12, bottom:12 → center (37, 48). 56×56 ring
     centered on that point ⇒ left:9, bottom:20. */
  .sn-countdown { width: 56px; height: 56px; left: 9px; bottom: 20px; }
}
/* While the countdown is active, hide the "tap to draw" CTA on the hero
   deck so the ring reads as the only call-to-action. Uses :has() on the
   shared parent .sn-deck-body. */
.sn-deck-body:has(.sn-countdown:not([hidden])) .sn-deck-cover-cta {
  display: none;
}
/* During cooldown the ring lives over the small bottom-left deck
   (so the revealed card on the hero stays unobstructed). The CTA on
   the hero deck stack still gets hidden via the rule above so the
   placeholder doesn't say "Tap to draw" when the user can't. */
.sn-countdown[hidden] { display: none; }

/* Near-end tint: switch to oxblood once fractionRemaining < 25%.
   Driven by JS toggling the .is-near-end class on the wrapper. */
.sn-countdown.is-near-end {
  color: var(--sn-deck-oxblood);
}

.sn-countdown-ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* drop-shadow glow matching the tint via filter (filter doesn't
     pick up currentColor, so use a layered transition on color). */
  filter: drop-shadow(0 0 6px rgba(233, 185, 106, 0.45));
  transition: filter 0.4s ease-in-out;
}
.sn-countdown.is-near-end .sn-countdown-ring {
  filter: drop-shadow(0 0 6px rgba(196, 80, 76, 0.5));
}

.sn-countdown-text {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  pointer-events: none;
  text-align: center;
}
.sn-countdown-digits {
  font-family: 'Outfit', var(--sn-display), system-ui, sans-serif;
  font-weight: 500;
  /* Tight type for the small 64px ring sitting over the deck. */
  font-size: 10px;
  letter-spacing: 0.02em;
  color: currentColor;
  line-height: 1;
  text-shadow: 0 0 4px currentColor;
}
@media (max-width: 640px) {
  .sn-countdown-digits { font-size: 9px; }
}
.sn-countdown-sub {
  font-family: var(--sn-mono);
  /* Subtitle is suppressed at this scale — the small ring is its own
     label, and forcing tiny text just creates visual noise. */
  display: none;
}

/* ──────────────────────────────────────────────────────────────────────
 * Bottom tab bar — mirrors the iOS app's bottom nav. Fixed to the
 * viewport bottom on all sizes. Image icons (PNG/WebP) from
 * /assets/tab-icons/, with active state shown by full opacity + small
 * gold pill underneath the label and a soft drop-shadow glow on the
 * active icon. Inactive icons render at 0.55 opacity.
 *
 * Layout: 4 equal-width buttons via flex:1. Mono uppercase labels at
 * 10px; below 360px wide, labels disappear (icon-only).
 *
 * Sits inside #signal-data; .signal-main reserves --sn-tabbar-bottom
 * (64px) on .signal-main-data so panel content never slides under it.
 * ────────────────────────────────────────────────────────────────────── */
/* Tag specificity boost (nav.signal-tabbar-bottom) defeats the global
   `nav { position: fixed; top: 0; ... }` rule in style.css that
   otherwise drags this bar to the top of the page. */
nav.signal-tabbar-bottom {
  position: fixed;
  top: auto;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 60;
  display: flex;
  align-items: stretch;
  justify-content: space-around;
  gap: 4px;
  height: 64px;
  padding: 6px 8px calc(6px + env(safe-area-inset-bottom));
  margin: 0;
  background: var(--sn-bg, var(--sn-night, #07050d));
  border-top: 1px solid rgba(214, 198, 255, 0.10);
  border-bottom: 0;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

.signal-tab-btn {
  position: relative;
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 4px 6px 6px;
  background: transparent;
  border: 0;
  border-radius: 8px;
  color: rgba(214, 198, 255, 0.55);
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 10px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color 0.15s ease, background 0.15s ease;
}
.signal-tab-btn:hover {
  color: rgba(214, 198, 255, 0.85);
}
.signal-tab-btn:focus-visible {
  outline: 2px solid var(--sn-gold, #e9b96a);
  outline-offset: 2px;
}

.signal-tab-icon-wrap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 28px;
}
/* Icons are recoloured via CSS mask so they read as brand gold against the
   dark Senary background. The source image is set via the per-button
   `--tab-icon-src` custom property on the .signal-tab-icon span. */
.signal-tab-icon {
  display: block;
  width: 28px;
  height: 28px;
  -webkit-mask: var(--tab-icon-src) center / contain no-repeat;
          mask: var(--tab-icon-src) center / contain no-repeat;
  background-color: rgba(233, 185, 106, 0.55);
  transition: background-color 0.18s ease, filter 0.18s ease, transform 0.18s ease;
  pointer-events: none;
}
.signal-tab-btn:hover .signal-tab-icon {
  background-color: rgba(233, 185, 106, 0.85);
}
.signal-tab-btn.active .signal-tab-icon {
  background-color: #e9b96a;
  filter: drop-shadow(0 0 5px rgba(233, 185, 106, 0.55));
}

/* Per-icon visual-weight overrides. Each source asset has a different
   intrinsic aspect ratio (e.g. the bodygraph silhouette is tall + narrow),
   so a plain `contain` makes them paint at noticeably different visual
   sizes. We tune `mask-size` per data-view so the four icons read at the
   same weight. */
.signal-tab-btn[data-view="transit"]   .signal-tab-icon {
  -webkit-mask-size: 88% 88%;
          mask-size: 88% 88%;
}
.signal-tab-btn[data-view="mandala"]   .signal-tab-icon {
  -webkit-mask-size: 88% 88%;
          mask-size: 88% 88%;
}
.signal-tab-btn[data-view="bodygraph"] .signal-tab-icon {
  /* The silhouette is much taller than wide — scale UP via cover so its
     vertical mass matches the others. Slight top/bottom crop is fine
     because the head + foot of the silhouette are negative space. */
  -webkit-mask-size: cover;
          mask-size: cover;
}
.signal-tab-btn[data-view="settings"]  .signal-tab-icon {
  -webkit-mask-size: 90% 90%;
          mask-size: 90% 90%;
}

.signal-tab-label {
  display: inline-block;
  line-height: 1;
}
.signal-tab-btn.active {
  color: var(--sn-gold, #e9b96a);
}

/* Active pill — small gold underline below the label */
.signal-tab-pill {
  position: absolute;
  left: 50%;
  bottom: 2px;
  width: 18px;
  height: 3px;
  border-radius: 999px;
  background: var(--sn-gold, #e9b96a);
  transform: translateX(-50%) scaleX(0);
  transform-origin: center;
  opacity: 0;
  transition: opacity 0.18s ease, transform 0.18s ease;
  pointer-events: none;
}
.signal-tab-btn.active .signal-tab-pill {
  opacity: 1;
  transform: translateX(-50%) scaleX(1);
}

/* Desktop: slightly larger icons + flip the tabbar from bottom to top.
   Bottom-fixed is right for mobile (thumb reach); on a wider viewport
   the same nav reads as a top app bar, stacked directly below the
   global site nav. The class name still says "bottom" — same bar, just
   repositioned. Bottom-padding reservations elsewhere collapse to 0
   here so nothing reserves dead space below. */
@media (min-width: 720px) {
  nav.signal-tabbar-bottom {
    height: 56px;
    top: var(--nav-height, 72px);
    bottom: auto;
    border-top: 0;
    border-bottom: 1px solid rgba(214, 198, 255, 0.10);
    padding: 6px 8px;
    z-index: 90;
  }
  .signal-tab-icon-wrap {
    height: 32px;
  }
  .signal-tab-icon {
    width: 32px;
    height: 32px;
  }
  /* Tabbar no longer occupies the bottom — collapse the reservation
     and instead shift the main container down by the tabbar height so
     content clears the stacked top bars. */
  .signal-main,
  .signal-main.signal-main-data {
    --sn-tabbar-bottom: 0px;
    padding-top: calc(var(--nav-height, 72px) + 56px + 0.75rem);
    --sn-chrome-top: calc(var(--nav-height, 72px) + 56px + 0.75rem);
  }
  /* Active-tab indicator: pin to the TOP of the button as a flush
     header underline. On mobile the pill sits at the bottom (below the
     label) which works for a bottom-fixed bar; at the top of the page
     the bar reads as a header so the indicator belongs on the top edge.
     Wider too — full-button minus 24px instead of fixed 18px — so the
     active tab is unmistakable. */
  .signal-tab-pill {
    top: 0;
    bottom: auto;
    width: calc(100% - 24px);
    height: 2px;
    border-radius: 0;
  }
}

/* Icon-only at very narrow viewports (per spec) */
@media (max-width: 359px) {
  .signal-tab-label {
    display: none;
  }
  .signal-tab-btn {
    gap: 0;
  }
}

/* Ensure scrollable panels (Bodygraph / Settings / Transit placeholder)
   don't slide under the fixed bottom nav. The Mandala deck calculates
   its own height from --sn-tabbar-bottom and doesn't need padding. */
.signal-main.signal-main-data .signal-view[data-view-panel="bodygraph"],
.signal-main.signal-main-data .signal-view[data-view-panel="settings"],
.signal-main.signal-main-data .signal-view[data-view-panel="transit"] {
  padding-bottom: calc(var(--sn-tabbar-bottom, 64px) + 1.5rem);
}

/* Transit placeholder — quick centered "Coming soon" panel */
.signal-transit-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: 60vh;
  padding: 2rem 1.5rem;
  color: var(--sn-text-2, #b8aee0);
}
.signal-transit-placeholder h2 {
  font-family: 'Playfair Display', 'DM Sans', serif;
  font-size: clamp(1.6rem, 3vw, 2.2rem);
  color: var(--sn-text, #ece6ff);
  margin: 0 0 0.5rem;
  letter-spacing: 0.01em;
}
.signal-transit-placeholder p {
  margin: 0;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.85rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--sn-text-3, #7a6ea3);
}

/* ─── Transit tab ──────────────────────────────────────────
   Five stacked sections — Cosmic Clock, Journal, Forecast,
   Timeline, ephemeris footer — all scoped under .sn-transit-view
   so they don't bleed into Mandala / Bodygraph / Settings.
*/
.sn-transit-view {
  position: relative;
  max-width: 720px;
  margin: 0 auto;
  padding: 1rem clamp(0.75rem, 3vw, 1.5rem) 2rem;
  color: var(--sn-text, #ece6ff);
}
.sn-transit-stars {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  /* match other Senary backgrounds — very subtle */
  background-image: radial-gradient(circle at 20% 15%, rgba(255,255,255,0.04) 0, transparent 35%),
                    radial-gradient(circle at 80% 75%, rgba(214,198,255,0.04) 0, transparent 40%);
}
.sn-transit-view > * { position: relative; z-index: 1; }

.sn-tx-section {
  position: relative;
  margin: 0 0 1.1rem;
  padding: 0.85rem 0.9rem 1rem;
  background: rgba(20, 16, 42, 0.3);
  border: 1px solid rgba(214,198,255,0.05);
  border-radius: 14px;
}
.sn-tx-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 0 0.35rem;
}
.sn-tx-title {
  font-family: 'Playfair Display', 'DM Sans', serif;
  font-weight: 500;
  font-size: clamp(0.95rem, 2.2vw, 1.15rem);
  color: var(--sn-text, #ece6ff);
  margin: 0;
  letter-spacing: 0.01em;
}
.sn-tx-subtitle {
  margin: 0 0 0.55rem;
  color: var(--sn-text-2, #b8aee0);
  font-style: italic;
  font-size: 0.78rem;
  line-height: 1.4;
}

/* Bottom-right corner info link, mirroring iOS:
   small circle "i" icon + short caption ("What am I looking at?").
   Tap opens the bottom-sheet info drawer. */
.sn-tx-info-link {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.4rem;
  width: 100%;
  margin: 0.65rem 0 0;
  padding: 0.25rem 0;
  background: transparent;
  border: 0;
  color: var(--sn-text-2, #b8aee0);
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: color 0.15s ease;
}
.sn-tx-info-link:hover,
.sn-tx-info-link:focus-visible {
  color: var(--sn-gold, #e9b96a);
  outline: none;
}
.sn-tx-info-link:hover .sn-tx-info-icon,
.sn-tx-info-link:focus-visible .sn-tx-info-icon {
  border-color: rgba(233,185,106,0.55);
  color: var(--sn-gold, #e9b96a);
}
.sn-tx-info-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 1px solid currentColor;
  font-family: 'Playfair Display', serif;
  font-style: italic;
  font-size: 0.72rem;
  line-height: 1;
  letter-spacing: 0;
  transition: color 0.15s, border-color 0.15s;
}
.sn-tx-info-text { line-height: 1; }

.sn-tx-info-btn {
  background: rgba(214,198,255,0.06);
  border: 1px solid rgba(214,198,255,0.18);
  color: var(--sn-text-2, #b8aee0);
  width: 22px;
  height: 22px;
  border-radius: 50%;
  font-family: 'Playfair Display', serif;
  font-style: italic;
  font-size: 0.78rem;
  line-height: 20px;
  text-align: center;
  cursor: pointer;
  padding: 0;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.sn-tx-info-btn:hover {
  color: var(--sn-gold, #e9b96a);
  border-color: rgba(233,185,106,0.5);
  background: rgba(233,185,106,0.07);
}

/* iOS-style hero strip above the cosmic clock — small mono caption
   ("TRANSIT · LIVE") + bold serif headline ("Your sky, right now."). */
.sn-tx-section-head--hero {
  align-items: flex-start;
}
.sn-tx-hero-text { flex: 1 1 auto; min-width: 0; }
.sn-tx-hero-eyebrow {
  margin: 0 0 0.15rem;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  color: rgba(233,185,106,0.65);
  text-transform: uppercase;
}
.sn-tx-hero-headline {
  margin: 0 0 0.5rem;
  font-family: 'Playfair Display', 'DM Sans', serif;
  font-weight: 500;
  font-size: clamp(1.1rem, 3.4vw, 1.45rem);
  line-height: 1.15;
  color: var(--sn-text, #ece6ff);
  letter-spacing: -0.01em;
}
.sn-tx-hero-headline--sm {
  font-size: clamp(1.05rem, 3.4vw, 1.35rem);
  margin: 0 0 0.35rem;
}

/* Small-caps eyebrow used inside transit sections (e.g. "Today" above
   the journal textarea — mirrors iOS Transit.html). */
.sn-tx-eyebrow {
  margin: 0.5rem 0 0.35rem;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  color: rgba(184,174,224,0.7);
  text-transform: uppercase;
}

/* Cosmic Clock */
.sn-tx-clock-section { padding-bottom: 1rem; }
.sn-tx-clock-host {
  width: 100%;
  max-width: 620px;
  margin: 0.5rem auto 0.25rem;
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
.sn-tx-clock-svg { width: 100%; height: 100%; }
.sn-tx-clock-foot {
  text-align: center;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.72rem;
  color: var(--sn-text-3, #7a6ea3);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-top: 0.5rem;
}

/* Live indicator — iOS-style pulsing pill. We previously pinned this to
   top-right of the clock host; the inside of the SVG is crowded with
   zodiac glyphs and gate numbers, so iter-6 lifts the pill OUT of the
   clock area and pins it to the top-right of the clock SECTION instead.
   The pill now floats next to the headline, not over the wheel. */
.sn-tx-clock-section { position: relative; }
.sn-tx-clock-host { position: relative; padding: 0.5rem 0 0.25rem; }
.sn-tx-live-pill {
  position: absolute;
  top: 1rem;
  right: 1rem;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px 3px 6px;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: #e9b96a;
  background: rgba(7, 5, 13, 0.55);
  border: 1px solid rgba(233, 185, 106, 0.35);
  border-radius: 999px;
  pointer-events: none;
  z-index: 2;
}
.sn-tx-live-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #e9b96a;
  box-shadow: 0 0 6px rgba(233, 185, 106, 0.75);
  animation: sn-tx-live-pulse 1.6s ease-in-out infinite;
}
@keyframes sn-tx-live-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%       { opacity: 0.35; transform: scale(0.7); }
}

.sn-tx-clock-gate-num { transition: fill 0.15s; }
.sn-tx-clock-gate-num:hover { fill: var(--sn-gold, #e9b96a); }

/* Journal */
.sn-tx-journal-input {
  width: 100%;
  background: rgba(28, 23, 64, 0.5);
  border: 1px solid rgba(214,198,255,0.14);
  border-radius: 10px;
  color: var(--sn-text, #ece6ff);
  font-family: inherit;
  font-size: 0.95rem;
  padding: 0.7rem 0.85rem;
  resize: vertical;
  min-height: 60px;
}
.sn-tx-journal-input::placeholder { color: var(--sn-text-3, #7a6ea3); }
.sn-tx-journal-input:focus {
  outline: none;
  border-color: rgba(233,185,106,0.45);
  background: rgba(28,23,64,0.7);
}
.sn-tx-journal-actions {
  display: flex;
  justify-content: flex-end;
  margin: 0.6rem 0 0.5rem;
}
/* Match the iOS Transit.html Journal Save — a slim gold-outline pill,
   not the heavier filled brand button. Scoped to journal-actions so it
   doesn't affect other "Save"-style CTAs elsewhere. */
.sn-tx-journal-actions .signal-btn-primary {
  background: transparent;
  border: 1px solid rgba(233,185,106,0.6);
  color: var(--sn-gold, #e9b96a);
  padding: 0.35rem 1rem;
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  border-radius: 999px;
  box-shadow: none;
  text-shadow: none;
}
.sn-tx-journal-actions .signal-btn-primary:hover,
.sn-tx-journal-actions .signal-btn-primary:focus {
  background: rgba(233,185,106,0.1);
  border-color: rgba(233,185,106,0.9);
  color: var(--sn-gold, #e9b96a);
}
.sn-tx-journal-list {
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.5rem;
}
.sn-tx-journal-entry {
  background: rgba(28, 23, 64, 0.35);
  border: 1px solid rgba(214,198,255,0.06);
  border-radius: 10px;
  padding: 0.55rem 0.75rem 0.65rem;
}
.sn-tx-journal-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.62rem;
  color: var(--sn-text-3, #7a6ea3);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 0 0 0.25rem;
}
.sn-tx-journal-del {
  background: transparent;
  border: none;
  color: var(--sn-text-3, #7a6ea3);
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 0.25rem;
}
.sn-tx-journal-del:hover { color: var(--sn-red, #c4504c); }
.sn-tx-journal-preview {
  margin: 0;
  color: var(--sn-text-2, #b8aee0);
  font-size: 0.82rem;
  line-height: 1.4;
}
/* "see N more" + "show less" — quiet inline text links, NOT buttons.
   Sit on one row beneath the entry list so they read as part of the list,
   not as primary actions. */
.sn-tx-journal-toggles {
  display: flex;
  gap: 1.1rem;
  margin: 0.4rem 0 0;
}
.sn-tx-journal-more,
.sn-tx-journal-less {
  display: inline-block;
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--sn-text-3, #7a6ea3);
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  text-transform: lowercase;
  cursor: pointer;
  border-radius: 0;
  transition: color 0.15s ease;
}
.sn-tx-journal-more:hover,
.sn-tx-journal-more:focus-visible,
.sn-tx-journal-less:hover,
.sn-tx-journal-less:focus-visible {
  color: var(--sn-gold, #e9b96a);
  outline: none;
}
.sn-tx-journal-more[hidden],
.sn-tx-journal-less[hidden] { display: none; }

/* PAST ENTRIES eyebrow above the entry list — only visible when there's
   at least one entry to label. */
.sn-tx-journal-past-eyebrow {
  margin: 0.9rem 0 0.3rem;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.65rem;
  letter-spacing: 0.18em;
  color: var(--sn-text-3, #7a6ea3);
  text-transform: uppercase;
}
.sn-tx-journal-past-eyebrow[hidden] { display: none; }

/* Forecast — iOS-style week cards + Upcoming Gate Alerts list */
.sn-tx-forecast-grid { margin: 0.4rem 0 0; }
.sn-tx-fc-week { margin: 0 0 1.4rem; }
.sn-tx-fc-week-head {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  margin: 0 0 0.55rem 0.15rem;
}
.sn-tx-fc-week-label {
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sn-text-3, #7a6ea3);
}
.sn-tx-fc-week-range {
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  color: var(--sn-text-3, #7a6ea3);
  opacity: 0.75;
}
.sn-tx-fc-row {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-auto-rows: 1fr;
  align-items: stretch;
  gap: 4px;
}
.sn-tx-fc-day {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  background: rgba(20, 17, 48, 0.7);
  border: 1px solid transparent;
  border-radius: 8px;
  color: var(--sn-text, #ece6ff);
  font-family: inherit;
  cursor: pointer;
  padding: 0.42rem 0.18rem 0.4rem;
  text-align: center;
  min-height: 86px;
  min-width: 0;
  overflow: hidden;
  transition: border-color 0.15s, background 0.15s;
}
.sn-tx-fc-day:hover {
  background: rgba(28, 24, 64, 0.85);
}
.sn-tx-fc-day:focus-visible {
  outline: 2px solid rgba(233,185,106,0.55);
  outline-offset: 1px;
}
.sn-tx-fc-dow {
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.55rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sn-text-3, #7a6ea3);
  white-space: nowrap;
}
.sn-tx-fc-dom {
  font-family: var(--sn-display, 'Outfit', system-ui, sans-serif);
  font-size: 1.25rem;
  font-weight: 500;
  line-height: 1.05;
  letter-spacing: 0.01em;
  margin: 0.12rem 0 0.14rem;
  color: var(--sn-text, #ece6ff);
  font-variant-numeric: tabular-nums;
}
/* The small gold bar between day number and glyph row — iOS visual rhythm. */
.sn-tx-fc-bar {
  display: block;
  width: 18px;
  height: 2px;
  border-radius: 2px;
  background: var(--sn-gold, #d4a843);
  opacity: 0.95;
  margin: 0 auto 0.28rem;
}
.sn-tx-fc-day.is-empty .sn-tx-fc-bar { opacity: 0.18; }

/* Glyph row: planet circle + gate number (natal) or planet + zodiac glyph
   (ingress). Sits right under the gold bar. */
.sn-tx-fc-glyph {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-family: 'DejaVu Sans', 'Segoe UI Symbol', serif;
  margin: 0 0 0.28rem;
}
.sn-tx-fc-planet {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 1px solid rgba(212, 168, 67, 0.55);
  background: rgba(8, 6, 18, 0.85);
  color: var(--sn-gold, #d4a843);
  font-size: 0.68rem;
  line-height: 1;
}
.sn-tx-fc-gate {
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--sn-text-2, #b8aee0);
  background: rgba(8, 6, 18, 0.5);
  border-radius: 5px;
  padding: 1px 4px;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
}
.sn-tx-fc-sign {
  font-size: 0.85rem;
  color: var(--sn-gold, #d4a843);
  line-height: 1;
}

/* Pip row at the bottom — single colored dot + event count number. */
.sn-tx-fc-pip-row {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-top: auto;
}
.sn-tx-fc-pip {
  display: inline-block;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--sn-gold, #d4a843);
}
.sn-tx-fc-pip[data-pole="negative"] { background: var(--sn-red, #c4504c); }
.sn-tx-fc-pip[data-pole="neutral"]  { background: var(--sn-gold, #d4a843); opacity: 0.85; }
.sn-tx-fc-pip-count {
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.6rem;
  font-weight: 600;
  color: var(--sn-gold, #d4a843);
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
}

/* Today: gold border + gold weekday + gold day number. The hero cell. */
.sn-tx-fc-day.is-today {
  border-color: rgba(212, 168, 67, 0.65);
  background: rgba(40, 30, 60, 0.55);
}
.sn-tx-fc-day.is-today .sn-tx-fc-dom { color: var(--sn-gold, #d4a843); }
.sn-tx-fc-day.is-today .sn-tx-fc-dow { color: var(--sn-gold, #d4a843); opacity: 0.95; }

/* Past cells fade slightly so the eye sweeps to today + the future half.
   Content (planet glyph, sign/gate, pip count, pole tint) still renders
   identically — the 60% opacity is the entire visual "past" cue. */
.sn-tx-fc-day.is-past:not(.is-today) { opacity: 0.6; }

/* The clicked day-cell whose alerts are showing below the grid. Same
   subtle border treatment as Today, but using a muted lavender so the
   two states never visually compete. */
.sn-tx-fc-day.is-open {
  border-color: rgba(214, 198, 255, 0.4);
  background: rgba(35, 28, 70, 0.85);
}

/* ── Per-day detail panel (renders below the grid on a cell click) ── */
.sn-tx-fc-day-detail {
  margin: 0.9rem 0 0;
  background: rgba(20, 17, 48, 0.6);
  border: 1px solid rgba(214, 198, 255, 0.1);
  border-radius: 12px;
  padding: 0.85rem 1rem 0.9rem;
}
.sn-tx-fc-day-detail[hidden] { display: none; }
.sn-tx-fc-day-detail-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
  margin: 0 0 0.7rem;
}
.sn-tx-fc-day-detail-date {
  font-family: 'Playfair Display', serif;
  font-size: 1rem;
  color: var(--sn-text, #ece6ff);
}
.sn-tx-fc-day-detail-count {
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  color: var(--sn-text-3, #7a6ea3);
  text-transform: uppercase;
}
.sn-tx-fc-day-detail-empty {
  margin: 0;
  color: var(--sn-text-3, #7a6ea3);
  font-size: 0.9rem;
  text-align: center;
  padding: 0.4rem 0;
}

/* ── Collapsible Timeline (advanced) section ── */
.sn-tx-collapsible { padding: 0; }
.sn-tx-collapsible > .sn-tx-collapsible-summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.4rem 0;
}
.sn-tx-collapsible > .sn-tx-collapsible-summary::-webkit-details-marker { display: none; }
.sn-tx-title-suffix {
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sn-text-3, #7a6ea3);
  font-weight: normal;
  margin-left: 0.35rem;
}
.sn-tx-collapsible-chevron {
  font-size: 0.85rem;
  color: var(--sn-text-3, #7a6ea3);
  transition: transform 0.18s ease;
}
.sn-tx-collapsible[open] .sn-tx-collapsible-chevron {
  transform: rotate(180deg);
}

/* ── Upcoming Gate Alerts ───────────────────────────────────────────── */
.sn-tx-fc-alerts { margin: 0.4rem 0 0; }
.sn-tx-fc-alerts-head {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  margin: 0 0 0.6rem 0.15rem;
}
.sn-tx-fc-alerts-label {
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--sn-text-2, #b8aee0);
}
.sn-tx-fc-alerts-meta {
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.7rem;
  color: var(--sn-text-3, #7a6ea3);
}
.sn-tx-fc-alerts-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.sn-tx-fc-alerts-empty {
  color: var(--sn-text-3, #7a6ea3);
  font-size: 0.85rem;
  padding: 0.6rem 0.15rem;
}
.sn-tx-fc-alert {
  background: rgba(20, 17, 48, 0.75);
  border: 1px solid rgba(214, 198, 255, 0.08);
  border-radius: 10px;
  padding: 0.7rem 0.9rem 0.55rem;
}
.sn-tx-fc-alert.is-lit-now {
  border-color: rgba(212, 168, 67, 0.35);
  background: rgba(40, 30, 60, 0.75);
}
.sn-tx-fc-alert.is-flash {
  border-color: rgba(212, 168, 67, 0.7);
  background: rgba(60, 45, 90, 0.9);
  transition: border-color 0.2s, background 0.2s;
}
.sn-tx-fc-alert-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
.sn-tx-fc-alert-glyph {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid rgba(212, 168, 67, 0.55);
  background: rgba(8, 6, 18, 0.85);
  color: var(--sn-gold, #d4a843);
  font-family: 'DejaVu Sans', 'Segoe UI Symbol', serif;
  font-size: 0.9rem;
}
.sn-tx-fc-alert-title {
  flex: 1 1 auto;
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem;
  font-size: 0.92rem;
  color: var(--sn-text, #ece6ff);
}
.sn-tx-fc-alert-title strong {
  font-weight: 600;
}
.sn-tx-fc-alert-dot {
  color: var(--sn-text-3, #7a6ea3);
  opacity: 0.6;
}
.sn-tx-fc-alert-gate {
  color: var(--sn-text-2, #b8aee0);
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.85rem;
}
.sn-tx-fc-alert-time {
  color: var(--sn-text-3, #7a6ea3);
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
}
.sn-tx-fc-alert-pill {
  flex: 0 0 auto;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  padding: 3px 8px;
  border-radius: 4px;
  background: rgba(60, 50, 95, 0.6);
  color: var(--sn-text-2, #b8aee0);
}
.sn-tx-fc-alert-subtitle {
  margin: 0.35rem 0 0 30px;
  font-size: 0.82rem;
  color: var(--sn-text-2, #b8aee0);
  opacity: 0.9;
}
.sn-tx-fc-alert-channel {
  margin: 0.2rem 0 0 30px;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.78rem;
  color: var(--sn-gold, #d4a843);
}
.sn-tx-forecast-detail { margin: 0.9rem 0 0; }
.sn-tx-fc-card {
  background: rgba(28, 23, 64, 0.65);
  border: 1px solid rgba(214,198,255,0.1);
  border-left-width: 3px;
  border-radius: 10px;
  padding: 0.85rem 1rem 1rem;
}
.sn-tx-fc-card[data-pole="positive"] { border-left-color: var(--sn-gold, #e9b96a); }
.sn-tx-fc-card[data-pole="negative"] { border-left-color: var(--sn-red, #c4504c); }
.sn-tx-fc-card[data-pole="neutral"]  { border-left-color: var(--sn-text-3, #7a6ea3); }
.sn-tx-fc-card-label {
  display: inline-block;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.6rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sn-text-3, #7a6ea3);
  margin-bottom: 0.25rem;
}
.sn-tx-fc-card[data-pole="positive"] .sn-tx-fc-card-label { color: var(--sn-gold, #e9b96a); }
.sn-tx-fc-card[data-pole="negative"] .sn-tx-fc-card-label { color: var(--sn-red, #c4504c); }
.sn-tx-fc-card h4 {
  margin: 0 0 0.25rem;
  font-family: 'Playfair Display', serif;
  font-weight: 500;
  font-size: 1.05rem;
  color: var(--sn-text, #ece6ff);
}
.sn-tx-fc-card-transition {
  margin: 0 0 0.4rem;
  font-family: inherit;
  font-size: 0.92rem;
  color: var(--sn-text-2, #b8aee0);
  font-style: italic;
}
.sn-tx-fc-card-note {
  margin: 0 0 0.5rem;
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--sn-text-2, #b8aee0);
}
.sn-tx-fc-card-tags { margin: 0; }
.sn-tx-fc-card-tag {
  display: inline-block;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: var(--sn-text-3, #7a6ea3);
  margin-right: 0.5rem;
}
.sn-tx-fc-loading, .sn-tx-fc-empty {
  text-align: center;
  color: var(--sn-text-3, #7a6ea3);
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  padding: 1rem;
}

/* (Older forecast styles intentionally removed — the iOS-styled rules
   above replace the prior pip/label/lit-now/detail-card system.) */

.sn-tx-fc-card-lit {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0.25rem 0 0.5rem;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.7rem;
  letter-spacing: 0.05em;
  color: var(--bg-mode-shifts, #4FC3D9);
  text-transform: uppercase;
}
.sn-tx-fc-card-lit-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--bg-mode-shifts, #4FC3D9);
  box-shadow: 0 0 6px var(--bg-mode-shifts, #4FC3D9);
}
.sn-tx-fc-card-draws-label {
  margin: 0.6rem 0 0.25rem;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.65rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sn-text-3, #7a6ea3);
}
.sn-tx-fc-card-draws {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.25rem;
  margin-bottom: 0.5rem;
  flex-wrap: wrap;
}
.sn-tx-fc-card-draw {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--sn-border, #2a2a38);
  border-radius: 6px;
  font-size: 11px;
  line-height: 1.3;
  max-width: 220px;
  background: rgba(255, 255, 255, 0.02);
}
.sn-tx-fc-card-draw-pole {
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.6rem;
  letter-spacing: 0.06em;
  padding: 1px 4px;
  border-radius: 3px;
  color: var(--sn-text-3, #7a6ea3);
  border: 1px solid currentColor;
}
.sn-tx-fc-card-draw-pole[data-pole="positive"] { color: var(--sn-gold, #e9b96a); }
.sn-tx-fc-card-draw-pole[data-pole="negative"] { color: var(--sn-red, #c4504c); }
.sn-tx-fc-card-draw-text {
  color: var(--sn-text-2, #b8b3a8);
}

@media (max-width: 640px) {
  /* Forecast: keep the 7-column grid but reduce cell size so it fits at
     phone widths. Cell content (small weekday, day number, gold bar, glyph,
     pip+count) is naturally compact and stays readable at narrow widths. */
  .sn-tx-fc-row {
    gap: 3px;
  }
  .sn-tx-fc-day {
    min-height: 78px;
    padding: 0.35rem 0.12rem 0.32rem;
  }
  .sn-tx-fc-dow {
    font-size: 0.5rem;
    letter-spacing: 0.08em;
  }
  .sn-tx-fc-dom {
    font-size: 1.1rem;
  }
  .sn-tx-fc-bar {
    width: 14px;
  }
  .sn-tx-fc-planet, .sn-tx-fc-gate, .sn-tx-fc-sign {
    font-size: 0.6rem;
  }
  .sn-tx-fc-planet { width: 14px; height: 14px; }
  .sn-tx-fc-pip-count { font-size: 0.55rem; }
  .sn-tx-fc-week-head { flex-wrap: wrap; }
  .sn-tx-fc-alert-row { flex-wrap: wrap; }
  .sn-tx-fc-alert-pill { margin-left: auto; }
  .sn-tx-fc-alert-subtitle, .sn-tx-fc-alert-channel { margin-left: 30px; }
}

/* Timeline host — hd-timeline.css provides .hdt-* internals. */
.sn-tx-timeline-host {
  width: 100%;
  min-height: 320px;
}

/* Footer line */
.sn-tx-ephemeris-foot {
  text-align: center;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  color: var(--sn-text-3, #7a6ea3);
  margin: 1rem 0 0;
}

/* Info bottom-sheet drawer — slides up from the bottom edge,
   matches the iOS Transit info sheet (drag handle + centred title +
   gold "Done" button). */
.sn-tx-info-dialog {
  position: fixed;
  inset: auto 0 0 0;
  margin: 0;
  width: 100%;
  max-width: 100%;
  max-height: 85vh;
  border: none;
  border-top: 1px solid rgba(214,198,255,0.18);
  border-radius: 18px 18px 0 0;
  background: rgba(12, 9, 26, 0.98);
  color: var(--sn-text, #ece6ff);
  padding: 0;
  overflow: hidden;
  box-shadow: 0 -18px 48px rgba(0, 0, 0, 0.55);

  translate: 0 100%;
  transition:
    translate 0.38s cubic-bezier(0.32, 0.72, 0, 1),
    overlay 0.38s allow-discrete,
    display 0.38s allow-discrete;
}
.sn-tx-info-dialog[open] { translate: 0 0; }
@starting-style {
  .sn-tx-info-dialog[open] { translate: 0 100%; }
}
.sn-tx-info-dialog::backdrop {
  background: rgba(7, 5, 13, 0);
  backdrop-filter: blur(0px);
  transition:
    background 0.38s ease,
    backdrop-filter 0.38s ease,
    overlay 0.38s allow-discrete,
    display 0.38s allow-discrete;
}
.sn-tx-info-dialog[open]::backdrop {
  background: rgba(7, 5, 13, 0.55);
  backdrop-filter: blur(3px);
}
@starting-style {
  .sn-tx-info-dialog[open]::backdrop {
    background: rgba(7, 5, 13, 0);
    backdrop-filter: blur(0px);
  }
}
.sn-tx-info-dialog-form {
  position: relative;
  display: flex;
  flex-direction: column;
  max-height: 85vh;
  padding: 0;
}
.sn-tx-info-dialog-handle {
  flex: 0 0 auto;
  width: 36px;
  height: 4px;
  margin: 0.55rem auto 0;
  border-radius: 2px;
  background: rgba(214,198,255,0.25);
}
.sn-tx-info-dialog-header {
  flex: 0 0 auto;
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 0.65rem 1rem 0.85rem;
}
.sn-tx-info-dialog-title {
  grid-column: 2;
  margin: 0;
  font-family: 'Playfair Display', serif;
  font-size: 1.15rem;
  font-weight: 500;
  color: var(--sn-text, #ece6ff);
  text-align: center;
}
.sn-tx-info-dialog-done {
  grid-column: 3;
  justify-self: end;
  background: transparent;
  border: none;
  padding: 0.35rem 0.6rem;
  color: var(--sn-gold, #e9b96a);
  font-family: var(--sn-sans, 'Inter', sans-serif);
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  cursor: pointer;
  border-radius: 999px;
  transition: background 0.15s;
}
.sn-tx-info-dialog-done:hover,
.sn-tx-info-dialog-done:focus-visible {
  background: rgba(233,185,106,0.1);
  outline: none;
}
.sn-tx-info-dialog-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 0.5rem 1.25rem 1.5rem;
  -webkit-overflow-scrolling: touch;
}
.sn-tx-info-dialog-body p {
  margin: 0 0 0.85rem;
  line-height: 1.55;
  color: var(--sn-text-2, #b8aee0);
  font-size: 0.95rem;
}
.sn-tx-info-dialog-body p:last-child { margin-bottom: 0; }

/* Sectioned info content — subhead + paragraph, mirroring iOS info sheets. */
.sn-tx-info-section {
  margin: 0 0 1.15rem;
}
.sn-tx-info-section:last-of-type { margin-bottom: 0; }
.sn-tx-info-section-title {
  margin: 0 0 0.35rem;
  font-family: var(--sn-sans, 'Inter', sans-serif);
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--sn-text, #ece6ff);
  letter-spacing: 0.005em;
}
.sn-tx-info-section-body {
  margin: 0;
  font-family: var(--sn-sans, 'Inter', sans-serif);
  font-size: 0.92rem;
  line-height: 1.55;
  color: var(--sn-text-2, #b8aee0);
}
.sn-tx-info-section-footnote {
  margin: 0.35rem 0 0;
  font-size: 0.7rem;
  line-height: 1.45;
  color: var(--sn-text-3, #7a6ea3);
}

/* Callout box (clock sheet "Explore each gate"). */
.sn-tx-info-callout {
  margin: 1.1rem 0 0;
  padding: 0.85rem 0.95rem;
  background: rgba(20, 16, 42, 0.55);
  border: 1px solid rgba(233,185,106,0.3);
  border-radius: 12px;
}
.sn-tx-info-callout-head {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0 0 0.35rem;
}
.sn-tx-info-callout-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 1px solid var(--sn-gold, #e9b96a);
  color: var(--sn-gold, #e9b96a);
  font-size: 0.7rem;
  line-height: 1;
}
.sn-tx-info-callout-title {
  font-family: var(--sn-sans, 'Inter', sans-serif);
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--sn-text, #ece6ff);
}
.sn-tx-info-callout-body {
  margin: 0;
  font-family: var(--sn-sans, 'Inter', sans-serif);
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--sn-text-2, #b8aee0);
}

@media (min-width: 720px) {
  .sn-tx-info-dialog {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    max-width: 520px;
    border-left: 1px solid rgba(214,198,255,0.18);
    border-right: 1px solid rgba(214,198,255,0.18);
  }
}

/* Gate popover (cosmic-clock gate-number click) */
.sn-tx-gate-popover {
  border: 1px solid rgba(214,198,255,0.18);
  background: rgba(20, 16, 42, 0.97);
  color: var(--sn-text, #ece6ff);
  border-radius: 14px;
  padding: 0;
  max-width: 480px;
  width: 92vw;
}
.sn-tx-gate-popover::backdrop {
  background: rgba(7, 5, 13, 0.7);
}
.sn-tx-gate-popover-form {
  position: relative;
  padding: 1.5rem 1.5rem 1.25rem;
}
.sn-tx-gate-popover-close {
  position: absolute;
  top: 0.5rem;
  right: 0.65rem;
  background: transparent;
  border: none;
  color: var(--sn-text-2, #b8aee0);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
}
.sn-tx-gate-popover-title {
  margin: 0 0 0.5rem;
  font-family: 'Playfair Display', serif;
  font-size: 1.3rem;
  color: var(--sn-text, #ece6ff);
}
.sn-tx-gate-popover-keynote {
  margin: 0 0 0.5rem;
  font-style: italic;
  color: var(--sn-gold-soft, #c79a4d);
  font-size: 0.95rem;
}
.sn-tx-gate-popover-body {
  margin: 0;
  line-height: 1.55;
  color: var(--sn-text-2, #b8aee0);
  font-size: 0.92rem;
}

@media (max-width: 540px) {
  .sn-tx-fc-row { gap: 2px; }
  .sn-tx-fc-day { min-height: 68px; padding: 0.25rem 0.08rem 0.3rem; }
  .sn-tx-fc-dow { font-size: 0.48rem; letter-spacing: 0.06em; }
  .sn-tx-fc-dom { font-size: 0.95rem; margin: 0.08rem 0 0.1rem; }
  .sn-tx-fc-bar { width: 12px; margin-bottom: 0.18rem; }
  .sn-tx-fc-planet { width: 12px; height: 12px; font-size: 0.55rem; }
  .sn-tx-fc-gate, .sn-tx-fc-sign { font-size: 0.55rem; }
  .sn-tx-fc-pip-count { font-size: 0.52rem; }
  .sn-tx-fc-label { font-size: 0.72rem; }
}

@media (max-width: 380px) {
  .sn-tx-fc-row { gap: 2px; }
  .sn-tx-fc-day { min-height: 62px; padding: 0.22rem 0.05rem 0.28rem; }
  .sn-tx-fc-dow { font-size: 0.45rem; }
  .sn-tx-fc-dom { font-size: 0.88rem; }
  .sn-tx-fc-bar { width: 10px; }
}

/* ─── Transit tab scroll fix ───────────────────────────────
   The Mandala :has selector locks body overflow because the hero
   ([data-state-1/2]) contains hidden .sn-mandala-view divs — those
   match :not([hidden]) (no hidden attr on the inner div). When the
   Transit tab is the active panel, restore scrolling. */
body:has(.signal-view[data-view-panel="transit"]:not([hidden])) {
  overflow-y: auto !important;
}
.signal-main.signal-main-data:has(.signal-view[data-view-panel="transit"]:not([hidden])) {
  height: auto !important;
  overflow: visible !important;
}
body:has(.signal-view[data-view-panel="transit"]:not([hidden])) > footer {
  display: revert;
}

/* ─── Settings tab scroll fix ───────────────────────────────
   Same lock-bypass as Transit. The Mandala :has rule above pins
   the page to 100vh + overflow:hidden whenever ANY .sn-mandala-view
   matches :not([hidden]) — even if it's tucked away in state-1/2.
   When Settings is the active panel, allow the page to scroll so
   the user can reach every section. */
body:has(.signal-view[data-view-panel="settings"]:not([hidden])) {
  overflow-y: auto !important;
}
.signal-main.signal-main-data:has(.signal-view[data-view-panel="settings"]:not([hidden])) {
  height: auto !important;
  overflow: visible !important;
}
body:has(.signal-view[data-view-panel="settings"]:not([hidden])) > footer {
  display: revert;
}

/* ─── Body Graph tab scroll fix ───────────────────────────────
   Mirror of Transit + Settings. Lets the user scroll to reach the
   gate-detail / center-detail panels under the chart. */
body:has(.signal-view[data-view-panel="bodygraph"]:not([hidden])) {
  overflow-y: auto !important;
}
.signal-main.signal-main-data:has(.signal-view[data-view-panel="bodygraph"]:not([hidden])) {
  height: auto !important;
  overflow: visible !important;
}
body:has(.signal-view[data-view-panel="bodygraph"]:not([hidden])) > footer {
  display: revert;
}


/* ─── Body Graph tab (Signal v3) ────────────────────────────────── */
/* Pole-driven projection over the bodygraph SVG. Color tokens live on
   the .signal-main root so consumers can override them per palette. */
.signal-main {
  --bg-pole-positive: #D4A843;
  --bg-pole-negative: #c4504c;
  --bg-mode-highs: #D4A843;
  --bg-mode-lows: #c4504c;
  --bg-mode-beats: #9b7cd4;
  --bg-mode-shifts: #4FC3D9;
  --bg-mode-shifts-good: #6BB8C9;
  --bg-mode-shifts-bad: #7B8AD4;
  --bg-natal: #a489d4;
  --bg-natal-defined: #a489d4;
  --bg-channel-empty: #3a3a48;
  --bg-center-fill: #1a1825;
}

/* ─── Resonance Bodygraph header ─────────────────────────────── */
.sn-bg-resonance-header {
  display: flex; flex-direction: column; align-items: center; gap: 0.4rem;
  padding: 0.8rem 1rem 0.6rem; text-align: center;
}
.sn-bg-resonance-tagline {
  margin: 0; font-style: italic; font-size: 0.78rem; line-height: 1.45;
  color: var(--sn-text-2, #b8aee0); opacity: 0.9;
}
.sn-bg-resonance-summary {
  margin: 0; font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--bg-natal, #a489d4);
}

/* Show Natal icon button — small, circular, mauve-accented. Replaces
   the old "Show Natal" pill. The optional-body pills appear next to it
   only after the icon is pressed. */
.sn-bg-natal-icon {
  width: 32px; height: 32px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 999px;
  background: rgba(164, 137, 212, 0.12);
  border: 1px solid rgba(164, 137, 212, 0.4);
  color: var(--bg-natal, #a489d4);
  cursor: pointer; transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.sn-bg-natal-icon:hover { background: rgba(164, 137, 212, 0.2); border-color: rgba(164, 137, 212, 0.7); }
.sn-bg-natal-icon[aria-pressed="true"] {
  background: var(--bg-natal, #a489d4); color: #1a1825; border-color: var(--bg-natal, #a489d4);
}
.sn-bg-natal-icon[aria-disabled="true"] { opacity: 0.4; cursor: not-allowed; }

.signal-view.sn-bg-view {
  padding: 0 0.75rem calc(var(--sn-tabbar-bottom, 64px) + 0.75rem);
  color: var(--sn-text, #ece6ff);
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.sn-bg-header {
  text-align: center;
  padding: 0.25rem 0 0.1rem;
}
.sn-bg-title {
  font-family: 'Playfair Display', 'DM Sans', serif;
  font-size: clamp(1.15rem, 2.4vw, 1.55rem);
  margin: 0;
  color: var(--sn-text, #ece6ff);
  letter-spacing: 0.01em;
}
.sn-bg-subtitle {
  margin: 0.2rem auto 0;
  color: var(--sn-text-2, #b8aee0);
  font-size: 0.78rem;
  font-style: italic;
  max-width: 32rem;
  line-height: 1.35;
}
.sn-bg-subtitle:empty { display: none; }

/* Pole + threshold on one tight row, equal heights, single-line labels. */
.sn-bg-controls {
  display: flex;
  gap: 0.4rem;
  justify-content: center;
  align-items: stretch;
  flex-wrap: nowrap;
  width: 100%;
}
.sn-bg-controls .signal-segment {
  flex: 0 1 auto;
  min-width: 0;
  display: flex;
  border-radius: 999px;
  align-items: stretch;
}
.sn-bg-controls .signal-seg-btn {
  flex: 1 1 0;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.4rem 0.65rem;
  font-size: 0.72rem;
  line-height: 1.1;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
@media (max-width: 400px) {
  .sn-bg-controls .signal-seg-btn {
    padding: 0.4rem 0.5rem;
    font-size: 0.66rem;
  }
}
@media (max-width: 340px) {
  .sn-bg-controls .signal-seg-btn {
    padding: 0.4rem 0.4rem;
    font-size: 0.6rem;
  }
}

/* Cosmic Pulse mode selector visuals. The active button takes the hue
   of the mode it represents so the segmented control echoes the colour
   of the gates that light up below. */
.sn-bg-mode .signal-seg-btn[data-bg-mode="highs"].active {
  background: var(--bg-mode-highs);
  color: var(--sn-night, #0c0917);
  border-color: var(--bg-mode-highs);
}
.sn-bg-mode .signal-seg-btn[data-bg-mode="lows"].active {
  background: var(--bg-mode-lows);
  color: #fff;
  border-color: var(--bg-mode-lows);
}
.sn-bg-mode .signal-seg-btn[data-bg-mode="beats"].active {
  background: var(--bg-mode-beats);
  color: #fff;
  border-color: var(--bg-mode-beats);
}
.sn-bg-mode .signal-seg-btn[data-bg-mode="shifts"].active {
  background: var(--bg-mode-shifts);
  color: var(--sn-night, #0c0917);
  border-color: var(--bg-mode-shifts);
}

/* Cluster filter chip row. Lives under the mode selector. */
.sn-bg-cluster-row {
  display: flex;
  flex-wrap: nowrap;
  gap: 0.35rem;
  align-items: center;
  justify-content: flex-start;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  padding: 0.1rem 0;
}
.sn-bg-cluster-chip {
  flex: 0 0 auto;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  border: 1px solid var(--sn-hairline, rgba(214, 198, 255, 0.12));
  background: transparent;
  color: var(--sn-text-2, #b8aee0);
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.7rem;
  letter-spacing: 0.02em;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.18s, color 0.18s, border-color 0.18s;
}
.sn-bg-cluster-chip:hover {
  color: var(--sn-text, #ece6ff);
  border-color: var(--sn-text-3, #7a6ea3);
}
.sn-bg-cluster-chip.active {
  background: var(--sn-gold, #e9b96a);
  color: var(--sn-night, #0c0917);
  border-color: var(--sn-gold, #e9b96a);
}

/* Shifts mode timeline. Swapped in for the bodygraph SVG when the
   user selects Shifts. Six horizontal lanes, each a cluster row. */
.sn-bg-shifts {
  width: 100%;
  min-height: 320px;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 0.4rem 0;
}
.sn-bg-shifts[hidden] { display: none; }
.sn-bg-shifts-empty {
  text-align: center;
  color: var(--sn-text-3, #7a6ea3);
  font-size: 0.85rem;
  padding: 2rem 0;
}
.sn-bg-shifts-lane {
  position: relative;
  display: grid;
  grid-template-columns: 5.5rem 1fr;
  align-items: center;
  gap: 0.5rem;
  height: 36px;
}
.sn-bg-shifts-lane-label {
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.7rem;
  color: var(--sn-text-2, #b8aee0);
  text-transform: capitalize;
}
.sn-bg-shifts-track {
  position: relative;
  height: 100%;
  background: var(--sn-violet, #14102a);
  border: 1px solid var(--sn-hairline, rgba(214, 198, 255, 0.10));
  border-radius: 6px;
  overflow: visible;
}
.sn-bg-shifts-marker {
  position: absolute;
  top: 50%;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  cursor: pointer;
  border: 1.5px solid var(--sn-night, #0c0917);
  transition: transform 0.12s;
}
.sn-bg-shifts-marker:hover,
.sn-bg-shifts-marker:focus-visible {
  transform: translate(-50%, -50%) scale(1.4);
  outline: none;
}
.sn-bg-shifts-marker.is-positive {
  background: var(--bg-mode-highs);
  box-shadow: 0 0 6px var(--bg-mode-highs);
}
.sn-bg-shifts-marker.is-negative {
  background: var(--bg-mode-lows);
  box-shadow: 0 0 6px var(--bg-mode-lows);
}

/* Footer row under the bodygraph: tracked-body chips on the left,
   Show Natal toggle on the right. Always sits above the fixed tab bar. */
.sn-bg-footer {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0;
}
.sn-bg-chips {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  gap: 0.35rem;
  align-items: center;
  padding: 0;
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scroll-snap-type: x proximity;
}
.sn-bg-chips::-webkit-scrollbar { height: 4px; }
.sn-bg-chips::-webkit-scrollbar-thumb {
  background: rgba(214,198,255,0.15);
  border-radius: 4px;
}
.sn-bg-chip {
  scroll-snap-align: start;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.32rem 0.7rem;
  border-radius: 999px;
  border: 1px solid var(--sn-hairline, rgba(214, 198, 255, 0.10));
  background: var(--sn-violet, #14102a);
  color: var(--sn-text-2, #b8aee0);
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.72rem;
  cursor: pointer;
  user-select: none;
  letter-spacing: 0.01em;
  transition: background 0.18s, color 0.18s, border-color 0.18s, opacity 0.18s;
  white-space: nowrap;
}
/* Opt-in chip rendered before the user has enough wearable history.
   The chip stays toggleable so the affordance is discoverable, but
   reads as muted to telegraph that it can't surface anything yet.
   The active state stays fully opaque + gold-filled so the toggle
   itself is obviously responsive even though the projection is empty. */
.sn-bg-chip.sn-bg-chip-ineligible {
  opacity: 0.55;
  border-style: dashed;
}
.sn-bg-chip.sn-bg-chip-ineligible.active {
  opacity: 1;
  border-style: solid;
}
.sn-bg-chip:hover {
  background: var(--sn-violet-2, #1c1740);
  color: var(--sn-text, #ece6ff);
}
.sn-bg-chip.active {
  background: var(--sn-gold, #e9b96a);
  color: var(--sn-night, #0c0917);
  border-color: var(--sn-gold, #e9b96a);
}
.sn-bg-chip-dot {
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: var(--sn-text-3, #7a6ea3);
  display: inline-block;
}
.sn-bg-chip.active .sn-bg-chip-dot {
  background: var(--sn-night, #0c0917);
}

/* The bodygraph claims the full width of the column and grows vertically
   to whatever room the viewport gives us, never spilling past the screen
   in either axis. Tracked-body chips + Show Natal sit below in a tight
   row above the fixed bottom tab bar.

   --sn-bg-h-pad    = horizontal padding around the view.
   --sn-bg-v-chrome = everything around the chart that isn't the chart
                       itself (header, controls, footer row, tabbar, gaps). */
.sn-bg-view {
  --sn-bg-h-pad: 1.5rem;
  --sn-bg-v-chrome: 230px;
}
.sn-bg-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
}
.sn-bg-canvas-wrap {
  position: relative;
  /* Pick the smaller of: viewport-room-height, or the height that keeps
     width inside the column (width × 1.18 since aspect is 1 : 1.18). */
  height: min(
    calc(100svh - var(--sn-tabbar-bottom, 64px) - var(--sn-bg-v-chrome)),
    calc((100vw - var(--sn-bg-h-pad)) * 1.18),
    720px
  );
  aspect-ratio: 1 / 1.18;
  width: auto;
  max-width: 100%;
  margin: 0 auto;
  border-radius: 14px;
  background: linear-gradient(180deg, rgba(20, 16, 42, 0.45), rgba(7, 5, 13, 0.6));
  border: 1px solid var(--sn-hairline, rgba(214, 198, 255, 0.10));
  padding: 0.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
}
.sn-bg-canvas {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.2s;
}
.sn-bg-canvas.sn-bg-canvas-empty { opacity: 0.4; }
.sn-bg-canvas svg {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
}

.sn-bg-empty {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  margin: 0;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.85rem;
  color: var(--sn-text-3, #7a6ea3);
  background: rgba(7, 5, 13, 0.88);
  border: 1px solid var(--sn-hairline, rgba(214, 198, 255, 0.10));
  border-radius: 8px;
  padding: 0.7rem 1rem;
  text-align: center;
  pointer-events: none;
}

/* Right-side cluster wrapping Show Natal + the Chiron/Lilith natal-overlay
   toggles. The cluster stays at the right edge of .sn-bg-footer while the
   body filter chips scroll on the left. */
.sn-bg-natal-group {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

/* Extras row: Chiron + Lilith natal-overlay toggles. Visible only when
   Show Natal is on. Animates in with a fade + small slide so it reads as
   "this belongs to the natal gesture". */
.sn-bg-natal-extras {
  display: inline-flex;
  flex-direction: row;
  align-items: center;
  gap: 0.3rem;
  opacity: 0;
  transform: translateX(6px);
  transition: opacity 0.18s ease-out, transform 0.18s ease-out;
  pointer-events: none;
}
.sn-bg-natal-extras.is-open {
  opacity: 1;
  transform: translateX(0);
  pointer-events: auto;
}
.sn-bg-natal-extras[hidden] {
  display: none;
}

/* Single Chiron / Lilith natal-overlay toggle. Glyph-led, mauve accent
   when active. Reads as part of the natal gesture, distinct from the
   gold body-filter chips. */
.sn-bg-natal-overlay-toggle {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.32rem 0.6rem 0.32rem 0.5rem;
  border-radius: 999px;
  border: 1px solid var(--bg-natal, #a489d4);
  background: transparent;
  color: var(--bg-natal, #a489d4);
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.72rem;
  line-height: 1.1;
  cursor: pointer;
  letter-spacing: 0.02em;
  white-space: nowrap;
  transition: background 0.18s, color 0.18s, border-color 0.18s, opacity 0.18s;
}
.sn-bg-natal-overlay-toggle:hover {
  background: rgba(164, 137, 212, 0.12);
}
.sn-bg-natal-overlay-toggle[aria-pressed="true"] {
  background: var(--bg-natal, #a489d4);
  color: var(--sn-night, #0c0917);
}
.sn-bg-natal-glyph {
  font-size: 0.95rem;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1rem;
  height: 1rem;
}
.sn-bg-natal-overlay-label {
  font-size: 0.7rem;
  letter-spacing: 0.02em;
}
/* On the tightest screens, drop the label and keep just the glyph so the
   row still fits next to Show Natal without horizontal overflow. */
@media (max-width: 420px) {
  .sn-bg-natal-overlay-label {
    display: none;
  }
  .sn-bg-natal-overlay-toggle {
    padding: 0.32rem 0.5rem;
  }
}

.sn-bg-natal-toggle {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  padding: 0.4rem 0.85rem;
  border-radius: 999px;
  border: 1px solid var(--sn-hairline, rgba(214, 198, 255, 0.10));
  background: var(--sn-violet, #14102a);
  color: var(--sn-text-2, #b8aee0);
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.72rem;
  line-height: 1.1;
  cursor: pointer;
  letter-spacing: 0.02em;
  white-space: nowrap;
  transition: background 0.18s, color 0.18s, border-color 0.18s;
}
.sn-bg-natal-toggle:hover {
  background: var(--sn-violet-2, #1c1740);
  color: var(--sn-text, #ece6ff);
}
.sn-bg-natal-toggle[aria-pressed="true"] {
  background: var(--bg-natal, #a489d4);
  color: var(--sn-night, #0c0917);
  border-color: var(--bg-natal, #a489d4);
}
.sn-bg-natal-toggle[disabled],
.sn-bg-natal-toggle[aria-disabled="true"] {
  opacity: 0.4;
  cursor: not-allowed;
}
.sn-bg-natal-dot {
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: var(--bg-natal, #a489d4);
  display: inline-block;
}
.sn-bg-natal-toggle[aria-pressed="true"] .sn-bg-natal-dot {
  background: var(--sn-night, #0c0917);
}

/* ─── Gate detail (inline) ─── */
.sn-bg-gate-detail {
  position: relative;
  width: 100%;
  max-width: 600px;
  margin: 0 auto;
  padding: 1rem 1.25rem 1.25rem;
  border-radius: 12px;
  background: var(--sn-violet, #14102a);
  border: 1px solid var(--sn-hairline-2, rgba(214, 198, 255, 0.18));
  color: var(--sn-text, #ece6ff);
}
.sn-bg-gate-detail[hidden] { display: none; }
.sn-bg-gate-detail-close {
  position: absolute;
  top: 0.4rem;
  right: 0.5rem;
  background: transparent;
  border: 0;
  font-size: 1.3rem;
  color: var(--sn-text-3, #7a6ea3);
  cursor: pointer;
  padding: 0.2rem 0.5rem;
  line-height: 1;
}
.sn-bg-gate-detail-title {
  font-family: 'Playfair Display', 'DM Sans', serif;
  font-size: 1.2rem;
  margin: 0 1.5rem 0.3rem 0;
}
.sn-bg-gate-detail-meta {
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.8rem;
  color: var(--sn-text-2, #b8aee0);
  margin: 0 0 0.75rem;
}
.sn-bg-gate-detail-bodies,
.sn-bg-gate-detail-outliers {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.sn-bg-gate-detail-bodies li,
.sn-bg-gate-detail-outliers li {
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.78rem;
  color: var(--sn-text-2, #b8aee0);
  padding: 0.3rem 0.55rem;
  background: var(--sn-violet-2, #1c1740);
  border-radius: 6px;
  border: 1px solid var(--sn-hairline, rgba(214, 198, 255, 0.10));
}
.sn-bg-gate-detail-subhead {
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sn-text-3, #7a6ea3);
  margin: 0.85rem 0 0.4rem;
}
.sn-bg-gate-detail-outliers li {
  display: flex;
  justify-content: space-between;
  gap: 0.5rem;
}

.sn-bg-svg-projection .bg-center-tint {
  mix-blend-mode: screen;
}

/* ─── Center detail (inline) — mirrors gate-detail layout ─── */
.sn-bg-center-detail {
  position: relative;
  width: 100%;
  max-width: 600px;
  margin: 0.75rem auto 0;
  padding: 1rem 1.25rem 1.25rem;
  border-radius: 12px;
  background: var(--sn-violet, #14102a);
  border: 1px solid var(--sn-hairline-2, rgba(214, 198, 255, 0.18));
  color: var(--sn-text, #ece6ff);
}
.sn-bg-center-detail[hidden] { display: none; }
.sn-bg-center-detail-close {
  position: absolute;
  top: 0.4rem;
  right: 0.5rem;
  background: transparent;
  border: 0;
  font-size: 1.3rem;
  color: var(--sn-text-3, #7a6ea3);
  cursor: pointer;
  padding: 0.2rem 0.5rem;
  line-height: 1;
}
.sn-bg-center-detail-title {
  font-family: 'Playfair Display', 'DM Sans', serif;
  font-size: 1.2rem;
  margin: 0 1.5rem 0.3rem 0;
}
.sn-bg-center-detail-status {
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.8rem;
  color: var(--sn-text-2, #b8aee0);
  margin: 0 0 0.55rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.sn-bg-center-detail-explanation {
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--sn-text, #ece6ff);
  margin: 0;
}

/* ─── Settings tab ────────────────────────────────────────────────────
   Vertical stack of section groups. Each section has an eyebrow + title
   + body, mirroring the iOS Settings layout. The wearable-connectors
   block sits inside the top section as a responsive 1/2-column grid of
   provider cards with brand-coloured logo badges and a status pill.
   ──────────────────────────────────────────────────────────────────── */
.sn-settings-view {
  /* Centered, max-width content column. Bottom padding clears the fixed
     tab bar even on devices where overscroll-bounce uncovers content. */
  max-width: 760px;
  margin: 0 auto;
  padding: 0.5rem 1rem calc(var(--sn-tabbar-bottom, 64px) + 2rem);
  display: flex;
  flex-direction: column;
  gap: 1.75rem;
  color: var(--sn-text, #ece6ff);
}

.sn-settings-head {
  padding: 1.25rem 0.25rem 0.25rem;
  text-align: left;
}
.sn-settings-title {
  font-family: var(--sn-display, 'Outfit'), 'Playfair Display', serif;
  font-size: clamp(1.5rem, 3.4vw, 2rem);
  font-weight: 400;
  color: var(--sn-text, #ece6ff);
  margin: 0 0 0.35rem;
  letter-spacing: -0.01em;
  line-height: 1.1;
}
.sn-settings-sub {
  margin: 0;
  font-family: var(--sn-body, 'Plus Jakarta Sans'), system-ui, sans-serif;
  font-size: 0.95rem;
  color: var(--sn-text-2, #b8aee0);
  line-height: 1.5;
  max-width: 38rem;
}

/* ─── Section group ───────────────────────────────────────── */
.sn-settings-section {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}
.sn-settings-section-head {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0 0.25rem;
}
.sn-settings-section-title {
  font-family: var(--sn-display, 'Outfit'), 'Playfair Display', serif;
  font-size: 1.15rem;
  font-weight: 500;
  color: var(--sn-text, #ece6ff);
  margin: 0;
  letter-spacing: -0.005em;
  line-height: 1.2;
}
.sn-settings-section-sub {
  font-family: var(--sn-body, 'Plus Jakarta Sans'), system-ui, sans-serif;
  font-size: 0.85rem;
  color: var(--sn-text-2, #b8aee0);
  margin: 0;
  line-height: 1.45;
  max-width: 36rem;
}
.sn-settings-section[hidden] { display: none; }
.sn-settings-section-foot {
  margin-top: 0.5rem;
}

/* ─── Connector grid ──────────────────────────────────────── */
.sn-connector-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.75rem;
  padding: 0;
  list-style: none;
  margin: 0;
}
@media (min-width: 560px) {
  .sn-connector-list {
    grid-template-columns: 1fr 1fr;
  }
}

.sn-connector-card {
  position: relative;
  display: grid;
  grid-template-columns: 44px 1fr auto;
  align-items: center;
  gap: 0.85rem;
  min-height: 84px;
  padding: 0.95rem 1.05rem;
  background: var(--sn-violet, #14102a);
  border: 1px solid var(--sn-hairline, rgba(214, 198, 255, 0.10));
  border-radius: 14px;
  transition: border-color 0.2s ease, background 0.2s ease, transform 0.2s ease;
}
.sn-connector-card:hover {
  border-color: var(--sn-hairline-2, rgba(214, 198, 255, 0.18));
}
.sn-connector-card.is-connected {
  border-color: var(--sn-gold, #e9b96a);
  background: linear-gradient(180deg, rgba(233, 185, 106, 0.05) 0%, var(--sn-violet, #14102a) 80%);
}
.sn-connector-card.is-disabled {
  opacity: 0.7;
}

/* ─── Status pill (top-right corner) ───────────────────────── */
.sn-connector-pill {
  position: absolute;
  top: 10px;
  right: 12px;
  padding: 2px 8px;
  border-radius: 999px;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.58rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.3;
  border: 1px solid var(--sn-hairline-2, rgba(214, 198, 255, 0.18));
  color: var(--sn-text-3, #7a6ea3);
  background: rgba(214, 198, 255, 0.04);
  white-space: nowrap;
}
.sn-connector-pill.is-connected {
  color: var(--sn-gold, #e9b96a);
  border-color: rgba(233, 185, 106, 0.45);
  background: rgba(233, 185, 106, 0.10);
}
.sn-connector-pill.is-idle {
  color: var(--sn-text-2, #b8aee0);
}
.sn-connector-pill.is-soon {
  color: var(--sn-text-3, #7a6ea3);
}

/* ─── Logo badge ──────────────────────────────────────────── */
.sn-connector-glyph {
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--sn-connector-tint, rgba(214, 198, 255, 0.08));
  border: 1px solid var(--sn-hairline-2, rgba(214, 198, 255, 0.16));
  /* Letter-monogram fallback styling */
  font-family: var(--sn-display, 'Outfit'), 'Playfair Display', serif;
  font-size: 1.25rem;
  color: var(--sn-gold, #e9b96a);
  overflow: hidden;
}
.sn-connector-glyph.has-logo {
  /* SVG logos handle their own colour; remove the gold tint */
  color: inherit;
}
.sn-connector-glyph svg {
  width: 26px;
  height: 26px;
  display: block;
}

/* ─── Card body (name + tagline) ──────────────────────────── */
.sn-connector-body {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
  /* Reserve room above for the status pill */
  padding-top: 0.15rem;
}
.sn-connector-name {
  font-family: var(--sn-display, 'Outfit'), 'Playfair Display', serif;
  font-size: 1rem;
  font-weight: 500;
  color: var(--sn-text, #ece6ff);
  letter-spacing: 0;
  line-height: 1.2;
}
.sn-connector-status {
  font-family: var(--sn-body, 'Plus Jakarta Sans'), system-ui, sans-serif;
  font-size: 0.78rem;
  color: var(--sn-text-2, #b8aee0);
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sn-connector-card.is-connected .sn-connector-status {
  color: var(--sn-text-2, #b8aee0);
}

/* ─── Card actions ────────────────────────────────────────── */
.sn-connector-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
}
.sn-connector-btn {
  padding: 0.45rem 0.9rem;
  font-family: var(--sn-mono, 'JetBrains Mono', monospace);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  border-radius: 999px;
  border: 1px solid var(--sn-gold, #e9b96a);
  background: transparent;
  color: var(--sn-gold, #e9b96a);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.sn-connector-btn:hover {
  background: var(--sn-gold, #e9b96a);
  color: #07050d;
}
.sn-connector-btn:disabled,
.sn-connector-btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
  border-color: var(--sn-hairline-2, rgba(214, 198, 255, 0.18));
  color: var(--sn-text-3, #7a6ea3);
}
.sn-connector-btn-secondary {
  border-color: var(--sn-hairline-2, rgba(214, 198, 255, 0.25));
  color: var(--sn-text-2, #b8aee0);
}
.sn-connector-btn-secondary:hover {
  background: var(--sn-violet-2, #1c1740);
  color: var(--sn-text, #ece6ff);
  border-color: var(--sn-hairline-2, rgba(214, 198, 255, 0.32));
}
.sn-connector-note {
  display: none;
}

/* ─── Skeleton state — shown until /api/wearables/status resolves ── */
.sn-connector-card-skeleton {
  pointer-events: none;
}
.sn-connector-card-skeleton .sn-connector-glyph {
  background: rgba(214, 198, 255, 0.06);
  border-color: transparent;
}
.sn-connector-card-skeleton .sn-connector-glyph,
.sn-connector-card-skeleton .sn-connector-name,
.sn-connector-card-skeleton .sn-connector-status {
  color: transparent;
}
.sn-connector-card-skeleton .sn-connector-name {
  height: 14px;
  width: 60%;
  background: rgba(214, 198, 255, 0.08);
  border-radius: 6px;
  margin-bottom: 6px;
}
.sn-connector-card-skeleton .sn-connector-status {
  height: 10px;
  width: 35%;
  background: rgba(214, 198, 255, 0.06);
  border-radius: 6px;
}

/* ─── Active-provider / inventory cards — restyled to match section grid ─── */
.sn-settings-view .signal-settings-grid {
  margin-bottom: 0;
}
.sn-settings-view .signal-settings-card {
  background: var(--sn-violet, #14102a);
  border: 1px solid var(--sn-hairline, rgba(214, 198, 255, 0.10));
  border-radius: 14px;
  padding: 1.25rem 1.35rem;
}
.sn-settings-view .signal-settings-card .sn-eyebrow {
  margin-bottom: 0.5rem;
}
.sn-settings-view .signal-settings-provider {
  font-family: var(--sn-display, 'Outfit'), serif;
  font-size: 1.4rem;
  font-weight: 500;
  margin: 0 0 0.5rem;
  color: var(--sn-text, #ece6ff);
}
.sn-settings-view .signal-summary {
  font-family: var(--sn-body, 'Plus Jakarta Sans'), system-ui, sans-serif;
  color: var(--sn-text-2, #b8aee0);
  font-size: 0.85rem;
  letter-spacing: 0;
  line-height: 1.45;
  margin: 0;
}
.sn-settings-view .signal-footnote {
  font-family: var(--sn-body, 'Plus Jakarta Sans'), system-ui, sans-serif;
  color: var(--sn-text-2, #b8aee0);
  font-size: 0.85rem;
  margin: 0;
  padding: 0 0.25rem;
  line-height: 1.55;
}
.sn-settings-view .signal-footnote a {
  color: var(--sn-gold, #e9b96a);
  text-decoration: none;
  border-bottom: 1px solid rgba(233, 185, 106, 0.35);
}
.sn-settings-view .signal-footnote a:hover {
  border-bottom-color: var(--sn-gold, #e9b96a);
}

/* ─── Narrow viewport polish ─────────────────────────────── */
@media (max-width: 380px) {
  .sn-connector-card {
    grid-template-columns: 40px 1fr;
    grid-template-rows: auto auto;
    row-gap: 0.5rem;
  }
  .sn-connector-actions {
    grid-column: 1 / -1;
    justify-content: flex-start;
  }
  .sn-connector-pill {
    top: 8px;
    right: 10px;
  }
}

/* ─── Polarity strip (deterministic card descriptor) ──────────────────
   Below the planet glyph row, replaces the binary positive/negative
   tone color with a 5-polarity color system: upbeat (gold), downbeat
   (oxblood), beat (mauve), shift (cyan), tilt (warm tan).
   Spec: reference-docs/specs/deterministic-card-descriptions.md §F.
*/
.sn-revealed-card.sn-rc-rich .sn-polarity-strip {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 4px 14px 5px;
  background: var(--polarity-color, #c89968);
  border-radius: 0 0 10px 10px;
  font-family: var(--sn-mono);
  font-size: 9px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  font-weight: 700;
  color: #0a0a0f;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
  z-index: 3;
}
.sn-polarity-strip[data-polarity="upbeat"]   { --polarity-color: #D4A843; }
.sn-polarity-strip[data-polarity="downbeat"] { --polarity-color: #c4504c; }
.sn-polarity-strip[data-polarity="beat"]     { --polarity-color: #9b7cd4; }
.sn-polarity-strip[data-polarity="shift"]    { --polarity-color: #4FC3D9; }
.sn-polarity-strip[data-polarity="tilt"]     { --polarity-color: #c89968; }

.sn-polarity-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background-color: #0a0a0f;
  flex-shrink: 0;
  position: relative;
}
.sn-polarity-glyph::before {
  content: '';
  display: block;
  width: 9px;
  height: 9px;
  background-color: var(--polarity-color, #c89968);
  -webkit-mask-image: var(--mask);
  -webkit-mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-image: var(--mask);
  mask-size: contain;
  mask-repeat: no-repeat;
  mask-position: center;
}
.sn-polarity-glyph.sn-polarity-glyph-img {
  background-color: transparent;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  width: 18px;
  height: 18px;
}
.sn-polarity-glyph.sn-polarity-glyph-img::before {
  display: none;
}
.sn-polarity-label {
  font-weight: 600;
  flex-shrink: 0;
}
.sn-polarity-tone-bar {
  flex: 1 1 auto;
  height: 2px;
  background: currentColor;
  opacity: 0.45;
  border-radius: 1px;
}

/* Cooldown / empty-pool caption — appended into .sn-deck-stage (full-width
   relative box) by flashEmptyPool / flashCooldownCaption. Anchored to the
   bottom-center of the stage, ABOVE the history-strip (which sits at
   bottom:16 + height:72 = 88px from the stage bottom edge) with breathing
   room so it doesn't overlap thumbnails or the revealed card sitting in
   .sn-deck-hero above. Width is generous so the italic phrase reads as a
   single tasteful banner rather than a narrow column. */
.sn-deck-cooldown-msg {
  position: absolute;
  left: 50%;
  bottom: 100px;                /* clears the 88px history strip + 12px gap */
  transform: translateX(-50%);
  width: min(360px, calc(100vw - 32px));
  max-width: 360px;
  padding: 10px 16px;
  background: rgba(20, 20, 24, 0.82);
  -webkit-backdrop-filter: blur(8px) saturate(120%);
  backdrop-filter: blur(8px) saturate(120%);
  border: 1px solid var(--sn-border, rgba(255, 255, 255, 0.12));
  border-radius: 10px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45);
  color: var(--sn-text-soft, #c8c5b9);
  font-family: var(--sn-serif, Georgia, serif);
  font-size: 13px;
  font-style: italic;
  line-height: 1.45;
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 280ms ease-out;
  z-index: 10;
}
.sn-deck-cooldown-msg.is-visible { opacity: 1; }

/* Narrow viewports — sit higher above the history row (which is shorter
   margin on mobile, bottom:12 + 72 = 84px) and shrink width to fit. */
@media (max-width: 640px) {
  .sn-deck-cooldown-msg {
    bottom: 96px;
    width: min(320px, calc(100vw - 24px));
    font-size: 12.5px;
    padding: 9px 14px;
  }
}

/* Discovery hint — small italic muted text anchored to the bottom-left
   corner, sitting ABOVE the draw deck. Collapsed default ("discovering
   more insights…") and expanded longer-phrase state differ only in
   max-width. Click toggles is-expanded; signal.js auto-collapses ~4s. */
.sn-deck-discovery {
  position: absolute;
  left: 16px;
  bottom: 96px;
  font-family: var(--sn-serif, Georgia, 'Times New Roman', serif);
  font-style: italic;
  font-size: 11px;
  line-height: 1.4;
  color: var(--sn-text-soft, rgba(200, 197, 185, 0.7));
  cursor: pointer;
  user-select: none;
  max-width: 200px;
  z-index: 4;
  opacity: 0.85;
  transition: opacity 280ms ease-out, max-width 320ms ease-out, color 280ms ease-out;
}
.sn-deck-discovery:hover {
  opacity: 1;
}
.sn-deck-discovery:focus-visible {
  outline: 1px dashed rgba(233, 185, 106, 0.5);
  outline-offset: 3px;
}
.sn-deck-discovery.is-expanded {
  max-width: 320px;
  opacity: 1;
  color: var(--sn-text-2, #c8c5b9);
}

@media (max-width: 640px) {
  .sn-deck-discovery {
    font-size: 10px;
    max-width: 160px;
    bottom: 92px;
  }
  .sn-deck-discovery.is-expanded {
    max-width: 200px;
  }
}

/* ─── Pool exhaustion — visual disabled state ──────────────────────────
   Applied to .sn-deck-view root by applyPoolExhaustionState() whenever
   drawStatus.untouchedCandidates === 0. The deck card-backs (both the
   hero stack and the small bottom-left draw deck) read as muted, no
   hover lift, cursor:not-allowed. The empty-pool caption + discovery
   hint surface in parallel; together they communicate "nothing to
   draw right now, here's why".

   We intentionally do NOT use pointer-events:none on the tap targets,
   because we want the click to bubble into the wireDeckUI handler so
   isPoolExhausted() can register a no-op (and refresh the banner if
   the user keeps tapping in confusion). */
.sn-deck-view.is-pool-exhausted .sn-draw-deck,
.sn-deck-view.is-pool-exhausted .sn-deck-stack-hero,
.sn-deck-view.is-pool-exhausted [data-deck-placeholder] {
  cursor: not-allowed;
}
.sn-deck-view.is-pool-exhausted .sn-draw-deck .sn-deck-card,
.sn-deck-view.is-pool-exhausted .sn-deck-stack-hero .sn-deck-cover {
  opacity: 0.42;
  filter: saturate(0.55) brightness(0.78);
  transition: opacity 220ms ease-out, filter 220ms ease-out;
}
.sn-deck-view.is-pool-exhausted .sn-draw-deck:hover .sn-deck-card,
.sn-deck-view.is-pool-exhausted .sn-deck-stack-hero:hover .sn-deck-cover {
  /* Suppress any hover-lift / brightness boost that the deck normally
     gets — exhausted state should feel inert, not invite a tap. */
  transform: none;
}
.sn-deck-view.is-pool-exhausted .sn-deck-cover-cta {
  opacity: 0.45;
}
