/* PHASE 3 — Complete CSS Rebuild to Spec */
/* Deep black base #0a0a0a, red accents #ff2b2b/#cc0000, subtle glow on active elements */
/* Monospace/tech font for numbers, responsive 1920x1080 → 375px */

:root {
  --bg: #0a0a0a;
  --red: #ff2b2b;
  --red2: #cc0000;
  --text: #eaeaea;
  --muted: #9aa0a6;
  --card: #0f0f0f;
  /* 10% on the slider (the default) maps to alpha 0.10 — see settings.js. */
  --card-alpha: 0.10;
  --border: rgba(255, 43, 43, 0.18);
  --glow: rgba(255, 43, 43, 0.35);
  --glow-mult: 1;
  --star-alpha: 1;
  --anim-mode: on;
  --accent: #ff2b2b;
  --ok: #22c55e;
  --bad: #ff2b2b;
  /* KPI text: independent color channel so hero numbers / sub labels NEVER
     inherit the card alpha. Driven live from --card-alpha so it stays readable
     even when the card backgrounds vanish at opacity 0. */
  --kpi-text: var(--text);
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  position: relative;
}

/* ---- Animated astronomy background (canvas z-index 0, content z-index 1) ---- */
.starfield {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  display: block;
}

/* Very subtle deep-red nebula ring glow behind the header area */
.nebula {
  position: fixed;
  top: -260px;
  left: 50%;
  width: 920px;
  height: 720px;
  transform: translateX(-50%);
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(circle at 50% 50%, rgba(255, 43, 43, 0.10) 0%, rgba(204, 0, 0, 0.06) 34%, rgba(255, 43, 43, 0.03) 52%, rgba(10, 10, 10, 0) 68%);
  animation: nebula-pulse 7s ease-in-out infinite alternate;
}

/* ---- Settings slide-in panel (M3) ---- */
.settings-backdrop {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(5, 5, 5, 0.55);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.settings-panel {
  position: fixed;
  top: 0;
  right: 0;
  height: 100vh;
  width: min(420px, 100%);
  z-index: 70;
  background: var(--card);
  border-left: 1px solid color-mix(in srgb, var(--accent) 20%, transparent);
  box-shadow: -8px 0 28px rgba(0,0,0,0.5);
  transform: translateX(100%);
  opacity: 0;
  pointer-events: none;
  transition: transform 0.22s ease, opacity 0.22s ease;
  display: flex;
  flex-direction: column;
}

/* Panel + backdrop open state is driven entirely by inline styles from
   settings.js (it sets transform/opacity/pointer-events on both), so no class or
   attribute selector is needed here. The previous rule matched on
   [style*="opacity: 1"] / [style*="translateX(0)"], strings nothing ever wrote
   (the real inline values are "opacity: 1" only on the panel, and the panel's
   transform is written as "translateX(0px)"), so the backdrop stayed at
   opacity 0 and could not be clicked. */

.settings-panel[style*="translateX(0)"] {
  transform: translateX(0);
}

.settings-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 15%, transparent);
}

.settings-panel-title {
  font-size: 0.875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--accent);
}

.settings-panel-body {
  flex: 1;
  overflow-y: auto;
  padding: 1rem 1.25rem 1.5rem;
}

.settings-section {
  margin-bottom: 1.25rem;
}

.settings-section:last-child {
  margin-bottom: 0;
}

.settings-section-title {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--muted);
  margin-bottom: 0.6rem;
}

.settings-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.6rem;
  font-size: 0.82rem;
  color: var(--text);
}

.settings-row:last-child {
  margin-bottom: 0;
}

.settings-label {
  min-width: 120px;
  flex-shrink: 0;
  color: var(--muted);
  font-size: 0.78rem;
}

.settings-row-with-value {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.settings-row input[type="range"] {
  flex: 1;
  height: 4px;
  -webkit-appearance: none;
  appearance: none;
  background: color-mix(in srgb, var(--accent) 25%, transparent);
  border-radius: 2px;
  outline: none;
}

.settings-row input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent);
  cursor: pointer;
  box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 60%, transparent);
}

.settings-row input[type="range"]::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent);
  cursor: pointer;
  border: none;
  box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 60%, transparent);
}

.settings-value {
  min-width: 38px;
  text-align: right;
  font-weight: 700;
  color: var(--accent);
  font-size: 0.82rem;
}

.settings-hint {
  width: 100%;
  display: block;
  font-size: 0.7rem;
  color: var(--muted);
  margin-top: 0.1rem;
}

.settings-toggle-row {
  flex-wrap: wrap;
}

.settings-toggle-row .settings-label {
  min-width: 120px;
}

.settings-switch {
  position: relative;
  display: inline-block;
  width: 42px;
  height: 22px;
  flex-shrink: 0;
}

.settings-switch input {
  opacity: 0;
  width: 0;
  height: 0;
  position: absolute;
}

.settings-switch-slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: color-mix(in srgb, var(--accent) 25%, #000);
  transition: 0.2s;
  border-radius: 22px;
  box-shadow: inset 0 0 4px rgba(0,0,0,0.6);
}

.settings-switch-slider::before {
  position: absolute;
  content: "";
  height: 16px;
  width: 16px;
  left: 3px;
  bottom: 3px;
  background-color: #fff;
  transition: 0.2s;
  border-radius: 50%;
  box-shadow: 0 0 6px rgba(255,255,255,0.4);
}

.settings-switch input:checked + .settings-switch-slider {
  background-color: var(--accent);
}

.settings-switch input:checked + .settings-switch-slider::before {
  transform: translateX(20px);
}

.settings-select {
  flex: 1;
  padding: 4px 8px;
  background: color-mix(in srgb, var(--accent) 12%, #000);
  color: var(--text);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  border-radius: 6px;
  font-size: 0.82rem;
  cursor: pointer;
  outline: none;
}

.settings-select:focus-visible {
  box-shadow: 0 0 8px color-mix(in srgb, var(--accent) 50%, transparent);
}

.settings-accents {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.settings-accent {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 4px 8px;
  border: 1px solid color-mix(in srgb, var(--accent) 20%, transparent);
  border-radius: 6px;
  cursor: pointer;
  font-size: 0.78rem;
}

.settings-accent input {
  display: none;
}

.settings-accent-swatch {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.15);
}

.settings-accents .settings-accents-swatch {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.15);
}

.settings-accents .settings-accents-label {
  color: var(--text);
  font-size: 0.78rem;
}

.settings-accents input:checked + .settings-accents-swatch + .settings-accents-label,
.settings-accent:has(input:checked) {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, #000);
}

.settings-motion-test-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.settings-motion-results {
  flex: 1;
  font-size: 0.78rem;
  color: var(--muted);
  line-height: 1.4;
}

.settings-motion-results.motion-ok {
  color: var(--accent);
}

.settings-motion-results.motion-low {
  color: var(--bad);
}

.settings-actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 1.25rem;
  padding-top: 1rem;
  border-top: 1px solid color-mix(in srgb, var(--accent) 12%, transparent);
}

.settings-actions .btn {
  flex: 1;
  text-align: center;
}

.settings-reset-btn {
  color: var(--muted);
}

.settings-toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 80;
  background: color-mix(in srgb, var(--accent) 18%, #000);
  color: #fff;
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  border-radius: 8px;
  padding: 8px 14px;
  font-size: 0.82rem;
  box-shadow: 0 0 calc(10px * var(--glow-mult)) color-mix(in srgb, var(--accent) 30%, transparent);
  opacity: 0;
  transition: opacity 0.2s ease;
  pointer-events: none;
}

.settings-toast[style*="display: block"] {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .settings-panel,
  .settings-backdrop,
  .settings-toast {
    transition: none;
  }
}


/* ---- Animated astronomy background (canvas z-index 0, content z-index 1) ---- */
@keyframes nebula-pulse {
  from { opacity: 0.7; transform: translateX(-50%) scale(0.98); }
  to { opacity: 1; transform: translateX(-50%) scale(1.03); }
}

.topbar,
.container {
  /* Z1 — explicit content z-index above the background canvas (z-index 0).
     The topbar is the sticky header that carries the nav + TODAY pill + LOGOUT. */
  position: relative;
  z-index: 40;
}

/* Z1 — canvas-stacking audit: every opaque UI layer above the background canvas.
   The background canvas is z-index 0; content is z-index 1+. If either was ever
   raised above content, it would repaint over the chart axis and the day-card
   EDIT/ADD buttons. The selectors below are duplicated in scripts/audit2.js as a
   runtime stacking audit, so keep them in sync. */

#sec-today,
#sec-chart,
#sec-weekly,
#warnings,
#kpiRow,
.week-group,
#weeklyStrip,
.section-nav,
.topbar,
.container {
  /* Z1 — explicit content z-index above the background canvas (z-index 0).
     These layers paint opaque UI (buttons, badges, text, chart axis/labels).
     The day chips and buttons keep position relative from their own rules.

     N1: overlays are deliberately NOT in this list. #settingsPanel,
     #settingsBackdrop, #modal and #splash are position:fixed with their own
     z-index (60/70/999), and an ID selector here used to overwrite both
     properties — the 100vh settings panel dropped into normal flow and pushed
     the whole page (KPI row included) 1080px below the fold, while also sinking
     the panel and modal under the sticky header. */
  position: relative;
  z-index: 1;
}

.week-group {
  position: relative;
  z-index: 1;
}

#kpiRow {
  position: relative;
  z-index: 1;
}

#warnings {
  position: relative;
  z-index: 1;
}

#scrollRocketSettingsOnly,
#scrollRocketSection2 {
  /* Z1 + Z2: these are the scroll-rocket elements; they are position absolute and
     z-index 1 in their static state, but the live rocket is display:none except
     mid-flight, so the only visible rocket layer is the flying one, which is
     explicitly above the cards via .scroll-rocket.flying (z-index 9999). */
  position: absolute;
  z-index: 1;
}

@media (prefers-reduced-motion: reduce) {
  :root {
    animation-play-state: paused;
  }
  .card { animation: none; }
  .kpi-val.hero { animation: none !important; animation-name: none !important; }
  .today-badge { animation: none !important; animation-name: none !important; }
  .day-ended-badge { animation: none !important; animation-name: none !important; }
  .nebula { animation: none; }
  .chart-today-marker { animation: none; }
  .topbar { transition: none; }
}
/* Thin dark-red styled scrollbar */
html {
  scrollbar-width: thin;
  scrollbar-color: rgba(204, 0, 0, 0.8) #0a0a0a;
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

::-webkit-scrollbar-track {
  background: #0a0a0a;
}

::-webkit-scrollbar-thumb {
  background: linear-gradient(180deg, rgba(204, 0, 0, 0.75), rgba(255, 43, 43, 0.45));
  border: 2px solid #0a0a0a;
  border-radius: 999px;
}

::-webkit-scrollbar-thumb:hover {
  background: linear-gradient(180deg, var(--red), var(--red2));
}

/* Splash animation */
.splash {
  position: fixed;
  inset: 0;
  background: var(--bg);
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  animation: splash-fade-out 0.45s ease 1.4s forwards;
}

.splash-content {
  text-align: center;
}

.splash-line {
  font-family: 'Courier New', monospace;
  font-size: 1.5rem;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.15em;
  opacity: 0;
  animation: splash-line-in 0.4s ease forwards;
}

#splashLine1 {
  animation-delay: 0.1s;
}

#splashLine2 {
  animation-delay: 0.5s;
  margin-top: 0.5rem;
}

.splash-bar {
  width: 300px;
  height: 3px;
  background: rgba(255, 43, 43, 0.2);
  margin-top: 1.5rem;
  border-radius: 2px;
  overflow: hidden;
  opacity: 0;
  animation: splash-line-in 0.3s ease 0.9s forwards;
}

.splash-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--red), var(--red2));
  width: 0;
  animation: splash-bar-fill 0.5s ease 1s forwards;
}

@keyframes splash-line-in {
  to {
    opacity: 1;
  }
}

@keyframes splash-bar-fill {
  to {
    width: 100%;
  }
}

@keyframes splash-fade-out {
  to {
    opacity: 0;
    pointer-events: none;
  }
}

.splash.fade-out {
  animation: splash-fade-out 0.45s ease forwards;
}

/* Header */
.topbar {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem 2rem;
  background: var(--card);
  border-bottom: 1px solid var(--border);
  /* Sticky: cycle range + today's remaining stay visible at a glance. */
  position: sticky;
  top: 0;
  z-index: 40;
  backdrop-filter: blur(6px);
}

/* Smart header (dashboard.js): at the top = full; scrolled down past 80px =
   slim condensed sticky bar (nav + TODAY pill + LOGOUT). No transition here:
   the JS measures the condensed height synchronously to compute the container
   margin compensation that keeps page content position-neutral. */
.topbar.topbar-slim {
  padding: 0.55rem 2rem;
}

.topbar.topbar-slim .brand,
.topbar.topbar-slim #cycleSub {
  display: none;
}

.topbar.topbar-slim .topbar-glance {
  margin-top: 0;
}

.topbar-center {
  text-align: center;
  z-index: 11;
}

/* At-a-glance today's remaining inside the sticky bar. */
.topbar-glance {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 6px;
  padding: 3px 10px;
  border: 1px solid rgba(255, 43, 43, 0.25);
  border-radius: 999px;
  background: rgba(255, 43, 43, 0.06);
}

.glance-label {
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  color: var(--muted);
}

.glance-val {
  font-family: var(--mono, monospace);
  font-size: 0.82rem;
  font-weight: 700;
  color: #fff;
  text-shadow: 0 0 8px rgba(255, 43, 43, 0.5);
}

.glance-val.negative {
  color: var(--bad, #ff6b6b);
}

/* Section anchor nav — smooth-scroll links, >=40px hit areas. */
.section-nav {
  position: absolute;
  left: 2rem;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  gap: 4px;
  z-index: 11;
}

.nav-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  min-width: 40px;
  padding: 0 12px;
  color: var(--muted);
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: 8px;
  transition: color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}

.nav-link:hover,
.nav-link:focus-visible {
  color: #fff;
  border-color: color-mix(in srgb, var(--accent) 40%, transparent);
  box-shadow: 0 0 calc(12px * var(--glow-mult)) color-mix(in srgb, var(--accent) 28%, transparent);
  outline: none;
}

/* Back-to-top control */
.back-to-top {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 45;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  color: #fff;
  background: rgba(10, 10, 10, 0.85);
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  border-radius: 8px;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
  transition: opacity 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
  box-shadow: 0 0 calc(12px * var(--glow-mult)) color-mix(in srgb, var(--accent) 25%, transparent);
}

.back-to-top.visible {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}

.back-to-top:hover,
.back-to-top:focus-visible {
  box-shadow: 0 0 16px rgba(255, 43, 43, 0.45);
  outline: none;
  z-index: 46;
}

.brand {
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--red);
  text-transform: uppercase;
}

.topbar-center .muted {
  font-size: 0.875rem;
  margin-top: 0.25rem;
}

.topbar-right {
  position: absolute;
  top: 50%;
  right: 2rem;
  transform: translateY(-50%);
  display: flex;
  gap: 8px;
  align-items: center;
  z-index: 11;
}

.topbar-icon-btn {
  padding: 6px;
  border-radius: 8px;
  color: var(--muted);
  background: rgba(10,10,10,0.6);
  border: 1px solid rgba(255,43,43,0.18);
}

.topbar-icon-btn:hover,
.topbar-icon-btn:focus-visible {
  color: #fff;
  border-color: color-mix(in srgb, var(--accent) 40%, transparent);
  box-shadow: 0 0 calc(12px * var(--glow-mult)) color-mix(in srgb, var(--accent) 25%, transparent);
  outline: none;
}

.topbar-icon {
  display: block;
}

.topbar-logout {
  margin-left: 4px;
}

/* Container */
.container {
  max-width: 1400px;
  margin: 0 auto;
  padding: 2rem;
}

/* Cards — FEATURE 1 neon pass: faint red glow at rest, breathing pulse on hover
   only (idle stays a static box-shadow so nothing animates off-screen). */
.card {
  background: rgba(10,10,10,var(--card-alpha));
  /* Card alpha must NOT leak onto text/badges/borders. Those layers use
     their own independent colors. This border stays red at the alpha the
     slider sets for the card chrome, but the hero numbers, sub labels, and
     badges keep reading from --kpi-text / --text / --accent directly. */
  border: 1.5px solid color-mix(in srgb, var(--accent) 40%, transparent);
  /* Static red hairline plus a faint breathing glow on the card itself so the
     card shape still reads against the starfield even at very low alpha. */
  box-shadow: 0 0 12px rgba(255, 43, 43, 0.15);
  transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.25s ease;
  border-radius: 12px;
  padding: 1.5rem;
  box-shadow: 0 0 calc(12px * var(--glow-mult)) color-mix(in srgb, var(--accent) 15%, transparent);
  animation: card-breathe 2.6s ease-in-out infinite alternate;
  transition: border-color 0.2s ease, box-shadow 0.2s ease, background 0.25s ease;
}

/* Readability guard: when cards get too transparent, blur the backdrop so
   text never loses contrast against the moving glow glow behind it. */
.card.backdrop-blur {
  backdrop-filter: blur(16px);
  text-shadow: 0 0 8px rgba(0,0,0,0.9);
}

.card.goosed {
  border-color: rgba(255, 43, 43, 0.45);
  animation-duration: 1.2s;
}

@keyframes card-breathe {
  from { box-shadow: 0 0 12px rgba(255, 43, 43, 0.15); }
  to { box-shadow: 0 0 22px rgba(255, 43, 43, 0.4); }
}

@media (prefers-reduced-motion: reduce) {
  .card { animation: none; }
}

.card.glow {
  box-shadow: 0 0 20px rgba(255, 43, 43, 0.1);
}

/* Section titles: 3px red accent bar on the left + letter-spacing */
.card-title {
  position: relative;
  padding-left: 12px;
  font-size: 0.875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--muted);
  margin-bottom: 1rem;
}

.card-title::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 14px;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--accent), color-mix(in srgb, var(--accent) 75%, #000));
  box-shadow: 0 0 calc(8px * var(--glow-mult)) color-mix(in srgb, var(--accent) 70%, transparent);
}

.chart-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.chart-indicators {
  display: flex;
  align-items: center;
  gap: 14px;
  text-transform: none;
  letter-spacing: normal;
  font-size: 0.75rem;
}

.chart-indicators .dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 6px;
  border-radius: 50%;
  vertical-align: middle;
}

.dot-spend {
  background: rgba(154, 160, 166, 0.9);
}

.dot-allow {
  background: var(--accent);
  box-shadow: 0 0 calc(8px * var(--glow-mult)) color-mix(in srgb, var(--accent) 70%, transparent);
}

/* Grid layouts */
.grid2 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 1rem;
  margin-bottom: 1rem;
}

/* KPI section */
.kpi {
  margin: 1rem 0;
}

/* KPI cards must never collapse from a scroll-reveal/no-js default.
   The redesign ships both the row and the cards with explicit flex sizing so
   the cards render fully at first paint — no IntersectionObserver reveal class
   is involved for KPI (the row is Z1 above the canvas and is never pushed
   below it). */
.kpi-row {
  display: flex;
  justify-content: center;
  align-items: stretch;
  gap: 1rem;
  width: 100%;
  flex-wrap: wrap;
  margin: 0 0 1rem;
  position: relative;
  z-index: 1;
}
.kpi-card {
  /* N1: the row lives in <main> now, so the cards share its width instead of
     shrink-wrapping their content in the middle of the page. flex-basis keeps
     the two-up layout and the min-width keeps them stacking on narrow screens. */
  flex: 1 1 320px;
  min-width: 280px;
  position: relative;
  z-index: 1;
  box-shadow: 0 0 12px rgba(255, 43, 43, 0.15);
}

.kpi-val {
  font-family: 'Courier New', monospace;
  font-size: 2.5rem;
  font-weight: 700;
  color: var(--kpi-text, var(--text));
  transition: color 0.3s ease;
}

.kpi-val.hero {
  font-size: 3.5rem;
  color: var(--kpi-text, var(--accent));
  /* FEATURE 1: neon number. Text color reads from --kpi-text so it never
     inherits the card alpha (--card-alpha only drives the card's own
     background, border, and glow — text, badges, and borders stay fully
     opaque at all slider positions, including opacity 0). */
  text-shadow: 0 0 calc(8px * var(--glow-mult)) color-mix(in srgb, var(--accent) 50%, transparent), 0 0 calc(22px * var(--glow-mult)) color-mix(in srgb, var(--accent) 25%, transparent);
  animation: hero-breathe 2.4s ease-in-out infinite alternate;
  animation-play-state: running;
}

/* END TODAY: the hero holds a historical number, so the breathe has to stop.
   The dashboard script already dims the number inline, but a running CSS
   animation outranks inline styles, so the hero-breathe keyframes kept
   repainting it neon green with a glow. (This rule replaces a dead
   .kpi-val.hero.goOSED_HACK that no code ever added to this element - the
   script put its classes on the .kpi wrapper, where nothing matched.) */
.kpi-val.hero.day-final {
  animation: none;
  color: var(--muted);
  text-shadow: none;
}

@keyframes hero-breathe {
  from {
    color: var(--ok);
    text-shadow: 0 0 8px rgba(255, 43, 43, 0.5), 0 0 22px rgba(255, 43, 43, 0.25);
  }
  to {
    color: #fff;
    text-shadow: 0 0 14px rgba(255, 43, 43, 0.85), 0 0 34px rgba(255, 43, 43, 0.5);
  }
}

.kpi-val.hero.overspent {
  /* An overspent hero must read as red. Without this the running
     hero-breathe animation (green -> white) outranks the class colour, so the
     number kept looking healthy while the balance was negative. */
  animation: none;
  color: var(--bad);
}

.kpi-sub {
  font-size: 0.875rem;
  color: var(--muted);
  margin-top: 0.25rem;
}

/* Progress bar */
.progress {
  width: 100%;
  height: 8px;
  background: rgba(255, 255, 255, 0.05);
  border-radius: 4px;
  overflow: hidden;
  margin: 1rem 0;
}

.progress-bar {
  position: relative;
  height: 100%;
  background: linear-gradient(90deg, var(--red), var(--red2));
  transition: width 0.7s cubic-bezier(0.4, 0, 0.2, 1);
  border-radius: 4px;
}

/* FEATURE 1: glowing tip on the progress bar (the track no longer clips it) */
.progress {
  overflow: visible;
}

.progress-bar::after {
  content: '';
  position: absolute;
  right: 0;
  top: 50%;
  width: 8px;
  height: 8px;
  transform: translate(50%, -50%);
  border-radius: 50%;
  background: var(--red);
  box-shadow: 0 0 8px rgba(255, 43, 43, 0.9), 0 0 16px rgba(255, 43, 43, 0.5);
  pointer-events: none;
}

/* Row layouts */
.row2 {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 1rem;
}

/* Buttons */
.btn {
  display: inline-block;
  padding: 0.75rem 1.5rem;
  background: var(--red);
  color: var(--text);
  border: none;
  border-radius: 8px;
  font-size: 0.875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  cursor: pointer;
  transition: all 0.2s ease;
  text-decoration: none;
}

.btn:hover {
  background: var(--red2);
  box-shadow: 0 0 15px var(--glow);
  z-index: 1;
}

.btn:active {
  transform: scale(0.98);
}

.btn.ghost {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
}

.btn.ghost:hover {
  border-color: var(--red);
  background: rgba(255, 43, 43, 0.1);
}

.btn.danger {
  background: var(--red);
}

.icon-btn {
  display: inline-block;
  padding: 0.4rem 0.8rem;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--text);
  cursor: pointer;
  transition: all 0.2s ease;
}

.icon-btn:hover {
  border-color: var(--red);
  background: rgba(255, 43, 43, 0.1);
  z-index: 1;
}

/* Cycle actions */
.cycle-actions {
  display: flex;
  gap: 0.75rem;
  margin-top: 1rem;
}

/* BUG 2: live cycle length + per-day allowance readout in the create form */
.cycle-preview {
  margin-bottom: 0.25rem;
  padding: 0.6rem 0.75rem;
  background: rgba(255, 255, 255, 0.03);
  border-left: 3px solid rgba(255, 43, 43, 0.3);
  border-radius: 6px;
  font-family: 'Courier New', monospace;
  font-size: 0.8rem;
  color: var(--muted);
  transition: color 150ms ease, border-color 150ms ease, box-shadow 150ms ease;
}

.cycle-preview.ready {
  color: var(--text);
  border-left-color: var(--red);
  box-shadow: 0 0 12px rgba(255, 43, 43, 0.12);
}

/* Weekly Allowance Breakdown — day cards per sketch */
/* <900px: single column stacked | 900-1399: auto-fit | >=1400: one row of 7 */
.weekly-strip {
  display: flex;
  flex-direction: column;
  gap: 18px;
  margin-top: 1rem;
}

/* Week group: a titled section wrapping one week's day cards. */
.week-group {
  display: flex;
  flex-direction: column;
  gap: 10px;
  z-index: 1;
}

.week-header {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  padding: 6px 2px;
  border-left: 3px solid var(--red);
  padding-left: 10px;
}

.week-title {
  font-family: var(--mono, monospace);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #fff;
}

.week-range {
  font-size: 0.72rem;
  color: #9aa0a6;
  letter-spacing: 0.04em;
}

.week-summary {
  margin-left: auto;
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
}

.week-sum-item {
  font-size: 0.7rem;
  color: #9aa0a6;
  letter-spacing: 0.03em;
}

.week-sum-item b {
  color: #eaeaea;
  font-weight: 600;
}

.week-sum-item.negative b {
  color: #ff6b6b;
}

/* Card grid inside a week — same responsive behavior the old flat strip had,
   so a 7-day cycle renders identically (7 equal cards at wide widths). */
.week-cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
}

@media (min-width: 900px) {
  .week-cards {
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  }
}

@media (min-width: 1400px) {
  .week-cards {
    /* N2: one equal column per day in THIS week (7 for a full week, fewer for a
       short cycle or the final partial week), so cards fill the row instead of
       leaving fixed 1/7 slots empty. dashboard.js sets --week-cols per group. */
    grid-template-columns: repeat(var(--week-cols, 7), minmax(0, 1fr));
  }
}

/* Day card — ALWAYS fully visible, NO accordion, NO click-to-toggle */
.day-chip {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
  min-width: 0;
  height: 100%;                 /* equal-height cards inside a grid row */
  overflow: hidden;             /* nothing may spill into the neighbouring card */
  padding: 1rem;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 10px;
  cursor: default;
  transition: border-color 150ms ease, box-shadow 150ms ease,
    background 150ms ease, transform 150ms ease;
  z-index: 1;
}

/* hover = red border glow + tiny lift */
.day-chip:hover {
  background: rgba(255, 255, 255, 0.05);
  border-color: rgba(255, 43, 43, 0.55);
  box-shadow: 0 0 18px rgba(255, 43, 43, 0.22);
  transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
  .day-chip,
  .day-chip:hover {
    transition: none;
    transform: none;
  }
}

.day-card-header {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* Glowing red TODAY badge (sketch's 4th button) */
.today-badge {
  margin-left: auto;
  padding: 2px 8px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: #fff;
  background: var(--red);
  border-radius: 999px;
  box-shadow: 0 0 8px var(--glow), 0 0 16px rgba(255, 43, 43, 0.45);
  animation: today-glow 1.6s ease-in-out infinite alternate;
  animation-play-state: running;
}

@keyframes today-glow {
  from { box-shadow: 0 0 6px var(--glow); }
  to { box-shadow: 0 0 16px rgba(255, 43, 43, 0.75); }
}

.day-chip.edit-mode {
  border-color: rgba(255, 43, 43, 0.55);
  box-shadow: 0 0 10px rgba(255, 43, 43, 0.2);
}

.day-chip-name {
  font-weight: 600;
  font-size: 0.875rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.day-chip-date {
  font-size: 0.75rem;
  color: var(--muted);
}

/* Labeled values — always "Label: BDT 142.86", exactly 2 decimals */
.day-values {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-family: 'Courier New', monospace;
  font-size: 0.85rem;
}

.day-value {
  color: var(--muted);
}

.day-value .day-val {
  color: var(--text);
}

.day-value.negative,
.day-value.negative .day-val {
  color: var(--bad);
}

/* Accordion/panel CSS DELETED — cards always fully visible (BUG 2) */
.day-empty {
  padding: 8px 0;
  color: var(--muted);
  font-size: 0.85rem;
}

/* THREE full-width buttons stacked, 8px gap, ALWAYS visible.
   margin-top:auto pins the row to the card bottom so every card in a row keeps
   identical button alignment, expanded or not (BUG 3). */
.day-card-buttons {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: auto;
  padding-top: 0.75rem;
  width: 100%;
  min-width: 0;
}

.day-card-buttons .day-btn {
  width: 100%;
}

.day-chip-items {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.5rem;
  min-width: 0;
}

.day-chip-expense-row {
  padding: 0.75rem;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid transparent;
  border-radius: 8px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.day-chip.edit-mode .day-chip-expense-row {
  border-color: rgba(255, 43, 43, 0.5);
}



/* Mini-form: grows downward inside the card only — never spills out (BUG 3) */
.day-add-form {
  display: none;
  flex-direction: column;
  gap: 0.6rem;
  width: 100%;
  min-width: 0;
  margin-top: 0.75rem;
  padding: 0.75rem;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 8px;
}

.day-add-form.open {
  display: flex;
}

/* FEATURE 2: today's mini-form after END TODAY — greyed out and inert. */
.day-add-form.form-locked {
  opacity: 0.42;
  filter: grayscale(0.5);
}

.day-add-form.form-locked input,
.day-add-form.form-locked select {
  cursor: not-allowed;
}

.day-btn:disabled,
.day-btn[disabled] {
  opacity: 0.4;
  cursor: not-allowed;
  box-shadow: none;
}

/* FEATURE 2: 4th button on today's card only — red outline, above ADD MORE */
.btn.outline {
  background: transparent;
  border: 1.5px solid var(--red);
  color: var(--red);
  box-shadow: 0 0 8px rgba(255, 43, 43, 0.18);
}

.btn.outline:hover {
  background: rgba(255, 43, 43, 0.12);
  box-shadow: 0 0 14px rgba(255, 43, 43, 0.4);
}

.day-end-today-btn {
  background: transparent;
  border: 1px solid var(--red);
  color: var(--red);
  box-shadow: 0 0 10px rgba(255, 43, 43, 0.22);
}

.day-end-today-btn:hover {
  background: rgba(255, 43, 43, 0.12);
  box-shadow: 0 0 16px rgba(255, 43, 43, 0.45);
}

/* "DAY ENDED" badge (hero card + today's card header) */
.day-ended-badge {
  display: inline-block;
  align-self: flex-start;
  margin-top: 0.35rem;
  padding: 2px 8px;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #fff;
  background: rgba(204, 0, 0, 0.85);
  border: 1px solid var(--red);
  border-radius: 999px;
  box-shadow: 0 0 10px rgba(255, 43, 43, 0.45);
  animation: day-ended-pulse 2s ease-in-out infinite alternate;
  animation-play-state: running;
}

@keyframes day-ended-pulse {
  from { box-shadow: 0 0 10px rgba(255, 43, 43, 0.45); }
  to { box-shadow: 0 0 18px rgba(255, 43, 43, 0.9); }
}

.day-card-header .day-ended-badge {
  margin: 0 0 0 auto;
  padding: 1px 6px;
  font-size: 0.6rem;
}

.confirm-copy {
  color: var(--text);
  font-size: 0.95rem;
  line-height: 1.7;
  margin-bottom: 1.25rem;
}

.confirm-copy strong {
  color: var(--red);
  font-family: 'Courier New', monospace;
}

.day-add-form .day-field {
  display: block;
  width: 100%;
  min-width: 0;
}

.day-add-form .day-field .label {
  margin-bottom: 0.3rem;
  font-size: 0.7rem;
}

/* All controls stay inside the card box: full width, border-box, no offsets */
.day-add-form input,
.day-add-form select {
  display: block;
  width: 100%;
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
  margin: 0;
  padding: 0.5rem 0.6rem;
}

.field-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1rem;
  margin-bottom: 1rem;
}

.label {
  display: block;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 0.5rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

input[type="text"],
input[type="number"],
input[type="date"],
input[type="password"],
.select,
select {
  width: 100%;
  padding: 0.75rem;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: 0.875rem;
  transition: all 0.2s ease;
  font-family: inherit;
}

input:focus,
select:focus {
  outline: none;
  border-color: var(--red);
  box-shadow: 0 0 10px var(--glow);
}

/* Chart — compact premium area chart (BUG 5): 200px tall */
.chart-wrap {
  height: 200px;
  margin-top: 1rem;
  position: relative;
}

.chart-wrap canvas {
  display: block;
  width: 100% !important;
  height: 200px !important;
}

/* Z1 — chart wrapper is z-index 1 above the background canvas, the marker inside
   it is z-index 2 within that wrapper so it can sit above the chart line/label
   canvas without being covered by the background disk. */
.chart-today-marker {
  position: absolute;
  top: 0;
  left: 0;
  width: 12px;
  height: 12px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #ff5a5a, var(--red));
  box-shadow: 0 0 10px 3px rgba(255, 43, 43, 0.85), 0 0 0 2px rgba(10, 10, 10, 0.25);
  pointer-events: none;
  z-index: 2;
  animation: marker-pulse 1.8s ease-in-out infinite;
}

/* Z1 — chart wrapper is z-index 1 above the background canvas, the marker inside
   it is z-index 2 within that wrapper so it can sit above the chart line/label
   canvas without being covered by the background disk. */
.chart-wrap {
  position: relative;
  z-index: 1;
}.chart-today-marker {
  position: absolute;
  top: 0;
  left: 0;
  width: 12px;
  height: 12px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #ff5a5a, var(--red));
  box-shadow: 0 0 10px 3px rgba(255, 43, 43, 0.85), 0 0 0 2px rgba(10, 10, 10, 0.25);
  pointer-events: none;
  z-index: 2;
  animation: marker-pulse 1.8s ease-in-out infinite;
}

/* Z1 — the chart marker lives inside the chart-wrap; the marker is above the chart
   line/label canvas AND above the background canvas (z-index 0). The marker's own
   rule sets z-index: 2 for that reason. */

@keyframes marker-pulse {
  0%, 100% { box-shadow: 0 0 10px 3px rgba(255, 43, 43, 0.85), 0 0 0 2px rgba(10, 10, 10, 0.25); }
  50% { box-shadow: 0 0 13px 5px rgba(255, 43, 43, 0.95), 0 0 0 2px rgba(10, 10, 10, 0.35); }
}

@media (prefers-reduced-motion: reduce) {
  .chart-today-marker { animation: none; }
}


/* Expenses list */
.expenses {
  padding-bottom: 100px;
}

.day-group {
  margin-bottom: 1.5rem;
}

.day-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--border);
  margin-bottom: 0.75rem;
  font-weight: 600;
}

.expense-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem;
  background: rgba(255, 255, 255, 0.03);
  border-radius: 8px;
  margin-bottom: 0.5rem;
  transition: all 0.2s ease;
}

.expense-row:hover {
  background: rgba(255, 255, 255, 0.05);
}

.expense-amt {
  font-family: 'Courier New', monospace;
  font-weight: 700;
  font-size: 1rem;
  color: var(--red);
  min-width: 120px;
}

.expense-cat {
  font-size: 0.875rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  min-width: 100px;
}

.expense-note {
  font-size: 0.875rem;
  color: var(--text);
  flex: 1;
}

.expense-actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

/* Warnings */
.warnings {
  margin-bottom: 1rem;
}

.warning {
  padding: 0.75rem 1rem;
  background: rgba(255, 43, 43, 0.1);
  border-left: 3px solid var(--red);
  border-radius: 6px;
  margin-bottom: 0.5rem;
  color: var(--text);
  font-size: 0.875rem;
}

/* Modal */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.8);
  z-index: 999;
  backdrop-filter: blur(4px);
}

.modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1.5rem;
  z-index: 1000;
  max-width: 500px;
  width: 90%;
  max-height: 80vh;
  overflow-y: auto;
}

.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1.5rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--border);
}

.modal-title {
  font-size: 1.125rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--red);
}

.modal-body {
  color: var(--text);
}

/* Login page */
.login-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
}

.login-wrap .card {
  max-width: 400px;
  width: 100%;
}

.login-wrap .brand {
  text-align: center;
  font-size: 2rem;
  margin-bottom: 0.5rem;
}

.login-wrap .muted {
  text-align: center;
  margin-bottom: 2rem;
}

.form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.err {
  padding: 0.75rem;
  background: rgba(255, 43, 43, 0.1);
  border: 1px solid var(--red);
  border-radius: 8px;
  color: var(--red);
  font-size: 0.875rem;
  text-align: center;
  min-height: 1rem;
}

.err:empty {
  display: none;
}

.muted {
  color: var(--muted);
  font-size: 0.875rem;
}

.negative {
  color: var(--bad);
}

/* Z2 — scroll-rocket styles: hidden by default, visible only mid-flight.
   The flying rocket is the only visible layer; the static rocket markup stays
   display:none so it can never paint the stray top-left ribbon/streak. */
.scroll-rocket {
  position: absolute;
  bottom: 22px;
  right: 22px;
  z-index: 50;
  pointer-events: none;
  display: none;
}

.scroll-rocket.flying {
  display: block;
  z-index: 9999;
  animation: rocket-fly 3.2s ease-out forwards;
}

.scroll-rocket.flying .rocket-flame {
  animation: rocket-flame-flicker 0.18s ease-in-out infinite alternate;
}

@keyframes rocket-fly {
  0% { transform: translate(0, 0); opacity: 1; }
  100% { transform: translate(-120px, -70px); opacity: 0; }
}

@keyframes rocket-flame-flicker {
  from { opacity: 0.55; transform: scaleY(0.6); }
  to { opacity: 1; transform: scaleY(1); }
}

/* Responsive */
@media (max-width: 768px) {
  .container {
    padding: 1rem;
  }

  .topbar {
    flex-direction: column;
    gap: 1rem;
    padding: 1rem;
  }

  .topbar-logout {
    position: static;
    transform: none;
  }

  .grid2 {
    grid-template-columns: 1fr;
  }

  .kpi-val.hero {
    font-size: 2.5rem;
  }

  .row2 {
    flex-direction: column;
    gap: 0.5rem;
  }

  .field-row {
    grid-template-columns: 1fr;
  }

  .expense-row {
    flex-direction: column;
    align-items: flex-start;
  }
}

@media (max-width: 375px) {
  .brand {
    font-size: 1.25rem;
  }

  .kpi-val.hero {
    font-size: 2rem;
  }

  .btn {
    padding: 0.6rem 1rem;
    font-size: 0.75rem;
  }
}
