/* Copyright (c) Edward James Harrison. All rights reserved. */

/* ═══════════════════════════════════════════════════════════
   NOW Reading V2 — Minimal, responsive, two-panel
   ═══════════════════════════════════════════════════════════ */

* { box-sizing: border-box; margin: 0; padding: 0; }

/* ── Theme: Dark (default) ────────────────────────────────── */
:root, [data-theme="dark"] {
  --bg: #0f1318;
  --surface: #161c24;
  --surface-hover: #1e2736;
  --border: rgba(255,255,255,0.1);
  --text: #e0dbd5;
  --text-muted: #9a9490;
  --text-dim: #7a7470;
  --accent: #b8b2f7;                        /* light periwinkle (unified with the celestial default) — nudged from the old sky blue toward purple, kept light */
  --accent-bg: rgba(184,178,247,0.12);
  --accent-border: rgba(184,178,247,0.3);
  --shadow: rgba(0,0,0,0.5);
  --input-bg: rgba(255,255,255,0.06);

  /* Calendar day/hour TILE — a deliberately light "off-white" surface (single source
     of truth for both month cells and day-view hour rows) with dark ink over it, so
     the colour lives in the favourability DOT, not the tile. Themeable per mode. */
  --cal-tile: #e7e3d9;
  --cal-tile-ink: #26221b;
  --cal-tile-dim: #6f685c;

  /* ── Typographic scale — ONE standard size for the whole app ─────────
     2026-07-17 standardization: every text tier collapses to a single 12px
     for clean, consistent typography everywhere. The ladder tokens are kept
     (so call sites don't change and the scale is easy to re-expand later),
     but they all resolve to --fs-standard. The ONLY intentional larger text
     is the module-title header (--fs-display, e.g. TRANSITS / SOLAR RETURN)
     and the LENS/LOADED/NOW chart-role readouts (pinned explicitly on their
     own selectors). Type is owned by the skin/base layer here; themes control
     COLOUR only. To revert to a graduated scale, restore per-tier px below. */
  --fs-standard: 13px;   /* app-wide TEXT size (2026-09-07: 12→13, +1pt; text only — emojis/icons use explicit px) */
  --fs-display:  18px;   /* module-title header exception (.reading-title) */
  /* Quotes (core/quotes) render in a literary serif, comfortably larger than body text,
     wherever they appear (KP-roulette card, day-summary section + modal). Sized RELATIVE
     to the standard text token AND to --mi-font-scale (the "Info Panel Text" setting) so
     the quote scales with the app's text-size control while staying a fixed step larger.
     The +7px accounts for Cormorant Garamond's small optical size (it reads ~2–3px
     smaller than the sans body at the same px). */
  --font-quote:  'Cormorant Garamond', Georgia, 'Times New Roman', serif;
  --fs-quote:    calc(var(--fs-standard) * var(--mi-font-scale, 1) + 7px);
  --fs-micro:    var(--fs-standard);
  --fs-caption:  var(--fs-standard);
  --fs-label:    var(--fs-standard);
  --fs-body:     var(--fs-standard);
  --fs-heading:  var(--fs-standard);
  --fs-subtitle: var(--fs-standard);
  --fs-title:    var(--fs-standard);
  --fs-lg:       var(--fs-standard);
  --fs-xl:       var(--fs-standard);
  --fs-2xl:      var(--fs-standard);
  --fs-3xl:      var(--fs-standard);
  /* --font-emoji (the emoji font stack) is defined in fonts/fonts.css so every
     entry point gets it — see that file. Its canvas twin is EMOJI_FONT_STACK in
     data/glyphs.js. Below we splice it into the middle of --font-body.
     'Noto Sans Symbols' and the emoji fonts are all unicode-range-scoped (see
     fonts/fonts.css): 'Noto Sans Symbols' owns zodiac/planet/aspect glyphs
     (monochrome), the emoji fonts own emoji codepoints (colour), everything
     else falls through to 'Outfit'. Emoji-font names carry no Latin glyphs, so
     they never hijack body text. */
  --font-body: 'Noto Sans Symbols', var(--font-emoji), 'Outfit', system-ui, -apple-system, sans-serif;
  --font-display: 'Noto Sans Symbols', 'Cinzel', serif;

  /* Cuspal Interlinks — flowing/forged potential palette (sage / rust)
     and the module's gold accent. Per-theme overrides below. */
  --potential-flowing:           #6b8e5a;
  --potential-flowing-via-star:  #7a9869;
  --potential-mixed-flowing:     #998755;
  --potential-mixed-forged:      #a06d4d;
  --potential-forged:            #8c5a4a;
  --potential-forged-via-star:   #9a6b5b;
  --potential-neutral:           #6e6a64;
  --interlink-accent:            #c9a35a;
}

/* ── Skin layout foundation (full-app skinning, Step 1) ───────
   Region hooks + named grid areas so a skin can reflow the shell
   without touching JS. These are THEME-INDEPENDENT layout tokens,
   so they live in their own :root block (not the per-theme palette
   above). Nothing here changes the default app:
     • --app-header-h just names the existing 60px header height.
     • grid-area on the regions is INERT while .app is display:flex
       (flex items ignore grid-area). It only takes effect if a skin
       flips .app to display:grid — see the ready template below.
   The default (Classic) skin keeps the flex-column layout untouched. */
:root {
  --app-header-h: 60px;
  /* Navigation icon/emoji size — the ONE source of truth for the size of the
     nav glyphs in BOTH the header panel tabs (☀ Day / 🎯 KP / ◎ Ring / 📄 Reports
     / 💬 Oracle) and the footer ring-nav items. Change here to resize all nav
     icons together. (These are icon glyphs, exempt from the flat 12px type rule.) */
  --nav-icon-size: 26px;
  /* Info-panel horizontal gutter — single source for both panel modes
     (.text-content two-panel + .sp-main single-panel) so content never
     touches the edge and the two modes stay consistent. A skin can bump
     it (Celestial does, for an airier editorial measure); the narrow
     breakpoints below tighten it via --panel-pad-x-narrow. */
  --panel-pad-x: 16px;
  --panel-pad-x-narrow: 12px;
}

/* Region → grid-area map. Inert under the default flex layout; a
   reflow skin activates it by setting `.app { display:grid }`.
   Matches the data-region hooks in index.html. */
.app-header { grid-area: header; }
.dept-nav   { grid-area: nav; }
.app-body   { grid-area: body; }
.chat-bar   { grid-area: chat; }

/* Region hint states — applySkinLayout() stamps data-region-state onto a
   region from the active skin's `layout.regions` descriptor. `hidden` is
   universal; `collapsed` is left for skins to define per region. No region
   carries this attribute under the Classic skin, so it's inert by default. */
[data-region-state="hidden"] { display: none !important; }

/* Ready-to-activate reflow grid (a skin scopes this under its own
   [data-skin="…"] to opt in — the default never sets it):

     [data-skin="compact"] .app {
       display: grid;
       grid-template-columns: 1fr;
       grid-template-rows: var(--app-header-h) auto 1fr auto;
       grid-template-areas: "header" "nav" "body" "chat";
     }

   A skin can then relocate/hide any region by remapping its
   grid-area or `display:none`-ing it, all in scoped CSS. */

/* ── Theme: Light ────────────────────────────────────────── */
[data-theme="light"] {
  --bg: #f5f3f0;
  --surface: #ffffff;
  --surface-hover: #edeae6;
  --border: rgba(0,0,0,0.1);
  --text: #1e1914;
  --text-muted: #5c554e;
  --text-dim: #8a827a;
  --accent: #2b6cb0;
  --accent-bg: rgba(43,108,176,0.08);
  --accent-border: rgba(43,108,176,0.2);
  --shadow: rgba(0,0,0,0.12);
  --input-bg: rgba(0,0,0,0.04);

  /* Calendar tile — light mode: crisp white tiles on the light page. */
  --cal-tile: #ffffff;
  --cal-tile-ink: #1e1914;
  --cal-tile-dim: #8a827a;

  /* Deeper sage/rust for contrast against light bg */
  --potential-flowing:           #4a7038;
  --potential-flowing-via-star:  #5a7d4a;
  --potential-mixed-flowing:     #7a6020;
  --potential-mixed-forged:      #82503a;
  --potential-forged:            #74402d;
  --potential-forged-via-star:   #855442;
  --potential-neutral:           #6e655a;
  --interlink-accent:            #a06820;
}

/* ── Theme: Warm (mid-tone) ───────────────────────────────── */
[data-theme="warm"] {
  --bg: #d5cabb;
  --surface: #e4dace;
  --surface-hover: #cbbfaf;
  --border: rgba(100,70,40,0.12);
  --text: #2c2218;
  --text-muted: #6b5d4e;
  --text-dim: #8e7e6c;
  --accent: #a06820;
  --accent-bg: rgba(160,104,32,0.1);
  --accent-border: rgba(160,104,32,0.25);
  --shadow: rgba(60,40,20,0.2);
  --input-bg: rgba(0,0,0,0.04);

  /* Calendar tile — warm mode: light cream tiles on the parchment page. */
  --cal-tile: #f2ecdd;
  --cal-tile-ink: #2c2218;
  --cal-tile-dim: #8e7e6c;

  /* Olive/terracotta harmonizing with parchment */
  --potential-flowing:           #586d3a;
  --potential-flowing-via-star:  #67793f;
  --potential-mixed-flowing:     #836828;
  --potential-mixed-forged:      #7e4a2e;
  --potential-forged:            #7e3a2a;
  --potential-forged-via-star:   #8e4d3a;
  --potential-neutral:           #6e5d4a;
  --interlink-accent:            #a06820;
}

/* ── Layout direction via data attributes ────────────────── */
[data-dock="left"] .dock { order: -1; border-left: none; border-right: 1px solid var(--border); }

[data-panel="left"] .viewport { order: 2; }
[data-panel="left"] .text-panel { order: 1; }

/* Viewport column sized by JS sizeViewport() — chart fills shortest dimension */

body {
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--text);
  overflow: hidden;
  height: 100vh;
  height: 100dvh;
}

/* ── Theme-aware scrollbars (everywhere by default) ───────── */
/* Element-specific overrides below (.dock, .ring-nav-scroll, etc.)
   that want to hide scrollbars use scrollbar-width: none and the
   ::-webkit-scrollbar { display: none; } pattern. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--text-dim) transparent;
}
*::-webkit-scrollbar { width: 8px; height: 8px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--text-dim);
  border-radius: 4px;
  opacity: 0.5;
}
*::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }
*::-webkit-scrollbar-corner { background: transparent; }

/* ── Loading overlay ──────────────────────────────────────── */

.loading-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  z-index: 2000;
  transition: opacity 0.6s ease-out;
}
.loading-overlay.fade-out { opacity: 0; pointer-events: none; }
.loading-spinner { position: relative; width: 200px; height: 200px; }
.loading-rings { width: 100%; height: 100%; }
.loading-rings .ring { fill: none; stroke-width: 2; stroke-linecap: round; stroke-dasharray: 180 360; }
.ring-outer { stroke: var(--accent); animation: loading-spin 3s linear infinite; transform-origin: center; }
.ring-mid { stroke: rgba(100, 150, 255, 0.6); animation: loading-spin 2s linear infinite reverse; transform-origin: center; }
.ring-inner { stroke: rgba(255, 136, 68, 0.5); animation: loading-spin 1.5s linear infinite; transform-origin: center; }
@keyframes loading-spin { to { transform: rotate(360deg); } }

/* Inline corpus-text placeholder (info panel `pending` block). A miniaturised
   version of the boot loading-rings shown in place of an interpretation chunk
   while it is fetched from the gated server — so a slow/failed load never leaves
   the panel blank. The failed state swaps the spinner for a tap-to-retry cue. */
.mi-corpus-chunk { display: flex; align-items: center; gap: 8px; padding: 6px 0; min-height: 24px; }
.mi-loading-rings { width: 22px; height: 22px; flex: 0 0 auto; }
.mi-loading-rings .ring { fill: none; stroke-width: 2.5; stroke-linecap: round; transform-origin: center; }
.mi-loading-rings .ring-outer { stroke: var(--accent); stroke-dasharray: 60 40; animation: loading-spin 3s linear infinite; }
.mi-loading-rings .ring-mid   { stroke: rgba(100, 150, 255, 0.6); stroke-dasharray: 40 35; animation: loading-spin 2s linear infinite reverse; }
.mi-loading-rings .ring-inner { stroke: rgba(255, 136, 68, 0.5); stroke-dasharray: 22 22; animation: loading-spin 1.5s linear infinite; }
.mi-corpus-pending-label { font-size: 11px; color: var(--text-muted); font-style: italic; }
.mi-corpus-retry { background: none; border: none; padding: 0; cursor: pointer; font: inherit; font-size: 12px; color: var(--text-muted); text-decoration: underline dotted; }
.mi-corpus-retry:hover { color: var(--text); }
/* ── Per-module chart-role line (three-chart model: Loaded/Lens/Now) ── */
.mi-chart-role { display: flex; align-items: flex-start; gap: 6px; font-size: var(--fs-label); font-style: italic; color: var(--text-muted); padding: 5px 9px; margin: 0 0 12px; border-left: 3px solid var(--accent); border-radius: 3px; background: rgba(123, 179, 224, 0.07); }
.mi-chart-role--dual { border-left-color: var(--accent-warm, #e0a37b); background: rgba(224, 163, 123, 0.07); }
/* Degenerate "lens sits on the loaded chart" heads-up. Block = output is
   meaningless (attention amber); annotate = still valid, softer note. */
.mi-chart-role--degenerate { font-style: normal; }
.mi-chart-role--degenerate-block { border-left-color: #e0b45a; background: rgba(224, 180, 90, 0.12); color: var(--text, #d8def0); }
.mi-chart-role--degenerate-annotate { border-left-color: #c9a86a; background: rgba(201, 168, 106, 0.08); }
.mi-chart-role-icon { opacity: 0.75; font-style: normal; }
.mi-chart-role-text { line-height: 1.35; }
/* Tier-2 shared navigation primer (expandable). Sits under the role line. */
.mi-nav-primer { margin: -6px 0 12px; font-size: var(--fs-label); font-style: normal; }
.mi-nav-primer-summary { cursor: pointer; color: var(--text-muted); padding: 2px 4px; list-style: none; user-select: none; opacity: 0.85; }
.mi-nav-primer-summary::-webkit-details-marker { display: none; }
.mi-nav-primer-summary::before { content: '▸ '; opacity: 0.7; }
.mi-nav-primer[open] .mi-nav-primer-summary::before { content: '▾ '; }
.mi-nav-primer-summary:hover { color: var(--text, #d8def0); }
.mi-nav-primer-body { padding: 6px 9px; margin-top: 4px; color: var(--text-muted); line-height: 1.45; border-left: 2px solid var(--border, rgba(123,179,224,0.2)); background: rgba(123, 179, 224, 0.04); border-radius: 3px; }
.mi-nav-primer-body strong { color: var(--text, #d8def0); font-weight: 600; }
/* ── Three-chart header (Loaded / Lens / Now) — horizontal ── */
#navModeToggle { display: none; } /* replaced by the header magnifiers */
/* Top-left brand. "iOnym NOW" at rest → animated "loading…" while any content
   is still resolving (toggled by _setBrandLoading). */
.app-brand { flex: 0 0 auto; display: inline-flex; align-items: baseline; margin-right: 12px; font-size: var(--fs-label); font-weight: 700; letter-spacing: 0.04em; white-space: nowrap; }
/* "iOnym" — light grey wordmark with a white O; kept in the body face so its
   lower-case letters read as intended (the display face is small-caps). */
.app-brand .brand-ionym { color: #c9c4bd; font-weight: 600; }
.app-brand .brand-o { color: #ffffff; }
.app-brand .brand-sep { color: #8a857e; margin: 0 3px; font-weight: 600; }
/* "NOW" — gold, in the login-screen display face (Cinzel via --font-display). */
.app-brand .brand-now { font-family: var(--font-display); color: var(--accent-warm, #e6c65c); font-weight: 700; letter-spacing: 0.08em; }
.app-brand.is-loading { color: var(--text-dim, #9a948e); font-weight: 600; letter-spacing: 0.06em; }
@keyframes brandDots { 0% { content: ''; } 25% { content: '.'; } 50% { content: '..'; } 75%, 100% { content: '...'; } }
.app-brand .brand-dots { display: inline-block; width: 1.4em; text-align: left; }
.app-brand .brand-dots::after { content: ''; animation: brandDots 1.2s steps(1, end) infinite; }
/* Exit KP Mode button — now rides on the KP Roulette panel's fixed title bar. */
.exit-kp-btn { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px; padding: 4px 11px; background: rgba(212, 175, 55, 0.14); border: 1px solid rgba(212, 175, 55, 0.55); color: var(--accent-warm, #e6c65c); border-radius: 14px; font-size: var(--fs-label); font-weight: 600; letter-spacing: 0.02em; cursor: pointer; white-space: nowrap; }
.exit-kp-btn:hover { background: rgba(212, 175, 55, 0.24); }
.exit-kp-btn[hidden] { display: none; }
/* KP Roulette panel title bar: title left, Exit button right, on one row. */
.mi-info-head--kp { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.mi-info-head--kp .reading-title { margin-bottom: 0; }
.chart-roles { display: flex; align-items: center; gap: 12px; min-width: 0; }
.chart-role-mag { flex: 0 0 auto; width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; background: none; border: none; padding: 0; cursor: pointer; opacity: 0.5; font-size: 12px; color: inherit; border-radius: 3px; line-height: 1; }
.chart-role-mag:hover { opacity: 1; background: rgba(127,127,127,0.15); }
.chart-role-col { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
/* LENS / LOADED / NOW chart-role readouts are EXEMPT from the app-wide 12px
   standardization — kept at their own established sizes (label 10, date 13,
   sub 10). Pinned explicitly so the --fs-* → 12 collapse can't touch them. */
.chart-role-label { font-size: 10px; text-transform: uppercase; letter-spacing: 0.07em; opacity: 0.45; white-space: nowrap; }
.chart-role-readout .chart-meta-date { font-size: 13px; }
.chart-role-readout .chart-meta-sub { font-size: 10px; }
/* .chart-meta on the readout provides the two-tier flex-column + date/sub styling. */
.chart-role-readout { max-width: 200px; }
button.chart-role-readout { background: none; border: none; padding: 0; text-align: left; font: inherit; color: inherit; }
button.chart-role-readout:hover { opacity: 1; }        /* editable rows brighten on hover */
.chart-role-readout--static { cursor: default; }
.chart-role-readout--static:hover { opacity: inherit; }
/* The Now readout is tap-to-set-location — override the static defaults. */
.chart-role-readout--clickable { cursor: pointer; }
.chart-role-readout--clickable:hover { opacity: 1; }
/* Lens is the emphasised (viewed) chart; the others are dimmed. */
.chart-role-col:not(.is-lens) .chart-role-readout { opacity: 0.5; }
.chart-role-col.is-lens .chart-role-readout { opacity: 1; }
.loading-text { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; }
.loading-title { font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: 700; color: var(--accent); letter-spacing: 4px; margin-bottom: 8px; }
.loading-step { font-size: var(--fs-label); color: var(--text-muted); letter-spacing: 1px; }

/* ── Modal ────────────────────────────────────────────────── */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  backdrop-filter: blur(8px);
}

.modal-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 32px 36px;
  width: 380px;
  max-width: 90vw;
}

.modal-title {
  font-family: var(--font-display);
  font-size: var(--fs-3xl);
  text-align: center;
  color: var(--text);
  letter-spacing: 4px;
  margin-bottom: 4px;
}

.modal-subtitle {
  text-align: center;
  font-size: var(--fs-body);
  color: var(--text-muted);
  margin-bottom: 24px;
}

.modal-form { display: flex; flex-direction: column; gap: 12px; }

.modal-row {
  display: flex;
  gap: 8px;
}

.modal-row label {
  flex: 1;
  font-size: var(--fs-label);
  color: var(--text-muted);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
/* Format hint under date inputs — disambiguates DD/MM vs MM/DD across
   browser locales. Smaller and dimmer than the field's main label. */
.input-format-hint {
  font-size: var(--fs-micro);
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-muted);
  opacity: 0.6;
  margin-top: 2px;
}

/* Explicit Day / Month / Year inputs — chosen over <input type="date">
   because the native picker's displayed format follows the browser
   locale (en-US shows MM/DD/YYYY, en-AU shows DD/MM/YYYY) and the
   "DAY / MONTH / YEAR" hint span underneath would lie to a user whose
   browser is set to US locale. Three explicit inputs are unambiguous. */
.dmy-inputs {
  display: inline-flex;
  align-items: center;
  gap: 2px;
}
.dmy-input {
  width: 38px;
  text-align: center;
}
.dmy-input--year { width: 56px; }
.dmy-sep { color: var(--text-muted); opacity: 0.6; }
.dmy-input::-webkit-inner-spin-button,
.dmy-input::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.dmy-input { -moz-appearance: textfield; }

.modal-row input, .modal-wide {
  background: var(--input-bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 8px 10px;
  font-size: var(--fs-heading);
  font-family: var(--font-body);
  width: 100%;
}

.modal-row input:focus {
  outline: none;
  border-color: var(--accent-border);
}

/* Own-birth-chart toggle row. Drives the voice resolver in core/voice.js. */
.modal-own-chart-row {
  margin-top: 2px;
}
.modal-own-chart-label {
  flex-direction: row !important;
  align-items: center;
  gap: 8px !important;
  font-size: var(--fs-body) !important;
  color: var(--text) !important;
  cursor: pointer;
  user-select: none;
}
.modal-own-chart-label input[type="checkbox"] {
  width: auto !important;
  margin: 0;
  cursor: pointer;
}

/* Auto-resolved timezone display under lat/lon. Read-only, dim. */
.modal-tz-display {
  font-size: var(--fs-label);
  color: var(--text-dim, rgba(220, 210, 200, 0.55));
  padding: 4px 2px 0;
  min-height: 16px;
  font-family: var(--font-body);
}
.modal-tz-display.tz-warn { color: rgba(255, 180, 80, 0.8); }

.modal-submit {
  margin-top: 8px;
  padding: 10px;
  background: var(--accent-bg);
  border: 1px solid var(--accent-border);
  border-radius: 8px;
  color: var(--accent);
  font-size: var(--fs-subtitle);
  font-family: var(--font-body);
  cursor: pointer;
  transition: all 0.15s;
}
.modal-submit:hover { background: rgba(99,179,237,0.18); }
.modal-submit:disabled { opacity: 0.4; cursor: default; }

.modal-status {
  text-align: center;
  font-size: var(--fs-label);
  color: var(--text-muted);
  min-height: 16px;
}

/* ── Chart management modal ──────────────────────────────── */

.chart-mgmt-card {
  width: 440px;
  max-height: 85vh;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(128,128,128,0.2) transparent;
}

.chart-mgmt-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}
.chart-mgmt-title span {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  letter-spacing: 2px;
  color: var(--text);
}
.chart-mgmt-close {
  background: none; border: none; color: var(--text-dim);
  font-size: var(--fs-xl); cursor: pointer; padding: 4px 8px; border-radius: 4px;
}
.chart-mgmt-close:hover { color: var(--text); background: var(--input-bg); }

.mgmt-section { margin-bottom: 18px; }
.mgmt-section-title {
  font-size: var(--fs-label); text-transform: uppercase; letter-spacing: 1px;
  color: var(--accent); margin-bottom: 8px; opacity: 0.8;
}
.mgmt-row { display: flex; gap: 8px; margin-bottom: 8px; }
.mgmt-row-half > * { flex: 1; min-width: 0; }
.mgmt-label { font-size: var(--fs-label); color: var(--text-muted); margin-bottom: 3px; display: block; }
.mgmt-input {
  width: 100%; padding: 6px 10px; border: 1px solid var(--border);
  border-radius: 6px; background: var(--input-bg); color: var(--text);
  font-size: var(--fs-heading); font-family: var(--font-body);
}
.mgmt-input:focus { outline: none; border-color: var(--accent-border); }
.mgmt-hint { font-size: var(--fs-caption); color: var(--text-dim); margin: 2px 0 6px; }
.mgmt-status { font-size: var(--fs-label); margin-top: 4px; }
.mgmt-actions { display: flex; gap: 6px; margin-top: 6px; }
/* Current-Chart two-column layout: identity (name/date/time) | place (city/lat/
   lon). Keeps the City field high in the modal so its autocomplete dropdown
   clears the mobile on-screen keyboard (issue 14). Columns stay side-by-side even
   on mobile — that compactness is the point. */
.mgmt-chart-cols { display: flex; gap: 14px; align-items: flex-start; }
.mgmt-chart-col { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 8px; }

/* mgmt-btn removed — all modal buttons now use .modal-btn classes */

.mgmt-chart-item {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 10px; border-bottom: 1px solid var(--border);
}
.mgmt-chart-item:last-child { border-bottom: none; }
.mgmt-chart-name { font-size: var(--fs-heading); color: var(--text); font-weight: 500; }
.mgmt-chart-detail { font-size: var(--fs-label); color: var(--text-dim); }
.mgmt-chart-actions { display: flex; gap: 4px; }

.mgmt-city-results {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 200;
  background: var(--surface); border: 1px solid var(--accent-border);
  border-radius: 4px; max-height: 180px; overflow-y: auto;
  box-shadow: 0 4px 12px var(--shadow);
}
.mgmt-city-item {
  padding: 6px 10px; cursor: pointer; font-size: var(--fs-body); color: var(--text);
  display: flex; justify-content: space-between;
}
.mgmt-city-item:hover { background: var(--surface-hover); }
.mgmt-city-country { color: var(--text-dim); font-size: var(--fs-label); }

/* ── App layout ───────────────────────────────────────────── */

.app {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
}

/* ── Header ───────────────────────────────────────────────── */

.app-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px;
  height: var(--app-header-h);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  z-index: 10;
  overflow: hidden;
  max-width: 100vw;
}

.header-left, .header-center, .header-right {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}

.header-left { flex: 1; min-width: 0; overflow: hidden; }
.header-center { flex: 0 0 auto; }
/* Tighter gap so the dock buttons + tabs read as one control strip.
   A vertical divider between #dock and #panelTabs marks the boundary
   without visually fragmenting the row. */
.header-right { flex: 0 0 auto; gap: 4px; align-items: center; }
.header-right > .panel-tabs:not(:empty)::before {
  content: '';
  display: inline-block;
  width: 1px;
  height: 18px;
  background: var(--border);
  margin: 0 8px 0 4px;
  flex-shrink: 0;
}

/* NOW / CHART toggle — single-label switch in the top-left, paired with
   the date display. Glows and pulses subtly to invite the click. */
.nav-mode-toggle {
  font-family: var(--font-display);
  font-size: var(--fs-heading);
  font-weight: 600;
  letter-spacing: 3px;
  color: var(--accent);
  background: var(--accent-bg);
  border: 1px solid var(--accent-border);
  border-radius: 14px;
  padding: 4px 12px;
  cursor: pointer;
  user-select: none;
  text-shadow: 0 0 8px var(--accent);
  box-shadow: 0 0 12px var(--accent-bg), inset 0 0 6px var(--accent-bg);
  animation: nav-mode-pulse 2.4s ease-in-out infinite;
  transition: transform 0.12s ease, box-shadow 0.18s ease;
}
.nav-mode-toggle:hover {
  transform: scale(1.04);
  box-shadow: 0 0 18px var(--accent-bg), inset 0 0 8px var(--accent-bg);
  animation-play-state: paused;
}
.nav-mode-toggle:active { transform: scale(0.97); }

@keyframes nav-mode-pulse {
  0%, 100% { box-shadow: 0 0 8px var(--accent-bg), inset 0 0 4px var(--accent-bg); opacity: 0.92; }
  50%      { box-shadow: 0 0 18px var(--accent-bg), inset 0 0 8px var(--accent-bg); opacity: 1; }
}

/* Live state: gold tint when NOW is actively ticking. CHART (default) keeps
   the neutral accent colour — this turns the toggle yellow only while the
   chart is following real time. */
.nav-mode-toggle.nav-mode-live {
  color: #FFD700;
  background: rgba(255, 215, 0, 0.12);
  border-color: rgba(255, 215, 0, 0.5);
  text-shadow: 0 0 10px rgba(255, 215, 0, 0.7);
  box-shadow: 0 0 14px rgba(255, 215, 0, 0.25), inset 0 0 8px rgba(255, 215, 0, 0.15);
  animation: nav-mode-live-pulse 2.4s ease-in-out infinite;
}
.nav-mode-toggle.nav-mode-live:hover {
  box-shadow: 0 0 22px rgba(255, 215, 0, 0.4), inset 0 0 10px rgba(255, 215, 0, 0.2);
}
@keyframes nav-mode-live-pulse {
  0%, 100% { box-shadow: 0 0 10px rgba(255,215,0,0.2), inset 0 0 6px rgba(255,215,0,0.1); }
  50%      { box-shadow: 0 0 22px rgba(255,215,0,0.45), inset 0 0 10px rgba(255,215,0,0.2); }
}

/* Per-module zodiac toggle — inline Tropical | Vedic segmented control that
   sits at the end of a module's info-panel title (.reading-title). Only shown
   for dual-capable modules; changing it overrides the zodiac for that one
   module. Single-tradition modules show a static .preset-chip instead. */
.mode-toggle {
  display: inline-flex;
  align-items: center;
  gap: 1px;
  margin-left: 8px;
  padding: 2px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  vertical-align: middle;
  flex-shrink: 0;
}
.mode-seg {
  font-family: var(--font-display);
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  padding: 2px 9px;
  border-radius: 10px;
  cursor: pointer;
  user-select: none;
  background: transparent;
  border: 1px solid transparent;
  color: rgba(255, 255, 255, 0.45);
  transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease, box-shadow 0.18s ease;
}
.mode-seg:hover { color: rgba(255, 255, 255, 0.85); }
.mode-seg.active {
  color: var(--preset-c, #888);
  background: color-mix(in srgb, var(--preset-c, #888) 15%, transparent);
  border-color: color-mix(in srgb, var(--preset-c, #888) 52%, transparent);
  text-shadow: 0 0 8px color-mix(in srgb, var(--preset-c, #888) 60%, transparent);
}

/* Static (non-toggle) zodiac chip carries a muted, non-interactive cue. */
.preset-chip-static { cursor: default; opacity: 0.85; }

/* Chart date is the title of the chart being viewed — the temporal lens. */
.chart-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 1px;
  cursor: pointer;
  transition: opacity 0.15s;
  min-width: 0;
  flex-shrink: 1;
  line-height: 1.15;
}
.chart-meta:hover { opacity: 0.85; }
.chart-meta-date {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: 500;
  color: var(--text);
  letter-spacing: 0.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.chart-meta-name {
  font-size: var(--fs-label);
  font-weight: 600;
  color: var(--accent, var(--text));
  letter-spacing: 0.3px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.chart-meta-sub {
  font-size: var(--fs-label);
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

.mode-toggle {
  display: flex;
  gap: 1px;
  background: var(--input-bg);
  border-radius: 6px;
  padding: 2px;
}

.mode-btn {
  padding: 4px 16px;
  border: none;
  border-radius: 5px;
  background: transparent;
  color: var(--text-dim);
  font-size: var(--fs-body);
  font-family: var(--font-body);
  cursor: pointer;
  transition: all 0.15s;
}
.mode-btn:hover { color: var(--text-muted); }
.mode-btn.active { background: var(--accent-bg); color: var(--accent); }


.icon-btn {
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.15s;
}
.icon-btn:hover { background: var(--surface-hover); color: var(--text-muted); }

.avatar-btn {
  width: 30px;
  height: 30px;
  border: none;
  background: transparent;   /* the logo sits cleanly on the header — no circle */
  padding: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: filter 0.15s, transform 0.15s;
}
.avatar-btn:hover { filter: brightness(1.12); }
.avatar-btn:active { transform: scale(0.94); }
/* iOnym logo (white + mustard variant) as the account button. Portrait mark, so
   size by height; a faint shadow gives it depth against the header. */
.avatar-btn .avatar-logo {
  height: 21px; width: auto; display: block;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.45));
}
#app.single-panel .sp-avatar-btn .avatar-logo {
  height: 26px; width: auto; display: block;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.45));
}

.reports-btn {
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--text-muted);
  font-size: var(--fs-subtitle);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.15s;
  margin-right: 4px;
}
.reports-btn:hover { background: var(--surface-hover); color: var(--text); }

/* Feedback icon — same shape as the reports button so the trio
   (reports / feedback / avatar) lines up consistently. */
.feedback-btn {
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--text-muted);
  font-size: var(--fs-subtitle);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.15s;
  margin-right: 4px;
}
.feedback-btn:hover { background: var(--surface-hover); color: var(--text); }

/* ── Body — viewport + panel + dock via CSS Grid ─────────── */

.app-body {
  flex: 1;
  display: grid;
  /* Grid columns set by JS sizeViewport() — chart fills shortest dimension.
     Dock is no longer in the body — moved to the header. The middle 6px
     auto-track is the draggable .panel-resize handle (see below). */
  grid-template-columns: 2fr 6px 3fr; /* initial, overridden by JS */
  overflow: hidden;
  position: relative;
}

/* ── Resizable panel divider (D.5) ────────────────────────── */
.panel-resize {
  background: var(--border);
  cursor: ew-resize;
  opacity: 0.4;
  transition: opacity 0.15s, background 0.15s;
  user-select: none;
  z-index: 5;
  /* JS owns this drag (pointer capture); tell the browser not to pan/scroll
     when a finger starts on the handle, or the touch-drag does nothing. */
  touch-action: none;
  position: relative;
}
.panel-resize:hover { opacity: 1; background: var(--accent); }
.panel-resize:active { opacity: 1; background: var(--accent); }
/* Invisible finger-sized hit target around the thin visual divider — a 6px bar
   is impossible to grab with a fingertip. pointerdown in this zone still targets
   the handle. Default = desktop vertical divider (widen horizontally). */
.panel-resize::after {
  content: '';
  position: absolute;
  inset: 0 -9px;
}
[data-panel="bottom"] .panel-resize::after,
[data-panel="top"] .panel-resize::after { inset: -9px 0; }
@media (max-width: 700px) {
  .panel-resize::after { inset: -11px 0; }
}
/* Vertical orientation (panel on top/bottom) flips the resize axis. */
[data-panel="bottom"] .panel-resize,
[data-panel="top"] .panel-resize { cursor: ns-resize; }

/* ── Viewport (chart or app) ─────────────────────────────── */

.viewport {
  display: flex;
  flex-direction: row;
  align-items: stretch;
  overflow: hidden;
  position: relative;
  /* Let the chart area fill the viewport column exactly */
}

.viewport-chart-area {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  min-height: 0;
  position: relative;
  --viewport-darken: 0;
}

.viewport-chart-area::before {
  content: '';
  position: absolute;
  inset: 0;
  background: black;
  opacity: var(--viewport-darken);
  pointer-events: none;
  z-index: 0;
}

.chart-backdrop {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  /* Position, size, color set by JS from renderer layout data */
}

/* ── Chart-role readouts in the chart corners ──────────────
   Permanent home for the Loaded / Lens / Now readouts. JS (_applyChartRoles-
   Position) moves the header elements in here on boot and stamps
   .roles-in-corners on .app; the header copy stays hidden. Lens = top-left,
   Loaded = bottom-left, Now = bottom-right. */
.app.roles-in-corners #chartRoles { display: none; }

.chart-role-corner {
  position: absolute;
  z-index: 12;
  display: none;                 /* revealed only in corners mode (below) */
  align-items: center;
  gap: 5px;
  max-width: 46%;
  pointer-events: none;          /* transparent gaps; children re-enable */
}
.app.roles-in-corners .chart-role-corner { display: flex; }
.chart-role-corner > * { pointer-events: auto; }
.chart-role-corner.top-left { top: 10px; left: 10px; }
.chart-role-corner.bottom-left { bottom: 10px; left: 10px; }
.chart-role-corner.bottom-right { bottom: 10px; right: 10px; }
.chart-role-corner.bottom-right .chart-role-col { align-items: flex-end; text-align: right; }
/* Legibility over the busy chart canvas. */
.chart-role-corner .chart-role-label,
.chart-role-corner .chart-role-readout,
.chart-role-corner .chart-meta-date,
.chart-role-corner .chart-meta-sub {
  text-shadow: 0 1px 3px rgba(0,0,0,0.95), 0 0 2px rgba(0,0,0,0.85);
}
.chart-role-corner .chart-role-mag { text-shadow: 0 1px 3px rgba(0,0,0,0.9); }
/* Hide when an embedded app/iframe owns the viewport (like the old chrome). */
.viewport.app-active .chart-role-corner,
.viewport.native-app-active .chart-role-corner { display: none; }

.chart-corner-btn {
  position: absolute;
  width: 42px;
  height: 42px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
  color: var(--text);
  font-size: var(--fs-2xl);
  line-height: 1;
  cursor: pointer;
  opacity: 0.5;
  transition: opacity 0.15s, background 0.15s, border-color 0.15s;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.chart-corner-btn:hover { opacity: 1; background: var(--surface-hover); }
.chart-corner-btn.active { opacity: 1; border-color: var(--accent); background: var(--accent-bg); }
.chart-corner-btn.top-left { top: 8px; left: 8px; }
.chart-corner-btn.top-right { top: 8px; right: 8px; }
.chart-corner-btn.bottom-left { bottom: 8px; left: 8px; }
.chart-corner-btn.bottom-right { bottom: 8px; right: 8px; }

/* KP Roulette buttons — bottom-left corner, entry + reroll side by side. */
#kpRouletteBtn { color: #4CAF50; }
#kpRouletteBtn.active { border-color: #4CAF50; background: rgba(76, 175, 80, 0.15); animation: kp-roulette-pulse 1.6s ease-in-out infinite; }
@keyframes kp-roulette-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(76, 175, 80, 0.5); }
  50%      { box-shadow: 0 0 0 8px rgba(76, 175, 80, 0);   }
}
.chart-corner-btn.kp-roulette-reroll {
  bottom: 8px;
  left: 58px; /* 8px + 42px button + 8px gap */
  display: none;
  color: #4CAF50;
}
.chart-corner-btn.kp-roulette-reroll.visible { display: flex; }

/* ── Speed sliders — bidirectional, zero-center ────────── */

.speed-slider {
  position: absolute;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  z-index: 10;
  opacity: 0.3;
  transition: opacity 0.2s;
}
.speed-slider:hover, .speed-slider:active { opacity: 0.8; }

/* Track */
.speed-slider::-webkit-slider-runnable-track {
  background: rgba(255,255,255,0.06);
  border-radius: 4px;
}
.speed-slider::-moz-range-track {
  background: rgba(255,255,255,0.06);
  border-radius: 4px;
}

/* Thumb */
.speed-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--accent, #d4af37);
  border: 2px solid rgba(0,0,0,0.4);
  cursor: grab;
  box-shadow: 0 0 6px rgba(212,175,55,0.4);
}
.speed-slider::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--accent, #d4af37);
  border: 2px solid rgba(0,0,0,0.4);
  cursor: grab;
  box-shadow: 0 0 6px rgba(212,175,55,0.4);
}

/* Vertical — right edge */
.speed-slider-v {
  writing-mode: vertical-lr;
  direction: rtl; /* top = positive, bottom = negative */
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  height: min(200px, 40vh);
  width: 22px;
}
.speed-slider-v::-webkit-slider-runnable-track { width: 6px; }
.speed-slider-v::-moz-range-track { width: 6px; }

/* Horizontal — bottom edge */
.speed-slider-h {
  bottom: 6px;
  left: 50%;
  transform: translateX(-50%);
  width: min(200px, 40vw);
  height: 22px;
}
.speed-slider-h::-webkit-slider-runnable-track { height: 6px; }
.speed-slider-h::-moz-range-track { height: 6px; }

/* ── Animate Chart modal ─────────────────────────────────
   The two speed sliders were relocated here from the chart overlay. Undo
   their absolute/overlay positioning and lay them out as ordinary
   horizontal controls, each with a label + Zero button. */
/* The animate modal is re-parented into #textPanel (openAnimateModal) and
   pinned to the panel bounds so it covers ONLY the info panel — the chart stays
   visible so the user can watch the animation while adjusting speeds. The
   backdrop is only lightly dimmed (panel content stays visible behind) and the
   card is a compact, semi-transparent floating box rather than a full cover. */
.animate-modal { position: absolute; inset: 0; z-index: 40; background: rgba(0,0,0,0.28); backdrop-filter: blur(2px); }
.animate-modal .modal-card {
  width: 200px;
  max-width: calc(100% - 24px);
  /* Override the mobile full-screen-modal rule (@media max-width:480px sets
     min-height:100vh) so the card hugs its content instead of filling the panel
     with empty space above/below the sliders. */
  min-height: 0;
  height: auto;
  align-self: center;
  border-radius: 12px;
  padding: 14px 16px;
  background: rgba(20, 22, 34, 0.82);                          /* fallback */
  background: color-mix(in srgb, var(--surface) 84%, transparent);
  backdrop-filter: blur(6px);
}
.animate-modal .chart-mgmt-title { margin-bottom: 6px; }
.animate-row { margin: 9px 0; }
.animate-row-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}
.animate-row-head label {
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--accent);
  opacity: 0.85;
}
.animate-zero {
  background: var(--input-bg, var(--surface-hover));
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-size: var(--fs-caption);
  font-family: var(--font-body);
  padding: 2px 10px;
  border-radius: 6px;
  cursor: pointer;
  transition: all 0.15s;
}
.animate-zero:hover { color: var(--text); background: var(--surface-hover); border-color: var(--accent); }

/* Neutralise the chart-overlay positioning: both sliders render as static,
   full-width horizontal ranges inside the modal. */
.animate-modal .speed-slider {
  position: static;
  writing-mode: horizontal-tb;
  direction: ltr;
  transform: none;
  width: 100%;
  height: 24px;
  opacity: 0.85;
  right: auto; left: auto; top: auto; bottom: auto;
}
.animate-modal .speed-slider::-webkit-slider-runnable-track { height: 6px; width: auto; }
.animate-modal .speed-slider::-moz-range-track { height: 6px; width: auto; }

.viewport canvas {
  display: block;
  background: transparent;
  position: relative;
  /* The chart owns ALL gestures on this canvas (rotate rings, scrub the
     calendar band, tap-select). Without this the browser pans/zooms the page
     during a drag and the chart interaction fights it — the #1 mobile issue. */
  touch-action: none;
}

.viewport-iframe {
  display: none;
  width: 100%;
  height: 100%;
  border: none;
  background: var(--bg);
  position: absolute;
  inset: 0;
}

.viewport-native-app {
  display: none;
  width: 100%;
  height: 100%;
  position: absolute;
  inset: 0;
  background: var(--bg);
}

.viewport.app-active .viewport-chart-area canvas { display: none; }
.viewport.app-active .viewport-iframe { display: block; }
.viewport.app-active .ring-nav { display: none; }
.viewport.app-active .chart-backdrop { display: none; }
.viewport.app-active .chart-corner-btn { display: none; }
.viewport.app-active .speed-slider { display: none; }
.viewport.app-active .ring-label { display: none; }

.viewport.native-app-active .viewport-chart-area canvas { display: none; }
.viewport.native-app-active .viewport-native-app { display: block; }
.viewport.native-app-active .ring-nav { display: none; }
.viewport.native-app-active .chart-backdrop { display: none; }
.viewport.native-app-active .chart-corner-btn { display: none; }
.viewport.native-app-active .speed-slider { display: none; }
.viewport.native-app-active .ring-label { display: none; }

/* ── Full-area astrological calendar grid view ───────────── */
.viewport-calendar-grid {
  display: none;
  position: absolute;
  inset: 0;
  overflow: auto;
  /* Transparent so the themed, --panel-bg-opacity-aware app surface shows
     through — matching the info panel, not an opaque slab. */
  background: transparent;
  padding: 10px 12px;
}
/* Hide the chart wheel canvas in calendar view — but NOT the timeline's own canvas. */
.viewport.calendar-view .viewport-chart-area canvas:not(.cal-tl-canvas) { display: none; }
.viewport.calendar-view .viewport-calendar-grid { display: block; }
.viewport.calendar-view .chart-backdrop,
.viewport.calendar-view .chart-role-corner,
.viewport.calendar-view .chart-center-toggle,
.viewport.calendar-view .ring-nav,
.viewport.calendar-view .chart-corner-btn,
.viewport.calendar-view .speed-slider,
.viewport.calendar-view .ring-label { display: none; }

/* ── Grid (chart-area side) ──────────────────────────────── */
.cal-view { color: var(--text); font-size: var(--fs-body, 13px); max-width: 1100px; margin: 0 auto; }
.cal-gridmonth { text-align: center; font-size: 15px; font-weight: 600; color: var(--text); margin: 0 0 8px; letter-spacing: .02em; }
/* Month title turned into a scrubbable time axis (see core/calendar/month-nav-strip.js).
   The current month sits in a focal rounded rectangle; prev/next flank it in a dull,
   themed purple. Drag / wheel / swipe navigate with momentum. */
.cal-gridmonth.cal-mstrip { padding: 0; }
.cal-mstrip-row { display: flex; align-items: center; justify-content: center; gap: 6px; }
.cal-mstrip-btn { flex: 0 0 auto; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; background: var(--surface); color: var(--text-muted); border: 1px solid var(--border); border-radius: 8px; cursor: pointer; line-height: 1; font-size: 16px; font-weight: 600; transition: background .12s, border-color .12s, color .12s; }
.cal-mstrip-btn:hover { background: var(--surface-hover); border-color: var(--accent-border, var(--accent)); color: var(--text); }
.cal-mstrip-window { position: relative; flex: 1 1 auto; height: 30px; max-width: 420px; overflow: hidden; cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; }
.cal-mstrip-window.is-grabbing { cursor: grabbing; }
.cal-mstrip-focus { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); height: 26px; width: 150px; border-radius: 9px; background: var(--accent-bg); border: 1px solid var(--accent-border); pointer-events: none; box-sizing: border-box; }
.cal-mstrip-label { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); white-space: nowrap; font-size: 14px; font-weight: 600; letter-spacing: .02em; color: var(--accent); pointer-events: none; will-change: transform, opacity; }
.cal-mstrip-label.is-center { color: var(--text); font-size: 15px; }
.cal-weekdays { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; margin-bottom: 3px; }
.cal-weekdays > div { text-align: center; font-size: 11px; color: var(--text-muted); }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; }
/* Timeline mode: a single canvas fills the chart area (not a 7-col grid). */
.cal-grid.cal-timeline { display: block; grid-template-columns: none; gap: 0; height: clamp(300px, 56vh, 540px); }
/* Default (precision) cursor so tapping a band to open its reading reads clearly;
   the JS sets cursor:pointer only while hovering a band. */
.cal-tl-canvas { display: block; width: 100%; height: 100%; border: 1px solid var(--border); border-radius: 8px; background: rgba(20, 22, 32, 0.22); cursor: default; touch-action: none; }
/* Timeline hover tooltip — matches the app's floating-surface treatment (.cal-dd-menu). */
.cal-tl-tip {
  position: fixed; z-index: 90; pointer-events: none; max-width: 300px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 8px 28px var(--shadow, rgba(0, 0, 0, .4));
  padding: 7px 10px; font-family: var(--font-body); color: var(--text);
}
.cal-tl-tip[hidden] { display: none; }
.cal-tl-tip-title { display: flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; }
.cal-tl-tip-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.cal-tl-tip-glyph { font-weight: 700; }
.cal-tl-tip-sub { margin-top: 3px; font-size: 11px; color: var(--text-muted); letter-spacing: .01em; }
/* Corpus interpretation streamed into the hover card. */
.cal-tl-tip-interp { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--border); font-size: 11.5px; line-height: 1.45; color: var(--text); }
.cal-tl-tip-interp[data-loading] { color: var(--text-muted); font-style: italic; }

/* Info-panel "Symbols on this ring" key — the mobile-friendly legend generated
   from what the renderer registered (reading-v3 buildRingSymbolKey). */
/* "Show symbol key" disclosure — the ring's legend, collapsed by default so it
   reads as an on-demand affordance rather than a static menu. Summary styled like
   a .section-label; the ▸ rotates open. Mirrors .mi-more. */
.ring-key-details { margin-top: 24px; padding-top: 12px; border-top: 1px solid var(--border); }
.ring-key-summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px;
  font-size: var(--fs-heading); font-weight: 600; color: var(--text-dim);
  text-transform: uppercase; letter-spacing: 0.8px; user-select: none;
}
.ring-key-summary::-webkit-details-marker { display: none; }
.ring-key-summary::before { content: '▸'; font-size: 0.85em; opacity: 0.7; transition: transform 0.15s ease; }
.ring-key-details[open] > .ring-key-summary::before { transform: rotate(90deg); }
.ring-key-details > .ring-key { margin-top: 4px; }
.ring-key { margin-top: 14px; }
.ring-key .ring-key-row {
  display: grid; grid-template-columns: 1.6em 1fr; align-items: baseline; gap: 8px;
  padding: 2px 0; font-size: 12px; color: var(--text);
}
.ring-key .ring-key-glyph { text-align: center; font-size: 14px; }
.ring-key .ring-key-label { color: var(--text); }
.ring-key .ring-key-meaning { grid-column: 2; color: var(--text-muted); font-size: 11px; }

/* Ring-symbol hover tooltip — names the object under the cursor (planet, emoji,
   icon). Same floating-surface treatment as the timeline tip, theme-cohesive via
   the surface/border/text tokens. Positioned in JS (input/scroll-physics.js). */
.ring-glyph-tooltip {
  position: fixed; z-index: 95; pointer-events: none; display: none;
  max-width: 260px; white-space: normal; overflow-wrap: break-word; line-height: 1.35;
  background: var(--surface); border: 1px solid var(--border); border-radius: 7px;
  box-shadow: 0 8px 28px var(--shadow, rgba(0, 0, 0, .4));
  padding: 5px 9px; font-family: var(--font-body, inherit);
  font-size: 12px; font-weight: 600; letter-spacing: .01em; color: var(--text);
}
/* Timeline control pills: compact per-planet glyph toggles. */
.cal-pill-mini { min-width: 30px; padding: 5px 6px; font-size: 15px; line-height: 1; text-align: center; }
/* Timeline range readout (replaces the month/day ‹ › nav in timeline mode). */
.cal-tl-rangebar { text-align: center; font-size: 12.5px; color: var(--text-muted); padding: 4px 0 8px; letter-spacing: .01em; }
/* Weekday header is meaningless in the continuous timeline — hide it there. */
.cal-view:has(.cal-timeline) .cal-weekdays { display: none; }
.cal-cell { position: relative; min-height: 74px; border: 1px solid var(--border); border-radius: 6px; padding: 3px 4px; cursor: pointer; overflow: hidden; transition: border-color .12s, box-shadow .12s; background: var(--cal-tile); color: var(--cal-tile-ink); }
.cal-cell:hover { border-color: var(--accent-border, var(--accent)); }
.cal-cell.cal-sel { outline: 2px solid var(--accent); outline-offset: -1px; box-shadow: 0 0 0 3px var(--accent-bg, transparent); }
.cal-blank { border: none; background: transparent !important; cursor: default; min-height: 0; }
.cal-cellhead { display: flex; justify-content: space-between; align-items: center; }
.cal-dnum { font-size: 11px; color: var(--cal-tile-ink); font-weight: 600; }
.cal-jdot { color: var(--cal-tile-dim); font-size: 9px; }
.cal-peak { color: var(--accent); font-size: 11px; }
.cal-markers { display: flex; flex-wrap: wrap; align-content: flex-start; margin-top: 3px; min-height: 30px; }
.cal-ev { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; font-size: 11px; border-radius: 4px; box-sizing: border-box; }
.cal-ev:first-child { margin-left: 0 !important; }
.cal-ev-p { color: #fff; }
.cal-ev-u { border: 1px solid currentColor; background: transparent; }
.cal-jsnip { font-size: 9px; line-height: 1.15; color: var(--cal-tile-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-ribs { position: absolute; left: 4px; right: 4px; bottom: 3px; }
.cal-rib { height: 4px; border-radius: 2px; margin-top: 2px; }
.cal-legend { display: flex; align-items: center; gap: 8px; margin-top: 12px; font-size: 12px; color: var(--text); flex-wrap: wrap; }
.cal-leg-name { font-weight: 600; color: var(--text); }
.cal-sw { width: 22px; height: 11px; border-radius: 3px; display: inline-block; border: 1px solid var(--border); }
.cal-leg-key { margin-left: auto; color: var(--text-dim); }

/* ── Calendar's own info panel (config + day reading) ─────── */
#calendarPanel { display: none; }
#app.calendar-active #calendarPanel { display: flex; flex-direction: column; min-height: 0; flex: 1; overflow: hidden; }
/* Hide only the normal panel BODY while the calendar owns the panel — the header
   icons (panel tabs, dept nav, etc.) stay visible; clicking one exits the
   calendar view (see the capture-phase handler in reading-v3.js). */
#app.calendar-active #textContent,
#app.calendar-active #breadcrumb,
#app.calendar-active #subNav { display: none !important; }
/* In calendar view the chart-mode header buttons (Day/KP/Ring panel tabs + the
   calendar-RING toggle) no longer reflect the current mode — drop their active
   highlight so only the 🗓 calendar-view button reads as active. Hover feedback
   stays (they exit the view on click). */
#app.calendar-active #panelTabs .panel-tab-btn.active,
#app.calendar-active #panelTabs .panel-tab-btn.kp-active,
#app.calendar-active #calendarToggle.active {
  background: transparent;
  color: var(--text-dim);
}
#app.calendar-active #panelTabs .panel-tab-btn.active:hover,
#app.calendar-active #panelTabs .panel-tab-btn.kp-active:hover,
#app.calendar-active #calendarToggle.active:hover {
  background: var(--surface-hover);
  color: var(--text);
}

.cal-panel { display: flex; flex-direction: column; min-height: 0; flex: 1; color: var(--text); font-size: var(--fs-body, 13px); }

.cal-monthnav { display: flex; align-items: center; justify-content: center; gap: 10px; }
.cal-nav { background: var(--surface); color: var(--text); border: 1px solid var(--border); border-radius: 8px; width: 30px; height: 30px; cursor: pointer; line-height: 1; font-size: 16px; transition: background .12s, border-color .12s; }
.cal-nav:hover { background: var(--surface-hover); border-color: var(--accent-border, var(--accent)); }
.cal-month { min-width: 150px; text-align: center; font-weight: 600; font-size: 14px; color: var(--text); }

.cal-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px; }
.cal-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.cal-field-full { grid-column: 1 / -1; }
.cal-field-lbl { font-size: 11px; letter-spacing: .04em; text-transform: uppercase; color: var(--text-muted); font-weight: 600; }
.cal-field-ctl { min-width: 0; }

/* Custom dropdown — theme-integrated replacement for <select>. */
.cal-dd { position: relative; }
.cal-dd-trigger {
  display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%;
  background: var(--input-bg, var(--surface)); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 7px 10px;
  font-size: 13px; font-family: var(--font-body); cursor: pointer; text-align: left;
  transition: border-color .12s, box-shadow .12s, background .12s;
}
.cal-dd-trigger:hover { border-color: var(--accent-border, var(--accent)); }
.cal-dd.open .cal-dd-trigger { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-bg, transparent); }
.cal-dd-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cal-dd-caret { color: var(--text-muted); font-size: 10px; transition: transform .12s; }
.cal-dd.open .cal-dd-caret { transform: rotate(180deg); }
.cal-dd-disabled { opacity: .55; }
.cal-dd-menu[hidden] { display: none; }
.cal-dd-menu {
  position: absolute; z-index: 60; top: calc(100% + 4px); left: 0; right: 0;
  max-height: 280px; overflow: auto;
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
  box-shadow: 0 8px 28px var(--shadow, rgba(0,0,0,.4)); padding: 4px;
}
.cal-dd-group { font-size: 10px; letter-spacing: .05em; text-transform: uppercase; color: var(--text-muted); font-weight: 700; padding: 7px 8px 3px; }
.cal-dd-opt {
  display: block; width: 100%; text-align: left; background: transparent; color: var(--text);
  border: none; border-radius: 6px; padding: 7px 9px; font-size: 13px; font-family: var(--font-body); cursor: pointer;
}
.cal-dd-opt:hover { background: var(--surface-hover); }
.cal-dd-opt.sel { background: var(--accent-bg); color: var(--accent); font-weight: 600; }

/* Location row */
.cal-loc-row { display: flex; align-items: center; gap: 10px; }
.cal-loc-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); font-weight: 500; }
.cal-loc-btn {
  background: var(--surface); color: var(--text); border: 1px solid var(--border); border-radius: 8px;
  padding: 6px 12px; font-size: 12px; font-family: var(--font-body); cursor: pointer; white-space: nowrap;
  transition: background .12s, border-color .12s;
}
.cal-loc-btn:hover { background: var(--surface-hover); border-color: var(--accent-border, var(--accent)); }

/* Pill toggles — replace the '90s checkboxes. */
.cal-toggles, .cal-modes { display: flex; flex-wrap: wrap; gap: 7px; }
.cal-modes { margin-top: 2px; }
.cal-pill {
  font-size: 12px; font-family: var(--font-body); padding: 6px 11px; cursor: pointer;
  background: var(--surface); color: var(--text); border: 1px solid var(--border); border-radius: 999px;
  transition: background .12s, border-color .12s, color .12s;
}
.cal-pill:hover { border-color: var(--accent-border, var(--accent)); }
.cal-pill.on { background: var(--accent-bg); color: var(--accent); border-color: var(--accent-border, var(--accent)); font-weight: 600; }
.cal-pill-disabled { opacity: .4; cursor: not-allowed; }
.cal-pill-disabled:hover { border-color: var(--border); }

/* Resonant journal entries (day-reading) */
.cal-reson-list { display: flex; flex-direction: column; gap: 6px; }
.cal-reson-item { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px;
  color: var(--text); cursor: pointer; font: inherit; transition: border-color .12s, background .12s; }
.cal-reson-item:hover { border-color: var(--accent-border, var(--accent)); }
.cal-reson-arrow { opacity: .6; font-size: 15px; width: 14px; text-align: center; flex: none; }
.cal-reson-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.cal-reson-row1 { font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-reson-why { font-size: 11px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-reson-go { opacity: .4; flex: none; }

/* Tabbed panel — Calendar Setup · Journal · Daily Reading */
.cal-tabs { display: flex; gap: 4px; padding: 0 4px; border-bottom: 1px solid var(--border); flex-shrink: 0; }
.cal-tab {
  background: transparent; color: var(--text-muted); border: none; border-bottom: 2px solid transparent;
  padding: 9px 12px; font-size: 13px; font-family: var(--font-body); font-weight: 600; cursor: pointer;
  margin-bottom: -1px; transition: color .12s, border-color .12s;
}
.cal-tab:hover { color: var(--text); }
.cal-tab.on { color: var(--accent); border-bottom-color: var(--accent); }
.cal-tabbody { min-height: 0; flex: 1; overflow: auto; }
.cal-tp { padding: 12px 14px; }
.cal-tp[hidden] { display: none !important; }
.cal-tp[data-tp="setup"] { display: flex; flex-direction: column; gap: 12px; }

.cal-reading-empty { color: var(--text-muted); font-size: 13px; padding: 24px 4px; text-align: center; }
.cal-rd-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.cal-reading-date { font-size: 16px; font-weight: 600; color: var(--text); }
.cal-reading-score { font-size: 13px; font-weight: 600; color: var(--accent); }

/* Journal tab — entry head (label + delete), account section */
.cal-journal-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.cal-journal-del { background: transparent; color: var(--danger, #D9534F); border: 1px solid var(--danger, #D9534F); border-radius: 8px; padding: 4px 10px; font-size: 12px; font-family: var(--font-body); cursor: pointer; opacity: .85; }
.cal-journal-del:hover { opacity: 1; background: color-mix(in srgb, var(--danger, #D9534F) 14%, transparent); }

.cal-journal-account { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--border); }
.cal-account-title { font-size: 11px; letter-spacing: .05em; text-transform: uppercase; color: var(--text-muted); font-weight: 700; margin-bottom: 8px; }
.cal-journal-sync { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.cal-sync-status { font-size: 13px; color: var(--text); }
.cal-sync-state.on { color: var(--accent); }
.cal-sync-state.off { color: var(--text-muted); }
.cal-journal-sync-note { font-size: 12px; color: var(--text-muted); margin-top: 6px; }
.cal-danger-btn { margin-top: 12px; background: transparent; color: var(--danger, #D9534F); border: 1px solid var(--danger, #D9534F); border-radius: 8px; padding: 7px 12px; font-size: 12px; font-family: var(--font-body); cursor: pointer; }
.cal-danger-btn:hover { background: color-mix(in srgb, var(--danger, #D9534F) 16%, transparent); }

/* Calendar-ring header icon */
.cal-ring-icon { display: block; margin: 0 auto; }

/* Per-tab Month/Day mode bar + reading icon key */
.cal-tab-modebar { display: flex; justify-content: center; margin-bottom: 12px; }
.cal-tab-body { min-height: 0; }
.cal-key { margin-bottom: 14px; padding: 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); }
.cal-key-title { font-size: 11px; letter-spacing: .04em; text-transform: uppercase; color: var(--text-muted); font-weight: 700; margin-bottom: 8px; }
.cal-key-list { display: flex; flex-direction: column; gap: 4px; }
.cal-key-item { display: flex; align-items: center; gap: 9px; width: 100%; text-align: left; font-size: 13px; font-family: var(--font-body); color: var(--text); background: transparent; border: none; border-radius: 6px; padding: 5px 6px; cursor: pointer; transition: background .12s; }
.cal-key-item:hover { background: var(--surface-hover); }
.cal-key-glyph { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; font-size: 12px; border-radius: 4px; box-sizing: border-box; flex-shrink: 0; }
.cal-key-label { min-width: 0; flex: 1; }
.cal-key-go { color: var(--text-muted); font-size: 14px; flex-shrink: 0; }

/* Hide the bottom module-nav bar while the calendar view is active. */
#app.calendar-active .ring-nav { display: none !important; }

/* Month/Day segmented control */
.cal-seg { display: inline-flex; border: 1px solid var(--border); border-radius: 999px; overflow: hidden; }
.cal-segbtn { background: transparent; color: var(--text); border: none; padding: 6px 14px; font-size: 12px; font-family: var(--font-body); cursor: pointer; transition: background .12s, color .12s; }
.cal-segbtn.on { background: var(--accent-bg); color: var(--accent); font-weight: 600; }
.cal-segbtn:disabled { opacity: .4; cursor: not-allowed; }
/* per-day net-favourability CORNER DOT (replaced the full-cell tint) */
.cal-headright { display: inline-flex; align-items: center; gap: 3px; }
.cal-daydot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
/* transit density control (Key / All / Off) in the Events field */
.cal-transit-ctl { display: inline-flex; align-items: center; gap: 6px; }
.cal-seg-lbl { font-size: 11px; color: var(--text-dim); }
.cal-transit-ctl .cal-segbtn { padding: 4px 10px; }
/* individual grid markers + dots are directly tappable → modal */
.cal-ev[data-mi] { cursor: pointer; }
.cal-ev[data-mi]:hover { filter: brightness(1.25); }
.cal-daydot[data-daykey], .cal-daydot[data-daydot] { cursor: pointer; }
.cal-daydot[data-daykey]:hover, .cal-daydot[data-daydot]:hover { transform: scale(1.35); }
.cal-daydot { transition: transform .1s; }
/* styled hover tooltip for calendar dots + markers (replaces unreliable native title) */
.cal-tip { position: fixed; z-index: 100001; pointer-events: none; background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: 6px; padding: 4px 8px; font-size: 11px; line-height: 1.3;
  max-width: 240px; box-shadow: 0 6px 20px var(--shadow); opacity: 0; transition: opacity .1s; }
.cal-tip.on { opacity: 1; }

/* Day mode — 24 hourly readout rows */
.cal-grid.cal-hours { display: flex; flex-direction: column; gap: 3px; }
.cal-hour { display: grid; grid-template-columns: 52px auto 1fr auto; align-items: center; gap: 8px; min-height: 32px; padding: 4px 8px; border: 1px solid var(--border); border-radius: 6px; cursor: pointer; background: var(--cal-tile); color: var(--cal-tile-ink); }
.cal-hour:hover { border-color: var(--accent-border, var(--accent)); }
.cal-hour.cal-sel { outline: 2px solid var(--accent); outline-offset: -1px; }
.cal-hour-time { font-size: 12px; font-weight: 600; color: var(--cal-tile-ink); }
.cal-hour-ruler { font-size: 12px; color: var(--cal-tile-dim); white-space: nowrap; }
.cal-hour-markers { display: flex; flex-wrap: wrap; gap: 2px; }
.cal-hour-score { font-size: 12px; font-weight: 600; color: var(--cal-tile-ink); display: inline-flex; align-items: center; justify-content: flex-end; gap: 5px; }

/* Day mode — CONTINUOUS "glide" hour stream (see calendar-view.js _ds*). A fixed-
   height, clipped viewport; its inner content layer is translated vertically and
   hour rows + dated dividers stream in/out. Custom momentum owns the gesture, so
   we suppress native scroll/selection here. */
.cal-view.cal-mode-day .cal-weekdays { display: none; }   /* weekday header is meaningless in day view */
.cal-grid.cal-daystream {
  display: block; position: relative; overflow: hidden;
  touch-action: none; user-select: none; -webkit-user-select: none;
  cursor: grab;
}
.cal-grid.cal-daystream:active { cursor: grabbing; }
.cal-ds-content { position: relative; will-change: transform; }
/* The ROW IS the text box: one bunched line (time · ruler · markers · note · score),
   growing taller ONLY when the note wraps. The note flexes to fill the leftover space. */
.cal-ds-row {
  position: relative; display: flex; align-items: flex-start; gap: 8px; margin: 0 0 3px;
  padding: 4px 8px; min-height: 30px; box-sizing: border-box; cursor: text;
  border: 1px solid var(--border); border-radius: 6px; background: var(--cal-tile); color: var(--cal-tile-ink);
}
.cal-ds-row.cal-sel { outline: 2px solid var(--accent); outline-offset: -1px; }
.cal-ds-row.cal-ds-hasnote { box-shadow: inset 3px 0 0 var(--accent); }
.cal-ds-row .cal-hour-time { flex: 0 0 auto; line-height: 22px; }
.cal-ds-row .cal-hour-ruler { flex: 0 0 auto; line-height: 22px; }
.cal-ds-row .cal-hour-markers { flex: 0 1 auto; align-self: center; }
.cal-ds-row .cal-hour-score { flex: 0 0 auto; line-height: 22px; }
/* The editable field — types ON the row, fills the empty space, wraps to grow the row. */
.cal-ds-note {
  flex: 1 1 auto; min-width: 44px; align-self: stretch; padding: 0 2px; border-radius: 4px;
  font-size: 12px; line-height: 1.35; min-height: 20px; white-space: pre-wrap; overflow-wrap: anywhere;
  color: var(--cal-tile-ink); outline: none; cursor: text;
  touch-action: none; user-select: text; -webkit-user-select: text;
}
.cal-ds-note:focus { background: rgba(127, 127, 127, .14); }
.cal-ds-note:empty::before { content: attr(data-ph); color: var(--cal-tile-dim); opacity: .45; pointer-events: none; }
/* Dated day-divider — a flow element whose top/bottom margin IS the inter-day gap. */
.cal-ds-divider { display: flex; align-items: center; margin: 13px 2px; pointer-events: none; }
.cal-ds-divider::before, .cal-ds-divider::after { content: ''; flex: 1; height: 1px; background: var(--border); }
.cal-ds-divlabel {
  padding: 1px 8px; margin: 0 6px; font-size: 11px; font-weight: 600; letter-spacing: .02em;
  white-space: nowrap; color: var(--text-muted); background: var(--panel-bg, rgba(8, 7, 26, .72)); border-radius: 6px;
}
/* "now" marker — absolute within the (relative) content layer, at the measured position. */
.cal-ds-now { position: absolute; left: 0; right: 0; height: 0; display: flex; align-items: center; pointer-events: none; z-index: 4; }
.cal-ds-now::before { content: ''; width: 7px; height: 2px; background: var(--accent); }
.cal-ds-now::after { content: ''; flex: 1; height: 2px; background: var(--accent); }
.cal-ds-nowlabel {
  padding: 1px 6px; font-size: 10px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--accent); background: var(--panel-bg, rgba(8, 7, 26, .72)); border-radius: 6px;
}

/* Day-level "hours journalled" review list (time: text). */
.cal-hourlog { display: flex; flex-direction: column; gap: 3px; margin-top: 4px; }
.cal-hourlog-item {
  display: flex; align-items: baseline; gap: 8px; width: 100%; text-align: left; cursor: pointer;
  border: 1px solid var(--border); border-radius: 6px; padding: 5px 8px;
  background: var(--cal-tile); color: var(--cal-tile-ink); font: inherit;
}
.cal-hourlog-item:hover { border-color: var(--accent-border, var(--accent)); }
.cal-hourlog-time { flex: 0 0 auto; font-size: 12px; font-weight: 700; color: var(--cal-tile-ink); }
.cal-hourlog-text { flex: 1 1 auto; font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── Ring navigator — vertical strip beside chart ────────── */

.ring-nav {
  display: flex;
  flex-direction: column;
  align-items: center;
  border-right: 1px solid var(--border);
  flex-shrink: 0;
  /* Matches .chart-corner-btn / .dock-item width so all navigation icons
     share the same visual rhythm. */
  width: 42px;
  position: relative;
  overflow: hidden;
}
.ring-nav:empty { display: none; }

/* ── Module bar: horizontal (bottom) mode — full-width row beneath the panels.
   The bar is a flex child of .app (a column), so it sits at the bottom; its
   internal axis flips to a row. Default per index.html data-modnav. ── */
.app[data-modnav="horizontal"] .ring-nav {
  flex-direction: row;
  width: 100%;
  height: 48px;
  border-right: none;
  border-top: 1px solid var(--border);
}
.app[data-modnav="horizontal"] .ring-nav-scroll {
  flex-direction: row;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 2px 4px;
}
.app[data-modnav="horizontal"] .ring-nav-arrow {
  width: 24px;
  height: 100%;
}

.ring-nav-arrow {
  width: 38px;
  height: 22px;
  border: none;
  background: transparent;
  color: var(--accent);
  font-size: var(--fs-caption);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  opacity: 0.5;
  transition: opacity 0.2s;
  text-shadow: 0 0 6px var(--accent);
}
.ring-nav-arrow:hover { opacity: 1; }

.ring-nav-scroll {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 2px 2px;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none;
  position: relative;
}
.ring-nav-scroll::-webkit-scrollbar { display: none; }

.ring-nav-item {
  /* Matches .chart-corner-btn so navigation icons share the same rhythm. */
  width: 42px;
  height: 42px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--text-dim);
  /* These are ICON glyphs, not text — EXEMPT from the flat 12px type standard.
     Sized from the shared --nav-icon-size so header + footer nav icons match. */
  font-size: var(--nav-icon-size);
  font-family: var(--font-body);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.12s, color 0.12s, box-shadow 0.12s;
  flex-shrink: 0;
  position: relative;
}
.ring-nav-item:hover {
  background: var(--surface-hover);
  color: var(--text);
}
.ring-nav-item.active {
  background: var(--accent-bg);
  color: var(--accent);
  box-shadow: inset 0 0 0 1.5px var(--accent-border);
}

.ring-nav-icon {
  flex-shrink: 0;
  /* Let the icon glyph occupy the button's full width — no narrow column. */
  width: 100%;
  text-align: center;
  line-height: 1;
}

/* Label floats outside the scroll container using fixed positioning.
   JS sets top/left on the label based on the button's position. */
.ring-nav-label {
  display: none;
  position: fixed;
  z-index: 50;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 2px 8px;
  font-size: var(--fs-caption);
  color: var(--text);
  white-space: nowrap;
  box-shadow: 0 2px 8px var(--shadow);
  pointer-events: none;
}
.ring-nav-item:hover .ring-nav-label,
.ring-nav-item.active .ring-nav-label {
  display: block;
}

/* ── Dock — horizontal icon group, lives in the header on desktop ── */

.dock {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 1px;
  z-index: 20;
}
.dock::-webkit-scrollbar { display: none; }

.dock-item {
  /* Matched to .chart-corner-btn so all top-level navigation icons share
     the same visual rhythm (header dock, chart corners, ring-nav column). */
  width: 42px;
  height: 42px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--text-dim);
  /* Glyph fills the 42px box (was 15px and looked lost in the frame). */
  font-size: var(--fs-2xl);
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.15s;
  position: relative;
  flex-shrink: 0;
}
.dock-item:hover { background: var(--surface-hover); color: var(--text); }
.dock-item.active { background: var(--accent-bg); color: var(--accent); }
.dock-item.has-children::after {
  content: '';
  position: absolute;
  right: 3px;
  top: 3px;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--text-dim);
  opacity: 0.4;
}

.dock-sep {
  width: 1px;
  height: 18px;
  background: var(--border);
  margin: 0 4px;
  flex-shrink: 0;
}

/* ── Dock flyout — child items panel ─────────────────────── */

.dock-flyout {
  display: none;
  position: fixed;
  z-index: 100;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 6px;
  min-width: 180px;
  max-height: 70vh;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,0.06) transparent;
  box-shadow: 0 8px 32px var(--shadow);
}
.dock-flyout.open { display: block; }

.dock-flyout-title {
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.6px;
  padding: 6px 10px 4px;
}

.dock-flyout-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 7px 10px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--text-muted);
  font-size: var(--fs-body);
  font-family: var(--font-body);
  cursor: pointer;
  transition: all 0.1s;
  text-align: left;
}
.dock-flyout-item:hover { background: var(--surface-hover); color: var(--text); }
.dock-flyout-item.active { background: var(--accent-bg); color: var(--accent); }
.dock-flyout-icon { font-size: var(--fs-lg); width: 22px; text-align: center; flex-shrink: 0; }
.dock-flyout-label { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dock-flyout-desc { font-size: var(--fs-micro); color: var(--text-dim); }

/* ── Disclosure primitive (full-app skinning, Step 2) ─────────
   A generic menu button + flyout the shell always contains. Hidden
   by default so the Classic skin shows nothing; a skin reveals the
   button (display:flex) and routes chrome into #appMenu. Mechanics
   mirror .dock-flyout; JS in initAppMenu() toggles the .open class. */
.app-menu-btn {
  display: none;              /* revealed by a skin, e.g. [data-skin="compact"] .app-menu-btn { display:flex } */
  width: 30px;
  height: 30px;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--text-muted);
  font-size: var(--fs-lg);
  cursor: pointer;
  align-items: center;
  justify-content: center;
  transition: all 0.15s;
  flex-shrink: 0;
}
.app-menu-btn:hover { background: var(--surface-hover); color: var(--text); }
.app-menu-btn[aria-expanded="true"] { background: var(--surface-hover); color: var(--text); }

.app-menu {
  display: none;
  position: fixed;
  z-index: 100;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 6px;
  min-width: 200px;
  max-height: 80vh;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,0.06) transparent;
  box-shadow: 0 8px 32px var(--shadow);
}
.app-menu.open { display: block; }

/* #appMenu rows — generic chrome any nav:'menu' skin reuses (renderDock's
   _renderDockMenu builds these). Styled to match .dock-flyout-item. */
.app-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: transparent;
  border: none;
  border-radius: 8px;
  padding: 8px 10px;
  color: var(--text-muted);
  font-family: var(--font-body);
  font-size: var(--fs-heading);
  cursor: pointer;
  text-align: left;
  transition: all 0.15s;
}
.app-menu-item:hover { background: var(--surface-hover); color: var(--text); }
.app-menu-item.active { background: var(--accent-bg); color: var(--accent); }
.app-menu-icon { font-size: var(--fs-lg); width: 22px; text-align: center; flex-shrink: 0; }
.app-menu-label { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.app-menu-title { font-size: var(--fs-caption); text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--text-dim); padding: 6px 10px 2px; }
.app-menu-sep { height: 1px; background: var(--border); margin: 4px 6px; }


.text-panel {
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: relative; /* anchor for the animate modal (covers only this panel) */
}

/* ── Department nav — full-width bar ──────────────────────── */

.dept-nav {
  display: flex;
  justify-content: center;
  gap: 1px;
  padding: 4px 16px;
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  flex-shrink: 0;
  min-width: 0;
}
.dept-nav::-webkit-scrollbar { display: none; }

.dept-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 5px 6px;
  min-width: 44px;
  border: none;
  border-radius: 4px;
  background: transparent;
  color: var(--text-dim);
  font-size: var(--fs-micro);
  font-family: var(--font-body);
  cursor: pointer;
  transition: all 0.12s;
  position: relative;
}
.dept-btn:hover { color: var(--text-muted); background: var(--surface-hover); }
.dept-btn.active { color: var(--text); background: var(--input-bg); }
.dept-btn .dept-icon { font-size: var(--fs-lg); }
.dept-btn .dept-signal {
  position: absolute;
  bottom: 0;
  left: 20%;
  right: 20%;
  height: 2px;
  border-radius: 1px;
  opacity: 0.4;
}

/* ── Breadcrumb ───────────────────────────────────────────── */

.breadcrumb {
  padding: 4px 12px;
  font-size: var(--fs-caption);
  color: var(--text-dim);
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
  min-height: 0;
}
.breadcrumb:empty { display: none; }
.breadcrumb span { cursor: pointer; }
.breadcrumb span:hover { color: var(--accent); }
.breadcrumb .bc-sep { cursor: default; opacity: 0.3; }

/* ── Sub-nav ──────────────────────────────────────────────── */

.sub-nav {
  display: flex;
  flex-wrap: nowrap;
  gap: 3px;
  padding: 4px 10px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  min-height: 0;
  min-width: 0;
  max-width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}
.sub-nav::-webkit-scrollbar { display: none; }
.sub-nav:empty { display: none; padding: 0; border: none; }

.sub-btn {
  padding: 2px 8px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: transparent;
  color: var(--text-dim);
  font-size: var(--fs-caption);
  font-family: var(--font-body);
  cursor: pointer;
  transition: all 0.1s;
  white-space: nowrap;
}
.sub-btn:hover { color: var(--text-muted); border-color: var(--border); }
.sub-btn.active { color: var(--text); border-color: var(--c, var(--accent-border)); background: var(--input-bg); }

/* ── Panel tabs (Day / Ring Detail) ───────────────────────── */
/* Lives in the header — the user picks Day Summary or Ring Detail and
   the panel sticks to that view across time scrubs. Styled as flat
   buttons matching the dock items so they read as one control strip. */

.panel-tabs {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  gap: 1px;
}
.panel-tabs:empty { display: none; }
.app-header .panel-tabs { padding: 0; }

/* Toggle wrapper is now a transparent inline-flex container — no pill
   background, so tabs look like siblings of the dock items. */
.panel-tab-toggle {
  display: inline-flex;
  align-items: center;
  gap: 1px;
}

/* Match dock-item dimensions: 32px tall, same hover/active scheme,
   text label rather than icon. */
.panel-tab-btn {
  height: 32px;
  padding: 0 12px;
  border: none;
  border-radius: 6px;
  background: transparent;
  color: var(--text-dim);
  font-size: var(--fs-body);
  font-family: var(--font-body);
  cursor: pointer;
  transition: all 0.15s;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.panel-tab-btn:hover { background: var(--surface-hover); color: var(--text); }
.panel-tab-btn.active { background: var(--accent-bg); color: var(--accent); }
/* Respect the `hidden` attribute — the base rule's display:inline-flex would
   otherwise override [hidden]'s user-agent display:none, leaving a phantom,
   unwired button (e.g. the Oracle 💬 toggle when Oracle is disabled) that looks
   clickable but does nothing. */
.panel-tab-btn[hidden] { display: none; }

/* Icon tabs (Day ☀ / KP 🎯 / Ring Detail ◎ / Reports 📄): square-ish,
   glyph-centred, sized from the shared --nav-icon-size (matches the footer). */
.panel-tab-btn.panel-tab-icon {
  padding: 0 9px;
  font-size: var(--nav-icon-size);
  line-height: 1;
}
.panel-tab-btn.panel-tab-icon svg { display: block; width: var(--nav-icon-size); height: var(--nav-icon-size); }
/* KP tab reflects the roulette chart preset being active (green, like the
   old chart-corner target button). */
.panel-tab-btn.kp-active { color: #4CAF50; }
.panel-tab-btn.kp-active.active { background: rgba(76,175,80,0.15); color: #4CAF50; }

/* ── Reading tab — inline department grid ────────────────── */

.reading-dept-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 4px;
  padding: 8px 0 12px;
}

.reading-dept-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 8px 4px 6px;
  border: 1px solid var(--border, rgba(255,255,255,0.06));
  border-radius: 8px;
  background: transparent;
  color: var(--text-dim);
  font-family: var(--font-body);
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: all 0.15s;
}

.reading-dept-btn:hover {
  color: var(--text-muted);
  background: var(--surface-hover);
  border-color: var(--dept-color);
}

.reading-dept-btn.active {
  color: var(--text);
  background: var(--input-bg);
  border-color: var(--dept-color);
}

.reading-dept-icon { font-size: var(--fs-xl); }

.reading-dept-name {
  font-size: var(--fs-caption);
  text-align: center;
  line-height: 1.2;
}

.reading-dept-signal {
  position: absolute;
  bottom: 0;
  left: 0;
  height: 2px;
  background: var(--dept-color);
  border-radius: 0 1px 0 0;
  opacity: 0.5;
}

/* ── Day panel sections ─────────────────────────────────── */

.day-section {
  margin-bottom: 4px;
}
.day-section .section-label:first-child {
  margin-top: 16px;
}

/* Day panel: "show more transits" disclosure. Hide the native marker (we render
   our own ▸) so WebKit/iOS doesn't show a duplicate triangle. */
.day-more-transits > summary { list-style: none; }
.day-more-transits > summary::-webkit-details-marker { display: none; }
.day-more-transits[open] > summary { opacity: 0.55; }

/* ── Day panel: photo strip ─────────────────────────────── */

.day-photo-strip {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 0;
  margin-bottom: 4px;
}
.photo-thumbnails {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  flex: 1;
  scrollbar-width: none;
}
.photo-thumbnails::-webkit-scrollbar { display: none; }
.photo-thumb {
  position: relative;
  width: 64px;
  height: 64px;
  border-radius: 6px;
  overflow: hidden;
  flex-shrink: 0;
  cursor: pointer;
}
.photo-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.photo-delete {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: rgba(0,0,0,0.6);
  color: #fff;
  border: none;
  font-size: var(--fs-caption);
  line-height: 18px;
  text-align: center;
  cursor: pointer;
  display: none;
}
.photo-thumb:hover .photo-delete { display: block; }
.photo-add-btn {
  width: 36px;
  height: 36px;
  border-radius: 6px;
  background: var(--input-bg);
  border: 1px dashed var(--border);
  color: var(--text-dim);
  font-size: var(--fs-xl);
  cursor: pointer;
  flex-shrink: 0;
  transition: all 0.15s;
}
.photo-add-btn:hover {
  background: var(--surface-hover);
  color: var(--accent);
  border-color: var(--accent-border);
}

/* ── Day panel: journal entry section ───────────────────── */

.day-journal-entry {
  position: relative;
  margin-bottom: 8px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
}
.day-journal-entry:hover { background: var(--surface-hover); border-radius: 6px; }
.day-journal-entry.has-entry {
  padding: 8px;
  border-radius: 6px;
  background: var(--input-bg);
  border: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.day-journal-actions {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}
.day-journal-btn {
  background: none;
  border: none;
  color: var(--accent);
  font-size: var(--fs-label);
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 4px;
  opacity: 0.7;
}
.day-journal-btn:hover { opacity: 1; background: var(--accent-bg); }

/* ── Daily visuals strip (Phase E carousel) ────────────────
   Six fixed-width cards that the user pages through with prev/next
   arrows. The strip clips overflow; the inner track translates by one
   card-width per click. */

.day-visuals-strip {
  display: flex;
  align-items: stretch;
  gap: 6px;
  padding: 4px 0 10px;
  margin-bottom: 4px;
}
.day-visuals-track-wrap {
  flex: 1;
  /* Native horizontal scroll so the card row drags with momentum on touch
     (the arrows still page it). touch-action: pan-x lets the browser own the
     horizontal drag; overflow-y hidden keeps a vertical swipe scrolling the
     panel, not this strip. Scrollbar hidden — drag + arrows are the affordance. */
  overflow-x: auto;
  overflow-y: hidden;
  touch-action: pan-x;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  cursor: grab;   /* mouse click-drag to scroll (see enableDragScroll) */
}
.day-visuals-track-wrap.is-dragging { cursor: grabbing; user-select: none; }
.day-visuals-track-wrap.is-dragging img { pointer-events: none; }
.day-visuals-track-wrap::-webkit-scrollbar { display: none; }
.day-visuals-track {
  display: flex;
  gap: 10px;   /* room between cards so tarot labels ("Day Ruler") don't crowd their neighbours */
  width: max-content;   /* lay out the full row width so it overflows and scrolls */
}
.day-visual-card {
  flex: 0 0 110px;
  height: 130px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  cursor: default;
  overflow: hidden;
  transition: transform 0.15s, border-color 0.15s;
}
/* Tarot — no card chrome. Image fills the strip-row height, label sits
   beneath. Width is set EXPLICITLY (not from img content) because flex's
   "auto basis" uses an img's natural width (190px) for the intrinsic
   measurement, not its rendered width — that was leaving huge gaps with
   the image floating in the middle of an oversized slot. Width here is
   tarot aspect (19:33) × image-area height (~108px) ≈ 64px. */
.day-visual-tarot {
  flex: 0 0 78px;
  width: 78px;   /* wider than the 64px image so the label (below) has room */
  height: 130px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  cursor: pointer;
  transition: transform 0.15s;
}
.day-visual-tarot:hover { transform: scale(1.04); }
.day-visual-tarot-img {
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  object-fit: contain;
  display: block;
  border-radius: 6px;
}
.day-visual-tarot-fallback {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-label);
  text-align: center;
  padding: 0 8px;
  border: 1px solid var(--border);
  border-radius: 6px;
  min-width: 60px;
}
.day-visual-tarot-label {
  flex: 0 0 auto;
  width: 100%;
  font-size: var(--fs-micro);
  letter-spacing: 0.6px;   /* was 1.2px — too wide for "Day Ruler" in one clipped line */
  text-transform: uppercase;
  color: var(--text-dim);
  opacity: 0.7;
  white-space: normal;     /* was nowrap — let two-word labels wrap instead of clipping */
  text-align: center;
  line-height: 1.15;
}
.day-visual-card-body {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px;
}
.day-visual-card-title {
  flex: 0 0 auto;
  font-size: var(--fs-micro);
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: var(--text-dim);
  text-align: center;
  padding: 4px 0;
  border-top: 1px solid var(--border);
  opacity: 0.7;
}

.day-visuals-arrow {
  flex: 0 0 28px;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-dim);
  border-radius: 6px;
  cursor: pointer;
  font-size: var(--fs-subtitle);
  line-height: 1;
  padding: 0;
  transition: opacity 0.15s, color 0.15s, border-color 0.15s;
}
.day-visuals-arrow:hover:not(:disabled) {
  color: var(--accent);
  border-color: var(--accent-border);
}
.day-visuals-arrow:disabled {
  opacity: 0.25;
  cursor: default;
}

/* ── Tarot card detail modal ────────────────────────────── */

.tarot-detail-modal {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(0,0,0,0.75);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.tarot-detail-card {
  background: var(--surface);
  border-radius: 12px;
  padding: 20px;
  max-width: 340px;
  width: 90%;
  cursor: default;
  text-align: center;
  box-shadow: 0 8px 32px rgba(0,0,0,0.5);
}
.tarot-detail-card img {
  width: 140px;
  border-radius: 8px;
  margin-bottom: 12px;
}
.tarot-detail-name {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  color: var(--text);
  margin-bottom: 4px;
}
.tarot-detail-source {
  font-size: var(--fs-label);
  color: var(--text-dim);
  margin-bottom: 10px;
}
.tarot-detail-desc {
  font-size: var(--fs-heading);
  color: var(--text-muted);
  line-height: 1.6;
}

/* ════════════════════════════════════════════════════════════
   TAROT RING PANEL
   ════════════════════════════════════════════════════════════ */

.tarot-panel__header {
  margin-bottom: 18px;
}
.tarot-panel__title {
  font-family: var(--font-display);
  font-size: var(--fs-2xl);
  color: var(--text);
  margin-bottom: 4px;
}
.tarot-panel__subtitle {
  font-size: var(--fs-body);
  color: var(--text-dim);
  font-style: italic;
}
.tarot-panel__section {
  margin-bottom: 28px;
}
.tarot-panel__section-title {
  font-family: var(--font-display);
  font-size: var(--fs-heading);
  color: var(--accent);
  letter-spacing: 1.4px;
  text-transform: uppercase;
  margin-bottom: 10px;
  border-bottom: 1px solid rgba(255,255,255,0.08);
  padding-bottom: 6px;
}
.tarot-panel__hint {
  font-size: var(--fs-label);
  color: var(--text-dim);
  margin-bottom: 10px;
}

/* ── Card info block ─────────────────────────────────────── */

.tarot-card-info {
  display: flex;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid rgba(255,255,255,0.04);
}
.tarot-card-info:last-child { border-bottom: none; }
.tarot-card-info__img {
  flex-shrink: 0;
}
.tarot-card-info__img img {
  border-radius: 6px;
  display: block;
  box-shadow: 0 2px 8px rgba(0,0,0,0.4);
}
.tarot-card-info--sm .tarot-card-info__img img { width: 48px; }
.tarot-card-info--md .tarot-card-info__img img { width: 80px; }
.tarot-card-info--lg .tarot-card-info__img img { width: 140px; }
.tarot-card-info__body {
  flex: 1;
  min-width: 0;
}
.tarot-card-info__label {
  font-size: var(--fs-caption);
  color: var(--accent);
  letter-spacing: 1.2px;
  text-transform: uppercase;
  margin-bottom: 2px;
}
.tarot-card-info__name {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  color: var(--text);
  margin-bottom: 2px;
}
.tarot-card-info__source {
  font-size: var(--fs-label);
  color: var(--text-dim);
  font-style: italic;
  margin-bottom: 6px;
}
.tarot-card-info__correspondences {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 8px;
}
.tcorr {
  display: inline-block;
  padding: 2px 8px;
  font-size: var(--fs-caption);
  border-radius: 10px;
  background: rgba(255,255,255,0.06);
  color: var(--text-muted);
  letter-spacing: 0.3px;
  white-space: nowrap;
}
.tcorr--muted {
  background: transparent;
  color: var(--text-dim);
  padding-left: 0;
  padding-right: 4px;
}
.tcorr--pair {
  background: rgba(159, 122, 234, 0.15);
  color: #c8b4f0;
}
.tarot-card-info__desc {
  font-size: var(--fs-heading);
  color: var(--text-muted);
  line-height: 1.55;
}

/* ── Draw section ────────────────────────────────────────── */

.tarot-draw__hint {
  font-size: var(--fs-body);
  color: var(--text-dim);
  font-style: italic;
  line-height: 1.5;
  margin-bottom: 12px;
}
.tarot-draw__counts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  margin-bottom: 12px;
}
.tarot-draw__counts-label {
  font-size: var(--fs-caption);
  color: var(--text-dim);
  letter-spacing: 1.2px;
  text-transform: uppercase;
  margin-right: 4px;
}
.tarot-draw__chip {
  font-family: inherit;
  font-size: var(--fs-body);
  min-width: 32px;
  padding: 5px 10px;
  border-radius: 14px;
  border: 1px solid rgba(255,255,255,0.12);
  background: rgba(255,255,255,0.04);
  color: var(--text-muted);
  cursor: pointer;
  transition: all 0.12s;
  letter-spacing: 0.3px;
  text-align: center;
}
.tarot-draw__chip:hover {
  border-color: rgba(255,255,255,0.25);
  color: var(--text);
  background: rgba(255,255,255,0.08);
}
.tarot-draw__chip--active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.tarot-draw__chip--active:hover {
  background: var(--accent);
  border-color: var(--accent);
  filter: brightness(1.08);
  color: #fff;
}
.tarot-draw__actions {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
}

/* ── Drawn-cards layout strip (shown before interpretations) ── */

.tarot-draw__layout {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: 10px;
  flex-wrap: wrap;
  margin: 4px 0 18px;
  padding: 16px 12px;
  background: rgba(0, 0, 0, 0.22);
  border-radius: 8px;
  border: 1px solid rgba(159, 122, 234, 0.16);
}
.tarot-draw__layout-card {
  width: 76px;
  flex-shrink: 0;
  text-align: center;
}
.tarot-draw__layout-card img {
  width: 100%;
  display: block;
  border-radius: 4px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
  transition: transform 0.18s;
}
.tarot-draw__layout-card:hover img {
  transform: translateY(-2px);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.6);
}
.tarot-draw__layout-name {
  font-size: var(--fs-micro);
  color: var(--text-dim);
  margin-top: 6px;
  letter-spacing: 0.3px;
  line-height: 1.25;
  word-break: break-word;
}
.tarot-draw__btn {
  font-family: inherit;
  font-size: var(--fs-body);
  padding: 8px 16px;
  border-radius: 6px;
  border: 1px solid rgba(255,255,255,0.15);
  background: rgba(255,255,255,0.05);
  color: var(--text-muted);
  cursor: pointer;
  transition: all 0.12s;
  letter-spacing: 0.4px;
}
.tarot-draw__btn:hover {
  border-color: rgba(255,255,255,0.3);
  color: var(--text);
}
.tarot-draw__btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  font-weight: 500;
}
.tarot-draw__btn--primary:hover {
  background: var(--accent);
  border-color: var(--accent);
  filter: brightness(1.1);
  color: #fff;
}
.tarot-draw__results {
  margin-top: 6px;
  padding-top: 12px;
  border-top: 1px solid rgba(255,255,255,0.06);
}

/* ── Full deck grid (compact thumbnails, click → modal) ──── */

.tarot-deck__group-title {
  font-size: var(--fs-caption);
  color: var(--text-dim);
  letter-spacing: 1.2px;
  text-transform: uppercase;
  margin: 12px 0 6px;
}
.tarot-deck__row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.tarot-deck__card {
  width: 46px;
  height: 80px;
  padding: 0;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 4px;
  background: transparent;
  cursor: pointer;
  overflow: hidden;
  transition: transform 0.12s, border-color 0.12s, box-shadow 0.12s;
}
.tarot-deck__card:hover {
  transform: translateY(-2px);
  border-color: var(--accent);
  box-shadow: 0 4px 12px rgba(0,0,0,0.5);
  z-index: 1;
}
.tarot-deck__card img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

/* ── Card-detail modal (full deck click) ─────────────────── */

.tarot-card-modal {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(0,0,0,0.78);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  cursor: pointer;
  backdrop-filter: blur(4px);
}
.tarot-card-modal__inner {
  background: var(--surface);
  border-radius: 12px;
  padding: 24px;
  max-width: 540px;
  width: 100%;
  max-height: 85vh;
  overflow-y: auto;
  cursor: default;
  box-shadow: 0 12px 48px rgba(0,0,0,0.6);
  position: relative;
}
.tarot-card-modal__close {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 32px;
  height: 32px;
  border: none;
  background: transparent;
  color: var(--text-muted);
  font-size: var(--fs-2xl);
  line-height: 1;
  cursor: pointer;
  border-radius: 50%;
  transition: background 0.12s, color 0.12s;
}
.tarot-card-modal__close:hover {
  background: rgba(255,255,255,0.08);
  color: var(--text);
}
.tarot-card-modal__inner .tarot-card-info {
  border-bottom: none;
  padding: 0;
}
.tarot-card-modal__inner .tarot-card-info__img img {
  width: 180px;
}

/* ── Hebrew letter chip (clickable correspondence) ──────── */

.tcorr--hebrew {
  font-family: inherit;
  border: 1px solid rgba(159, 122, 234, 0.3);
  background: rgba(159, 122, 234, 0.1);
  color: var(--text-muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 9px;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.tcorr--hebrew:hover {
  background: rgba(159, 122, 234, 0.2);
  border-color: rgba(159, 122, 234, 0.55);
  color: var(--text);
}
.tcorr__glyph {
  font-size: var(--fs-title);
  line-height: 1;
  color: #c8b4f0;
  font-family: 'Times New Roman', serif;
}

/* ── Hebrew letter modal ─────────────────────────────────── */

.hebrew-letter-modal {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(0,0,0,0.78);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  cursor: pointer;
  backdrop-filter: blur(4px);
}
.hebrew-letter-modal__inner {
  background: var(--surface);
  border-radius: 12px;
  padding: 32px 28px 24px;
  max-width: 460px;
  width: 100%;
  cursor: default;
  text-align: center;
  position: relative;
  box-shadow: 0 12px 48px rgba(0,0,0,0.6);
}
.hebrew-letter-modal__close {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 32px;
  height: 32px;
  border: none;
  background: transparent;
  color: var(--text-muted);
  font-size: var(--fs-2xl);
  line-height: 1;
  cursor: pointer;
  border-radius: 50%;
  transition: background 0.12s, color 0.12s;
}
.hebrew-letter-modal__close:hover {
  background: rgba(255,255,255,0.08);
  color: var(--text);
}
.hebrew-letter-modal__glyph {
  font-family: 'Times New Roman', serif;
  font-size: 96px;
  line-height: 1;
  color: #c8b4f0;
  margin-bottom: 8px;
  text-shadow: 0 2px 12px rgba(159, 122, 234, 0.35);
}
.hebrew-letter-modal__name {
  font-family: var(--font-display);
  font-size: var(--fs-2xl);
  color: var(--text);
  margin-bottom: 10px;
  letter-spacing: 0.5px;
}
.hebrew-letter-modal__meta {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 18px;
}
.hebrew-letter-modal__interpretation {
  font-size: var(--fs-subtitle);
  color: var(--text-muted);
  line-height: 1.65;
  text-align: left;
  padding: 0 4px;
}

/* ════════════════════════════════════════════════════════════
   CHART INDICATOR + CONFIG MODAL (per-module chart settings)
   ════════════════════════════════════════════════════════════ */

.chart-indicator {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: inherit;
  font-size: var(--fs-label);
  letter-spacing: 0.4px;
  padding: 4px 10px;
  margin: 4px 0 12px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(255, 255, 255, 0.025);
  color: var(--text-dim);
  border-radius: 12px;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.chart-indicator:hover {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.22);
  color: var(--text);
}
.chart-indicator__label {
  font-size: var(--fs-micro);
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--text-dim);
}
.chart-indicator__sep {
  color: rgba(255, 255, 255, 0.25);
}
.chart-indicator__value {
  color: inherit;
}
.chart-indicator--overridden {
  border-color: rgba(251, 191, 36, 0.35);
  background: rgba(251, 191, 36, 0.06);
}
.chart-indicator--overridden:hover {
  border-color: rgba(251, 191, 36, 0.6);
  background: rgba(251, 191, 36, 0.12);
}
.chart-indicator__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #fbbf24;
  box-shadow: 0 0 5px rgba(251, 191, 36, 0.6);
  display: inline-block;
}

/* Static, non-clickable indicator for chart-independent modules
   (numerology, bazi, biorhythms — anything that derives only from
   the chart's date and ignores zodiac/ayanamsa/houseSystem). */
.chart-indicator--independent {
  cursor: default;
  border-style: dashed;
  border-color: rgba(255, 255, 255, 0.08);
  background: transparent;
  opacity: 0.85;
}
.chart-indicator--independent:hover {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.08);
  color: var(--text-dim);
}

/* ── Modal ─────────────────────────────────────────────────── */

.chart-config-modal {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(0, 0, 0, 0.78);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  cursor: pointer;
  backdrop-filter: blur(4px);
}
.chart-config-modal__inner {
  background: var(--surface);
  border-radius: 12px;
  padding: 24px 26px 22px;
  max-width: 640px;
  width: 100%;
  max-height: 85vh;
  overflow-y: auto;
  cursor: default;
  position: relative;
  box-shadow: 0 12px 48px rgba(0, 0, 0, 0.6);
}
.chart-config-modal__close {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 32px;
  height: 32px;
  border: none;
  background: transparent;
  color: var(--text-muted);
  font-size: var(--fs-2xl);
  line-height: 1;
  cursor: pointer;
  border-radius: 50%;
  transition: background 0.12s, color 0.12s;
}
.chart-config-modal__close:hover {
  background: rgba(255, 255, 255, 0.08);
  color: var(--text);
}

.chart-config-modal__header {
  margin-bottom: 16px;
  padding-right: 32px;
}
.chart-config-modal__module {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  color: var(--text);
  margin-bottom: 2px;
}
.chart-config-modal__title {
  font-size: var(--fs-label);
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 4px;
}
.chart-config-modal__hint {
  font-size: var(--fs-label);
  color: var(--text-dim);
  font-style: italic;
  line-height: 1.5;
}

/* Reset row */

.chart-config-modal__reset-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  margin-bottom: 18px;
  background: rgba(255, 255, 255, 0.04);
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.06);
  flex-wrap: wrap;
}
.chart-config-modal__default-summary {
  font-size: var(--fs-body);
  color: var(--text-muted);
  flex: 1;
  min-width: 0;
}
.chart-config-modal__default-label {
  font-size: var(--fs-micro);
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-right: 8px;
}
.chart-config-modal__reset {
  font-family: inherit;
  font-size: var(--fs-label);
  padding: 6px 14px;
  border-radius: 14px;
  border: 1px solid rgba(251, 191, 36, 0.4);
  background: rgba(251, 191, 36, 0.1);
  color: #fbbf24;
  cursor: pointer;
  transition: all 0.12s;
  letter-spacing: 0.3px;
  flex-shrink: 0;
}
.chart-config-modal__reset:hover {
  background: rgba(251, 191, 36, 0.2);
  border-color: rgba(251, 191, 36, 0.7);
}
.chart-config-modal__reset--disabled,
.chart-config-modal__reset:disabled {
  border-color: rgba(255, 255, 255, 0.08);
  background: transparent;
  color: var(--text-dim);
  cursor: default;
}
.chart-config-modal__reset--disabled:hover,
.chart-config-modal__reset:disabled:hover {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.08);
}

/* Bake-as-default row */

.chart-config-modal__bake-row {
  margin-bottom: 18px;
  padding: 10px 12px;
  background: rgba(123, 179, 224, 0.06);
  border: 1px solid rgba(123, 179, 224, 0.18);
  border-radius: 6px;
}
.chart-config-modal__bake {
  font-family: inherit;
  font-size: var(--fs-label);
  padding: 7px 14px;
  border-radius: 14px;
  border: 1px solid var(--accent);
  background: rgba(123, 179, 224, 0.18);
  color: var(--text);
  cursor: pointer;
  transition: background 0.12s;
  letter-spacing: 0.3px;
  font-weight: 500;
}
.chart-config-modal__bake:hover {
  background: rgba(123, 179, 224, 0.32);
}
.chart-config-modal__bake-hint {
  display: block;
  font-size: var(--fs-caption);
  color: var(--text-dim);
  font-style: italic;
  line-height: 1.45;
  margin-top: 6px;
}

/* Option sections */

.chart-config-section {
  margin-bottom: 18px;
}
.chart-config-section__title {
  font-size: var(--fs-caption);
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  padding-bottom: 4px;
}
.chart-config-section__options {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.chart-config-option {
  font-family: inherit;
  font-size: var(--fs-label);
  padding: 6px 12px;
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(255, 255, 255, 0.03);
  color: var(--text-muted);
  cursor: pointer;
  transition: all 0.12s;
  text-align: left;
  display: inline-flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.chart-config-option:hover {
  border-color: rgba(255, 255, 255, 0.25);
  background: rgba(255, 255, 255, 0.07);
  color: var(--text);
}
.chart-config-option--active {
  border-color: var(--accent);
  background: rgba(123, 179, 224, 0.16);
  color: var(--text);
}
.chart-config-option--active:hover {
  border-color: var(--accent);
  background: rgba(123, 179, 224, 0.24);
}
.chart-config-option__name {
  font-weight: 500;
}
.chart-config-option__tradition {
  font-size: var(--fs-micro);
  color: var(--text-dim);
  letter-spacing: 0.3px;
}

/* ══ NOW CLOCK — Read tab: verdict apex + standouts + topic board ════════
   Conclusion-first reading. The apex is the moment's one-word verdict; standouts
   surface the brightest/most-strained topics; the board is every topic, scannable
   and tappable (each opens its full modal). Rendered as raw `html` info-blocks. */
.nc-read-apex { display: flex; align-items: center; gap: 12px; margin: 2px 0 8px; }
.nc-read-apex__emoji { font-size: 2.4em; line-height: 1; }
.nc-read-apex__word { font-family: var(--font-display, inherit); font-size: 1.9em; font-weight: 600; color: var(--text); letter-spacing: 0.01em; }

.nc-read-standouts { display: flex; flex-direction: column; gap: 5px; margin-top: 4px; }
.nc-read-standout {
  display: flex; align-items: flex-start; gap: 10px; width: 100%; text-align: left;
  font-family: inherit; cursor: pointer; background: rgba(255, 255, 255, 0.02);
  border: 1px solid transparent; border-left: 2px solid var(--c, var(--border));
  border-radius: 0 8px 8px 0; padding: 8px 10px; transition: background 0.12s;
}
.nc-read-standout:hover { background: rgba(255, 255, 255, 0.07); }
.nc-read-standout__mark { flex: 0 0 auto; font-size: 18px; line-height: 1.3; }
.nc-read-standout__body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.nc-read-standout__label { font-size: 13px; font-weight: 600; color: var(--text); display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.nc-read-standout__tag { font-size: 9.5px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--c, var(--text-dim)); }
.nc-read-standout__line { font-size: 12.5px; line-height: 1.4; color: var(--text-muted); }

/* The board — every topic, full name always visible (wraps, never truncates). */
.nc-read-board { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 4px; margin: 2px 0 8px; }
.nc-read-chip {
  display: flex; align-items: flex-start; gap: 8px; text-align: left; font-family: inherit;
  cursor: pointer; background: rgba(255, 255, 255, 0.02);
  border: 1px solid transparent; border-left: 2px solid var(--c, var(--border));
  border-radius: 0 7px 7px 0; padding: 6px 9px; transition: background 0.12s;
}
.nc-read-chip:hover { background: rgba(255, 255, 255, 0.07); }
.nc-read-chip__mark { flex: 0 0 auto; font-size: 15px; line-height: 1.35; }
.nc-read-chip__text { flex: 1 1 auto; min-width: 0; font-size: 12.5px; line-height: 1.35; white-space: normal; overflow-wrap: anywhere; }
.nc-read-chip__label { color: var(--text); }
.nc-read-chip__word { color: var(--c, var(--text-muted)); opacity: 0.95; white-space: nowrap; }

/* NOW CLOCK — Configure: segment palette picker (swatch buttons + Random). */
.nc-pal-list { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.nc-pal {
  display: flex; flex-direction: column; gap: 5px; min-width: 92px; cursor: pointer;
  font-family: inherit; background: rgba(255, 255, 255, 0.02);
  border: 1px solid var(--border); border-radius: 8px; padding: 6px;
  transition: border-color 0.12s, background 0.12s;
}
.nc-pal:hover { background: rgba(255, 255, 255, 0.06); border-color: var(--accent); }
.nc-pal.is-active { border-color: var(--accent); background: rgba(255, 255, 255, 0.08); }
.nc-pal-sws { display: flex; height: 16px; border-radius: 4px; overflow: hidden; }
.nc-pal-sw { flex: 1 1 auto; }
.nc-pal-sws--none { align-items: center; justify-content: center; font-size: 12px; color: var(--text-dim); background: rgba(255, 255, 255, 0.04); }
.nc-pal-name { font-size: 11px; color: var(--text-muted); text-align: center; }
.nc-pal.is-active .nc-pal-name { color: var(--text); }

/* ══ NOW CLOCK — Configure tab: playlist segment list + presets ══════════
   The segment list reads like a playlist: one compact row per segment (its
   emoji + name, a small voice select, reorder ▲▼, Change, ✕). Rendered as a raw
   `html` info-block; buttons carry data-action so the shared dispatcher routes
   + re-renders them. */
.nc-cfg-list { display: flex; flex-direction: column; gap: 5px; margin-top: 6px; }
.nc-cfg-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 5px 8px;
  padding: 5px 8px; border: 1px solid var(--border); border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
}
.nc-cfg-row__icon {
  flex: 0 0 auto; width: 1.5em; text-align: center; font-size: 15px; line-height: 1.2;
  color: var(--c, var(--text));
}
/* Full name, always visible: it wraps within its own space, and keeps a minimum
   width so the voice select + controls drop to a second line on a thin panel
   rather than crushing the label to an ellipsis. */
.nc-cfg-row__label { flex: 1 1 auto; min-width: 130px; font-size: 13px; line-height: 1.3; color: var(--text); white-space: normal; overflow-wrap: anywhere; }
.nc-cfg-row__voice {
  flex: 0 0 auto; max-width: 8.5em; font-family: inherit; font-size: 11px;
  color: var(--text-muted); background: var(--surface); border: 1px solid var(--border);
  border-radius: 5px; padding: 2px 4px; cursor: pointer;
}
.nc-cfg-row__ctrls { flex: 0 0 auto; margin-left: auto; display: inline-flex; align-items: center; gap: 3px; }
.nc-cfg-ico, .nc-cfg-change, .nc-cfg-add {
  font-family: inherit; cursor: pointer; border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.03); color: var(--text-muted);
  border-radius: 6px; transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.nc-cfg-ico { width: 24px; height: 24px; padding: 0; font-size: 11px; line-height: 1; display: inline-flex; align-items: center; justify-content: center; }
.nc-cfg-change { padding: 3px 9px; font-size: 11px; }
.nc-cfg-ico:hover:not(:disabled), .nc-cfg-change:hover:not(:disabled) { background: rgba(255, 255, 255, 0.08); color: var(--text); border-color: var(--accent); }
.nc-cfg-ico--rm:hover:not(:disabled) { color: #ff8080; border-color: #ff8080; }
.nc-cfg-ico:disabled { opacity: 0.28; cursor: default; }
.nc-cfg-add {
  margin-top: 3px; align-self: flex-start; padding: 6px 14px; font-size: 12px;
  color: var(--accent); border-style: dashed;
}
.nc-cfg-add:hover:not(:disabled) { background: rgba(255, 255, 255, 0.06); }
.nc-cfg-add:disabled { opacity: 0.4; cursor: default; }
.nc-cfg-empty { font-size: 12px; color: var(--text-dim); font-style: italic; padding: 6px 2px; }

/* Presets — prominent list of ready-made + user-saved dials. */
.nc-preset-list { display: flex; flex-direction: column; gap: 5px; margin: 4px 0 8px; }
.nc-preset-row {
  display: flex; align-items: center; gap: 10px; padding: 7px 10px;
  border: 1px solid var(--border); border-radius: 8px; background: rgba(255, 255, 255, 0.02);
}
.nc-preset-row__main { flex: 1 1 auto; min-width: 0; }
.nc-preset-row__name { font-size: 13px; color: var(--text); font-weight: 500; }
.nc-preset-row__desc { font-size: 11px; color: var(--text-dim); margin-top: 1px; line-height: 1.35; }

/* Segment identity selection modal — reuses the .chart-config-modal shell. */
/* The default accent (light periwinkle) reads poorly on the grey modal surface,
   so this modal uses a gold accent — titles, group headers, the "Segment colour"
   label, badges and the active-swatch ring all pick it up. Scoped to this modal. */
.nc-seg-modal { --accent: #ffd36a; }
/* In-app text prompt (textPrompt) — reliable replacement for window.prompt(). */
.nc-prompt-inner { max-width: 400px; }
.nc-prompt-label { font-size: 13px; color: var(--text-muted); margin: 0 0 8px; }
.nc-prompt-input {
  width: 100%; box-sizing: border-box; font-family: inherit; font-size: 15px; color: var(--text);
  background: rgba(255, 255, 255, 0.04); border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px;
}
.nc-prompt-input:focus { outline: none; border-color: var(--accent); }
.nc-prompt-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; }
.nc-prompt-ok { background: var(--accent); color: #1a1408; border-color: var(--accent); font-weight: 600; }
.nc-prompt-ok:hover { filter: brightness(1.08); }
.nc-seg-inner { max-width: 600px; display: flex; flex-direction: column; max-height: 82vh; }
/* Per-segment colour control (swatches + default + native picker). */
.nc-seg-color { margin: 2px 0 12px; }
.nc-seg-color__label { font-size: var(--fs-label); letter-spacing: 1.2px; text-transform: uppercase; color: var(--accent); margin-bottom: 6px; }
.nc-seg-color__row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.nc-seg-sw {
  width: 24px; height: 24px; padding: 0; cursor: pointer; border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.18); box-sizing: border-box; transition: transform 0.1s, box-shadow 0.1s;
}
.nc-seg-sw:hover { transform: scale(1.12); }
.nc-seg-sw.is-active { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--accent); }
.nc-seg-sw--default { display: inline-flex; align-items: center; justify-content: center; background: rgba(255, 255, 255, 0.05); color: var(--text-dim); font-size: 12px; }
.nc-seg-sw--custom { position: relative; overflow: hidden; background: linear-gradient(135deg, #ff3b3b, #ffe000, #20e070, #00c8ff, #7b3bff, #ff3df0); }
.nc-seg-sw--custom input[type="color"] { position: absolute; inset: -4px; width: calc(100% + 8px); height: calc(100% + 8px); opacity: 0; cursor: pointer; border: none; padding: 0; }

.nc-seg-search { margin: 2px 0 12px; }
.nc-seg-search__input {
  width: 100%; box-sizing: border-box; font-family: inherit; font-size: 14px;
  color: var(--text); background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--border); border-radius: 8px; padding: 9px 12px;
}
.nc-seg-search__input:focus { outline: none; border-color: var(--accent); }
.nc-seg-scroll { overflow-y: auto; flex: 1 1 auto; margin: 0 -6px; padding: 0 6px; }
.nc-seg-group { margin-bottom: 14px; }
.nc-seg-group__title {
  font-size: var(--fs-label); letter-spacing: 1.2px; text-transform: uppercase;
  color: var(--accent); margin-bottom: 6px;
}
.nc-seg-group--used .nc-seg-group__title { color: var(--text-dim); }
.nc-seg-group__hint { font-size: 11px; color: var(--text-dim); font-style: italic; margin: -3px 0 6px; }
/* Two wide columns (single column when narrow) so the FULL topic name is always
   visible — long electional names wrap to a second line rather than truncate.
   Reads as a tidy list of rows, not a smattering of fixed-width buttons. */
.nc-seg-group__items { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 4px; }
.nc-seg-topic {
  display: flex; align-items: flex-start; gap: 10px; text-align: left; min-height: 38px;
  font-family: inherit; font-size: 13px; line-height: 1.3; color: var(--text); cursor: pointer;
  border: 1px solid transparent; border-left: 2px solid var(--border); border-radius: 0 7px 7px 0;
  padding: 8px 10px; background: rgba(255, 255, 255, 0.02);
  transition: background 0.12s, border-color 0.12s;
}
.nc-seg-topic:hover { background: rgba(255, 255, 255, 0.07); border-left-color: var(--c, var(--accent)); }
.nc-seg-topic__icon { flex: 0 0 auto; width: 1.4em; text-align: center; font-size: 16px; line-height: 1.25; color: var(--c, var(--text)); }
/* Full name, wrapping — never clipped. */
.nc-seg-topic__label { flex: 1 1 auto; min-width: 0; white-space: normal; overflow-wrap: anywhere; }
.nc-seg-topic.is-current { border-left-color: var(--accent); background: rgba(255, 255, 255, 0.07); }
.nc-seg-topic.is-used { opacity: 0.6; }
.nc-seg-topic__badge { flex: 0 0 auto; align-self: center; font-size: 9.5px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--accent); }
.nc-seg-empty { font-size: 13px; color: var(--text-dim); font-style: italic; padding: 12px 2px; }

/* ── Tree of life path chip (clickable correspondence) ──── */

.tcorr--path {
  font-family: inherit;
  border: 1px solid rgba(180, 200, 240, 0.3);
  background: rgba(180, 200, 240, 0.08);
  color: var(--text-muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 9px;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.tcorr--path:hover {
  background: rgba(180, 200, 240, 0.18);
  border-color: rgba(180, 200, 240, 0.55);
  color: var(--text);
}

/* ── Tree of life path modal ─────────────────────────────── */

.tree-path-modal {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(0,0,0,0.78);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  cursor: pointer;
  backdrop-filter: blur(4px);
}
.tree-path-modal__inner {
  background: var(--surface);
  border-radius: 12px;
  padding: 32px 28px 24px;
  max-width: 480px;
  width: 100%;
  cursor: default;
  text-align: center;
  position: relative;
  box-shadow: 0 12px 48px rgba(0,0,0,0.6);
}
.tree-path-modal__close {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 32px;
  height: 32px;
  border: none;
  background: transparent;
  color: var(--text-muted);
  font-size: var(--fs-2xl);
  line-height: 1;
  cursor: pointer;
  border-radius: 50%;
  transition: background 0.12s, color 0.12s;
}
.tree-path-modal__close:hover {
  background: rgba(255,255,255,0.08);
  color: var(--text);
}
.tree-path-modal__title {
  font-family: var(--font-display);
  font-size: var(--fs-subtitle);
  color: var(--accent);
  letter-spacing: 1.4px;
  text-transform: uppercase;
  margin-bottom: 8px;
}
.tree-path-modal__connection {
  font-family: var(--font-display);
  font-size: var(--fs-2xl);
  color: var(--text);
  margin-bottom: 12px;
  letter-spacing: 0.5px;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.tree-path-modal__sephira {
  color: #b4c8f0;
}
.tree-path-modal__arrow {
  color: var(--text-dim);
  font-size: var(--fs-xl);
}
.tree-path-modal__meta {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 14px;
}
.tree-path-modal__sephira-row {
  font-size: var(--fs-body);
  color: var(--text-muted);
  text-align: left;
  padding: 4px 6px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  margin-bottom: 4px;
}
.tree-path-modal__sephira-row:last-of-type {
  margin-bottom: 16px;
}
.tree-path-modal__sephira-row strong {
  color: #b4c8f0;
  font-weight: 500;
  margin-right: 6px;
}
.tree-path-modal__sephira-meaning {
  color: var(--text-dim);
  font-style: italic;
}
.tree-path-modal__interpretation {
  font-size: var(--fs-subtitle);
  color: var(--text-muted);
  line-height: 1.65;
  text-align: left;
  padding: 8px 4px 0;
  border-top: 1px solid rgba(255,255,255,0.06);
}

/* ── Fixed star clickable link ──────────────────────────── */

.fixed-star-link {
  cursor: pointer;
  border-bottom: 1px dotted currentColor;
  transition: opacity 0.12s;
}
.fixed-star-link:hover { opacity: 0.75; }

/* ── Fixed star detail modal ────────────────────────────── */

.star-detail-modal {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(0,0,0,0.75);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 20px;
}
.star-detail-card {
  background: var(--surface);
  border-radius: 12px;
  padding: 24px;
  max-width: 520px;
  width: 100%;
  max-height: 85vh;
  overflow-y: auto;
  cursor: default;
  box-shadow: 0 8px 32px rgba(0,0,0,0.5);
}
.star-detail-name {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  color: var(--text);
  margin-bottom: 6px;
}
.star-detail-meta {
  font-size: var(--fs-label);
  color: var(--text-dim);
  margin-bottom: 10px;
  font-style: italic;
}
.star-detail-keywords {
  font-size: var(--fs-body);
  color: var(--accent);
  margin-bottom: 14px;
  letter-spacing: 0.3px;
}
.star-detail-section-label {
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.8px;
  margin: 16px 0 6px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.star-detail-body {
  font-size: var(--fs-heading);
  color: var(--text-muted);
  line-height: 1.65;
  white-space: pre-wrap;
}
.star-detail-angle {
  margin-top: 10px;
}
.star-detail-angle-label {
  font-size: var(--fs-label);
  font-weight: 600;
  color: var(--accent);
  margin-bottom: 3px;
}

/* ── Prasna rule link (clickable badge in info panel) ──── */

.prasna-rule-link {
  transition: opacity 0.15s, filter 0.15s;
}
.prasna-rule-link:hover {
  filter: brightness(1.4);
  text-decoration-style: solid !important;
}

/* ── Cuspal interlinks: clickable entity links ─────────── */

.cuspal-house-link,
.cuspal-planet-link,
.cuspal-sign-link {
  cursor: pointer;
  text-decoration: underline;
  text-decoration-style: dotted;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  transition: filter 0.15s;
  font-weight: 600;
}
.cuspal-house-link:hover,
.cuspal-planet-link:hover,
.cuspal-sign-link:hover {
  filter: brightness(1.35);
  text-decoration-style: solid;
}

/* ── Cuspal interlinks: 12-segment compact bar (Phase 4) ── */

.cuspal-interlink-bar {
  display: flex;
  width: 100%;
  height: 38px;
  margin: 6px 0 0;
  border-radius: 4px;
  overflow: hidden;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid rgba(255, 255, 255, 0.06);
}
.cuspal-interlink-bar .cuspal-interlink-segment {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background-color: var(--potential-color, #888);
  border-right: 1px solid rgba(0, 0, 0, 0.45);
  cursor: pointer;
  transition: filter 0.15s, transform 0.15s;
  position: relative;
  text-decoration: none;
  font-weight: 500;
  min-width: 0;
}
.cuspal-interlink-bar .cuspal-interlink-segment:last-child { border-right: none; }
.cuspal-interlink-bar .cuspal-interlink-segment:hover {
  filter: brightness(1.3);
  transform: translateY(-1px);
  z-index: 2;
}
.cuspal-interlink-segment__house {
  font-size: var(--fs-micro);
  font-weight: 700;
  color: rgba(0, 0, 0, 0.75);
  line-height: 1;
  margin-bottom: 2px;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
}
.cuspal-interlink-segment__sublord {
  font-size: var(--fs-label);
  font-weight: 700;
  color: var(--sublord-color, #fff);
  line-height: 1;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}
.cuspal-interlink-segment--empty {
  background: rgba(60, 60, 80, 0.3);
  cursor: default;
}
.cuspal-interlink-segment--active-bhukti {
  box-shadow: inset 0 0 0 1px var(--interlink-accent, #c9a35a);
  z-index: 1;
}
.cuspal-interlink-segment--active-dasa {
  box-shadow: inset 0 0 0 2px var(--interlink-accent, #c9a35a),
              0 0 8px color-mix(in srgb, var(--interlink-accent, #c9a35a) 45%, transparent);
  z-index: 1;
  animation: cuspalDasaPulse 2.6s ease-in-out infinite;
}
@keyframes cuspalDasaPulse {
  0%, 100% {
    box-shadow: inset 0 0 0 2px var(--interlink-accent, #c9a35a),
                0 0 6px color-mix(in srgb, var(--interlink-accent, #c9a35a) 40%, transparent);
  }
  50% {
    box-shadow: inset 0 0 0 2px var(--interlink-accent, #c9a35a),
                0 0 14px color-mix(in srgb, var(--interlink-accent, #c9a35a) 70%, transparent);
  }
}

/* ── Cuspal interlinks: standalone interlink-web SVG widget ── */

.cuspal-interlink-web__wrap {
  display: flex;
  justify-content: center;
  margin: 4px 0;
}
.cuspal-interlink-web {
  width: min(220px, 100%);
  height: auto;
  overflow: visible;
}
.cuspal-interlink-web__cusp {
  cursor: pointer;
  transition: filter 0.15s, r 0.15s;
}
.cuspal-interlink-web__cusp:hover {
  filter: brightness(1.4);
}
.cuspal-interlink-web__chord {
  cursor: pointer;
  transition: opacity 0.15s, stroke-width 0.15s;
}
.cuspal-interlink-web__chord:hover {
  opacity: 0.95 !important;
  stroke-width: 2.5;
}
.cuspal-interlink-web__chord--blazing {
  animation: cuspalChordBlaze 1.8s ease-in-out infinite;
  filter: drop-shadow(0 0 3px currentColor);
}
@keyframes cuspalChordBlaze {
  0%, 100% { opacity: 0.7; }
  50%      { opacity: 1.0; }
}

/* ── Shared modal buttons (used by all modals) ──────────── */

.modal-btn {
  padding: 8px 20px;
  border-radius: 7px;
  font-size: var(--fs-heading);
  font-family: var(--font-body);
  cursor: pointer;
  transition: all 0.15s;
  border: 1px solid transparent;
}
.modal-btn-primary {
  background: var(--accent-bg);
  border-color: var(--accent-border);
  color: var(--accent);
  font-weight: 500;
}
.modal-btn-primary:hover {
  background: var(--accent-border);
}
.modal-btn-secondary {
  background: transparent;
  border-color: var(--border);
  color: var(--text-muted);
}
.modal-btn-secondary:hover {
  background: var(--input-bg);
  color: var(--text);
}
.modal-btn-danger {
  background: rgba(200,80,80,0.08);
  border-color: rgba(200,80,80,0.3);
  color: #c85050;
}
.modal-btn-danger:hover {
  background: rgba(200,80,80,0.2);
}

/* ── Shared modal overlay ───────────────────────────────── */

.modal-overlay-common {
  position: fixed;
  inset: 0;
  z-index: 9998;
  background: rgba(0,0,0,0.7);
  display: flex;
  align-items: center;
  justify-content: center;
}
.modal-card-common {
  background: var(--surface);
  border-radius: 12px;
  padding: 24px;
  max-width: 440px;
  width: 92%;
  max-height: 85vh;
  overflow-y: auto;
  box-shadow: 0 8px 32px rgba(0,0,0,0.5);
  scrollbar-width: thin;
  scrollbar-color: rgba(128,128,128,0.2) transparent;
}

/* ── Journal entry form ─────────────────────────────────── */

.journal-form-modal {
  position: fixed;
  inset: 0;
  z-index: 9998;
  background: rgba(0,0,0,0.7);
  display: flex;
  align-items: center;
  justify-content: center;
}
.journal-form-card {
  background: var(--surface);
  border-radius: 12px;
  padding: 24px;
  max-width: 440px;
  width: 92%;
  max-height: 85vh;
  overflow-y: auto;
  box-shadow: 0 8px 32px rgba(0,0,0,0.5);
  scrollbar-width: thin;
  scrollbar-color: rgba(128,128,128,0.2) transparent;
}

.jf-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.jf-row {
  display: flex;
  gap: 8px;
  align-items: center;
}
.jf-input {
  width: 100%;
  padding: 8px 12px;
  background: var(--input-bg);
  border: 1px solid var(--border);
  border-radius: 7px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-heading);
  box-sizing: border-box;
}
.jf-input:focus {
  outline: none;
  border-color: var(--accent-border);
}
.jf-textarea {
  width: 100%;
  padding: 10px 12px;
  background: var(--input-bg);
  border: 1px solid var(--border);
  border-radius: 7px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-heading);
  line-height: 1.6;
  min-height: 120px;
  resize: vertical;
  box-sizing: border-box;
}
.jf-textarea:focus {
  outline: none;
  border-color: var(--accent-border);
}
.jf-textarea::placeholder,
.jf-input::placeholder {
  color: var(--text-dim);
}
.jf-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  padding-top: 4px;
}

/* ── Emoji picker ───────────────────────────────────────── */

.jf-emoji-picker {
  position: relative;
  flex-shrink: 0;
}
.jf-emoji-trigger {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px 10px;
  background: var(--input-bg);
  border: 1px solid var(--border);
  border-radius: 7px;
  color: var(--text);
  font-size: var(--fs-xl);
  cursor: pointer;
  transition: border-color 0.15s;
}
.jf-emoji-trigger:hover {
  border-color: var(--accent-border);
}
.jf-emoji-display {
  font-size: var(--fs-xl);
  line-height: 1;
}
.jf-emoji-grid {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 100;
  padding: 8px;
  margin-top: 4px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 16px var(--shadow);
  width: 260px;
  max-height: 320px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(128,128,128,0.2) transparent;
}
.jf-emoji-section {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 2px;
}
.jf-emoji-divider {
  height: 1px;
  background: var(--border);
  margin: 6px 0;
}
.jf-emoji-option {
  width: 28px;
  height: 28px;
  border: none;
  background: transparent;
  border-radius: 4px;
  font-size: var(--fs-lg);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.1s;
  padding: 0;
}
.jf-emoji-option:hover {
  background: var(--accent-bg);
}

/* ── Tag autocomplete ───────────────────────────────────── */

.jf-tag-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 100;
  background: var(--surface);
  border: 1px solid var(--accent-border);
  border-radius: 6px;
  margin-top: 2px;
  box-shadow: 0 4px 12px var(--shadow);
  max-height: 140px;
  overflow-y: auto;
}
.jf-tag-suggestion {
  padding: 6px 10px;
  font-size: var(--fs-body);
  color: var(--text);
  cursor: pointer;
}
.jf-tag-suggestion:hover {
  background: var(--surface-hover);
}

/* ── Photo lightbox ─────────────────────────────────────── */

.photo-lightbox {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(0,0,0,0.85);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.photo-lightbox img {
  max-width: 90vw;
  max-height: 90vh;
  object-fit: contain;
  border-radius: 8px;
}

/* ── Text content ─────────────────────────────────────────── */

.text-content {
  flex: 1;
  overflow-y: auto;
  padding: 14px var(--panel-pad-x);
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,0.06) transparent;
  /* Info-panel base size — the single scope for ALL module readouts. Matches
     .module-visual / .mi-info-scope so em-based mi-* helpers and inline STY
     text size correctly even when a module renders its markup directly into
     .text-content without a .module-visual / .mi-info-scope wrapper. Without
     this the app-wide root font-size (a responsive rem base ≈20px) leaks in
     and blows up every em-relative readout (scores, %, table cells) to 17–20px.
     Scales with --mi-font-scale (the "Info Panel Text" setting) ONLY, like the
     wrappers — independent of the app-wide --font-scale. */
  font-size: calc(var(--fs-standard) * var(--mi-font-scale, 1));
  line-height: 1.6;
}

/* Module info panel = a fixed title row + a contained scroll region. When the
   body is wrapped in .mi-info-scroll (module panels), .text-content itself stops
   scrolling and becomes a flex column: the title row (.mi-info-head) stays put
   and ONLY the body below it scrolls, so the scrollbar starts below the title,
   never behind it. Panels without that wrapper (departments/apps/selection)
   fall through to the normal whole-panel scroll. No added background — the title
   keeps its plain appearance. */
.text-content:has(> .mi-info-scroll) {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.mi-info-head { flex: 0 0 auto; padding-bottom: 8px; }
.mi-info-head .reading-title { margin-bottom: 4px; }
.mi-info-scroll {
  flex: 1 1 auto;
  min-height: 0;               /* let the flex child shrink so it can scroll */
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.06) transparent;
}
/* .mi-info-scroll is an INDEPENDENT scroller ONLY in the two-panel layout, where it
   is the direct child of .text-content that fills the panel below the fixed title row.
   Everywhere else (single-panel #spInfo, corner-chart REST zone, compact) it must FLOW
   into its container's own scroller. Otherwise its overflow-y:auto + overscroll-behavior:
   contain SWALLOW the mouse wheel when it isn't actually overflowing — the recurring
   "can't wheel-scroll the module info" bug (scrollbar-drag still worked). So the scroller
   behavior is scoped to the two-panel case only. */
.text-content:has(> .mi-info-scroll) > .mi-info-scroll {
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
  -webkit-overflow-scrolling: touch;
}

/* ── Foolproof scroll (see ui/scroll-assist.js) ─────────────────────
   The chart owns VERTICAL SWIPE as its primary navigation gesture, so
   page/panel scrolling is confined to these inner containers and nowhere
   else. `pan-y` explicitly allows vertical touch-scroll HERE (and, given the
   chart canvas's `touch-action:none`, only here). `overscroll-behavior:
   contain` stops the gesture from chaining up to the locked body — a
   nested-scroll failure mode that silently swallows the swipe on some Android
   browsers. Momentum for iOS. */
.text-content,
.chat-tab-log,
.cal-tabbody {
  touch-action: pan-y;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

/* Tap PAGE-UP / PAGE-DOWN affordance — the GUARANTEE that scrolling works on
   every device/browser even where touch-drag-scroll is broken. Hidden until the
   active scroller overflows (toggled by ui/scroll-assist.js). Anchored to the
   persistent #textPanel (position:relative), bottom-right, above the content. */
.scroll-assist {
  position: absolute;
  right: 8px;
  bottom: 10px;
  z-index: 40;
  display: none;
  flex-direction: column;
  gap: 6px;
  pointer-events: none;   /* the group is inert; the buttons re-enable pointer events */
}
.scroll-assist.is-visible { display: flex; }
.scroll-assist-btn {
  pointer-events: auto;
  width: 34px;
  height: 34px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface, rgba(20, 22, 32, 0.86));
  color: var(--text, #e8e8f0);
  font-size: 17px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
  opacity: 0.82;
  transition: opacity 0.12s, background 0.12s, transform 0.06s;
  user-select: none;
  -webkit-user-select: none;
  touch-action: manipulation;   /* no 300ms tap delay / double-tap zoom on the buttons */
}
.scroll-assist-btn:hover { opacity: 1; background: var(--surface-hover, var(--surface)); }
.scroll-assist-btn:active { transform: translateY(1px); }
.scroll-assist-btn.is-disabled { opacity: 0.28; pointer-events: none; }

.placeholder {
  color: var(--text-dim);
  font-size: var(--fs-heading);
  text-align: center;
  padding: 40px 0;
}

.reading-title {
  font-family: var(--font-display);
  font-size: var(--fs-display);   /* module-title header exception — stays larger */
  font-weight: 400;
  color: var(--text);
  margin-bottom: 8px;
  letter-spacing: 0.3px;
}

/* P14 — preset indicator chip inside .reading-title. Sits inline at
   the end of the title and shows which chart preset is active. */
.preset-chip {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 7px;
  font-size: var(--fs-caption);
  font-weight: 500;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--preset-c, #888);
  border: 1px solid var(--preset-c, #888);
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.15);
  vertical-align: middle;
  white-space: nowrap;
  user-select: none;
}
/* KP-Roulette variant: clickable, pulses to draw the eye and
   communicate that interaction exits the preset. */
.preset-chip-kp {
  cursor: pointer;
  animation: preset-chip-kp-pulse 1.6s ease-in-out infinite;
}
.preset-chip-kp:hover {
  background: rgba(76, 175, 80, 0.2);
}
@keyframes preset-chip-kp-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(76, 175, 80, 0.0); }
  50%      { box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.35); }
}

.reading-desc {
  font-size: var(--fs-label);
  color: var(--text-muted);
  font-style: italic;
  margin-bottom: 12px;
  line-height: 1.5;
}

.reading-context {
  font-size: var(--fs-label);
  color: var(--text-dim);
  font-style: italic;
  margin-bottom: 6px;
  line-height: 1.5;
  letter-spacing: 0.2px;
}

.section-label {
  font-size: var(--fs-heading);
  font-weight: 600;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.8px;
  margin: 24px 0 8px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.section-label:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}

/* ── "Additional information" disclosure ───────────────────────────────
   Sections a module flags `more` (e.g. Aspects' Stelliums / Element / Mode /
   Hemisphere balance) are collected by the skin into one native <details> at
   the bottom of the panel. The summary reads like a .section-label but toggles. */
.mi-more {
  margin-top: 24px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.mi-more-summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-heading);
  font-weight: 600;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.8px;
  user-select: none;
}
.mi-more-summary::-webkit-details-marker { display: none; }
.mi-more-summary::before {
  content: '▸';
  font-size: 0.85em;
  opacity: 0.7;
  transition: transform 0.15s ease;
}
.mi-more[open] > .mi-more-summary::before {
  transform: rotate(90deg);
}
.mi-more-body {
  margin-top: 4px;
}
/* The disclosure owns the top separator; its first inner section shouldn't
   redraw one directly under the summary. */
.mi-more-body > .mi-section:first-child .section-label {
  margin-top: 8px;
  padding-top: 0;
  border-top: none;
}

.entry {
  margin-bottom: 8px;
  padding: 8px 12px;
  border-left: 2px solid var(--border);
  border-radius: 0 4px 4px 0;
  background: var(--input-bg);
  cursor: pointer;
  transition: all 0.12s;
}
.entry:hover {
  background: var(--surface-hover);
  border-left-color: var(--accent-border);
}
.entry.highlighted {
  border-left-color: var(--accent);
  background: rgba(99,179,237,0.04);
}

.entry-condition {
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--accent);
  margin-bottom: 3px;
}

.entry-text {
  font-size: var(--fs-body);
  color: var(--text);
  line-height: 1.55;
}

.entry-visual {
  margin-top: 6px;
  padding: 6px;
  background: rgba(0,0,0,0.2);
  border-radius: 4px;
  font-size: var(--fs-label);
  overflow: hidden;
}

/* ── Selection sections with pulsing borders ─────────────── */

@keyframes selection-pulse {
  0%, 100% { border-color: rgba(var(--accent-rgb, 99,179,237), 0.3); }
  50% { border-color: rgba(var(--accent-rgb, 99,179,237), 0.6); }
}

:root, [data-theme="dark"] { --accent-rgb: 99,179,237; }
[data-theme="light"] { --accent-rgb: 43,108,176; }
[data-theme="warm"] { --accent-rgb: 160,104,32; }

.selection-section {
  border: 2px solid var(--accent-border);
  border-radius: 8px;
  padding: 12px;
  margin-bottom: 10px;
  animation: selection-pulse 2s ease-in-out infinite;
}

.selection-secondary {
  border-width: 1px;
  opacity: 0.9;
}

.selection-ring {
  border-width: 1px;
  border-style: dashed;
  animation: selection-pulse 2s ease-in-out infinite;
}

/* ── Module info visual output (mi-* classes) ────────────── */

/* Theme-controlled CSS variables for module info HTML.
   Modules reference these via var(--mi-text) etc. in inline styles,
   or via mi-* CSS classes from the helpers. */
:root, [data-theme="dark"] {
  --mi-text: rgba(220,210,200,0.85);
  --mi-muted: rgba(200,190,180,0.5);
  --mi-track: rgba(255,255,255,0.06);
}
[data-theme="light"] {
  --mi-text: #2c2218;
  --mi-muted: #6b5d4e;
  --mi-track: rgba(0,0,0,0.08);
}
[data-theme="warm"] {
  --mi-text: #2c2218;
  --mi-muted: #6b5d4e;
  --mi-track: rgba(100,70,40,0.1);
}

.module-visual {
  padding: 8px 10px;
  /* Info-panel base size (bumped from 12px) × the info-panel-only scale
     (--mi-font-scale, set from the "Info Panel Text" setting; default 1).
     The mi-* helpers and inline STY below use em, so they scale with this and
     ONLY this — independent of the app-wide --font-scale. */
  font-size: calc(var(--fs-standard) * var(--mi-font-scale, 1));
  line-height: 1.6;
  overflow-x: auto;
  border-radius: 6px;
  background: var(--input-bg);
  color: var(--mi-text);
}
.module-visual div { max-width: 100%; }
/* Font-only info-panel scope (the detail-panel overlay wraps getInfo bodies in
   this) — gives the same base + --mi-font-scale as .module-visual so em-based
   mi-* / STY text sizes correctly there too, without the card styling. */
.mi-info-scope { font-size: calc(var(--fs-standard) * var(--mi-font-scale, 1)); }
/* Flat "website" sections: a module can wrap each section body in a top-level
   .syn to neutralise the filled .entry.module-visual card — the .section-label
   headings + whitespace carry structure instead of nested boxes (synastry uses
   this). Other modules are unaffected. */
.entry.module-visual:has(> .syn) {
  background: transparent;
  border-left: none;
  border-radius: 0;
  padding: 2px 4px;
  margin-bottom: 6px;
}
/* Synastry flat layout — faint hair-line dividers between subsection groups
   (the _subhead headings). Theme-aware via var(--border). !important overrides
   the inline spacing from _subhead's STY base. The first subhead in a section
   sits directly under the .section-label, so it drops its own divider. */
.syn-subhead {
  border-top: 1px solid var(--border);
  margin-top: 16px !important;
  padding-top: 11px !important;
  /* Typography moved off the module's inline style so the skin owns it and it
     scales (em-relative to the .syn base, which Celestial ties to the slider). */
  font-size: 1em;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.5;
  font-weight: 600;
}
/* A muted, italic framing line under a subhead (provenance only). Was an inline
   font-size: 1em on the module; now skin-owned + em-relative. */
.syn-framing {
  font-size: 1em;
  opacity: 0.6;
  font-style: italic;
  margin: 0 0 6px;
}
.syn > .syn-subhead:first-child {
  border-top: none;
  margin-top: 2px !important;
  padding-top: 0 !important;
}
/* Synastry items — one SUBTLE box per datum (header sentence + its prose) for
   delineation. The section card is flattened by .syn, so this is a single box
   level, not box-within-box. */
.syn-item {
  border: 1px solid var(--border);
  border-radius: 6px;
  background: rgba(255,255,255,0.025);
  padding: 6px 9px;
  margin: 7px 0;
}
[data-theme="light"] .syn-item,
[data-theme="warm"] .syn-item { background: rgba(0,0,0,0.03); }
/* Synastry main section headings (e.g. "VEDIC COMPATIBILITY") — larger + in the
   theme highlight color so they clearly head their section above the flat items.
   Scoped to synastry only: the heading is the previous sibling of the
   .syn-flattened entry. Keeps the inherited uppercase + top-divider. */
.section-label:has(+ .entry.module-visual > .syn) {
  font-size: var(--fs-subtitle);
  font-weight: 700;
  color: var(--accent);
}
/* Synastry name / chart-reference highlighting. Colors MATCH each person's
   chart identity used by the biwheel / rose / header dots (modules/synastry.js
   ACCENT='#C86496' for A; '#6E82C8' for B) so a name reads in that person's
   color everywhere. Keep these in sync with those JS literals. Both bold. */
.syn-name { font-weight: 600; }
.syn-name-a { color: #C86496; }
.syn-name-b { color: #6E82C8; }
/* Light/warm themes: force readable text contrast.
   Inline styles from modules use light-on-dark colors (rgba(220,...)).
   These must be overridden with !important since inline styles win specificity.
   Accent-colored elements (.mi-accent) keep their color but get darkened via filter. */
[data-theme="light"] .module-visual span:not(.mi-accent):not(.mi-bar-value):not(.syn-name),
[data-theme="light"] .module-visual div:not(.mi-bar-fill):not(.mi-bar-track),
[data-theme="warm"] .module-visual span:not(.mi-accent):not(.mi-bar-value):not(.syn-name),
[data-theme="warm"] .module-visual div:not(.mi-bar-fill):not(.mi-bar-track) {
  color: var(--mi-text) !important;
}
/* Subtle backgrounds designed for dark themes (rgba(255,255,255,0.0x)) are
   invisible on light backgrounds. Override to dark-on-light equivalents. */
[data-theme="light"] .module-visual [style*="background:rgba(255"],
[data-theme="light"] .module-visual [style*="background: rgba(255"],
[data-theme="warm"] .module-visual [style*="background:rgba(255"],
[data-theme="warm"] .module-visual [style*="background: rgba(255"] {
  background: rgba(0,0,0,0.04) !important;
}

/* mi-* helper classes */
/* Sizes are em-relative to .module-visual so the "Info Panel Text" setting
   scales them all proportionally (ratios preserve the prior px design). */
.mi-line { margin: 2px 0; padding: 3px 6px; line-height: 1.6; font-size: 1em; color: var(--mi-text); }
.mi-accent { color: var(--c); font-weight: bold; }
/* Tappable symbol references (inline {{type:id}} tokens + auto-linked planet/sign
   names) → the shared entity modal. Subtle: a dotted underline on hover only. */
.mi-entity-link { cursor: pointer; }
.mi-entity-link:hover { text-decoration: underline dotted; text-underline-offset: 2px; }
.mi-entity-link:focus-visible { outline: 1px dotted currentColor; outline-offset: 2px; }

/* Correspondence strip — the thin chip carousel after an interpretation heading.
   Reuses the shared .day-visuals-* carousel chrome (scroll/drag/arrows) with a
   short chip in place of the 130px card. */
.mi-corr-strip { margin: 2px 0 8px; }
.mi-corr-strip .day-visuals-track { gap: 7px; align-items: center; }
.dv-corrchip { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 11px;
  background: var(--surface); border: 0.5px solid var(--border); border-radius: 8px;
  font-size: 12.5px; white-space: nowrap; flex: 0 0 auto; }
.dv-corrchip-ic { font-size: 14px; line-height: 1; }
.dv-corrchip-gl { font-size: 15px; line-height: 1; }
.dv-corrchip-img { height: 16px; width: auto; border-radius: 2px; display: block; }
.dv-corrchip--lead { background: var(--accent-border, rgba(139, 156, 255, 0.13)); border-color: var(--accent-border, rgba(139, 156, 255, 0.5)); font-weight: 500; }
.dv-corrchip--primary { border-color: var(--accent-border, rgba(139, 156, 255, 0.34)); }
.dv-corrchip--img { max-width: 280px; }
.dv-corrchip--img .dv-corrchip-lb { overflow: hidden; text-overflow: ellipsis; font-style: italic; opacity: 0.85; }
[data-theme="light"] .mi-accent,
[data-theme="warm"] .mi-accent { filter: brightness(0.55) saturate(1.4); }
.mi-bold { font-weight: bold; }
.mi-large { font-size: 1em; }
.mi-small { font-size: 1em; }
.mi-muted { opacity: 0.6; }
.mi-interp { opacity: 0.85; font-size: 1em; font-style: italic; line-height: 1.5; display: block; margin-top: 3px; color: var(--mi-text); }
/* Prose typography tiers (skin-owned; em-relative so the "Info Panel Text"
   setting scales them). Modules pick a tier via B.prose(text,{variant}) — never
   a px size. `default`/body needs no class. */
.mi-prose-caption { font-size: 1em; opacity: 0.75; }
.mi-prose-muted  { opacity: 0.6; }
.mi-prose-lead   { font-size: 1em; }
.mi-prose-label  { font-size: 1em; letter-spacing: 0.06em; text-transform: uppercase; opacity: 0.7; }

/* Declarative interactive blocks (image/button/choiceChips/cardGrid + action
   chips) — rendered by the Classic skin; behaviour via ui/info-render/interactions.js. */
.mi-image { margin: 6px 0; }
.mi-image img { max-width: 120px; width: 100%; height: auto; border-radius: 6px; display: block; }
.mi-image figcaption { font-size: 1em; opacity: 0.6; margin-top: 3px; }
.mi-btn { cursor: pointer; font: inherit; padding: 5px 12px; margin: 4px 6px 4px 0; border-radius: 6px;
  border: 1px solid var(--border, rgba(255,255,255,0.2)); background: rgba(255,255,255,0.06); color: var(--mi-text); }
.mi-btn:hover { background: rgba(255,255,255,0.12); }
.mi-btn--primary { background: #9F7AEA; border-color: transparent; color: #fff; }
.mi-btn.is-active { outline: 2px solid var(--accent, #d4af37); }
.mi-choices { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin: 5px 0; }
.mi-choices-label { font-size: 1em; opacity: 0.6; margin-right: 4px; }
.mi-choice { cursor: pointer; font: inherit; min-width: 26px; padding: 3px 8px; border-radius: 5px;
  border: 1px solid rgba(255,255,255,0.18); background: rgba(255,255,255,0.05); color: var(--mi-text); }
.mi-choice:hover { background: rgba(255,255,255,0.12); }
.mi-choice.is-active { background: var(--accent, #d4af37); color: #1a1a1a; border-color: transparent; }
.mi-chip--action { cursor: pointer; font: inherit; }
.mi-chip--action:hover { filter: brightness(1.3); }
.mi-cardgrid { margin: 6px 0; }
.mi-cardgrid-hint { font-size: 1em; opacity: 0.6; margin-bottom: 4px; }
.mi-cardgrid-title { font-size: 1em; text-transform: uppercase; letter-spacing: 0.06em; opacity: 0.6; margin: 9px 0 3px; }
.mi-cardgrid-row { display: flex; flex-wrap: wrap; gap: 4px; }
.mi-cardgrid-card { cursor: pointer; padding: 0; border: none; background: none; border-radius: 4px; line-height: 0; }
.mi-cardgrid-card img { width: 38px; height: auto; display: block; border-radius: 4px; transition: transform 0.12s; }
.mi-cardgrid-card:hover img { transform: scale(1.15); }

/* ── Section layout: peer-unit columns + readable measure ─────────────────────
   A section tagged layout:'grid' arranges its peer cards as responsive columns —
   1 col when narrow (two-panel), several when wide (single-panel). Mirrors the
   Celestial skin's cel-grid so both skins lay collections out the same way. */
.mi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 8px 14px; align-items: start; }
/* Meters are short (label + bar), so they pack 2-up at a much narrower width
   than prose cards. */
.mi-grid--meters { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 4px 14px; }
/* Content-aware: card runs carrying substantial interpretation prose (classified
   in skins/default.js by avg text length) use a much wider min-column so a
   paragraph never gets crushed into a ~160px sliver. They only split into 2+
   columns when the panel is genuinely wide, and stay single-column on phones
   (the ≤480px override below). Short readout cards keep the narrow .mi-grid. */
.mi-grid--prose { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 8px 20px; }
/* Hard single-column for substantial-prose runs on phones. */
@media (max-width: 480px) { .mi-grid--prose { grid-template-columns: 1fr; } }
.mi-grid > .mi-bordered { margin: 0; }   /* the grid gap owns the spacing */
/* Cards establish a BFC so a floated leading image is contained and margins
   don't collapse. */
.mi-bordered { display: flow-root; }
/* A leading image inside a card floats left; text sits beside it, then wraps
   below — a tidy unit instead of image-on-top + a full-width text block. */
.mi-bordered .mi-image { float: left; margin: 2px 10px 4px 0; }
.mi-bordered .mi-image img { max-width: 88px; }
/* Cap the line length of flowing prose so it stays readable in wide single-panel
   instead of running edge-to-edge. Harmless in narrow panels and inside grid
   columns (both are already narrower than the cap). */
.module-visual .entry-text, .mi-section .entry-text { max-width: 66ch; }
.mi-bordered { margin: 2px 0; padding: 3px 6px 3px 8px; line-height: 1.6; font-size: 1em; color: var(--mi-text); border-left: 3px solid var(--c); margin-bottom: 6px; }
.mi-bar-row { display: flex; align-items: center; gap: 6px; margin: 2px 0; }
.mi-bar-track { flex: 1; height: 6px; background: var(--mi-track); border-radius: 3px; overflow: hidden; }
.mi-bar-fill { height: 100%; background: var(--c); border-radius: 3px; opacity: 0.7; }
.mi-bar-value { color: var(--c); font-size: 1em; min-width: 18px; text-align: right; opacity: 0.8; }
/* Extra bottom gap so consecutive meters/bars breathe instead of stacking into
   a wall — one clear break before the next bar starts. */
.mi-pct-bar { margin: 3px 0 12px; }
.mi-pct-header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 2px; font-size: 1em; }
/* Second line under a meter header: the supporting detail, dropped below the
   "Name: … %" row instead of crammed onto it. */
.mi-pct-detail { opacity: 0.7; line-height: 1.4; margin: 0 0 5px; }
.mi-balance-bar { display: flex; height: 8px; margin-top: 4px; border-radius: 4px; overflow: hidden; }
.mi-balance-rest { flex: 1; background: var(--mi-track); }
/* Structured-block extras (used by migrated modules under the Classic skin). */
.mi-card-head { display: flex; align-items: center; gap: 6px; margin-bottom: 3px; }
.mi-chip { display: inline-block; font-size: 1em; padding: 1px 8px; margin: 1px 2px; border-radius: 999px; color: var(--c, var(--mi-text)); border: 1px solid var(--c, var(--mi-track)); }

/* ── Chat bar — full-width footer ─────────────────────────── */

.chat-bar {
  display: flex;
  gap: 6px;
  padding: 8px 16px;
  border-top: 1px solid var(--border);
  flex-shrink: 0;
  background: var(--bg);
  max-width: 100%;
}

.chat-input {
  flex: 1;
  background: var(--input-bg);
  border: 1px solid var(--border);
  border-radius: 20px;
  color: var(--text);
  padding: 8px 16px;
  font-size: var(--fs-heading);
  font-family: var(--font-body);
  outline: none;
  transition: border-color 0.15s;
}
.chat-input:focus { border-color: var(--accent-border); }
.chat-input::placeholder { color: var(--text-dim); }

.chat-send {
  width: 34px;
  height: 34px;
  border: none;
  border-radius: 50%;
  background: var(--accent-bg);
  color: var(--accent);
  font-size: var(--fs-lg);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background 0.15s;
}
.chat-send:hover { background: rgba(99,179,237,0.2); }


/* ── Chat tab — conversation log inside the info panel ────── */

.chat-tab {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 4px 8px;
  height: 100%;
  min-height: 0;
  /* Cap the chat to a readable, centred column. On a wide panel (desktop widescreen)
     it stops growing at --chat-measure and sits centred with margin either side; below
     that width (mobile vertical / narrow panels) it just fills the space. The max-width
     IS the "resolution threshold" — it only bites once the panel is wider than the column. */
  width: 100%;
  max-width: var(--chat-measure, 820px);
  margin-inline: auto;
}

.chat-tab-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 4px 10px;
  border-bottom: 1px solid var(--border);
}

.chat-tab-title {
  font-size: var(--fs-subtitle);
  font-weight: 600;
  color: var(--text);
  letter-spacing: 0.5px;
}

/* ── Personality picker (chat header; doubles as the title) ── */
.chat-personality { position: relative; }
.chat-personality-trigger {
  display: flex;
  align-items: center;
  gap: 7px;
  background: transparent;
  border: none;
  padding: 2px 4px;
  border-radius: 12px;
  cursor: pointer;
  font-family: var(--font-body);
  color: var(--text);
}
.chat-personality-trigger.is-single { cursor: default; }
.chat-personality-trigger:not(.is-single):hover { background: var(--surface-hover, rgba(255,255,255,0.05)); }
.chat-personality-name {
  font-size: var(--fs-subtitle);
  font-weight: 600;
  color: var(--text);
  letter-spacing: 0.5px;
}
.chat-personality-caret { font-size: 10px; color: var(--text-dim); }
.chat-personality-avatar {
  width: 22px; height: 22px; border-radius: 50%;
  flex-shrink: 0; object-fit: cover;
  border: 1px solid var(--border);
}
.chat-personality-avatar--glyph {
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700;
  color: var(--accent, #9db4ff);
  background: rgba(120, 140, 255, 0.12);
}

.chat-personality-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 40;
  min-width: 240px;
  max-width: 320px;
  background: var(--surface, #14152b);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
  padding: 5px;
}
.chat-personality-item {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  border-radius: 9px;
  padding: 8px 9px;
  cursor: pointer;
  font-family: var(--font-body);
}
.chat-personality-item:hover { background: var(--surface-hover, rgba(255,255,255,0.05)); }
.chat-personality-item.is-active { background: rgba(120, 140, 255, 0.12); }
.chat-personality-item-name {
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--text);
}
.chat-personality-item.is-active .chat-personality-item-name { color: var(--accent, #9db4ff); }
.chat-personality-item-desc {
  font-size: var(--fs-label);
  color: var(--text-dim);
  margin-top: 2px;
  line-height: 1.35;
}

.chat-tab-new-btn {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-size: var(--fs-label);
  padding: 4px 10px;
  border-radius: 12px;
  cursor: pointer;
  font-family: var(--font-body);
  transition: color 0.15s, border-color 0.15s;
}

.chat-tab-new-btn:hover {
  color: var(--accent);
  border-color: var(--accent-border);
}

.chat-tab-new-btn.is-active {
  color: var(--accent);
  border-color: var(--accent-border);
  background: rgba(99, 179, 237, 0.10);
}

/* ── Trace pane — collapsed-by-default behind-the-scenes view ─ */

.chat-trace-pane {
  margin-top: 10px;
  padding: 8px 10px;
  border: 1px dashed var(--border);
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.02);
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
  font-size: var(--fs-label);
  color: var(--text-dim);
}

.chat-trace-pane-header {
  font-weight: 600;
  color: var(--text);
  margin-bottom: 6px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-size: var(--fs-caption);
}

.chat-trace-section {
  margin: 4px 0;
}

.chat-trace-section > summary {
  cursor: pointer;
  padding: 3px 0;
  color: var(--text-dim);
  list-style: revert;        /* keep the disclosure triangle */
}

.chat-trace-section > summary:hover {
  color: var(--text);
}

.chat-trace-section[open] > summary {
  color: var(--text);
  margin-bottom: 4px;
}

.chat-trace-pre {
  margin: 0 0 6px 14px;
  padding: 6px 8px;
  background: rgba(0, 0, 0, 0.25);
  border-radius: 4px;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 360px;
  overflow: auto;
  font-size: var(--fs-label);
  line-height: 1.45;
  color: var(--text);
}

/* ── Token-info strip — balance / tier / last call cost ───── */

.token-strip {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 12px;
  font-size: var(--fs-label);
  color: var(--text-dim);
  border-bottom: 1px solid var(--border);
  margin-bottom: 4px;
  background: rgba(255, 255, 255, 0.02);
}

.token-strip-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.token-strip-row--header {
  justify-content: space-between;
  align-items: baseline;
}
.token-strip-row--header .token-strip-balance-value {
  font-size: var(--fs-xl);
  font-weight: 600;
  color: var(--text);
}

.token-strip-row--secondary {
  align-items: center;
  margin-top: 2px;
}
.token-strip-row--secondary .token-strip-tier-value {
  margin-right: auto;
}

.token-strip-label {
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--text-dim);
  font-size: var(--fs-caption);
}

.token-strip-balance-value,
.token-strip-tier-value,
.token-strip-last-value,
.token-strip-monthly-value {
  color: var(--text);
  font-weight: 500;
}

.token-strip-balance-value.token-strip-balance-low {
  color: #ff9b6a;
}

/* Usage bar — fills proportionally to balance / monthly grant. */
.token-strip-usage-wrap {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.token-strip-usage {
  position: relative;
  height: 6px;
  width: 100%;
  background: rgba(255, 255, 255, 0.08);
  border-radius: 3px;
  overflow: hidden;
}
.token-strip-usage__fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, #5fd17c, #8bd86a);
  transition: width 0.4s ease, background 0.4s ease;
}
.token-strip-usage[data-level='warn'] .token-strip-usage__fill {
  background: linear-gradient(90deg, #e8a64a, #f0b85f);
}
.token-strip-usage[data-level='crit'] .token-strip-usage__fill {
  background: linear-gradient(90deg, #d5604a, #e87968);
}
.token-strip-usage[data-level='unknown'] .token-strip-usage__fill {
  background: rgba(255, 255, 255, 0.12);
}
.token-strip-usage-meta {
  display: flex;
  justify-content: space-between;
  font-size: var(--fs-caption);
  color: var(--text-dim);
}
.token-strip-usage__pct {
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  color: var(--text-muted, var(--text-dim));
}

.token-strip-buy-btn {
  margin-left: auto;
  padding: 3px 10px;
  font-size: var(--fs-caption);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--text);
  background: rgba(99, 179, 237, 0.16);
  border: 1px solid rgba(99, 179, 237, 0.36);
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.18s;
}
.token-strip-buy-btn:hover {
  background: rgba(99, 179, 237, 0.28);
}


/* ── Conversation library — slide-in drawer ───────────────── */

.chat-library-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  z-index: 1000;
  display: flex;
  justify-content: flex-end;
  opacity: 0;
  transition: opacity 0.2s;
}

.chat-library-overlay.chat-library-open {
  opacity: 1;
}

.chat-library-drawer {
  width: 360px;
  max-width: 90vw;
  background: var(--bg, #1a1a1a);
  border-left: 1px solid var(--border, #333);
  display: flex;
  flex-direction: column;
  height: 100vh;
  transform: translateX(100%);
  transition: transform 0.2s ease-out;
  box-shadow: -4px 0 24px rgba(0, 0, 0, 0.4);
}

.chat-library-overlay.chat-library-open .chat-library-drawer {
  transform: translateX(0);
}

.chat-library-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
}

.chat-library-title {
  font-size: var(--fs-title);
  font-weight: 600;
  color: var(--text);
}

/* Opt-in "save chats to my account" toggle row at the top of the History drawer. */
.chat-library-sync {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-label);
  color: var(--text-dim);
  cursor: pointer;
}
.chat-library-sync .chat-library-sync-checkbox { cursor: pointer; margin: 0; }

.chat-library-close {
  background: transparent;
  border: none;
  color: var(--text-dim);
  font-size: var(--fs-xl);
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 4px;
}

.chat-library-close:hover {
  color: var(--text);
  background: var(--input-bg);
}

.chat-library-list {
  flex: 1;
  overflow-y: auto;
  padding: 8px;
}

.chat-library-empty {
  padding: 24px 12px;
  text-align: center;
  color: var(--text-dim);
  font-style: italic;
  font-size: var(--fs-heading);
}

.chat-library-item {
  display: flex;
  align-items: stretch;
  border: 1px solid var(--border);
  border-radius: 6px;
  margin-bottom: 8px;
  background: var(--input-bg, transparent);
  transition: border-color 0.15s;
}

.chat-library-item:hover {
  border-color: var(--accent-border);
}

.chat-library-item-main {
  flex: 1;
  padding: 10px 12px;
  cursor: pointer;
  min-width: 0;          /* allow text truncation */
}

.chat-library-item-meta {
  font-size: var(--fs-label);
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 4px;
}

.chat-library-item-preview {
  font-size: var(--fs-heading);
  color: var(--text);
  line-height: 1.4;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  word-break: break-word;
}

.chat-library-item-delete {
  background: transparent;
  border: none;
  border-left: 1px solid var(--border);
  color: var(--text-dim);
  font-size: var(--fs-subtitle);
  padding: 0 14px;
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
}

.chat-library-item-delete:hover {
  color: #ff8866;
  background: rgba(255, 130, 100, 0.1);
}


/* ── Export modal — format + template picker ─────────────── */

.export-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 24px;
}

.export-modal-card {
  background: var(--bg, #1a1a1a);
  border: 1px solid var(--border, #333);
  border-radius: 10px;
  padding: 20px 22px;
  max-width: 380px;
  width: 100%;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
  font-family: var(--font-body);
  color: var(--text);
}

.export-modal-title {
  font-size: var(--fs-lg);
  font-weight: 600;
  margin-bottom: 18px;
  letter-spacing: 0.3px;
}

.export-modal-group {
  margin-bottom: 16px;
}

.export-modal-label {
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--text-dim);
  margin-bottom: 8px;
}

.export-modal-select {
  width: 100%;
  padding: 7px 10px;
  background: var(--input-bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-family: var(--font-body);
  font-size: var(--fs-heading);
}

.export-modal-radio {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 4px;
  font-size: var(--fs-heading);
  cursor: pointer;
}

.export-modal-radio input {
  margin: 0;
}

.export-modal-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  margin-top: 8px;
}


/* ── Ring action buttons — compass (guide) + report ───────── */

.ring-action-buttons {
  position: absolute;
  top: 6px;
  right: 8px;
  display: flex;
  gap: 4px;
  z-index: 5;
}

.ring-action-btn {
  background: transparent;
  border: 1px solid var(--border, #333);
  color: var(--text-dim);
  font-size: var(--fs-subtitle);
  width: 28px;
  height: 28px;
  border-radius: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}

.ring-action-btn:hover {
  color: var(--text);
  border-color: var(--accent-border);
  background: var(--input-bg);
}

.ring-action-guide:hover { color: var(--accent, #63b3ed); }
.ring-action-report:hover { color: #c8a96b; }


/* ── Guide mode — info-panel-as-narration surface ────────── */

.guide-active { position: relative; }

.guide-narration {
  font-size: var(--fs-subtitle);
  line-height: 1.55;
  color: var(--text);
  padding: 14px 4px 18px;
  white-space: pre-wrap;
  border-bottom: 1px solid var(--border);
  margin-bottom: 12px;
}

.guide-narration:empty::after {
  content: '·';
  color: var(--accent, #63b3ed);
  animation: guide-pulse 1.2s infinite;
}

@keyframes guide-pulse {
  0%, 100% { opacity: 0.3; }
  50%      { opacity: 1; }
}

.guide-section-reveal {
  border-left: 2px solid var(--accent-border, rgba(99,179,237,0.4));
  padding: 4px 0 4px 12px;
  margin: 12px 0 18px;
}

.guide-controls {
  display: flex;
  gap: 8px;
  justify-content: space-between;
  align-items: center;
  padding: 8px 4px;
  border-top: 1px solid var(--border);
  margin-top: 12px;
}

.guide-control-btn {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-dim);
  font-size: var(--fs-body);
  padding: 5px 12px;
  border-radius: 14px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background-color 0.15s;
}

.guide-control-btn:hover {
  color: var(--text);
  border-color: var(--accent-border);
}

.guide-control-btn.is-active {
  color: var(--text);
  border-color: var(--accent-border);
  background: rgba(99, 179, 237, 0.08);
}

/* Concise / Elaborated segmented toggle — left side of the controls
   strip, paired with the Exit button on the right. */
.guide-tier-pill {
  display: flex;
  gap: 4px;
}


.chat-tab-log {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 4px 2px;
}

.chat-tab-empty {
  text-align: center;
  color: var(--text-dim);
  font-style: italic;
  padding: 32px 16px;
}

.chat-turn {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.chat-turn-role {
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: var(--text-dim);
  font-weight: 600;
}

.chat-turn-body {
  font-size: var(--fs-subtitle);
  line-height: 1.55;
  color: var(--text);
  word-wrap: break-word;
}

/* User turns are plain text — preserve their line breaks */
.chat-turn-user .chat-turn-body {
  color: var(--text);
  padding-left: 12px;
  border-left: 2px solid var(--accent-border);
  white-space: pre-wrap;
}

/* Assistant turns may be plain text (during streaming) or markdown */
.chat-turn-assistant .chat-turn-body {
  color: var(--text);
  white-space: pre-wrap;          /* preserved during streaming */
}

/* Thinking indicator — visible between request-fired and the first
   stream chunk. Pulsing dots make it obvious the request is in flight
   rather than silently hung. Shared between chat turn and report viewer. */
.chat-turn-thinking {
  display: inline-block;
  letter-spacing: 0.2em;
  font-size: 1.1em;
  color: var(--text-muted, var(--text-dim, #888));
  animation: chat-turn-thinking-pulse 1.2s ease-in-out infinite;
}
@keyframes chat-turn-thinking-pulse {
  0%, 100% { opacity: 0.35; }
  50%      { opacity: 1; }
}
/* Mid-reply "still thinking" indicator — shown when the oracle pauses AFTER it
   has already started answering (a tool lookup, or continuing past a length cap)
   so the reply never looks stalled during the gap. Reuses the pulse animation but
   reads as a normal status sentence on its own line beneath the text so far,
   rather than the wide-tracked glyph styling of the pre-answer indicator. */
.chat-turn-thinking--resume {
  display: block;
  margin-top: 0.6em;
  letter-spacing: normal;
  font-size: 0.95em;
  font-style: italic;
}
.reports-viewer-thinking {
  padding: 24px 12px;
  text-align: center;
}
.reports-viewer-thinking__label {
  color: var(--text-muted, var(--text-dim, #888));
  font-size: 0.85em;
  margin: 8px 0 0;
}

/* Sign-out banner — surfaced when chat has turns but no session id,
   i.e. signed-out users whose conversation will be lost on reload. */
.chat-tab-signedout-banner {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  margin: 0 12px 8px;
  background: rgba(255, 200, 60, 0.08);
  border: 1px solid rgba(255, 200, 60, 0.25);
  border-radius: 6px;
  color: var(--text-muted, var(--text-dim, #b8b09f));
  font-size: 0.85em;
}
.chat-tab-signedout-banner__icon {
  color: rgba(255, 200, 60, 0.9);
  font-weight: 600;
}

/* ── Shared "prose" styles for assistant turns + report viewer ──
   Applies to LLM chat output AND offline/LLM report viewer bodies.
   Tuned for readability: generous line-height, paragraph rhythm,
   coloured heading hierarchy with accent rules, entity colours
   (planet / sign / house mentions auto-highlighted by the markdown
   renderer's linkify pass). */

.chat-turn-assistant .chat-turn-body,
.reports-viewer-body {
  font-size: var(--fs-subtitle);
  line-height: 1.65;
  color: var(--text);
  word-wrap: break-word;
}

.chat-turn-assistant .chat-turn-body :is(p, ul, ol, blockquote, pre, table) {
  white-space: normal;
  margin: 0.85em 0;
}
.reports-viewer-body :is(p, ul, ol, blockquote, pre, table) {
  margin: 0.95em 0;
}

/* Inline report visuals (a rendered module figure embedded via request_visual). */
.rp-visual {
  margin: 1.4em 0;
  padding: 0.9em 1em;
  border: 1px solid var(--border, rgba(255,255,255,0.12));
  border-radius: 10px;
  background: rgba(255,255,255,0.03);
}
.rp-visual-caption {
  margin-top: 0.6em;
  font-size: var(--fs-caption, 0.85em);
  color: var(--text-secondary, #a8a39b);
  font-style: italic;
  text-align: center;
}
/* Chart-figure SVGs render responsively; scoped to figures so module-readout
   inline SVGs keep their intrinsic size. Multiple SVGs (figure + optional key)
   stack centred. */
.rp-figure svg {
  width: 100%;
  height: auto;
  max-width: 520px;
  display: block;
  margin: 0.4em auto;
}
.reports-viewer-streaming {
  white-space: pre-wrap;
}
.rp-compose-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1em;
}

.chat-turn-assistant .chat-turn-body :first-child,
.reports-viewer-body :first-child { margin-top: 0; }
.chat-turn-assistant .chat-turn-body :last-child,
.reports-viewer-body  :last-child { margin-bottom: 0; }

/* Heading hierarchy — coloured, with accent rule on the larger levels */
.chat-turn-assistant .chat-turn-body .md-heading,
.reports-viewer-body .md-heading {
  font-weight: 600;
  color: var(--text);
  line-height: 1.3;
  letter-spacing: 0.005em;
}

/* h1 — only used as report title; chat usually starts at h2 */
.chat-turn-assistant .chat-turn-body .md-heading--1,
.reports-viewer-body .md-heading--1 {
  font-size: var(--fs-2xl);
  color: var(--gold-light, #f5d28b);
  margin: 0 0 0.5em;
  padding-bottom: 0.3em;
  border-bottom: 1px solid var(--gold-dim, rgba(212,175,55,0.25));
}

/* h2 — section heading. Coloured accent + extra top margin to break rhythm. */
.chat-turn-assistant .chat-turn-body .md-heading--2,
.reports-viewer-body .md-heading--2 {
  font-size: var(--fs-lg);
  color: var(--accent, #63b3ed);
  margin: 1.6em 0 0.5em;
  padding-bottom: 0.2em;
  border-bottom: 1px solid var(--accent-dim, rgba(99,179,237,0.18));
}

/* h3 — sub-section. No rule, but coloured + extra top margin. */
.chat-turn-assistant .chat-turn-body .md-heading--3,
.reports-viewer-body .md-heading--3 {
  font-size: var(--fs-subtitle);
  color: var(--violet, #a380e8);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
  margin: 1.3em 0 0.4em;
}

/* h4 and below — denser sub-headings */
.chat-turn-assistant .chat-turn-body .md-heading--4,
.reports-viewer-body .md-heading--4 {
  font-size: var(--fs-heading);
  color: var(--text);
  margin: 1.1em 0 0.3em;
}

.chat-turn-assistant .chat-turn-body code,
.reports-viewer-body code,
.chat-turn-assistant .chat-turn-body .md-inline-code,
.reports-viewer-body .md-inline-code {
  font-family: var(--font-mono, monospace);
  font-size: var(--fs-body);
  background: var(--input-bg, rgba(255,255,255,0.06));
  padding: 1px 5px;
  border-radius: 3px;
}

.chat-turn-assistant .chat-turn-body pre,
.reports-viewer-body pre {
  background: var(--input-bg, rgba(255,255,255,0.06));
  padding: 10px 12px;
  border-radius: 5px;
  overflow-x: auto;
  font-size: var(--fs-body);
  line-height: 1.5;
}

.chat-turn-assistant .chat-turn-body ul,
.chat-turn-assistant .chat-turn-body ol,
.reports-viewer-body ul,
.reports-viewer-body ol {
  padding-left: 22px;
}

.chat-turn-assistant .chat-turn-body li,
.reports-viewer-body li {
  margin: 0.35em 0;
}

.chat-turn-assistant .chat-turn-body blockquote,
.reports-viewer-body blockquote {
  border-left: 3px solid var(--accent-dim, rgba(99,179,237,0.4));
  padding: 0.4em 0 0.4em 14px;
  color: var(--text-muted);
  font-style: italic;
  background: rgba(99,179,237,0.04);
  border-radius: 0 4px 4px 0;
}

.chat-turn-assistant .chat-turn-body hr,
.reports-viewer-body hr {
  border: none;
  border-top: 1px solid var(--border);
  margin: 1.6em 0;
}

/* ── Entity colours — auto-applied by markdown-renderer.js linkify ──
   The colours are tuned for dark backgrounds; signs use element-family
   tints (fire = warm, earth = ochre, air = cool blue, water = violet).
   Planets follow common Western planetary symbolism. */

.md-entity {
  font-weight: 600;
  letter-spacing: 0.01em;
}

/* Planets */
.md-entity--planet[data-entity="sun"]      { color: #ffd166; }
.md-entity--planet[data-entity="moon"]     { color: #e6e6e6; }
.md-entity--planet[data-entity="mars"]     { color: #ef6c5b; }
.md-entity--planet[data-entity="mercury"]  { color: #7ed3a8; }
.md-entity--planet[data-entity="jupiter"]  { color: #f5a93a; }
.md-entity--planet[data-entity="venus"]    { color: #e9aab5; }
.md-entity--planet[data-entity="saturn"]   { color: #7895c1; }
.md-entity--planet[data-entity="rahu"]     { color: #888aaf; }
.md-entity--planet[data-entity="ketu"]     { color: #8b8076; }
.md-entity--planet[data-entity="uranus"]   { color: #6dd0c5; }
.md-entity--planet[data-entity="neptune"]  { color: #6bb4d8; }
.md-entity--planet[data-entity="pluto"]    { color: #8a6b9c; }
.md-entity--planet[data-entity="chiron"]   { color: #c0a890; }

/* Signs — element-family tints */
.md-entity--sign[data-entity="aries"],
.md-entity--sign[data-entity="leo"],
.md-entity--sign[data-entity="sagittarius"]  { color: #ef8a5a; }   /* fire */
.md-entity--sign[data-entity="taurus"],
.md-entity--sign[data-entity="virgo"],
.md-entity--sign[data-entity="capricorn"]    { color: #b8956a; }   /* earth */
.md-entity--sign[data-entity="gemini"],
.md-entity--sign[data-entity="libra"],
.md-entity--sign[data-entity="aquarius"]     { color: #7fb6db; }   /* air */
.md-entity--sign[data-entity="cancer"],
.md-entity--sign[data-entity="scorpio"],
.md-entity--sign[data-entity="pisces"]       { color: #a98fd2; }   /* water */

/* Houses — neutral gold accent (vs sign colours) */
.md-entity--house { color: #d6b988; }

/* Unified term pass (ui/oracle/term-decorate.js): colour stays from the rules
   above; these add the interactive affordance when a term is tap-to-modal. */
.term--interactive { cursor: pointer; }
.term--interactive:hover { text-decoration: underline dotted; text-underline-offset: 2px; }
.term--interactive:focus-visible { outline: 1px dotted currentColor; outline-offset: 2px; }

/* Placement mark (◉ after "Planet in Sign/Nakshatra/House"): tinted to the planet's
   ink, small but with a finger-sized hit area; no underline on hover. */
.term--placement {
  display: inline-block; line-height: 1; font-size: 0.74em; vertical-align: 0.06em;
  margin-left: 1px; padding: 0 3px; opacity: 0.9; cursor: pointer;
}
.term--placement:hover { text-decoration: none; opacity: 1; }
.term--placement:focus-visible { outline: 1px dotted currentColor; outline-offset: 2px; }
@media (pointer: coarse) { .term--placement { padding: 5px 7px; } }


/* ── Confirmation modal — expensive-request approval ───────── */

.confirm-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 24px;
}

.confirm-modal-card {
  background: var(--bg, #1a1a1a);
  border: 1px solid var(--border, #333);
  border-radius: 10px;
  padding: 20px 22px;
  max-width: 420px;
  width: 100%;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
  font-family: var(--font-body);
  color: var(--text);
}

.confirm-modal-title {
  font-size: var(--fs-lg);
  font-weight: 600;
  margin-bottom: 14px;
  letter-spacing: 0.3px;
}

.confirm-modal-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: var(--fs-heading);
  margin-bottom: 12px;
}

.confirm-modal-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
}

.confirm-modal-label {
  color: var(--text-dim);
  font-size: var(--fs-body);
  text-transform: uppercase;
  letter-spacing: 0.8px;
}

.confirm-modal-value {
  color: var(--text);
  text-align: right;
}

.confirm-modal-value-cost {
  font-weight: 600;
  color: var(--accent, #63b3ed);
}

.confirm-modal-breakdown {
  margin-top: 6px;
  font-size: var(--fs-body);
  color: var(--text-dim);
}

.confirm-modal-breakdown summary {
  cursor: pointer;
  user-select: none;
  padding: 4px 0;
}

.confirm-modal-breakdown-line {
  padding: 2px 0 2px 14px;
}

.confirm-modal-note {
  font-size: var(--fs-label);
  color: var(--text-dim);
  font-style: italic;
  margin: 10px 0 16px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

.confirm-modal-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
}

.confirm-modal-btn {
  padding: 8px 18px;
  border-radius: 6px;
  font-size: var(--fs-heading);
  font-family: var(--font-body);
  border: 1px solid var(--border);
  background: var(--input-bg, #2a2a2a);
  color: var(--text);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}

.confirm-modal-btn:hover {
  border-color: var(--accent-border);
}

.confirm-modal-btn-proceed {
  background: var(--accent-bg, rgba(99, 179, 237, 0.18));
  color: var(--accent, #63b3ed);
  border-color: var(--accent-border, rgba(99, 179, 237, 0.4));
}

.confirm-modal-btn-proceed:hover {
  background: rgba(99, 179, 237, 0.28);
}

.confirm-modal-btn-cancel:focus,
.confirm-modal-btn-proceed:focus {
  outline: 2px solid var(--accent-border);
  outline-offset: 2px;
}


/* ── Settings panel ───────────────────────────────────────── */

.settings-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 500;
  /* No background or blur — keep the page visible while styling */
  pointer-events: none;
}
.settings-overlay.open { display: flex; align-items: flex-start; justify-content: flex-end; padding: 52px 8px 8px; }
.settings-overlay .settings-card { pointer-events: auto; }

.settings-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 20px 24px;
  width: 360px;
  max-width: 92vw;
  max-height: 85vh;
  overflow-y: auto;
  box-shadow: 0 12px 48px var(--shadow);
  scrollbar-width: thin;
  scrollbar-color: rgba(128,128,128,0.2) transparent;
}

.settings-title {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  color: var(--text);
  letter-spacing: 1px;
  padding-bottom: 12px;
  margin: -20px -24px 12px;
  padding: 16px 24px 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: sticky;
  top: -20px;
  background: var(--surface);
  z-index: 1;
  border-bottom: 1px solid var(--border);
  border-radius: 12px 12px 0 0;
}

.settings-close {
  width: 28px; height: 28px;
  border: none; border-radius: 50%;
  background: transparent;
  color: var(--text-dim);
  font-size: var(--fs-lg); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.settings-close:hover { background: var(--input-bg); color: var(--text); }

.settings-tabs {
  display: flex;
  gap: 2px;
  margin: 0 -24px 12px;
  padding: 0 16px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  overflow-x: auto;
  scrollbar-width: thin;
  position: sticky;
  top: 44px;
  z-index: 1;
}
.settings-tab {
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  color: var(--text-muted);
  font-size: var(--fs-caption);
  font-weight: 600;
  padding: 8px 10px;
  cursor: pointer;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  white-space: nowrap;
  transition: color 0.12s, border-color 0.12s;
  font-family: var(--font-body);
}
.settings-tab:hover { color: var(--text); }
.settings-tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

.settings-group {
  margin-bottom: 16px;
}

.settings-group-label {
  font-size: var(--fs-micro);
  font-weight: 600;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.8px;
  margin-bottom: 8px;
}

.settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 6px;
}

.settings-label {
  font-size: var(--fs-body);
  color: var(--text-muted);
  flex: 1;
}

.settings-toggle-group {
  display: flex;
  gap: 1px;
  background: var(--input-bg);
  border-radius: 6px;
  padding: 2px;
}

.settings-toggle {
  padding: 3px 10px;
  border: none;
  border-radius: 4px;
  background: transparent;
  color: var(--text-dim);
  font-size: var(--fs-label);
  font-family: var(--font-body);
  cursor: pointer;
  transition: all 0.12s;
}
.settings-toggle:hover { color: var(--text-muted); }
.settings-toggle.active { background: var(--accent-bg); color: var(--accent); }

/* Dropdown variant for long option lists (themes, skins) — avoids the button-row
   overflow that pushed extra themes off the edge of the settings panel. */
.settings-select {
  max-width: 100%;
  background: var(--input-bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 3px 8px;
  font-size: var(--fs-label);
  font-family: var(--font-body);
  cursor: pointer;
}

/* Collapsed "Advanced" disclosure for power-user / editor-redundant settings. */
.settings-advanced { margin-top: 10px; border-top: 1px solid var(--border); padding-top: 6px; }
.settings-advanced > summary {
  cursor: pointer; list-style: none; user-select: none;
  font-size: var(--fs-label); letter-spacing: 1px; text-transform: uppercase;
  color: var(--text-dim); padding: 4px 0;
}
.settings-advanced > summary::-webkit-details-marker { display: none; }
.settings-advanced > summary::before { content: '\25B8  '; }
.settings-advanced[open] > summary::before { content: '\25BE  '; }
.settings-advanced > summary:hover { color: var(--text-muted); }

.settings-slider {
  width: 100px;
  accent-color: var(--accent);
  cursor: pointer;
}

.settings-slider-val {
  font-size: var(--fs-caption);
  color: var(--text-dim);
  width: 30px;
  text-align: right;
}

.settings-color-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.settings-color-swatch {
  width: 28px; height: 28px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
  transition: all 0.12s;
}
.settings-color-swatch:hover { transform: scale(1.15); }
.settings-color-swatch.active { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-bg); }

.settings-color-picker {
  width: 40px;
  height: 28px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: transparent;
  cursor: pointer;
  padding: 1px;
}
.settings-color-picker::-webkit-color-swatch-wrapper { padding: 0; }
.settings-color-picker::-webkit-color-swatch { border: none; border-radius: 4px; }

/* ── Oracle app info-panel output (ai-* classes) ─────────── */

.ai-header { display: flex; align-items: center; gap: 10px; padding: 10px 0; margin-bottom: 8px; border-bottom: 1px solid var(--border); }
.ai-header-icon { font-size: var(--fs-2xl); flex-shrink: 0; }
.ai-header-title { font-size: var(--fs-subtitle); font-weight: 600; color: var(--accent); letter-spacing: 0.02em; }
.ai-header-sub { font-size: var(--fs-label); color: var(--text-muted); margin-top: 1px; }
.ai-card { background: var(--input-bg); border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; margin-bottom: 8px; }
.ai-card-title { font-size: var(--fs-body); font-weight: 600; color: var(--text); margin-bottom: 4px; display: flex; align-items: center; gap: 6px; }
.ai-card-label { font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); margin-bottom: 4px; }
.ai-card-body { font-size: var(--fs-body); line-height: 1.7; color: var(--text); }
.ai-card-body p { margin: 4px 0; }
.ai-accent {
  padding-left: 10px;
  margin: 16px 0;
  border-left: 3px solid transparent;
  transition: opacity 0.18s ease, border-left-color 0.18s ease, background 0.18s ease;
}
.ai-accent-title { font-size: var(--fs-body); font-weight: 600; color: var(--accent); margin-bottom: 4px; }
.ai-accent-body { font-size: var(--fs-body); line-height: 1.7; color: var(--text); }

/* Bidirectional highlight (astromap reading ↔ map). When any block is
   highlighted via hover or click, the others fade back so the focal
   block reads clearly. The active block gets a coloured left edge using
   the per-block --ai-accent-color custom property. */
.ai-accent.acg-dim { opacity: 0.28; }
.ai-accent.acg-active {
  opacity: 1;
  border-left-color: var(--ai-accent-color, var(--accent));
  background: rgba(255, 255, 255, 0.03);
}
.ai-stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 6px; margin: 8px 0; }
.ai-stat { background: var(--input-bg); border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px; text-align: center; }
.ai-stat-label { font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); margin-bottom: 3px; }
.ai-stat-value { font-size: var(--fs-heading); font-weight: 600; color: var(--accent); }
.ai-tags { display: flex; flex-wrap: wrap; gap: 4px; margin: 6px 0; }
.ai-tag { font-size: var(--fs-caption); padding: 2px 8px; border-radius: 10px; background: var(--accent-bg); border: 1px solid var(--accent-border); color: var(--accent); }
.ai-prose { font-size: var(--fs-body); line-height: 1.75; color: var(--text); margin: 12px 0; }
.ai-divider { height: 1px; background: var(--border); margin: 18px 0; }
.ai-section-title { font-size: var(--fs-label); text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); margin: 12px 0 6px; padding-bottom: 4px; border-bottom: 1px solid var(--border); }
.ai-row { display: flex; gap: 10px; align-items: flex-start; margin: 8px 0; padding: 10px; background: var(--input-bg); border: 1px solid var(--border); border-radius: 10px; }
.ai-row-thumb { width: 50px; flex-shrink: 0; border-radius: 4px; overflow: hidden; }
.ai-row-thumb img { width: 100%; height: auto; display: block; }
.ai-row-body { flex: 1; min-width: 0; }
.ai-row-title { font-size: var(--fs-body); font-weight: 600; margin-bottom: 2px; color: var(--text); }
.ai-row-sub { font-size: var(--fs-caption); color: var(--text-muted); margin-bottom: 4px; }
.ai-row-text { font-size: var(--fs-label); line-height: 1.6; color: var(--text); }
.ai-meter { margin: 6px 0; }
.ai-meter-label { font-size: var(--fs-caption); color: var(--text-muted); margin-bottom: 3px; display: flex; justify-content: space-between; }
.ai-meter-bar { height: 4px; background: var(--mi-track); border-radius: 2px; overflow: hidden; }
.ai-meter-fill { height: 100%; background: linear-gradient(90deg, var(--accent), var(--accent-border)); border-radius: 2px; }
.ai-reading { padding: 12px; background: var(--input-bg); border: 1px solid var(--border); border-radius: 10px; margin-bottom: 8px; }

/* ── Account panel styles ────────────────────────────────── */

.account-section { padding: 10px; background: var(--input-bg); border-radius: 6px; margin-bottom: 10px; }
.account-section h4 { font-size: var(--fs-label); text-transform: uppercase; letter-spacing: 1px; color: var(--accent); margin-bottom: 10px; opacity: 0.8; }
.current-chart-info { display: flex; flex-direction: column; gap: 2px; margin-bottom: 8px; }
.chart-detail { font-size: var(--fs-body); color: var(--text); }
.chart-detail.dim { font-size: var(--fs-caption); color: var(--text-muted); }
.save-chart-row { display: flex; gap: 6px; align-items: center; }
.save-chart-input { flex: 1; background: var(--input-bg); border: 1px solid var(--border); border-radius: 4px; color: var(--text); padding: 5px 8px; font-size: var(--fs-label); font-family: var(--font-body); }
.save-chart-input:focus { outline: none; border-color: var(--accent); }
.save-chart-input.input-error { border-color: #e74c3c; }
.new-chart-form { display: flex; flex-direction: column; gap: 6px; }
.form-row { display: flex; flex-direction: column; gap: 2px; }
.form-row-half { flex-direction: row; gap: 8px; }
.form-row-half > div { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.form-label { font-size: var(--fs-caption); color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; }
.form-input { background: var(--input-bg); border: 1px solid var(--border); border-radius: 4px; padding: 5px 8px; color: var(--text); font-size: var(--fs-body); font-family: inherit; width: 100%; box-sizing: border-box; }
.form-input:focus { outline: none; border-color: var(--accent); }
.form-actions { flex-direction: row; gap: 8px; margin-top: 4px; }
.city-results { position: absolute; top: 100%; left: 0; right: 0; z-index: 200; background: var(--surface); border: 1px solid var(--accent-border); border-radius: 4px; max-height: 200px; overflow-y: auto; box-shadow: 0 4px 12px var(--shadow); }
.city-result-item { display: flex; justify-content: space-between; align-items: center; padding: 6px 8px; cursor: pointer; font-size: var(--fs-label); border-bottom: 1px solid var(--border); }
.city-result-item:hover { background: var(--surface-hover); }
.city-result-item:last-child { border-bottom: none; }
.city-result-name { font-weight: 600; color: var(--text); }
.city-result-country { opacity: 0.5; font-size: var(--fs-caption); color: var(--text-muted); }
.saved-charts-section { overflow-y: auto; max-height: 300px; }
.saved-charts-list { display: flex; flex-direction: column; gap: 4px; }
.saved-chart-item { display: flex; align-items: center; justify-content: space-between; padding: 6px 8px; background: var(--input-bg); border-radius: 4px; border-left: 2px solid var(--border); transition: background 0.15s, border-color 0.15s; }
.saved-chart-item:hover { background: var(--surface-hover); border-left-color: var(--accent); }
.saved-chart-info { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.saved-chart-name { font-size: var(--fs-body); color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.saved-chart-detail { font-size: var(--fs-caption); color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.saved-chart-actions { display: flex; gap: 4px; flex-shrink: 0; margin-left: 6px; }
.btn-sm { padding: 3px 8px; font-size: var(--fs-caption); border-radius: 3px; cursor: pointer; font-family: var(--font-body); }
.btn-primary { background: var(--accent-bg); border: 1px solid var(--accent-border); color: var(--accent); }
.btn-primary:hover { background: var(--accent-border); }
.btn-secondary { background: var(--input-bg); border: 1px solid var(--border); color: var(--text-muted); }
.btn-secondary:hover { background: var(--surface-hover); }
.btn-load { background: var(--accent-bg); border: 1px solid var(--accent-border); color: var(--accent); }
.btn-load:hover { background: var(--accent-border); }
.btn-delete { background: rgba(231,76,60,0.1); border: 1px solid rgba(231,76,60,0.3); color: #e74c3c; font-size: var(--fs-subtitle); line-height: 1; padding: 2px 6px; }
.btn-delete:hover { background: rgba(231,76,60,0.25); }
.empty-state { font-size: var(--fs-label); color: var(--text-muted); text-align: center; padding: 12px 0; }
.account-login-compact { display: flex; align-items: center; gap: 8px; padding: 4px 0; }
.current-location-status { font-size: var(--fs-label); color: var(--text-muted); margin-top: 6px; }
.section-hint { font-size: var(--fs-label); color: var(--text-muted); }

/* ── Compact mode ────────────────────────────────────────── */

/* Compact mode: collapse chart-meta to a single line so the date stays
   visible without forcing the header to expand. */
.compact .app-header { height: 36px; }
.compact .nav-mode-toggle { font-size: var(--fs-caption); padding: 3px 9px; letter-spacing: 2px; }
.compact .chart-meta { flex-direction: row; gap: 8px; align-items: baseline; }
.compact .chart-meta-date { font-size: var(--fs-heading); letter-spacing: 0.3px; }
.compact .chart-meta-sub { font-size: var(--fs-caption); }
.compact .dept-btn { padding: 3px 4px; min-width: 36px; }
.compact .dept-btn .dept-icon { font-size: var(--fs-subtitle); }
.compact .dept-btn span:not(.dept-icon):not(.dept-signal) { display: none; }
/* Nav icons keep their 42px base in .compact mode too — calendar match. */
.compact .text-content { padding: 10px 12px; }
.compact .entry { padding: 6px 10px; margin-bottom: 6px; }
.compact { --fs-title: var(--fs-standard); --fs-body: var(--fs-standard); }
.compact .section-label { margin: 10px 0 4px; }
.compact .chat-bar { padding: 6px 10px; }
.compact .chat-input { padding: 6px 12px; font-size: var(--fs-body); }

/* ── Responsive — narrow desktop ──────────────────────────── */

@media (max-width: 1100px) {
  .chart-meta { max-width: 320px; text-overflow: ellipsis; overflow: hidden; }
  /* Dept nav: tighter spacing, labels stay visible. Row scrolls
     horizontally if the 12 buttons don't fit at this width. */
  .dept-btn { min-width: 36px; padding: 4px 4px; font-size: 7px; }
  /* Navigation icons (.dock-item, .ring-nav-item, .chart-corner-btn) keep
     their 42px base size so they all visually match the calendar button.
     If the viewport is too narrow to fit the row, .header-right wraps. */
  .ring-nav { padding: 3px 1px; }
}

/* ── Responsive — short viewport ─────────────────────────── */

@media (max-height: 700px) {
  /* Short viewport: single-line date so header stays at 36px without
     hiding the chart's title. */
  .app-header { height: 36px; }
  .chart-meta { flex-direction: row; gap: 8px; align-items: baseline; }
  .chart-meta-date { font-size: var(--fs-heading); letter-spacing: 0.3px; }
  .chart-meta-sub { font-size: var(--fs-caption); }
  .dept-nav { padding: 2px 6px; }
  .dept-btn { padding: 3px 3px; }
  .dept-btn .dept-icon { font-size: var(--fs-subtitle); }
  .breadcrumb { padding: 2px 8px; }
  .sub-nav { padding: 2px 6px; }
  .text-content { padding: 8px var(--panel-pad-x-narrow); }
  :root { --fs-title: var(--fs-standard); --fs-body: var(--fs-standard); }
  .entry { padding: 6px 8px; margin-bottom: 5px; }
  .section-label { margin: 8px 0 3px; }
  .reading-title { margin-bottom: 4px; }
  .reading-desc { margin-bottom: 8px; }
  .chat-bar { padding: 5px 8px; }
  .chat-input { padding: 5px 12px; font-size: var(--fs-body); }
  .chat-send { width: 30px; height: 30px; font-size: var(--fs-subtitle); }
  /* Nav icons retain their 42px base; only spacing tightens. */
  .ring-nav { gap: 0; padding: 2px 1px; }
}

/* ── Responsive — narrow viewport, vertical stack ─────────── */
/* Rule for this app: nothing hides on narrow. Elements collapse to
   smaller forms (icon-only, smaller padding, scrollable rows) but the
   complete UI surface stays accessible at every width. */

@media (max-width: 700px) {
  .app-body {
    grid-template-columns: 1fr;
    /* Chart row sized to the chart's own square; divider; text panel
       takes the rest. Mirrors the horizontal layout (chart fills column,
       panel takes remainder) — just rotated vertically. */
    grid-template-rows: auto 6px 1fr;
  }
  .panel-resize { cursor: ns-resize; }

  /* The viewport spans the FULL window width so the themed chart-area
     background reaches both edges; its HEIGHT is the square's side (capped
     at 70vh so the text panel keeps ≥30vh). The chart canvas centres itself
     as a square inside this via JS (size = min(area width, area height)), so
     the wheel stays square while the backdrop fills the row edge-to-edge. */
  .viewport {
    width: 100%;
    height: min(100vw, 70vh);
    margin: 0;
  }
  /* Native apps (e.g. AstroMap) and iframe apps want the full area, not a
     square — they're not chart canvases. Let them fill the (auto) grid row
     rather than the fixed square height. */
  .viewport.app-active,
  .viewport.native-app-active {
    width: 100%;
    height: auto;
    aspect-ratio: auto;
    margin: 0;
  }

  .dock-sep { width: 1px; height: 14px; margin: 0 2px; }
  .dock-item.has-children::after { display: none; }
  .panel-tab-btn { height: 28px; padding: 0 6px; font-size: var(--fs-label); }
  .panel-tab-btn.panel-tab-icon { padding: 0 6px; }

  .dock-flyout {
    top: 44px; left: 4px; right: 4px;
    max-height: 50vh;
    border-radius: 10px;
  }

  /* Header stays a SINGLE row on narrow. header-left (toggle + three-chart
     dates) is allowed to shrink and clip; header-right (tabs + calendar +
     avatar) holds its size with a tight gap. It must NEVER wrap to a 2nd row. */
  .app-header {
    flex-direction: row;
    align-items: center;
    flex-wrap: nowrap;
    gap: 6px;
    padding: 4px 8px;
    height: auto;
    min-height: 38px;
    overflow: hidden;
  }
  .header-left {
    gap: 6px;
    min-width: 0;
    flex: 1 1 auto;
    overflow: hidden;
  }
  .header-right {
    flex: 0 0 auto;
    flex-wrap: nowrap;
    gap: 1px;
    justify-content: flex-end;
  }
  /* Pull the top-right buttons closer: trim the divider gutter before the tabs. */
  .header-right > .panel-tabs:not(:empty)::before { margin: 0 3px 0 1px; }
  .nav-mode-toggle { font-size: var(--fs-label); padding: 3px 8px; letter-spacing: 1px; flex-shrink: 0; }
  /* Tighten the space around the 🔍 magnifiers and between the date columns. */
  .chart-roles { gap: 5px; }
  .chart-role-mag { width: 15px; height: 18px; font-size: 11px; }
  /* Date columns stay compact — don't flex-grow (that would push the row wider
     and force the buttons to wrap). Date keeps its two-line layout; clip with
     an ellipsis rather than wrapping so the header stays one row tall. */
  .chart-meta { flex-direction: column; gap: 1px; min-width: 0; flex: 0 1 auto; }
  .chart-meta-date {
    font-size: var(--fs-subtitle);
    letter-spacing: 0.4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.15;
  }
  .chart-meta-sub {
    font-size: var(--fs-label);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* Dept nav: tighter padding, scrolls horizontally if 12 buttons
     don't fit. Labels stay visible. */
  .dept-nav { padding: 2px 4px; gap: 0; }
  .dept-btn { min-width: 30px; padding: 3px 2px; font-size: 7px; }
  .dept-btn .dept-icon { font-size: var(--fs-subtitle); }

  /* Sub-nav / breadcrumb */
  .sub-btn { padding: 2px 6px; font-size: var(--fs-micro); }
  .breadcrumb { padding: 2px 6px; font-size: var(--fs-micro); }

  /* Ring nav stays visible — items keep 42px to match calendar; scrollable. */
  .ring-nav-tooltip { display: none !important; }

  /* Text — sizes via the responsive token scale */
  :root { --fs-title: var(--fs-standard); --fs-body: var(--fs-standard); }
  .text-content { padding: 8px var(--panel-pad-x-narrow); }
  .entry { padding: 5px 8px; margin-bottom: 5px; }
  .section-label { margin: 8px 0 3px; }
  .chat-input { padding: 5px 12px; font-size: var(--fs-body); }

  /* Modal */
  .modal-card {
    border-radius: 0; width: 100%; max-width: 100%;
    min-height: 100vh; min-height: 100dvh;
    display: flex; flex-direction: column;
    justify-content: center; padding: 24px 20px;
  }
}

/* ── Responsive — small mobile ────────────────────────────── */

@media (max-width: 480px) {
  .app-header { padding: 4px 6px; min-height: 34px; }
  .nav-mode-toggle { font-size: var(--fs-caption); padding: 2px 8px; letter-spacing: 1.5px; }
  .chart-meta-date { font-size: var(--fs-heading); }
  .chart-meta-sub { font-size: var(--fs-caption); }
  .dept-btn { min-width: 28px; padding: 2px 2px; }
  .dept-btn .dept-icon { font-size: var(--fs-body); }
  .panel-tab-btn { height: 26px; padding: 0 6px; font-size: var(--fs-caption); }
  /* Nav icons stay 42px to match the calendar button — overflow wraps. */
  .chat-send { width: 28px; height: 28px; font-size: var(--fs-heading); }
}

/* ── Reports tab — generate + library inside the info panel ──── */

.reports-tab {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 6px 8px;
  height: 100%;
  min-height: 0;
  overflow-y: auto;
}

.reports-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 4px;
  border-bottom: 1px solid var(--border);
}

.reports-section:last-child { border-bottom: none; }

.reports-section__title {
  font-size: var(--fs-heading);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0;
}

.reports-section__placeholder {
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--text-muted);
  margin: 0;
  opacity: 0.7;
}

.reports-tab-empty {
  padding: 24px 12px;
  font-size: var(--fs-heading);
  color: var(--text-muted);
  text-align: center;
}

/* ── Generate form ────────────────────────────────────────── */

.generate-form { display: flex; flex-direction: column; gap: 10px; }

.gf-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.gf-label {
  font-size: var(--fs-label);
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.gf-select {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 6px 8px;
  font-size: var(--fs-heading);
  font-family: var(--font-body);
}

.gf-type-desc {
  font-size: var(--fs-body);
  color: var(--text-muted);
  line-height: 1.5;
  margin: 0;
}

.gf-section { display: flex; flex-direction: column; gap: 6px; margin-top: 4px; }

.gf-section-title {
  font-size: var(--fs-label);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  margin: 8px 0 4px;
}

.gf-kind-row { flex-direction: row; gap: 6px; }

.gf-kind-btn {
  flex: 1;
  background: transparent;
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 6px 10px;
  font-size: var(--fs-body);
  font-family: var(--font-body);
  cursor: pointer;
  transition: all 0.15s;
}
.gf-kind-btn:hover { background: var(--surface-hover); color: var(--text); }
.gf-kind-btn.is-active { background: var(--accent-dim); color: var(--accent); border-color: var(--accent); }
.gf-kind-static { font-size: var(--fs-body); color: var(--text-muted); font-style: italic; }

.gf-modules-list { display: flex; flex-direction: column; gap: 4px; }

.gf-module-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-body);
  color: var(--text);
  cursor: pointer;
}

.gf-checkbox { cursor: pointer; }

.gf-module-id { font-family: var(--font-mono, monospace); font-size: var(--fs-label); }

.gf-radio-row { display: flex; gap: 14px; }
.gf-radio-label { display: flex; align-items: center; gap: 6px; font-size: var(--fs-body); cursor: pointer; }

.gf-textarea {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 6px 8px;
  font-size: var(--fs-body);
  font-family: var(--font-body);
  resize: vertical;
}

.gf-slider-row { display: flex; align-items: center; gap: 10px; }
.gf-slider { flex: 1; }
.gf-slider-label { font-size: var(--fs-body); color: var(--text-muted); min-width: 160px; text-align: right; }

.gf-actions { margin-top: 12px; }

.gf-cta {
  background: var(--accent);
  color: var(--bg);
  border: none;
  border-radius: 4px;
  padding: 8px 16px;
  font-size: var(--fs-heading);
  font-weight: 600;
  font-family: var(--font-body);
  cursor: pointer;
  transition: all 0.15s;
}
.gf-cta:hover { filter: brightness(1.1); }

/* Secondary action (e.g. Export PDF) — outlined, subordinate to the primary CTA. */
.gf-secondary {
  background: transparent;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 4px;
  padding: 8px 16px;
  font-size: var(--fs-heading);
  font-weight: 600;
  font-family: var(--font-body);
  cursor: pointer;
  transition: all 0.15s;
}
.gf-secondary:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }

.gf-hint { font-size: var(--fs-body); color: var(--text-muted); font-style: italic; margin: 0; }

/* ── Report viewer ──────────────────────────────────────────── */

.reports-viewer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 4px 10px;
  border-bottom: 1px solid var(--border);
}

.reports-viewer-back {
  background: transparent;
  color: var(--text-muted);
  border: none;
  font-size: var(--fs-body);
  font-family: var(--font-body);
  cursor: pointer;
  padding: 4px 0;
}
.reports-viewer-back:hover { color: var(--text); }

.reports-viewer-meta { font-size: var(--fs-label); color: var(--text-muted); }

.reports-viewer-title {
  font-size: var(--fs-xl);
  font-weight: 600;
  margin: 12px 0 4px;
  color: var(--text);
}

.reports-viewer-subtitle {
  font-size: var(--fs-heading);
  font-style: italic;
  color: var(--text-muted);
  margin: 0 0 12px;
}

.reports-viewer-body {
  font-size: var(--fs-heading);
  line-height: 1.6;
  color: var(--text);
}

.reports-viewer-footer {
  margin-top: 24px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.reports-viewer-footer-hint { font-size: var(--fs-label); color: var(--text-muted); font-style: italic; }

/* ── Offline report — module cards with rich HTML pass-through ── */

.report-module-card {
  --module-accent: var(--accent, #63b3ed);
  margin: 1.8em 0;
  padding: 14px 16px 12px;
  border-radius: 6px;
  background: rgba(255,255,255,0.025);
  border: 1px solid var(--border, rgba(255,255,255,0.08));
  border-left: 3px solid var(--module-accent);
}

.report-module-card__title {
  font-size: var(--fs-xl);
  font-weight: 600;
  color: var(--module-accent);
  margin: 0 0 0.6em;
  padding-bottom: 0.3em;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  letter-spacing: 0.005em;
}

.report-module-card__projection {
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 1.2em 0 0.5em;
  padding-bottom: 0.2em;
  border-bottom: 1px dotted var(--border, rgba(255,255,255,0.08));
}

.report-section {
  margin: 0.8em 0;
}

.report-section__title {
  font-size: var(--fs-heading);
  font-weight: 600;
  color: var(--violet, #a380e8);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin: 1.1em 0 0.4em;
}

.report-section__prose {
  font-size: var(--fs-heading);
  line-height: 1.65;
  color: var(--text);
}

/* Rich HTML — passed through from the module's getInfo(). Module
   inline styles cascade naturally; we override only the structural
   bits that would clash with the card container's tighter padding. */
.report-section__rich {
  font-size: var(--fs-heading);
  line-height: 1.6;
}

.report-section__rich > div {
  margin: 0.4em 0;
}

/* ── Proposal modal ─────────────────────────────────────────── */

.proposal-modal-overlay {
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(0,0,0,0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.proposal-modal-card {
  width: min(560px, 92vw);
  max-height: 88vh;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 18px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.proposal-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.proposal-modal-title { font-size: var(--fs-lg); font-weight: 600; margin: 0; }

.proposal-modal-close {
  background: transparent;
  color: var(--text-muted);
  border: none;
  font-size: var(--fs-lg);
  cursor: pointer;
}
.proposal-modal-close:hover { color: var(--text); }

.proposal-modal-rationale {
  font-size: var(--fs-body);
  font-style: italic;
  color: var(--text-muted);
  margin: 0;
  padding: 6px 10px;
  background: var(--surface);
  border-radius: 4px;
  border-left: 2px solid var(--accent);
}

.proposal-modal-form .gf-host { margin-top: 4px; }

/* ── Reports library list ───────────────────────────────────── */

.reports-library { display: flex; flex-direction: column; gap: 14px; }

.reports-library-group { display: flex; flex-direction: column; gap: 4px; }

.reports-library-group__title {
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 4px 0;
}

.reports-library-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 4px;
  border-bottom: 1px solid var(--border);
}

.reports-library-row:last-child { border-bottom: none; }

.reports-library-icon { font-size: var(--fs-subtitle); opacity: 0.8; }

.reports-library-row-body {
  flex: 1;
  cursor: pointer;
  min-width: 0;
}

.reports-library-row-body:hover .reports-library-title { color: var(--accent); }

.reports-library-title {
  font-size: var(--fs-heading);
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.reports-library-meta {
  display: flex;
  gap: 8px;
  font-size: var(--fs-label);
  color: var(--text-muted);
  margin-top: 2px;
}

.reports-library-tokens {
  background: var(--surface);
  padding: 1px 5px;
  border-radius: 3px;
  font-size: var(--fs-caption);
}

.reports-library-delete {
  background: transparent;
  color: var(--text-muted);
  border: none;
  font-size: var(--fs-subtitle);
  cursor: pointer;
  padding: 2px 4px;
  border-radius: 3px;
}
.reports-library-delete:hover { background: var(--surface-hover); color: var(--ember, #d65b5b); }

/* ── Export modal ────────────────────────────────────────────── */

.export-modal-overlay {
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(0,0,0,0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.export-modal-card {
  width: min(540px, 96vw);
  max-height: min(720px, 92vh);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.export-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--border);
}

.export-modal-title { font-size: var(--fs-lg); font-weight: 600; margin: 0; }

.export-modal-close {
  background: transparent;
  color: var(--text-muted);
  border: none;
  font-size: var(--fs-lg);
  cursor: pointer;
}

.export-modal-body {
  flex: 1;
  display: flex;
  gap: 12px;
  min-height: 0;
}

.export-template-list {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
  overflow-y: auto;
}

.export-template-row {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 8px 10px;
  text-align: left;
  cursor: pointer;
  transition: all 0.15s;
  color: var(--text);
  font-family: var(--font-body);
}
.export-template-row:hover { background: var(--surface-hover); }
.export-template-row.is-active { border-color: var(--accent); background: var(--accent-dim, rgba(99,179,237,0.12)); }

.export-template-name { font-size: var(--fs-heading); font-weight: 600; }
.export-template-desc { font-size: var(--fs-label); color: var(--text-muted); margin-top: 2px; }

.export-modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}

.export-modal-cancel {
  background: transparent;
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 7px 14px;
  font-size: var(--fs-heading);
  font-family: var(--font-body);
  cursor: pointer;
}
.export-modal-cancel:hover { background: var(--surface-hover); color: var(--text); }

/* ── Responsive — very small ──────────────────────────────── */

@media (max-width: 360px) {
  /* Cap the chart more aggressively at this size so the panel keeps
     at least 50vh of room. */
  .viewport { width: min(100vw, 50vh); }
  .ring-nav-item { width: 18px; height: 18px; font-size: var(--fs-micro); }
}

/* ════════════════════════════════════════════════════════════
   ORACLE CHAT MODE  (#app.chat-mode)
   Chat is a PANEL mode (like Day Summary), NOT a full-view takeover: the chart
   stays visible on the left and the oracle chat renders in the info panel on the
   right. The `.chat-mode` class is a state flag the JS keys off (chat-bar
   visibility, header 💬 button state, enter/exit); it no longer collapses the
   layout. Entered/left via the 💬 button (_toggleChatMode) or by selecting another
   panel tab (renderPanelTabs → _exitChatMode).

   The input (#chatBar) is re-parented into the info panel (#textPanel) on enter so
   it PINS to the panel bottom while the conversation scrolls above it. To make the
   chat log the single scroller (so the input stays put), the content area becomes a
   flex column that clips, and the chat wrap fills it — the inner .chat-tab-log does
   the scrolling.
   ════════════════════════════════════════════════════════════ */
#app.chat-mode #textContent { display: flex; flex-direction: column; overflow: hidden; }
#app.chat-mode .chat-tab { flex: 1 1 auto; min-height: 0; }
#textPanel > .chat-bar { flex: 0 0 auto; border-top: 1px solid var(--border); }

/* Oracle chat UI fixes (2026-09-09):
   1) Lift the input bar off the very bottom so the bottom-menu tooltips no longer
      overlap the text field (tunable — "a bit higher").
   2) Hide the panel scroll-assist page-up/down buttons in chat mode: they are
      position:absolute at the panel's bottom-right and collided with the Send button. */
#app.chat-mode #textPanel > .chat-bar { margin-bottom: 34px; }
#app.chat-mode .scroll-assist { display: none !important; }

/* ════════════════════════════════════════════════════════════
   CORNER-CHART MODE  (#app.corner-chart)
   Mobile-optimized compact layout (distinct from the .compact UI-density mode).
   The chart shrinks to a tappable icon in the top-left corner, OVERLAPPING the
   now full-width info panel; the info panel keeps all its normal behavior (day
   summary, KP roulette, ring detail, oracle chat) with the oracle chat INPUT
   pinned to the bottom (re-parented into #textPanel, like chat-mode). The bottom
   ring-nav is hidden until swiped up from the bottom edge, then auto-hides.
   Tapping the corner chart returns to the two-panel view at its last size.
   See reading-v3.js "CORNER-CHART MODE" + docs/plans/DESIGN-2026-09-12-compact-mode.md.
   ════════════════════════════════════════════════════════════ */

/* Fixed 3-region layout. The chart is PINNED at the screen's top-left (permanent +
   fully navigable — scroll-wheel/drag/click as normal); the app header becomes a
   strip to its right (brand hidden); each mode's content splits into a LEAD zone
   (top-right, beside the chart, internal scroll) and a REST zone (full-width, below
   the chart, scrolls). The split is done in JS (_applyCornerLayout wraps content into
   .corner-lead / .corner-rest); this file positions the zones. --corner-size is fixed
   for now (a "scale with screen" option is a planned setting). */
#app.corner-chart {
  --corner-size: 320px;
  --corner-header-h: var(--app-header-h, 60px);   /* the NORMAL header height */
  position: relative;
}

/* Chart — pinned to the viewport's top-left (fixed = never scrolls), beside the
   relocated header strip. Fully interactive; no tap-to-return (that's the ◰ button). */
#app.corner-chart #viewport {
  position: fixed;
  top: var(--corner-header-h);   /* sit BELOW the header bar — no overlap with the icons */
  left: 0;
  width: var(--corner-size);
  height: var(--corner-size);
  z-index: 40;
}
/* Transparent chart: no disc, no square, no darken overlay — just the rings. */
#app.corner-chart #chartBackdrop,
#app.corner-chart .viewport-chart-area::before { display: none; }
#app.corner-chart #viewport,
#app.corner-chart .viewport,
#app.corner-chart .viewport-chart-area { background: transparent !important; }
#app.corner-chart #viewport .chart-role-corner { display: none; }
#app.corner-chart .panel-resize { display: none; }

/* Header stays fully NORMAL (full-width, icons in their usual spots) — the chart now
   sits below it, so there's no overlap to work around. Only the brand text is hidden. */
#app.corner-chart .app-brand { display: none; }
#app.corner-chart .dept-nav { display: none; }

/* Body is a single flow (the chart is fixed, out of flow); the panel fills it and
   its chat input pins to the bottom. */
#app.corner-chart .app-body {
  display: flex;
  flex-direction: column;
  position: relative;
}
#app.corner-chart #textPanel { flex: 1; min-height: 0; }
#app.corner-chart .breadcrumb,
#app.corner-chart .sub-nav { display: none; }

/* The content area is a 3-cell grid: an empty top-left GAP the fixed chart overlays,
   the LEAD zone (top-right, beside the chart, below the header) and the REST zone
   (full-width, below the chart). Both zones scroll internally. */
#app.corner-chart #textContent {
  display: grid;
  grid-template-columns: var(--corner-size) 1fr;
  grid-template-rows: var(--corner-size) 1fr;
  grid-template-areas: "gap lead" "rest rest";
  overflow: hidden;
  min-height: 0;
  padding: 0;
  column-gap: 12px;
}
#app.corner-chart .corner-lead {
  grid-area: lead;
  overflow: hidden;          /* NEVER scrolls — JS fills it only to what fits */
  min-width: 0;
  min-height: 0;
  padding: 6px 10px;
}
/* Oracle: let the toolbar (history / credits / save / new / personality) WRAP onto
   multiple rows in the top-right zone instead of overflowing off the side. */
#app.corner-chart .corner-lead .chat-tab-header {
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: 6px;
  border-bottom: none;
}
#app.corner-chart .corner-rest {
  grid-area: rest;
  overflow: auto;
  min-width: 0;
  min-height: 0;
  padding: 12px var(--panel-pad-x, 14px);
}
/* Oracle: its toolbar is the LEAD; the log fills the REST. The .chat-tab wrapper
   (now holding just the log) fills the rest cell so the log scrolls internally. */
#app.corner-chart .corner-rest .chat-tab { height: 100%; min-height: 0; padding-top: 0; }

/* The vestigial "switch to single-panel" center toggle (#chartModeToggle) must
   never appear, in any mode — it's an unwired leftover in prod's index.html. */
#chartModeToggle { display: none !important; }

/* Bottom ring-nav becomes a swipe-revealed overlay pinned to the screen bottom;
   it sits over the pinned chat input (intended — selecting a ring navigates away).
   Hidden by default (slid off-screen); JS adds .revealed on a bottom-edge swipe
   and removes it after a few seconds of no touch. */
#app.corner-chart .ring-nav {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  width: auto;
  flex-direction: row;
  border-right: none;
  border-top: 1px solid var(--border);
  background: var(--surface, var(--bg, #0d0d1a));
  transform: translateY(115%);
  transition: transform 0.2s ease;
  z-index: 40;
}
#app.corner-chart .ring-nav.revealed { transform: translateY(0); }

/* ════════════════════════════════════════════════════════════
   SINGLE-PANEL MODE
   Additive layout toggled via _layout.singlePanel (#app.single-panel).
   See reading-v3.js "SINGLE-PANEL MODE" section.
   ════════════════════════════════════════════════════════════ */

/* Header toggle button — matches the reports/feedback button shape. */
.sp-toggle-btn {
  width: 30px; height: 30px;
  border: none; border-radius: 50%;
  background: transparent; color: var(--text-muted);
  font-size: var(--fs-title); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: all 0.15s; margin-right: 4px;
}
.sp-toggle-btn:hover { background: var(--surface-hover); color: var(--text); }
.sp-toggle-btn.active { color: var(--accent); background: var(--accent-bg); }

/* The scrollable page + the FAB/sheet are hidden until single-panel is on. */
.single-panel-page { display: none; }
.sp-fab { display: none; }
.sp-sheet { display: none; }

/* When single-panel is active: hide the two-panel chrome (the header and
   ring-nav are physically relocated into the sheet by JS, so they are not
   hidden here) and show the scrollable page. */
#app.single-panel .app-body,
#app.single-panel .dept-nav,
#app.single-panel .chat-bar { display: none; }

#app.single-panel .single-panel-page {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
}

/* Single-panel body: a vertical column. Top row = chart + intro/overview;
   everything else spans full width beneath it. The page scrolls vertically. */
.sp-main {
  display: flex;
  flex-direction: column;
  gap: 22px;
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  padding: 18px var(--panel-pad-x) 96px;   /* bottom space clears the FAB */
  box-sizing: border-box;
}

/* Top row: chart (left) + module intro/overview (right). */
.sp-top {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 22px;
  width: 100%;
}

/* The single chart with two concentric rings. Square, sized to viewport. */
.sp-chart-wrap {
  position: relative;
  flex: 0 0 auto;
  width: min(48vw, 62vh);
  aspect-ratio: 1 / 1;
}
.sp-chart-wrap canvas {
  width: 100%;
  height: 100%;
  display: block;
  touch-action: pan-y;   /* allow vertical page scroll; JS handles horizontal swipe */
}

/* Prev/next module arrows (desktop affordance; swipe/keys also work). */
.sp-arrow {
  position: absolute;
  top: 50%; transform: translateY(-50%);
  width: 34px; height: 34px;
  border: 1px solid var(--border); border-radius: 50%;
  background: var(--surface); color: var(--text);
  font-size: var(--fs-xl); line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  z-index: 3; opacity: 0.7; transition: opacity 0.15s, background 0.15s;
}
.sp-arrow:hover { opacity: 1; background: var(--surface-hover); }
.sp-arrow-prev { left: -6px; }
.sp-arrow-next { right: -6px; }

/* Flip inner/outer ring button (top-right of the chart). */
.sp-flip-btn {
  position: absolute;
  top: 4px; right: 4px;
  width: 32px; height: 32px;
  border: 1px solid var(--border); border-radius: 50%;
  background: var(--surface); color: var(--text);
  font-size: var(--fs-lg); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  z-index: 3; opacity: 0.8; transition: opacity 0.15s, background 0.15s;
}
.sp-flip-btn:hover { opacity: 1; background: var(--surface-hover); }

/* Center-circle layout toggle — a small circle dead-center of the chart,
   present in BOTH layouts (#chartModeToggle two-panel, #spCenterToggle
   single-panel). Tapping switches modes. */
.chart-center-toggle {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--surface);
  opacity: 0.5;
  cursor: pointer;
  z-index: 6;
  transition: opacity 0.15s, transform 0.12s;
}
.chart-center-toggle:hover { opacity: 1; transform: translate(-50%, -50%) scale(1.15); }
/* Hide the two-panel center toggle when an embedded app/iframe owns the viewport. */
.viewport.app-active .chart-center-toggle,
.viewport.native-app-active .chart-center-toggle { display: none; }

/* ── Year selector — the on-wheel calendar's year axis (ui/year-selector.js) ──
   Top-right of the chart area (the other corners hold the chart-role dates).
   Shown only while the calendar band is up; hidden when the wheel is replaced. */
.year-selector {
  position: absolute;
  top: 8px; right: 8px;
  z-index: 7;
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  user-select: none; -webkit-user-select: none;
  pointer-events: none;   /* children re-enable pointer events */
}
.year-selector.is-visible { display: flex; }
.viewport.calendar-view .year-selector,
.viewport.app-active .year-selector,
.viewport.native-app-active .year-selector { display: none; }
.year-sel-btn {
  pointer-events: auto;
  width: 30px; height: 22px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--surface, rgba(20, 22, 32, 0.82));
  color: var(--text, #e8e8f0);
  font-size: 13px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; opacity: 0.8;
  touch-action: manipulation;
  transition: opacity .12s, background .12s;
}
.year-sel-btn:hover { opacity: 1; background: var(--surface-hover, var(--surface)); }
.year-sel-btn:active { transform: translateY(1px); }
.year-sel-btn.is-disabled { opacity: 0.25; pointer-events: none; }
.year-sel-window {
  pointer-events: auto;
  position: relative;
  width: 46px;
  height: 130px;                 /* 5 rows × 26px */
  overflow: hidden;
  cursor: ns-resize;
  touch-action: none;            /* we own the vertical drag */
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 20%, #000 80%, transparent);
  mask-image: linear-gradient(180deg, transparent, #000 20%, #000 80%, transparent);
}
.year-sel-strip { position: absolute; inset: 0; }
.year-sel-label {
  position: absolute; left: 0; right: 0; top: 0;
  height: 26px; line-height: 26px; text-align: center;
  font-size: 12px; color: var(--text, #e8e8f0);
  font-variant-numeric: tabular-nums;
  will-change: transform, opacity;
}
.year-sel-label.is-center { font-weight: 700; font-size: 13px; color: var(--accent, #d4af37); }
.year-sel-marker {
  position: absolute; left: 3px; right: 3px; top: 50%;
  height: 26px; transform: translateY(-50%);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  pointer-events: none;
}

/* Module intro/overview — beside the chart in the top row. */
.sp-overview {
  flex: 1 1 320px;
  min-width: 0;
  box-sizing: border-box;
}

/* All other sections — full page width, below the top row. */
.sp-info {
  width: 100%;
  box-sizing: border-box;
}

/* Narrow screens: stack the top row (chart over overview); chart full-width. */
@media (max-width: 760px) {
  .sp-chart-wrap { width: min(92vw, 70vh); margin: 0 auto; }
  .sp-overview { flex-basis: 100%; }
}

/* Fixed bottom-left controls button. */
#app.single-panel .sp-fab {
  position: fixed;
  left: 16px; bottom: 16px;
  width: 52px; height: 52px;
  border: none; border-radius: 50%;
  background: var(--accent); color: #fff;
  font-size: var(--fs-2xl); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 4px 14px rgba(0,0,0,0.35);
  z-index: 60;
}
#app.single-panel .sp-fab:hover { filter: brightness(1.08); }

/* Fly-up sheet hosting the relocated header + ring-nav controls. */
#app.single-panel .sp-sheet {
  display: block;
  position: fixed;
  left: 0; right: 0; bottom: 0;
  max-height: 70vh;
  overflow-y: auto;
  padding: 14px 14px 80px;
  background: var(--surface);
  border-top: 1px solid var(--border);
  box-shadow: 0 -6px 24px rgba(0,0,0,0.4);
  transform: translateY(110%);
  transition: transform 0.25s ease;
  z-index: 55;
}
#app.single-panel .sp-sheet.open { transform: translateY(0); }

/* The relocated header must wrap freely inside the sheet (its two-panel
   styling is a fixed-height, no-wrap, overflow-hidden top bar). */
.sp-sheet .app-header {
  height: auto;
  flex-wrap: wrap;
  gap: 10px;
  border-bottom: none;
  overflow: visible;
  max-width: 100%;
  padding: 0;
}
.sp-sheet .header-left,
.sp-sheet .header-right { flex-wrap: wrap; overflow: visible; flex: 0 1 auto; }

/* The ring-nav strip is a vertical 42px rail in two-panel; in the sheet
   let it flow horizontally and wrap. */
.sp-sheet .ring-nav {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  width: auto;
  gap: 6px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

/* Persistent user-menu trigger, single-panel mode only. The header (with
   its own #avatarBtn) is relocated into the fly-up sheet, so this fixed
   top-right button keeps the menu reachable. */
.sp-avatar-btn { display: none; }
#app.single-panel .sp-avatar-btn {
  position: fixed;
  top: 12px; right: 12px;
  width: 44px; height: 44px;
  border: none; border-radius: 50%;
  background: var(--surface); color: var(--accent);
  font-size: var(--fs-xl); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 2px 12px rgba(0,0,0,0.35);
  z-index: 60;
}
#app.single-panel .sp-avatar-btn:hover { filter: brightness(1.1); }
