/* =============================================================================
   Pasaka — Design System
   ----------------------------------------------------------------------------- */

:root {
  /* Typography — one face. Nunito for body + display.
     Fredoka was dropped: two rounded-friendly fonts competed instead of
     complemented, and a single subset face saves ~80–120 KB on first paint
     (matters for the "jalan di antrian warung" PWA promise). */
  --font-body:    "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-display: "Nunito", system-ui, sans-serif;
  --font-arcade:  var(--font-display);

  /* Palette — deliberate, calm, Indonesia-rooted.
     Primary is terracotta (was indigo). Indigo #6366f1 is the default
     SaaS color of the last 5 years; terracotta carries the "pusaka /
     heritage" feel of the brand name without changing a single icon. */
  --bt-bg:           #f6f8fb;
  --bt-surface:      #ffffff;
  --bt-surface-alt:  #f1f4f9;
  --bt-border:       #e6eaf2;
  --bt-border-strong:#d3d9e6;

  --bt-ink:          #0f1729;
  /* Muted text — used for eyebrows, founder microcopy, small captions. The
     previous #5b6478 was ~5:1 on white, borderline for <14px text. #475569
     hits 6.6:1 so the small surfaces stay readable per WCAG 2.1 AA. Dark
     mode lifts to its own value below — no change needed there. */
  --bt-ink-muted:    #475569;
  --bt-ink-soft:     #8a93a6;

  --bt-primary:      #ea580c;
  --bt-primary-700:  #c2410c;
  --bt-primary-900:  #7c2d12;
  --bt-primary-100:  #fed7aa;
  --bt-primary-50:   #fff7ed;
  /* Text-color companion: same as primary-700 in light mode (dark
     terracotta on light tints), but lifts to a lighter terracotta in
     dark mode so it stays legible on the now-dark tint backgrounds.
     Use this whenever `--bt-primary-700` is being applied as a text
     color, not a background. */
  --bt-primary-ink:  #c2410c;

  --bt-success:      #047857;
  --bt-success-100:  #d1fae5;
  --bt-success-700:  #065f46;

  --bt-warning:      #b45309;
  --bt-warning-100:  #fef3c7;
  --bt-warning-700:  #92400e;

  --bt-danger:       #b91c1c;
  --bt-danger-500:   #ef4444;
  --bt-danger-100:   #fee2e2;
  --bt-danger-700:   #991b1b;

  /* Secondary accent — kept as a soft sand / clay tone for low-emphasis
     surfaces (was the previous accent slot). */
  --bt-accent:       #d97757;
  --bt-accent-100:   #fbe4d6;
  --bt-accent-50:    #fdf2eb;
  --bt-accent-700:   #a14e2f;

  /* Category swatches — restructured around semantic intent. Red is now
     reserved exclusively for the "overspent" state; "bills" is hidden from
     the daily picker entirely (recurring outflows live in Plan), so its
     swatch only shows on historical rows. */
  --cat-food:          #ea580c;   /* warm orange */
  --cat-transport:     #92400e;   /* clay */
  --cat-shopping:      #be185d;   /* rose */
  --cat-bills:         #6b7280;   /* slate — legacy display only */
  --cat-household:     #0e7490;   /* teal — kosan / listrik / internet */
  --cat-entertainment: #6d28d9;   /* lavender */
  --cat-health:        #4d7c0f;   /* sage — not red */
  --cat-other:         #57534e;   /* stone */

  /* Geometry */
  --bt-radius-sm: 8px;
  --bt-radius:    14px;
  --bt-radius-lg: 20px;
  --bt-radius-pill: 999px;

  --bt-shadow-sm: 0 1px 2px rgba(15,23,41,0.05), 0 1px 3px rgba(15,23,41,0.04);
  --bt-shadow:    0 4px 12px -2px rgba(15,23,41,0.06), 0 2px 6px -1px rgba(15,23,41,0.04);
  --bt-shadow-lg: 0 14px 32px -10px rgba(15,23,41,0.18), 0 6px 14px -4px rgba(15,23,41,0.08);

  --bt-ring:      0 0 0 3px rgba(234,88,12,0.18);
}

/* ──────────────────────────────────────────────────────────────────────
   Dark mode — finance apps get checked at night.

   Triggered by `data-theme="dark"` on <html>, set by the inline head
   script before render based on (a) stored user choice or (b) the OS
   `prefers-color-scheme` preference. The navbar's theme toggle persists
   the user's pick to localStorage; matchMedia changes only apply when
   the user hasn't opted out of auto.

   Layout: a single rule for design-token + Bootstrap-variable overrides,
   then a flat list of selectors scoped under [data-theme="dark"] so they
   only fire when the attribute is set. No media query — JS owns OS pref.
   ────────────────────────────────────────────────────────────────────── */
:root[data-theme="dark"] {
  --bt-bg:           #0b1220;
  --bt-surface:      #131a2c;
  --bt-surface-alt:  #1a2238;
  --bt-border:       #232c44;
  --bt-border-strong:#2d3754;

  --bt-ink:          #f1f5f9;
  --bt-ink-muted:    #94a3b8;
  --bt-ink-soft:     #64748b;

  --bt-primary-50:   #2a1808;
  --bt-primary-100:  #3a2110;
  /* Lifted terracotta for text — see --bt-primary-ink rationale in :root. */
  --bt-primary-ink:  #fdba74;

  /* Bootstrap 5 component variables — overriding here cascades into
     every .card, .modal, .form-control, .btn-close, .dropdown-menu,
     .alert, .table, etc. without touching their per-component CSS. */
  --bs-body-bg:           #0b1220;
  --bs-body-color:        #f1f5f9;
  /* Bootstrap utilities like .text-body, .text-secondary, .text-emphasis
     resolve to `rgba(var(--bs-*-color-rgb), opacity)` — they read the RGB
     triplet, not the hex. Without these overrides those utilities fall
     back to Bootstrap's light-mode dark grays and render near-invisibly
     on the dark surfaces. */
  --bs-body-color-rgb:        241, 245, 249;
  --bs-secondary-color:       #94a3b8;
  --bs-secondary-color-rgb:   148, 163, 184;
  --bs-tertiary-color:        #64748b;
  --bs-tertiary-color-rgb:    100, 116, 139;
  --bs-tertiary-bg:           #1a2238;
  --bs-border-color:          #232c44;
  --bs-border-color-translucent: rgba(255,255,255,0.08);
  --bs-emphasis-color:        #f1f5f9;
  --bs-emphasis-color-rgb:    241, 245, 249;
  --bs-link-color:        #fb923c;
  --bs-link-hover-color:  #fdba74;
  --bs-card-bg:           #131a2c;
  --bs-card-color:        #f1f5f9;
  --bs-card-border-color: #232c44;
  --bs-modal-bg:          #131a2c;
  --bs-modal-color:       #f1f5f9;
  --bs-modal-border-color:#232c44;
  --bs-modal-header-border-color: #232c44;
  --bs-modal-footer-border-color: #232c44;
  --bs-dropdown-bg:       #131a2c;
  --bs-dropdown-color:    #f1f5f9;
  --bs-dropdown-border-color: #232c44;
  --bs-dropdown-link-color: #f1f5f9;
  --bs-dropdown-link-hover-bg: #1a2238;
  --bs-dropdown-link-hover-color: #fff;
  --bs-form-control-bg:   #131a2c;
  --bs-form-control-disabled-bg: #1a2238;
  --bs-form-select-bg:    #131a2c;
  --bs-table-bg:          transparent;
  --bs-table-color:       #f1f5f9;
  --bs-table-border-color:#232c44;
  --bs-table-striped-bg:  rgba(255,255,255,0.03);
  --bs-table-hover-bg:    rgba(255,255,255,0.05);
}

/* Bootstrap text/bg utilities — Bootstrap 5.3 binds these to `data-bs-theme`
   but this project uses `data-theme`, so the native dark-mode variants
   never fire. Force the dark colors explicitly. */
[data-theme="dark"] .text-body { color: #f1f5f9 !important; }
[data-theme="dark"] .text-body-secondary { color: #94a3b8 !important; }
[data-theme="dark"] .text-body-tertiary { color: #64748b !important; }
[data-theme="dark"] .text-body-emphasis { color: #f1f5f9 !important; }
[data-theme="dark"] .bg-body-secondary { background-color: #1a2238 !important; }
[data-theme="dark"] .bg-body-tertiary { background-color: #232c44 !important; }

/* Form fields: Bootstrap pins color but not bg in some places — force. */
[data-theme="dark"] .form-control,
[data-theme="dark"] .form-select {
  background-color: var(--bs-form-control-bg);
  color: var(--bt-ink);
  border-color: var(--bt-border);
}
[data-theme="dark"] .form-control:focus,
[data-theme="dark"] .form-select:focus {
  background-color: var(--bs-form-control-bg);
  color: var(--bt-ink);
  border-color: var(--bt-primary);
}
[data-theme="dark"] .form-control::placeholder { color: var(--bt-ink-soft); }
[data-theme="dark"] .form-control:disabled { background-color: var(--bt-surface-alt); color: var(--bt-ink-soft); }

/* Bootstrap's .btn-close uses a black SVG mask. Invert it. */
[data-theme="dark"] .btn-close { filter: invert(1) grayscale(100%) brightness(200%); }

/* `.alert-*` variants ship with light bg / dark text; remap. */
[data-theme="dark"] .alert-light,
[data-theme="dark"] .alert-info {
  background-color: var(--bt-surface-alt);
  color: var(--bt-ink);
  border-color: var(--bt-border);
}
[data-theme="dark"] .alert-success { background-color: rgba(4,120,87,0.18); color: #6ee7b7; border-color: rgba(4,120,87,0.35); }
[data-theme="dark"] .alert-warning { background-color: rgba(180,83,9,0.18); color: #fbbf24; border-color: rgba(180,83,9,0.35); }
[data-theme="dark"] .alert-danger  { background-color: rgba(185,28,28,0.18); color: #fca5a5; border-color: rgba(185,28,28,0.35); }

/* Hardcoded light fills (grep'd) remapped to surface vars. */
[data-theme="dark"] .bt-navbar,
[data-theme="dark"] .month-pager-select,
[data-theme="dark"] .modal-content,
[data-theme="dark"] .toast,
[data-theme="dark"] .dropdown-menu {
  background-color: var(--bt-surface);
  color: var(--bt-ink);
}

/* Category badge / expense-icon tints — the light palette uses near-white
   tinted backgrounds (#fff7ed etc.) which become bright bricks on a dark
   page. Single subtle surface, keep the text accent. */
[data-theme="dark"] .expense-icon,
[data-theme="dark"] .cat-badge {
  background: rgba(255,255,255,0.06) !important;
}
[data-theme="dark"] .cat-pill { background: transparent; border-color: var(--bt-border); }
[data-theme="dark"] .cat-pill:hover { background: var(--bt-surface-alt); }

/* Lift success/danger text for WCAG on dark surfaces. */
[data-theme="dark"] .text-success,
[data-theme="dark"] .day-saldo.text-success,
[data-theme="dark"] .day-budget.text-success { color: #6ee7b7 !important; }
[data-theme="dark"] .text-danger,
[data-theme="dark"] .day-saldo.text-danger,
[data-theme="dark"] .day-budget.text-danger { color: #fca5a5 !important; }
/* --bt-danger-700 (#991b1b) is tuned for white surfaces; on the navy
   dark-mode bg it fails AA. Lift to the same red used by .text-danger. */
[data-theme="dark"] .spent-amount,
[data-theme="dark"] .daily-card-mobile-spent { color: #fca5a5; }
[data-theme="dark"] .text-muted-soft { color: var(--bt-ink-muted) !important; }

/* calc-result gradient: --bt-accent-100 (#fbe4d6) isn't dark-remapped,
   so the card lands brown→cream and the subtitle disappears in the warm
   end. Pin both stops to dark browns and lift the subtitle to a warm
   light tone. */
[data-theme="dark"] .calc-result {
  background: linear-gradient(135deg, var(--bt-primary-50) 0%, var(--bt-primary-100) 100%);
}
[data-theme="dark"] .calc-result-sub { color: rgba(255,255,255,0.78); }

/* Support link (donate/buy-coffee) — pink is its semantic. Lift the hue
   in dark mode so it stays legible on the near-black surface. */
[data-theme="dark"] .bt-support-link { color: #f9a8d4; }
[data-theme="dark"] .bt-support-link:hover {
  color: #fbcfe8;
  background: rgba(244,114,182,0.12);
}
[data-theme="dark"] .bt-support-link.active {
  color: #f9a8d4;
  background: rgba(244,114,182,0.12);
}

/* Hero gradient stays terracotta — it's branded surface. Overspent gets a
   darker base so it doesn't glow against near-black. */
[data-theme="dark"] .hero-card.hero-overspent {
  background: linear-gradient(135deg, var(--bt-primary-900) 0%, #9a1f0e 55%, #6b1f08 100%);
}
[data-theme="dark"] .hero-card-bare,
[data-theme="dark"] .first-time-hero { color: var(--bt-ink); }

/* Donation / welcome-back banners — pin to surface-alt. */
[data-theme="dark"] .welcome-back-banner,
[data-theme="dark"] .donation-prompt {
  background-color: var(--bt-surface-alt);
  border-color: var(--bt-border-strong) !important;
  color: var(--bt-ink);
}

/* Plan surfaces — setup modal was removed; plan tiles are the only surface. */
[data-theme="dark"] .plan-tile {
  background: var(--bt-surface);
  color: var(--bt-ink);
  border-color: var(--bt-border);
}

/* Coba preview frame, pricing card, landing surfaces. */
[data-theme="dark"] .coba-preview-frame,
[data-theme="dark"] .coba-result,
[data-theme="dark"] .landing-pricing-card,
[data-theme="dark"] .landing-feature,
[data-theme="dark"] .landing-mock,
[data-theme="dark"] .landing-quote-card,
[data-theme="dark"] .landing-principle-card {
  background: var(--bt-surface);
  color: var(--bt-ink);
  border-color: var(--bt-border);
}

[data-theme="dark"] .landing-principle-why {
  background: rgba(234,88,12,0.14);
  color: #fdba74;
}
[data-theme="dark"] .landing-principle-why strong { color: #fed7aa; }

/* Landing feature icons — lift the tint + text in dark mode so they don't
   render dark-on-dark (primary variant) or jar as bright bricks on the
   dark feature card (warning / success variants). Same pattern as the
   dark-mode alert overrides. */
[data-theme="dark"] .landing-feature-icon--primary {
  background: rgba(234,88,12,0.18);
  color: #fdba74;
}
[data-theme="dark"] .landing-feature-icon--warning {
  background: rgba(180,83,9,0.18);
  color: #fbbf24;
}
[data-theme="dark"] .landing-feature-icon--success {
  background: rgba(4,120,87,0.18);
  color: #6ee7b7;
}

/* Landing trifecta + mock savestate — `--bt-success-700` (#065f46) on the
   dark page reads at ~2.4:1, well below AA. Lift the green in dark mode
   the same way `[data-theme="dark"] .text-success` does. */
[data-theme="dark"] .landing-trust-trifecta li { color: #6ee7b7; }
[data-theme="dark"] .landing-mock-savestate {
  background: rgba(4,120,87,0.18);
  color: #6ee7b7;
}

/* Founder card stays a warm pastel surface in both themes, so the buttons
   inside it must keep their light-mode styling — otherwise the dark-mode
   `.btn-outline-secondary` flips to a dark-on-pastel chip. */
[data-theme="dark"] .landing-founder-links .btn-outline-secondary {
  background: #ffffff;
  color: #5b6478;
  border-color: #d3d9e6;
}
[data-theme="dark"] .landing-founder-links .btn-outline-secondary:hover {
  background: #f1f4f9;
  color: #0f1729;
  border-color: #c7ced9;
}
[data-theme="dark"] .coba-preview-tag {
  background: var(--bt-surface-alt);
  border-color: var(--bt-border-strong);
  color: var(--bt-ink-muted);
}

/* Week strip + mobile day cards. */
[data-theme="dark"] .week-pill,
[data-theme="dark"] .daily-card-mobile {
  background: var(--bt-surface);
  border-color: var(--bt-border);
  color: var(--bt-ink);
}
[data-theme="dark"] .daily-card-mobile.is-today {
  background: rgba(234,88,12,0.12);
  border-color: var(--bt-primary);
}

/* PWA install nudge. */
[data-theme="dark"] .pwa-install-nudge {
  background: linear-gradient(135deg, var(--bt-surface) 0%, var(--bt-surface-alt) 100%);
  border-color: var(--bt-border-strong);
  color: var(--bt-ink);
}

/* Onboarding shell. */
[data-theme="dark"] .onboarding-shell { background: var(--bt-surface); color: var(--bt-ink); border-color: var(--bt-border); }
[data-theme="dark"] .onboarding-amount-input { background: var(--bt-surface-alt); border-color: var(--bt-border); }
[data-theme="dark"] .onboarding-currency { color: var(--bt-ink-muted); }

/* Settings-page danger receipt + coachmark. */
[data-theme="dark"] .settings-danger-receipt { background: var(--bt-surface-alt); color: var(--bt-ink-muted); }
[data-theme="dark"] .settings-danger-receipt strong { color: var(--bt-ink); }
[data-theme="dark"] .coachmark-card { background: var(--bt-surface); color: var(--bt-ink); }

/* ----------------------------------------------------------------------------
   Base
   ---------------------------------------------------------------------------- */

html, body { height: 100%; }

body {
  background: var(--bt-bg);
  color: var(--bt-ink);
  font-family: var(--font-body);
  letter-spacing: -0.005em;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Display headings — single-face system, heavier weight does the display
   work. */
.auth-marketing h2,
h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1.2;
}

main.container { max-width: 1100px; }

h1, h2, h3, h4, h5 { letter-spacing: -0.02em; color: var(--bt-ink); }

a { color: var(--bt-primary); text-decoration: none; }
a:hover { color: var(--bt-primary-ink); text-decoration: underline; }

::selection { background: var(--bt-primary-100); color: var(--bt-primary-ink); }

/* ----------------------------------------------------------------------------
   Navigation
   ---------------------------------------------------------------------------- */

.bt-navbar {
  background: var(--bt-surface);
  border-bottom: 1px solid var(--bt-border);
  padding: 0.65rem 0;
  margin-bottom: 2rem;
  position: sticky;
  top: 0;
  z-index: 1020;
  backdrop-filter: saturate(180%) blur(8px);
}

.bt-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.4rem;
  color: var(--bt-ink) !important;
  text-decoration: none;
  letter-spacing: 0;
}
.bt-brand:hover { text-decoration: none; color: var(--bt-ink) !important; }
.bt-brand-mark {
  display: inline-flex; align-items: center; justify-content: center;
}

.bt-nav { display: flex; gap: 0.25rem; align-items: center; }
.bt-nav-link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.45rem 0.85rem;
  border-radius: var(--bt-radius-sm);
  color: var(--bt-ink-muted);
  font-weight: 500;
  font-size: 0.92rem;
  text-decoration: none;
  transition: background 0.12s ease, color 0.12s ease;
}
.bt-nav-link:hover { background: var(--bt-surface-alt); color: var(--bt-ink); text-decoration: none; }
.bt-nav-link.active {
  background: var(--bt-primary-50);
  color: var(--bt-primary-ink);
}
.bt-support-link { color: #be185d; }
.bt-support-link:hover { color: #9f1239; background: #fdf2f8; }
.bt-support-link.active { background: #fdf2f8; color: #be185d; }

.bt-nav-icon { width: 18px; height: 18px; flex-shrink: 0; }

.bt-lang-select {
  height: 36px;
  border: 1px solid var(--bt-border);
  background: var(--bt-surface);
  border-radius: var(--bt-radius-pill);
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--bt-ink);
  /* Hide the native chevron — we paint our own SVG via background-image
     so the rounded pill look stays consistent across Chrome/Safari/FF. */
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  padding: 0 1.7rem 0 0.7rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none' stroke='%2364748b' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='1 1 5 5 9 1'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.6rem center;
  cursor: pointer;
  transition: transform 120ms ease, border-color 140ms ease, box-shadow 180ms ease;
}
.bt-lang-select:hover {
  border-color: var(--bt-primary);
  transform: translateY(-1px);
  box-shadow: 0 4px 10px -4px rgba(0, 0, 0, 0.1);
}
.bt-lang-select:focus {
  outline: none;
  border-color: var(--bt-primary);
  box-shadow: var(--bt-ring);
}
/* Options inherit OS-painted dropdown chrome — we can only style the
   text + emoji. Bump the font and add a touch of padding so flag glyphs
   render cleanly across emoji fonts (especially on Linux/Win). */
.bt-lang-select option {
  font-size: 0.95rem;
  padding: 4px 8px;
  color: var(--bt-ink);
  background: var(--bt-surface);
}

.bt-user-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  height: 36px;
  padding: 0 0.85rem;
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  color: var(--bt-ink);
  border-radius: var(--bt-radius-sm);
  font-size: 0.85rem;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}
.bt-user-btn:hover { background: var(--bt-surface-alt); border-color: var(--bt-border-strong); }
.bt-user-btn::after { display: none; }
.bt-avatar {
  width: 22px; height: 22px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--bt-primary), var(--bt-primary-700));
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.bt-dropdown-menu {
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius);
  box-shadow: var(--bt-shadow-lg);
  padding: 0.5rem;
  min-width: 220px;
}
.bt-dropdown-menu .dropdown-item {
  border-radius: var(--bt-radius-sm);
  padding: 0.5rem 0.75rem;
  font-size: 0.9rem;
}
.bt-dropdown-menu .dropdown-item:hover {
  background: var(--bt-surface-alt);
  color: var(--bt-ink);
}

/* ----------------------------------------------------------------------------
   Buttons
   ---------------------------------------------------------------------------- */

.btn {
  border-radius: var(--bt-radius-sm);
  font-weight: 500;
  letter-spacing: -0.005em;
  transition: transform 0.06s ease, box-shadow 0.12s ease, background 0.12s ease, border-color 0.12s ease;
}
.btn:focus-visible { box-shadow: var(--bt-ring); outline: none; }
.btn:active { transform: translateY(1px); }

.btn-primary {
  background: var(--bt-primary);
  border-color: var(--bt-primary);
  box-shadow: 0 1px 0 rgba(255,255,255,0.15) inset, 0 1px 2px rgba(15,23,41,0.08);
}
.btn-primary:hover { background: var(--bt-primary-700); border-color: var(--bt-primary-ink); }
.btn-primary:focus, .btn-primary:active { background: var(--bt-primary-700) !important; border-color: var(--bt-primary-ink) !important; }

.btn-outline-primary {
  border-color: var(--bt-border-strong);
  color: var(--bt-primary);
  background: var(--bt-surface);
}
.btn-outline-primary:hover { background: var(--bt-primary-50); color: var(--bt-primary-ink); border-color: var(--bt-primary); }

.btn-outline-secondary {
  border-color: var(--bt-border);
  color: var(--bt-ink-muted);
  background: var(--bt-surface);
}
.btn-outline-secondary:hover {
  background: var(--bt-surface-alt);
  color: var(--bt-ink);
  border-color: var(--bt-border-strong);
}

.btn-outline-danger {
  border-color: var(--bt-border);
  color: var(--bt-danger);
  background: var(--bt-surface);
}
.btn-outline-danger:hover { background: var(--bt-danger-100); color: var(--bt-danger-700); border-color: var(--bt-danger-100); }

.btn-secondary {
  background: var(--bt-surface-alt);
  border-color: var(--bt-border);
  color: var(--bt-ink);
}
.btn-secondary:hover { background: var(--bt-surface-alt); color: var(--bt-ink); border-color: var(--bt-border-strong); }

.btn-light {
  background: var(--bt-surface);
  color: var(--bt-ink);
  border-color: var(--bt-border);
}

.btn-icon {
  width: 32px; height: 32px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* ----------------------------------------------------------------------------
   Cards
   ---------------------------------------------------------------------------- */

.card {
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius);
  background: var(--bt-surface);
  box-shadow: none;
}
.card-body { padding: 1.25rem 1.4rem; }

.eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--bt-ink-muted);
}

.metric { font-variant-numeric: tabular-nums; letter-spacing: 0; }
.metric-xl { font-family: var(--font-display); font-size: 2.6rem; font-weight: 700; line-height: 1.1; }
.metric-lg { font-family: var(--font-display); font-size: 1.65rem; font-weight: 700; line-height: 1.2; }
.metric-md { font-family: var(--font-display); font-size: 1.25rem; font-weight: 600; }
@keyframes metric-tick-up {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.05); }
  100% { transform: scale(1); }
}
@keyframes metric-tick-down {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.03); }
  100% { transform: scale(1); }
}
.metric.is-tick-up   { animation: metric-tick-up   0.7s ease-out; color: var(--bt-success-700); }
.metric.is-tick-down { animation: metric-tick-down 0.7s ease-out; color: var(--bt-warning-700); }
@media (prefers-reduced-motion: reduce) {
  .metric.is-tick-up,
  .metric.is-tick-down { animation: none; }
}

/* ----------------------------------------------------------------------------
   Hero card (today's allowance)
   ---------------------------------------------------------------------------- */

.hero-card {
  position: relative;
  overflow: hidden;
  border-radius: var(--bt-radius-lg);
  background: linear-gradient(135deg, var(--bt-accent) 0%, var(--bt-primary) 55%, var(--bt-primary-700) 100%);
  color: #fff;
  padding: 1.6rem 1.75rem;
  box-shadow: 0 14px 30px -12px rgba(234,88,12,0.45);
}
.hero-card::after {
  content: "";
  position: absolute;
  right: -60px; top: -60px;
  width: 240px; height: 240px;
  background: radial-gradient(circle at center, rgba(255,255,255,0.18), transparent 60%);
  pointer-events: none;
}
.hero-card .eyebrow { color: rgba(255,255,255,0.92); }  /* was 0.78 → 4.3:1; 0.92 → ~6:1, passes AA */
.hero-card .metric-xl { color: #fff; }
.hero-card .hero-sub { color: rgba(255,255,255,0.92); font-size: 0.92rem; }  /* was 0.85 → 5:1; 0.92 → ~6:1, more comfortable */
/* Microstrip + buttons inside the terracotta hero — without these overrides
   text-muted-soft renders dark gray on terracotta and fails AA contrast. */
.hero-card .hero-microstrip { color: rgba(255,255,255,0.88); }  /* was 0.82; 0.88 → ~5.6:1, comfortably above AA */
.hero-card .text-muted-soft { color: rgba(255,255,255,0.88) !important; }
.hero-card .hero-microstrip .btn-link { color: #fff; text-decoration: underline; text-underline-offset: 3px; font-weight: 600; }
.hero-card .hero-microstrip .btn-link:hover { color: #fff; opacity: 0.92; }
.hero-card .opacity-75 { color: rgba(255,255,255,0.6); }  /* divider dot — slightly more visible */

/* ── Primary CTA inside the hero (Catat pengeluaran). Solid white pill on
   the terracotta gradient with terracotta-700 text — passes AAA. 48px
   min-height clears Apple HIG; full-width on mobile for thumb-reach. ── */
.hero-card .hero-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 48px;
  padding: 0.75rem 1.5rem;
  background: #fff;
  color: var(--bt-primary-700);
  border: 0;
  border-radius: var(--bt-radius-pill);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: -0.01em;
  cursor: pointer;
  box-shadow: 0 8px 20px -10px rgba(0,0,0,0.35);
  transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease;
}
.hero-card .hero-cta:hover {
  transform: translateY(-1px);
  background: var(--bt-primary-50);
  box-shadow: 0 12px 24px -10px rgba(0,0,0,0.4);
  color: var(--bt-primary-ink);
}
.hero-card .hero-cta:active { transform: translateY(0); }
.hero-card .hero-cta:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(255,255,255,0.65), 0 8px 20px -10px rgba(0,0,0,0.35);
}
@media (max-width: 480px) {
  /* Full-width on phones — the most reachable target on a single-hand grip. */
  .hero-card .hero-cta {
    width: 100%;
    font-size: 1.05rem;
  }
}
.hero-card.hero-overspent {
  background: linear-gradient(135deg, var(--bt-danger-500) 0%, var(--bt-danger) 60%, var(--bt-danger-700) 100%);
  box-shadow: 0 14px 30px -12px rgba(239,68,68,0.45);
}

/* When the hero card has no gradient background (bare + first-time
   variants), the white-pill CTA designed for the gradient floats as
   white-on-page. Flip it to a solid terracotta pill with white text so
   it reads as the page's primary action instead of a stray chip. */
.hero-card-bare .hero-cta,
.first-time-hero .hero-cta {
  background: var(--bt-primary);
  color: #fff;
  box-shadow: 0 6px 16px -6px rgba(234, 88, 12, 0.35);
}
.hero-card-bare .hero-cta:hover,
.first-time-hero .hero-cta:hover {
  background: var(--bt-primary-700);
  color: #fff;
  box-shadow: 0 8px 20px -6px rgba(234, 88, 12, 0.45);
}
.hero-card-bare .hero-cta:focus-visible,
.first-time-hero .hero-cta:focus-visible {
  box-shadow: 0 0 0 3px var(--bt-primary-100), 0 6px 16px -6px rgba(234, 88, 12, 0.35);
}
/* Lift the bare-hero pill slightly in dark mode so it still has presence
   on the near-black page background. Triggered by [data-theme="dark"]
   like every other dark rule. */
[data-theme="dark"] .hero-card-bare .hero-cta,
[data-theme="dark"] .first-time-hero .hero-cta {
  box-shadow: 0 8px 20px -6px rgba(0, 0, 0, 0.5);
}

/* ----------------------------------------------------------------------------
   Stat tiles
   ---------------------------------------------------------------------------- */

.stat-tile {
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius);
  background: var(--bt-surface);
  padding: 1.1rem 1.2rem;
  height: 100%;
}

/* ----------------------------------------------------------------------------
   Progress
   ---------------------------------------------------------------------------- */

.progress {
  height: 10px;
  background: var(--bt-surface-alt);
  border-radius: var(--bt-radius-pill);
  overflow: hidden;
}
.progress-bar {
  background: var(--bt-success);
  transition: width 0.5s ease, background 0.2s ease;
}
.progress-bar.bg-success { background: var(--bt-success) !important; }
.progress-bar.bg-warning { background: var(--bt-warning) !important; }
.progress-bar.bg-danger  { background: var(--bt-danger) !important; }

.progress-track {
  background: rgba(255,255,255,0.22);
}
.progress-track .progress-bar { background: rgba(255,255,255,0.85) !important; }

/* ----------------------------------------------------------------------------
   Forms
   ---------------------------------------------------------------------------- */

.form-control, .form-select {
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius-sm);
  background: var(--bt-surface);
  color: var(--bt-ink);
  font-size: 0.95rem;
  padding: 0.55rem 0.75rem;
  transition: border-color 0.12s, box-shadow 0.12s;
}
.form-control:hover, .form-select:hover { border-color: var(--bt-border-strong); }
.form-control:focus, .form-select:focus {
  border-color: var(--bt-primary);
  box-shadow: var(--bt-ring);
  outline: none;
}
.form-control-lg { font-size: 1.1rem; padding: 0.7rem 0.9rem; }
.form-label { font-weight: 500; font-size: 0.88rem; color: var(--bt-ink); margin-bottom: 0.35rem; }
.form-text { color: var(--bt-ink-soft); }

.form-control.is-invalid, .form-select.is-invalid {
  border-color: var(--bt-danger);
  background-image: none;
  padding-right: 0.75rem;
}
.invalid-feedback { color: var(--bt-danger-700); font-size: 0.82rem; }

/* Currency field with a leading symbol */
.input-currency { position: relative; }
.input-currency::before {
  content: attr(data-symbol);
  position: absolute;
  left: 0.85rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--bt-ink-soft);
  font-weight: 500;
  pointer-events: none;
  font-size: 1.05rem;
}
.input-currency .form-control { padding-left: 2.6rem; }

/* ----------------------------------------------------------------------------
   List group / expense rows
   ---------------------------------------------------------------------------- */

.list-group-flush .list-group-item {
  border-color: var(--bt-border);
  padding: 0.85rem 1.4rem;
}
.expense-row { gap: 0.75rem; transition: background 0.12s ease; }
.expense-row:hover { background: var(--bt-surface-alt); }

.expense-icon {
  flex-shrink: 0;
  width: 38px; height: 38px;
  border-radius: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  background: var(--bt-surface-alt);
  color: var(--bt-ink-muted);
}
.expense-icon.cat-food          { background: #fff7ed; color: var(--cat-food); }
.expense-icon.cat-transport     { background: #fef3c7; color: var(--cat-transport); }
.expense-icon.cat-shopping      { background: #fdf2f8; color: var(--cat-shopping); }
.expense-icon.cat-bills         { background: #f1f5f9; color: var(--cat-bills); }
.expense-icon.cat-household     { background: #ecfeff; color: var(--cat-household); }
.expense-icon.cat-entertainment { background: #f5f3ff; color: var(--cat-entertainment); }
.expense-icon.cat-health        { background: #f7fee7; color: var(--cat-health); }
.expense-icon.cat-other         { background: #f5f5f4; color: var(--cat-other); }

.expense-amount {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: var(--bt-ink);
}

.cat-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.72rem;
  font-weight: 500;
  padding: 0.18rem 0.55rem;
  border-radius: var(--bt-radius-pill);
  border: 1px solid transparent !important;
  background: var(--bt-surface-alt);
  color: var(--bt-ink-muted);
}
.cat-badge.cat-food          { background: #fff7ed !important; color: var(--cat-food) !important; }
.cat-badge.cat-transport     { background: #fef3c7 !important; color: var(--cat-transport) !important; }
.cat-badge.cat-shopping      { background: #fdf2f8 !important; color: var(--cat-shopping) !important; }
.cat-badge.cat-bills         { background: #f1f5f9 !important; color: var(--cat-bills) !important; }
.cat-badge.cat-household     { background: #ecfeff !important; color: var(--cat-household) !important; }
.cat-badge.cat-entertainment { background: #f5f3ff !important; color: var(--cat-entertainment) !important; }
.cat-badge.cat-health        { background: #f7fee7 !important; color: var(--cat-health) !important; }
.cat-badge.cat-other         { background: #f5f5f4 !important; color: var(--cat-other) !important; }

.row-actions {
  display: inline-flex;
  gap: 0.25rem;
  opacity: 0;
  transition: opacity 0.12s ease;
}
.expense-row:hover .row-actions,
.expense-row:focus-within .row-actions { opacity: 1; }
/* Inside the day-detail expansion the row is the editing surface itself —
   keep the actions visible on hover/focus on desktop, and always-on once
   touched. The opacity:0 default would hide them entirely on rows that
   never carry a `.expense-row` class. */
.day-detail-item .row-actions { opacity: 0.55; }
.day-detail-item:hover .row-actions,
.day-detail-item:focus-within .row-actions { opacity: 1; }

.row-actions .btn {
  width: 30px; height: 30px;
  padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
}

@media (max-width: 768px) {
  .row-actions { opacity: 1; } /* always visible on touch */
}

/* ----------------------------------------------------------------------------
   Category picker (in expense modal)
   ---------------------------------------------------------------------------- */

.cat-picker {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.5rem;
}
@media (max-width: 480px) { .cat-picker { grid-template-columns: repeat(3, 1fr); } }

.cat-pill {
  cursor: pointer;
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius);
  padding: 0.55rem 0.4rem;
  text-align: center;
  background: var(--bt-surface);
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--bt-ink-muted);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  transition: border-color 0.12s, background 0.12s, transform 0.06s;
}
.cat-pill:hover { border-color: var(--bt-border-strong); background: var(--bt-surface-alt); }
.cat-pill input { display: none; }
.cat-pill.is-active {
  border-color: var(--bt-primary);
  background: var(--bt-primary-50);
  color: var(--bt-primary-ink);
}
.cat-pill .cat-pill-icon {
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 1rem;
  border-radius: 8px;
  background: var(--bt-surface-alt);
}
.cat-pill.is-active .cat-pill-icon {
  background: rgba(234,88,12,0.12);
}

.quick-amounts {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
  margin-top: 0.5rem;
}
.quick-amounts .quick-amount {
  border: 1px solid var(--bt-border);
  background: var(--bt-surface);
  border-radius: var(--bt-radius-pill);
  padding: 0.25rem 0.7rem;
  font-size: 0.78rem;
  color: var(--bt-ink-muted);
  cursor: pointer;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.quick-amounts .quick-amount:hover {
  background: var(--bt-primary-50);
  color: var(--bt-primary-ink);
  border-color: var(--bt-primary);
}

/* ----------------------------------------------------------------------------
   Modal
   ---------------------------------------------------------------------------- */

.modal-content {
  border: 0;
  border-radius: var(--bt-radius-lg);
  box-shadow: var(--bt-shadow-lg);
  overflow: hidden;
}
.modal-header {
  border-bottom: 1px solid var(--bt-border);
  padding: 1.1rem 1.4rem;
}
.modal-title { font-weight: 600; }
.modal-body { padding: 1.4rem; }
.modal-footer {
  border-top: 1px solid var(--bt-border);
  padding: 0.9rem 1.4rem;
  background: var(--bt-surface-alt);
}

/* ----------------------------------------------------------------------------
   Alerts & toasts
   ---------------------------------------------------------------------------- */

.alert {
  border: 1px solid transparent;
  border-radius: var(--bt-radius);
  padding: 0.85rem 1.1rem;
  font-size: 0.93rem;
}
.alert-info    { background: var(--bt-primary-50); color: var(--bt-primary-ink); border-color: rgba(234,88,12,0.18); }
.alert-success { background: var(--bt-success-100); color: var(--bt-success-700); border-color: rgba(16,185,129,0.22); }
.alert-warning { background: var(--bt-warning-100); color: var(--bt-warning-700); border-color: rgba(245,158,11,0.22); }
.alert-danger  { background: var(--bt-danger-100); color: var(--bt-danger-700); border-color: rgba(239,68,68,0.22); }

#toast-area {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  /* Above Bootstrap modal (1055/1060) so a save-failure toast surfaces
     while the expense modal is still open. The previous 1080 was just
     above modal-backdrop but BELOW the modal itself in some browsers. */
  z-index: 1090;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-width: 360px;
  pointer-events: none;
}
.bt-toast {
  pointer-events: auto;
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-left: 3px solid var(--bt-primary);
  border-radius: var(--bt-radius);
  box-shadow: var(--bt-shadow-lg);
  padding: 0.75rem 1rem;
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  font-size: 0.9rem;
  color: var(--bt-ink);
  animation: bt-toast-in 0.18s ease;
}
.bt-toast.success { border-left-color: var(--bt-success); }
.bt-toast.warning { border-left-color: var(--bt-warning); }
.bt-toast.danger  { border-left-color: var(--bt-danger); }
.bt-toast.is-leaving { animation: bt-toast-out 0.18s ease forwards; }
.bt-toast-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
}
.bt-toast-detail {
  font-size: 0.78rem;
  color: var(--bt-ink-muted);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.005em;
}
.bt-toast.warning .bt-toast-detail { color: var(--bt-warning-700); }
.bt-toast.success .bt-toast-detail { color: var(--bt-success-700); }
.bt-toast-action {
  flex-shrink: 0;
  margin-left: 0.4rem;
  background: transparent;
  border: 0;
  color: var(--bt-primary-ink);
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: 0.2rem 0.55rem;
  border-radius: var(--bt-radius-sm);
  cursor: pointer;
}
.bt-toast-action:hover { background: var(--bt-primary-50); }

@keyframes bt-toast-in  { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
@keyframes bt-toast-out { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(8px); } }

@media (max-width: 480px) {
  #toast-area { left: 1rem; right: 1rem; bottom: 5.5rem; max-width: none; }
}

/* ----------------------------------------------------------------------------
   Month pager — prev / jump-to-month / next, sits in a single pill row
   ---------------------------------------------------------------------------- */

.month-pager {
  display: inline-flex;
  align-items: stretch;
  flex-wrap: nowrap;
  flex-shrink: 0;
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius-pill);
  padding: 3px;
  gap: 2px;
  max-width: 100%;
}

.month-pager-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: var(--bt-radius-pill);
  color: var(--bt-ink-muted);
  background: transparent;
  border: 0;
  flex-shrink: 0;
  text-decoration: none;
  transition: background 0.12s ease, color 0.12s ease;
}
.month-pager-arrow:hover {
  background: var(--bt-surface-alt);
  color: var(--bt-ink);
  text-decoration: none;
}

.month-pager-select {
  border: 0;
  background: transparent;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--bt-ink);
  padding: 0 0.6rem;
  min-width: 0;
  max-width: 200px;
  text-align: center;
  cursor: pointer;
  outline: none;
}
.month-pager-select:hover { color: var(--bt-primary-ink); }
.month-pager-select:focus-visible {
  background: var(--bt-surface-alt);
  border-radius: var(--bt-radius-pill);
}

@media (max-width: 380px) {
  .month-pager-select { max-width: 130px; }
}

/* ----------------------------------------------------------------------------
   Daily breakdown table (list view)
   ---------------------------------------------------------------------------- */

/* Plan summary cards (Pemasukan / Pengeluaran tetap / Budget·Bulan)
   — 3-up row above the rincian table. Each card is a button that opens
   the Setup modal, since tapping the totals is the natural way to edit. */
.plan-cards .stat-tile { padding: 0.85rem 1rem; }
.plan-cards .eyebrow { font-size: 0.65rem; }
.plan-cards .metric-md { font-size: 1.05rem; line-height: 1.15; }
@media (min-width: 768px) {
  .plan-cards .metric-md { font-size: 1.25rem; }
}
.stat-tile-tappable {
  border: 1px solid var(--bt-border);
  background: var(--bt-surface);
  cursor: pointer;
  transition: border-color 0.12s ease, transform 0.06s ease, box-shadow 0.12s ease;
}
.stat-tile-tappable:hover,
.stat-tile-tappable:focus-visible {
  border-color: var(--bt-primary);
  box-shadow: 0 0 0 3px rgba(234, 88, 12, 0.08);
  outline: none;
}
.stat-tile-tappable:active { transform: scale(0.99); }

/* Calc list tables — Income / Fixed Expenses side-by-side on the public
   /calc/ pages. Compact rows, tabular nums, tfoot total separated from
   the body with a soft top border. */
.calc-list-table { font-size: 0.92rem; }
.calc-list-table td {
  padding: 0.45rem 0.5rem;
  border-color: var(--bt-border);
  font-variant-numeric: tabular-nums;
}
.calc-list-table tfoot td {
  border-top: 1px solid var(--bt-border);
  background: var(--bt-surface-alt);
}

/* Description cell — truncate long expense names so a single multi-word
   note doesn't blow the row up. Cap width prevents the description column
   from dominating on desktop. */
.daily-table .day-desc { max-width: 22ch; }
.daily-table .day-desc-text {
  display: inline-block;
  max-width: 100%;
  vertical-align: middle;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Overspend "!" prefix — sits inline before a negative saldo. Pure visual
   reinforcement, no extra column needed. */
.overspend-bang {
  display: inline-block;
  font-weight: 700;
  font-size: 0.75rem;
  width: 16px; height: 16px;
  line-height: 16px;
  text-align: center;
  border-radius: 50%;
  background: var(--bt-danger-100);
  color: var(--bt-danger);
  margin-right: 4px;
}

/* Day-detail expand-list — inline expense rows revealed by the
   per-row chevron. Horizontal: icon · text · amount · actions.
   Show/hide is handled by Bootstrap's .collapse / .collapse.show rules
   above; we only style the inner layout here. */
.daily-table tbody tr.day-detail > td { background: var(--bt-surface-alt); }
.day-detail-list { padding: 0; }
.day-detail-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0.55rem 1rem 0.55rem 1.5rem;
  border-top: 1px solid var(--bt-border);
}
.day-detail-item:first-child { border-top: 0; }
.day-detail-item .expense-icon { flex-shrink: 0; }
.day-detail-text {
  flex: 1 1 auto;
  min-width: 0;
}
.day-detail-text .fw-semibold {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.day-detail-item .expense-amount {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}
.day-detail-item .row-actions {
  display: inline-flex;
  gap: 4px;
  flex-shrink: 0;
}

.daily-table { font-size: 0.92rem; }
.daily-table th {
  white-space: nowrap;
  font-weight: 600;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--bt-ink-soft);
  background: transparent !important;
  border-bottom: 1px solid var(--bt-border) !important;
  border-top: 0;
  padding: 0.7rem 0.75rem;
}
.daily-table td {
  vertical-align: middle;
  font-variant-numeric: tabular-nums;
  padding: 0.7rem 0.75rem;
  border-color: var(--bt-border);
}
.daily-table tbody tr.day-row { transition: background 0.12s ease; }
.daily-table tbody tr.day-row:hover { background: var(--bt-surface-alt); }
.daily-table tbody tr.collapse { display: none; }
.daily-table tbody tr.collapse.show { display: table-row; }

.daily-table tbody tr.is-today {
  background: linear-gradient(90deg, var(--bt-primary-50) 0%, transparent 80%);
}
.daily-table tbody tr.is-today:hover {
  background: linear-gradient(90deg, var(--bt-primary-100) 0%, var(--bt-surface-alt) 80%);
}
.daily-table tbody tr.is-today td { border-color: rgba(234,88,12,0.15); }

.daily-table tbody tr.is-future { color: var(--bt-ink-soft); }
.daily-table tbody tr.is-future td { padding-top: 0.55rem; padding-bottom: 0.55rem; opacity: 0.55; }

/* Empty days hidden by default; "show empty" toggle reveals them. */
.daily-table tbody tr.is-empty td { padding-top: 0.5rem; padding-bottom: 0.5rem; }
.daily-table tbody tr.is-empty .day-cell-num { color: var(--bt-ink-soft); }
.daily-card:not(.show-empty) .daily-table tbody tr.is-empty { display: none; }

.daily-table tfoot td {
  background: var(--bt-surface-alt);
  border-top: 2px solid var(--bt-border-strong);
  font-weight: 600;
  padding: 0.85rem 0.75rem;
}

.day-cell { display: flex; align-items: center; gap: 0.7rem; min-width: 0; }
.day-cell-num {
  font-weight: 700;
  font-size: 1rem;
  color: var(--bt-ink);
  width: 24px;
  text-align: right;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}
.day-cell-name {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.9rem;
  color: var(--bt-ink-muted);
}

.today-pill {
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  background: var(--bt-primary-100);
  color: var(--bt-primary-ink);
  padding: 0.1rem 0.45rem;
  border-radius: var(--bt-radius-pill);
  display: inline-block;
  margin-left: 0.4rem;
  vertical-align: middle;
}

/* Weekend pill — same shape as the today-pill but in a calm blue so it
   reads as informational, not "this is the row you should be acting on
   right now." Shown on Sat/Sun rows when they aren't also today. */
.weekend-pill {
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  background: #dbeafe;
  color: #1e40af;
  padding: 0.1rem 0.45rem;
  border-radius: var(--bt-radius-pill);
  display: inline-block;
  margin-left: 0.4rem;
  vertical-align: middle;
}
[data-theme="dark"] .weekend-pill {
  background: rgba(59, 130, 246, 0.18);
  color: #93c5fd;
}

.spent-amount {
  color: var(--bt-danger-700);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.items-pill {
  display: inline-block;
  min-width: 24px;
  padding: 0.1rem 0.4rem;
  background: var(--bt-surface-alt);
  border-radius: var(--bt-radius-pill);
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--bt-ink-muted);
}

/* Detail collapse arrow rotation */
.detail-toggle svg { transition: transform 0.2s ease; }
.detail-toggle[aria-expanded="true"] svg { transform: rotate(180deg); }

/* ───────── Setup page (income + fixed → derived cap) ───────── */
.setup-headline {
  border-radius: var(--bt-radius-lg);
  padding: 1.4rem 1.5rem;
  background: linear-gradient(135deg, var(--bt-primary) 0%, var(--bt-primary-700) 100%);
  color: #fff;
  box-shadow: 0 14px 30px -12px rgba(234,88,12,0.45);
}
.setup-headline .eyebrow,
.setup-headline .hero-sub { color: rgba(255,255,255,0.85); }
.setup-headline .metric-xl { color: #fff; }
.setup-headline .text-muted-soft { color: rgba(255,255,255,0.78) !important; }
.setup-headline .text-success,
.setup-headline .text-danger { color: #fff !important; }

/* Setup list rows */
.setup-row {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.6rem 0.75rem;
  border-radius: var(--bt-radius-sm);
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  transition: background 0.12s ease;
}
.setup-row:hover { background: var(--bt-surface-alt); }
.setup-row.is-paused { opacity: 0.55; }
.setup-row-name { color: var(--bt-ink); }
.setup-row-amount { font-variant-numeric: tabular-nums; }
.setup-row-actions {
  display: inline-flex;
  gap: 0.2rem;
  flex-shrink: 0;
}
.setup-row-actions .btn { width: 30px; height: 30px; padding: 0; line-height: 1; }

.setup-add-form {
  display: grid;
  grid-template-columns: 1fr 130px auto;
  gap: 0.4rem;
  align-items: stretch;
}
@media (max-width: 540px) {
  .setup-add-form { grid-template-columns: 1fr; }
}

/* Smaller currency input variant for setup add-forms */
.input-currency-sm::before { font-size: 0.85rem; left: 0.65rem; }
.input-currency-sm .form-control { padding-left: 2rem; }

/* Date quick-chips inside the expense modal — Today / Yesterday shortcuts. */
.date-quick-chips {
  display: flex;
  gap: 0.4rem;
  margin-top: 0.45rem;
  flex-wrap: wrap;
}
.date-chip {
  padding: 0.2rem 0.65rem;
  background: var(--bt-surface-alt);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius-pill);
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--bt-ink-muted);
  cursor: pointer;
  transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.date-chip:hover {
  background: var(--bt-primary-50);
  color: var(--bt-primary-ink);
  border-color: var(--bt-primary-100);
}
.date-chip.is-active {
  background: var(--bt-primary);
  color: #fff;
  border-color: var(--bt-primary);
}

@media (max-width: 768px) {
  .daily-table { font-size: 0.88rem; }
  .daily-table th, .daily-table td { padding: 0.55rem 0.4rem; }
  .daily-table th.ps-4, .daily-table td.ps-4 { padding-left: 1rem !important; }
  .daily-table th.pe-4, .daily-table td.pe-4 { padding-right: 1rem !important; }
  .day-cell-num { font-size: 0.95rem; width: 20px; }
  .day-cell-name { font-size: 0.85rem; }
}

/* ----------------------------------------------------------------------------
   Auth split-screen
   ---------------------------------------------------------------------------- */

.auth-shell {
  min-height: calc(100vh - 75px);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
}
.auth-form-side {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem 1.5rem;
}
.auth-form-card {
  width: 100%;
  max-width: 420px;
}
.auth-form-card h1 {
  font-size: 1.65rem;
  font-weight: 700;
  margin-bottom: 0.4rem;
}
.auth-form-card .auth-sub {
  color: var(--bt-ink-muted);
  font-size: 0.95rem;
  margin-bottom: 1.5rem;
}
.auth-marketing {
  background: linear-gradient(135deg, var(--bt-primary) 0%, var(--bt-primary-700) 55%, var(--bt-primary-900) 110%);
  color: #fff;
  padding: 3rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: relative;
  overflow: hidden;
}
.auth-marketing::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 80% 20%, rgba(255,255,255,0.18), transparent 40%),
    radial-gradient(circle at 20% 80%, rgba(255,255,255,0.12), transparent 50%);
  pointer-events: none;
}
.auth-marketing > * { position: relative; }
.auth-marketing h2 {
  color: #fff;
  font-size: 2rem;
  font-weight: 700;
  margin-bottom: 0.85rem;
  letter-spacing: -0.02em;
}
.auth-marketing .auth-marketing-sub {
  color: rgba(255,255,255,0.86);
  font-size: 1.05rem;
  margin-bottom: 2rem;
  max-width: 420px;
}
.auth-feature {
  display: flex;
  gap: 0.85rem;
  align-items: flex-start;
  margin-bottom: 1.1rem;
  max-width: 420px;
}
.auth-feature .auth-feature-icon {
  flex-shrink: 0;
  width: 36px; height: 36px;
  border-radius: 10px;
  background: rgba(255,255,255,0.18);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 1.1rem;
}
.auth-feature h4 { color: #fff; font-size: 1rem; font-weight: 600; margin: 0 0 0.15rem; }
.auth-feature p { color: rgba(255,255,255,0.82); font-size: 0.9rem; margin: 0; }

@media (max-width: 900px) {
  .auth-shell { grid-template-columns: 1fr; }
  .auth-marketing { display: none; }
}

/* "Continue with Google" button — Google-recommended look (white, gray
   border, Google logo + "Continue with Google" text). Matches Google's
   identity guidelines closely enough for a self-hosted app. */
.btn-google {
  background: #fff;
  color: #1f2937;
  border: 1px solid var(--bt-border-strong);
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.7rem;
  padding: 0.7rem 1.2rem;
  border-radius: var(--bt-radius-sm);
  transition: background 0.12s, border-color 0.12s, box-shadow 0.12s;
}
.btn-google:hover {
  background: var(--bt-surface-alt);
  color: var(--bt-ink);
  border-color: var(--bt-border-strong);
  text-decoration: none;
}
.btn-google:focus-visible { outline: none; box-shadow: var(--bt-ring); }
.btn-google svg { flex-shrink: 0; }

/* ----------------------------------------------------------------------------
   Settings page
   ---------------------------------------------------------------------------- */

.settings-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
}
.settings-grid > section { min-width: 0; }
.settings-grid .settings-danger { grid-column: 1 / -1; border-color: var(--bt-danger-100); }
.settings-grid .settings-danger .eyebrow { color: var(--bt-danger-700); }

@media (max-width: 768px) {
  .settings-grid { grid-template-columns: 1fr; }
}

/* The danger-zone form sits flat in the card now (collapsible <details>
   was removed per audit §9.2 #4 — export and delete carry equal weight). */

/* ----------------------------------------------------------------------------
   Monthly view — search input
   ---------------------------------------------------------------------------- */

.monthly-search { max-width: 460px; }
.monthly-search-wrap {
  position: relative;
  display: flex;
  align-items: center;
}
.monthly-search-icon {
  position: absolute;
  left: 0.85rem;
  color: var(--bt-ink-soft);
  pointer-events: none;
}
.monthly-search-input {
  padding-left: 2.4rem !important;
  padding-right: 2.4rem !important;
  background: var(--bt-surface);
}
.monthly-search-clear {
  position: absolute;
  right: 0.65rem;
  width: 22px; height: 22px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--bt-surface-alt);
  color: var(--bt-ink-muted);
  text-decoration: none;
  font-size: 0.78rem;
  line-height: 1;
}
.monthly-search-clear:hover { background: var(--bt-border); color: var(--bt-ink); text-decoration: none; }

/* ----------------------------------------------------------------------------
   Dashboard — first-run welcome state
   ---------------------------------------------------------------------------- */

.hero-card.hero-welcome {
  text-align: center;
}
.hero-card.hero-welcome .metric-lg {
  font-size: 1.5rem;
  color: #fff;
  margin: 0;
}
.hero-card.hero-welcome .btn-light {
  color: var(--bt-primary-700);
  border-color: rgba(255,255,255,0.7);
}
.hero-card.hero-welcome .btn-outline-light {
  color: #fff;
  border-color: rgba(255,255,255,0.55);
  background: transparent;
}
.hero-card.hero-welcome .btn-outline-light:hover {
  background: rgba(255,255,255,0.12);
  border-color: rgba(255,255,255,0.85);
  color: #fff;
}

/* Streak callout removed — design-rejected anti-pattern. */

/* ----------------------------------------------------------------------------
   Setup — inline-editable rows in the plan tiles. The standalone setup
   modal was removed; tiles in monthly.html are the only editing surface.
   ---------------------------------------------------------------------------- */

.setup-section { padding: 0.25rem 0; }
.setup-list { min-height: 1px; }
.setup-empty {
  padding: 0.5rem 0.25rem;
  font-style: italic;
}

/* Inline-editable setup rows */
.setup-row {
  display: block;
  padding: 0;
  border-radius: var(--bt-radius-sm);
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  transition: background 0.12s ease, border-color 0.12s ease;
}
.setup-row:hover { background: var(--bt-surface-alt); }
.setup-row.is-paused { opacity: 0.55; }
.setup-row.is-editing {
  background: var(--bt-primary-50);
  border-color: var(--bt-primary-100);
}

.setup-row-display {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.55rem 0.75rem;
}
.setup-row.is-editing > .setup-row-display { display: none; }

.setup-row-name { color: var(--bt-ink); }
.setup-row-amount { font-variant-numeric: tabular-nums; }

.setup-row-actions {
  display: inline-flex;
  gap: 0.2rem;
  flex-shrink: 0;
}
.setup-row-actions .btn { width: 30px; height: 30px; padding: 0; line-height: 1; display: inline-flex; align-items: center; justify-content: center; }

/* Edit form is hidden by default — `is-editing` on the parent row reveals it.
   Author CSS would normally override the UA `[hidden] { display: none }` rule
   if we relied on the attribute alone, so use a class toggle instead. */
.setup-row > .setup-row-edit { display: none; }
.setup-row.is-editing > .setup-row-edit {
  display: grid;
  grid-template-columns: 1fr 130px auto;
  gap: 0.4rem;
  padding: 0.5rem 0.6rem;
  align-items: center;
}
.setup-row-edit-actions {
  display: inline-flex;
  gap: 0.2rem;
  flex-shrink: 0;
}
.setup-row-edit-actions .btn { width: 30px; height: 30px; padding: 0; line-height: 1; display: inline-flex; align-items: center; justify-content: center; }

@media (max-width: 540px) {
  .setup-row-edit { grid-template-columns: 1fr; }
  .setup-row-edit-actions { justify-content: flex-end; }
}

/* ----------------------------------------------------------------------------
   Empty states
   ---------------------------------------------------------------------------- */

.empty-state {
  text-align: center;
  padding: 2.25rem 1rem;
  color: var(--bt-ink-soft);
}
.empty-state .empty-icon {
  width: 56px; height: 56px;
  margin: 0 auto 0.75rem;
  border-radius: 50%;
  background: var(--bt-surface-alt);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--bt-ink-soft);
  font-size: 1.4rem;
}
.empty-state h6 { color: var(--bt-ink); font-weight: 600; margin: 0 0 0.25rem; }
.empty-state p { margin: 0; font-size: 0.9rem; }

/* ----------------------------------------------------------------------------
   Misc helpers
   ---------------------------------------------------------------------------- */

/* Resolved to the darker --bt-ink-muted (#5b6478) so timestamps/labels meet
   WCAG AA contrast on white surfaces (4.7:1). Use --bt-ink-soft only on
   surfaces dimmer than white (badges, muted controls). */
.text-muted-soft { color: var(--bt-ink-muted) !important; }
.divider {
  height: 1px; background: var(--bt-border); margin: 1.25rem 0;
}
hr { border-color: var(--bt-border); }


/* Mobile niceties */
@media (max-width: 576px) {
  main.container { padding-bottom: 6rem; }
  .metric-xl { font-size: 2.1rem; }
  .hero-card { padding: 1.3rem 1.4rem; }
  .card-body { padding: 1.1rem 1.2rem; }
  .modal-body { padding: 1.1rem; }
  .modal-footer { padding: 0.75rem 1.1rem; }
  .bt-nav-link { padding: 0.4rem 0.6rem; font-size: 0.85rem; }
  .bt-nav-link span:not(.visually-hidden) { display: none; }
  .bt-brand span:last-child { display: none; }
}

@media (max-width: 576px) {
}
#dayDetailModal .modal-body { padding: 0; }
#dayDetailModal .row-actions { display: inline-flex; gap: 0.25rem; }

/* ----------------------------------------------------------------------------
   Landing page (public marketing surface at /)
   ---------------------------------------------------------------------------- */

.landing-hero {
  margin: -2rem -12px 4rem;
  padding: 4rem 1.5rem 3rem;
  background:
    radial-gradient(circle at 90% 10%, rgba(234,88,12,0.08), transparent 45%),
    radial-gradient(circle at 10% 90%, rgba(236,72,153,0.06), transparent 45%);
}
.landing-hero-inner {
  max-width: 1100px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3rem;
  align-items: center;
}
.landing-hero-copy { max-width: 520px; }
.landing-eyebrow {
  display: inline-block;
  background: var(--bt-primary-50);
  color: var(--bt-primary-ink);
  font-size: 0.78rem;
  font-weight: 700;
  padding: 0.3rem 0.7rem;
  border-radius: var(--bt-radius-pill);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 1.2rem;
}
.landing-h1 {
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 5vw, 3.4rem);
  line-height: 1.05;
  margin: 0 0 1rem;
  color: var(--bt-ink);
}
.landing-lede {
  font-size: 1.15rem;
  color: var(--bt-ink-muted);
  line-height: 1.55;
  margin-bottom: 1.6rem;
}
.landing-cta-row {
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.landing-microcopy { font-size: 0.85rem; }

.landing-hero-visual {
  display: flex;
  justify-content: center;
  align-items: center;
}
.landing-mock {
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius-lg);
  box-shadow: var(--bt-shadow-lg);
  padding: 1.4rem 1.5rem;
  width: 100%;
  max-width: 380px;
  transform: rotate(-1.5deg);
}
.landing-mock-eyebrow {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--bt-ink-soft);
}
.landing-mock-amount {
  font-family: var(--font-display);
  font-size: 2.6rem;
  color: var(--bt-primary-ink);
  line-height: 1.05;
  margin: 0.2rem 0 0.4rem;
}
.landing-mock-sub {
  font-size: 0.85rem;
  color: var(--bt-ink-muted);
  margin-bottom: 0.85rem;
}
.landing-mock-bar {
  height: 6px;
  background: var(--bt-surface-alt);
  border-radius: var(--bt-radius-pill);
  overflow: hidden;
  margin-bottom: 1rem;
}
.landing-mock-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--bt-primary), var(--bt-accent));
  border-radius: var(--bt-radius-pill);
}
.landing-section-head {
  text-align: center;
  margin-bottom: 2rem;
}
.landing-section-head .eyebrow {
  display: inline-block;
  margin-bottom: 0.6rem;
}
.landing-h2 {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 3.5vw, 2.2rem);
  line-height: 1.15;
  margin: 0;
}

.landing-features { margin-bottom: 4rem; }
.landing-feature {
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius);
  padding: 1.6rem;
  height: 100%;
  transition: transform 0.18s, box-shadow 0.18s;
}
.landing-feature:hover {
  transform: translateY(-2px);
  box-shadow: var(--bt-shadow);
}
.landing-feature-icon {
  width: 48px; height: 48px;
  border-radius: 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0.9rem;
}
.landing-feature-icon--primary { background: var(--bt-primary-50); color: var(--bt-primary-ink); }
.landing-feature-icon--warning { background: var(--bt-warning-100); color: var(--bt-warning); }
.landing-feature-icon--success { background: var(--bt-success-100); color: var(--bt-success); }
.landing-feature h3 {
  font-size: 1.1rem;
  font-weight: 700;
  margin: 0 0 0.4rem;
  font-family: var(--font-body);
  color: var(--bt-ink);
  letter-spacing: -0.01em;
}
.landing-feature p {
  color: var(--bt-ink-muted);
  font-size: 0.95rem;
  line-height: 1.55;
  margin: 0;
}

.landing-how { margin-bottom: 4rem; }
.landing-steps {
  list-style: none;
  padding: 0;
  margin: 0;
  max-width: 720px;
  margin-left: auto;
  margin-right: auto;
  display: flex;
  flex-direction: column;
  gap: 1.2rem;
}
.landing-steps li {
  display: flex;
  gap: 1.2rem;
  align-items: flex-start;
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius);
  padding: 1.3rem 1.5rem;
}
.landing-step-num {
  flex-shrink: 0;
  width: 36px; height: 36px;
  border-radius: 999px;
  background: var(--bt-primary-50);
  color: var(--bt-primary-ink);
  font-weight: 800;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.landing-steps h4 {
  font-size: 1rem;
  font-weight: 700;
  margin: 0 0 0.25rem;
  font-family: var(--font-body);
  color: var(--bt-ink);
  letter-spacing: -0.01em;
}
.landing-steps p {
  color: var(--bt-ink-muted);
  font-size: 0.92rem;
  margin: 0;
}

.landing-pricing { margin-bottom: 4rem; }
.landing-pricing-card {
  max-width: 380px;
  margin: 0 auto;
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius-lg);
  padding: 1.8rem;
  text-align: center;
  box-shadow: var(--bt-shadow);
}
.landing-pricing-amount {
  font-family: var(--font-display);
  font-size: 2.8rem;
  color: var(--bt-primary-ink);
  line-height: 1;
}
.landing-pricing-period {
  color: var(--bt-ink-muted);
  font-size: 0.9rem;
  margin-bottom: 1.2rem;
}
.landing-pricing-features {
  list-style: none;
  padding: 0;
  margin: 0;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}
.landing-pricing-features li {
  font-size: 0.95rem;
  color: var(--bt-ink);
}

.landing-faq { margin-bottom: 4rem; }
.landing-faq-list {
  max-width: 720px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
.landing-faq-item {
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius);
  padding: 1rem 1.2rem;
}
.landing-faq-item summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--bt-ink);
  list-style: none;
  position: relative;
  padding-right: 1.5rem;
}
.landing-faq-item summary::-webkit-details-marker { display: none; }
.landing-faq-item summary::after {
  content: "+";
  position: absolute;
  right: 0;
  top: 0;
  font-size: 1.2rem;
  color: var(--bt-ink-soft);
  transition: transform 0.18s;
}
.landing-faq-item[open] summary::after {
  transform: rotate(45deg);
}
.landing-faq-item p {
  color: var(--bt-ink-muted);
  font-size: 0.92rem;
  margin: 0.7rem 0 0;
  line-height: 1.55;
}

.landing-final-cta {
  text-align: center;
  padding: 3rem 1rem;
  background: var(--bt-primary-50);
  border-radius: var(--bt-radius-lg);
  margin: 0 -12px 3rem;
}

.landing-footer {
  border-top: 1px solid var(--bt-border);
  padding: 1.5rem 0;
  margin-top: 1rem;
}

/* .landing-quote-card is rendered directly inside .landing-principle now;
   the previous section wrapper was removed in the Filosofi merge. */
.landing-quote-card {
  max-width: 760px;
  margin: 0 auto 2rem;
  position: relative;
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-left: 4px solid var(--bt-primary);
  border-radius: var(--bt-radius-lg);
  padding: 2rem 2rem 1.6rem;
  box-shadow: var(--bt-shadow);
}
.landing-quote-mark {
  position: absolute;
  top: -0.4rem;
  left: 1.2rem;
  font-family: var(--font-display);
  font-size: 5rem;
  line-height: 1;
  color: var(--bt-primary);
  opacity: 0.18;
  pointer-events: none;
  user-select: none;
}
.landing-quote-text {
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 2.6vw, 1.7rem);
  line-height: 1.35;
  color: var(--bt-ink);
  margin: 0 0 0.8rem;
  font-style: italic;
}
.landing-quote-author {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--bt-ink-muted);
  letter-spacing: 0.02em;
}
.landing-quote-gloss {
  margin: 1.1rem 0 0;
  padding-top: 1rem;
  border-top: 1px dashed var(--bt-border);
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--bt-ink-muted);
}

.landing-principle {
  margin-bottom: 4rem;
}
.landing-principle-grid {
  list-style: none;
  padding: 0;
  margin: 0 auto;
  max-width: 1100px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.2rem;
}
.landing-principle-card {
  position: relative;
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius);
  padding: 1.6rem 1.5rem 1.4rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
.landing-principle-num {
  width: 32px; height: 32px;
  border-radius: 999px;
  background: var(--bt-primary-50);
  color: var(--bt-primary-ink);
  font-weight: 800;
  font-size: 0.95rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0.2rem;
}
.landing-principle-card h3 {
  font-size: 1.05rem;
  font-weight: 700;
  margin: 0;
  font-family: var(--font-body);
  color: var(--bt-ink);
  letter-spacing: -0.01em;
  line-height: 1.3;
}
.landing-principle-card > p {
  color: var(--bt-ink-muted);
  font-size: 0.93rem;
  line-height: 1.55;
  margin: 0;
}
.landing-principle-why {
  margin-top: auto;
  background: var(--bt-primary-50);
  border-radius: var(--bt-radius-sm, 0.5rem);
  padding: 0.75rem 0.9rem;
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--bt-primary-ink);
}
.landing-principle-why strong {
  font-weight: 700;
  margin-right: 0.25rem;
}
.landing-principle-footer {
  max-width: 760px;
  margin: 1.6rem auto 0;
  padding: 1.2rem 1.5rem;
  text-align: center;
  border-top: 1px dashed var(--bt-border);
}
.landing-principle-footer p {
  margin: 0;
  font-size: 0.98rem;
  line-height: 1.55;
  color: var(--bt-ink-muted);
}
.landing-principle-footer strong { color: var(--bt-ink); }

@media (max-width: 900px) {
  .landing-hero { padding: 3rem 1rem 2rem; }
  .landing-hero-inner {
    grid-template-columns: 1fr;
    gap: 2rem;
  }
  .landing-mock { transform: none; max-width: 340px; }
  .landing-cta-row .btn { width: 100%; }
  .landing-principle-grid { grid-template-columns: 1fr; }
  .landing-quote-card { padding: 1.6rem 1.4rem 1.4rem; }
  .landing-quote-mark { font-size: 4rem; }
}

/* ── Onboarding shell ─────────────────────────────────────────────────── */
.onboarding-shell {
  max-width: 460px;
  margin: 0 auto;
  padding: 1rem 0 4rem;
}
.onboarding-progress {
  width: 100%;
  height: 6px;
  background: var(--bt-border);
  border-radius: 6px;
  overflow: hidden;
  margin-bottom: 8px;
}
.onboarding-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--bt-primary) 0%, var(--bt-primary-700) 100%);
  border-radius: 6px;
  transition: width 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.onboarding-step-counter {
  text-align: right;
  font-family: var(--font-arcade);
  font-size: 0.78rem;
  color: var(--bt-ink-soft);
  margin-bottom: 1.5rem;
}
.onboarding-step {
  display: none;
  text-align: center;
  animation: ob-fade 0.3s ease;
}
.onboarding-step.is-active { display: block; }
@keyframes ob-fade {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}
.onboarding-mascot {
  margin: 0 auto 1.25rem;
  display: inline-block;
}
.onboarding-mascot-celebrate {
  animation: ob-bounce 0.8s ease infinite alternate;
}
@keyframes ob-bounce {
  from { transform: translateY(0); }
  to { transform: translateY(-6px); }
}
.onboarding-h1 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 2rem;
  margin: 0 0 0.5rem;
  color: var(--bt-ink);
}
.onboarding-h2 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.45rem;
  margin: 0 0 0.5rem;
  color: var(--bt-ink);
}
.onboarding-lede, .onboarding-sub {
  color: var(--bt-ink-muted);
  font-size: 1rem;
  line-height: 1.5;
  margin-bottom: 1.25rem;
}
.onboarding-input {
  text-align: center;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.2rem;
}
.onboarding-amount-input {
  display: flex;
  align-items: center;
  background: var(--bt-surface);
  border: 2px solid var(--bt-border-strong);
  border-radius: 14px;
  padding: 4px 12px 4px 16px;
  transition: border-color 0.15s ease;
}
.onboarding-amount-input:focus-within {
  border-color: var(--bt-primary);
  box-shadow: 0 0 0 4px var(--bt-primary-50);
}
.onboarding-currency {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.4rem;
  color: var(--bt-ink-muted);
  margin-right: 8px;
}
.onboarding-amount-input input {
  border: none !important;
  box-shadow: none !important;
  background: transparent !important;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.6rem;
  text-align: left;
  padding-left: 0;
}
.onboarding-quick-amounts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  margin: 12px 0;
}
/* Income-anchor disclosure (optional) — collapsed by default so the primary
   CTA "Mulai" stays the dominant action. Opening it reveals the Income field
   so users who want their cap anchored to a real salary can do that in one
   form instead of finding /setup/ later. */
.onboarding-income-anchor {
  background: var(--bt-surface-alt);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius);
  padding: 0.6rem 0.9rem;
}
.onboarding-income-anchor > summary {
  cursor: pointer;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--bt-ink-muted);
  list-style: none;
}
.onboarding-income-anchor > summary::-webkit-details-marker { display: none; }
.onboarding-income-anchor > summary::after {
  content: "▾";
  margin-left: 0.5rem;
  transition: transform 0.15s ease;
  display: inline-block;
}
.onboarding-income-anchor[open] > summary::after { transform: rotate(180deg); }
.onboarding-income-anchor[open] > summary { color: var(--bt-ink); }
.onboarding-income-body {
  padding-top: 0.5rem;
}
.onboarding-preview {
  background: var(--bt-primary-50);
  border-radius: 12px;
  padding: 12px 16px;
  margin-top: 12px;
  text-align: center;
}
.onboarding-preview-amount {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.6rem;
  color: var(--bt-primary-ink);
}
.onboarding-prev {
  display: block;
  margin: 8px auto 0;
  color: var(--bt-ink-soft);
  text-decoration: none;
}
.onboarding-skip {
  display: block;
  text-align: center;
  margin-top: 1rem;
  text-decoration: underline;
}

/* ── /coba public calculator ──────────────────────────────────────────── */
.coba-shell {
  max-width: 480px;
  margin: 0 auto;
  padding: 2rem 0 4rem;
  text-align: center;
}
.coba-mascot { margin-bottom: 1rem; display: inline-block; }
.coba-h1 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.9rem;
  color: var(--bt-ink);
}
.coba-lede {
  color: var(--bt-ink-muted);
  margin-bottom: 1.5rem;
}
.coba-card {
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-radius: 18px;
  padding: 1.25rem;
  text-align: left;
  box-shadow: var(--bt-shadow-sm, 0 1px 3px rgba(0,0,0,0.06));
}
.coba-label {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--bt-ink);
  margin-bottom: 6px;
}
.coba-amount-input {
  display: flex;
  align-items: center;
  background: var(--bt-surface-alt);
  border: 1px solid var(--bt-border);
  border-radius: 12px;
  padding: 4px 14px;
}
.coba-amount-input input {
  border: none !important;
  box-shadow: none !important;
  background: transparent !important;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.4rem;
}
.coba-currency {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--bt-ink-muted);
  margin-right: 8px;
}
.coba-quick {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}
.coba-quick button {
  border: 1px solid var(--bt-border-strong);
  background: var(--bt-surface);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 0.85rem;
  cursor: pointer;
}
.coba-quick button:hover {
  background: var(--bt-primary-50);
  border-color: var(--bt-primary);
}
.coba-preview-frame {
  margin-top: 1.25rem;
  position: relative;
  padding: 1.5rem 0.5rem 0.5rem;
  background: var(--bt-surface-alt);
  border-radius: var(--bt-radius);
  border: 1px dashed var(--bt-border-strong);
}
.coba-preview-tag {
  position: absolute;
  top: -10px;
  left: 14px;
  background: var(--bt-surface);
  color: var(--bt-ink-muted);
  font-size: 0.7rem;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: var(--bt-radius-pill);
  border: 1px solid var(--bt-border-strong);
}
.coba-result {
  background: linear-gradient(135deg, var(--bt-primary-50) 0%, var(--bt-accent-50) 100%);
  border-radius: 12px;
  padding: 16px;
  text-align: center;
  margin: 0;
}
.coba-result-eyebrow {
  font-family: var(--font-arcade);
  font-size: 0.78rem;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--bt-primary-ink);
}
.coba-result-amount {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 2.4rem;
  color: var(--bt-ink);
  margin-top: 4px;
}
.coba-result-sub {
  font-size: 0.85rem;
  color: var(--bt-ink-muted);
  margin-top: 4px;
}
.coba-cta-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  margin-top: 1.5rem;
}

/* ── Landing trust trifecta + new sections ──────────────────────────── */
.landing-trust-trifecta {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  padding: 0;
  margin: 0 0 1.25rem;
}
.landing-trust-trifecta li {
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--bt-success-700);
}

.landing-mock-savestate {
  margin-top: 12px;
  background: var(--bt-success-100);
  color: var(--bt-success-700);
  border-radius: 999px;
  padding: 6px 12px;
  display: inline-block;
  font-size: 0.85rem;
  font-weight: 600;
}
.landing-mock-savestate-dot { font-size: 1rem; }

.landing-founder {
  padding: 3rem 0;
}
.landing-founder-card {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  align-items: center;
  /* Warm sand-to-clay tints, hardcoded so they don't theme-flip — the
     founder card stays a light pastel surface in dark mode too (text
     below is hardcoded dark for the same reason). */
  background: linear-gradient(135deg, #fdf2eb 0%, #fbe4d6 50%, #fed7aa 100%);
  border-radius: 24px;
  padding: 1.5rem;
  margin: 0 -12px;
}
.landing-founder-mascot {
  flex-shrink: 0;
  background: rgba(255, 255, 255, 0.55);
  border-radius: 50%;
  padding: 12px;
  width: 120px;
  height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.landing-founder-photo {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
}
.landing-founder-initials {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--bt-primary) 0%, var(--bt-accent) 100%);
  color: #fff;
  font-family: var(--font-display);
  font-size: 48px;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
  letter-spacing: -1px;
  /* Soft shadow + inner highlight so the initials feel more "person-shaped"
     than the generic-circle look. Real photo is preferred (set FOUNDER_PHOTO)
     but this carries the "indie creator" trust signal better than a flat disk. */
  box-shadow: 0 6px 18px -6px rgba(124, 45, 18, 0.6),
              inset 0 -8px 24px rgba(0, 0, 0, 0.12);
  position: relative;
}
.landing-founder-initials::after {
  /* Subtle online-presence dot, mirroring the "Made by someone real" vibe. */
  content: "";
  position: absolute;
  bottom: 4px;
  right: 4px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #22c55e;
  border: 3px solid var(--bt-surface, #fff);
}
.landing-founder-text {
  flex: 1;
  min-width: 240px;
}
/* The founder card stays a warm pastel surface in dark mode too — so text
   inside MUST stay dark regardless of theme, otherwise the dark-mode
   `--bt-ink` near-white renders invisibly on the pastel. These colors are
   absolute (#hex), not var(--bt-ink), on purpose. */
.landing-founder-text p {
  margin-bottom: 0.75rem;
  font-size: 1rem;
  color: #0f1729;
}
.landing-founder-quote {
  margin: 0 0 1rem;
  padding: 0;
  border: 0;
  font-size: 1.25rem;
  line-height: 1.4;
  font-weight: 600;
  color: #0f1729;
}
.landing-founder-quote cite {
  display: block;
  margin-top: 0.5rem;
  font-style: normal;
  font-size: 0.875rem;
  font-weight: 500;
  color: #5b6478;
}
.landing-founder-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 0.5rem;
}

.landing-final-mascot {
  margin: 0 auto 0.75rem;
  display: inline-block;
}

/* ── Landing v2: animations, mini-mocks, polish ────────────────────── */

/* Scroll-reveal: sections fade-in-up the first time they cross the viewport.
   IntersectionObserver in landing.html toggles .is-revealed. The base state
   is invisible + translated so the first paint never flashes the final
   position; reduced-motion users skip straight to .is-revealed via JS. */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.55s ease, transform 0.55s ease;
}
.reveal.is-revealed {
  opacity: 1;
  transform: none;
}

/* Hero eyebrow gets a small pulsing dot to read more "live indie project"
   than the static pill it replaces. */
.landing-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
.landing-eyebrow-dot {
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: var(--bt-success, #22c55e);
  box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.55);
  animation: landing-pulse-dot 1.8s ease-in-out infinite;
}
@keyframes landing-pulse-dot {
  0%, 100% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.55); }
  60%      { box-shadow: 0 0 0 8px rgba(34, 197, 94, 0); }
}

/* Two-line hero h1 with a tinted accent line so the page has a clear
   focal point above the fold without needing a hero image. */
.landing-h1-accent {
  background: linear-gradient(90deg, var(--bt-primary) 0%, var(--bt-accent) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Trust chips replace the bullet trifecta — heavier visual weight, less
   reading, scans in under a second. */
.landing-chip-row {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 0;
  margin: 0 0 1.5rem;
}
.landing-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius-pill);
  padding: 0.45rem 0.9rem;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--bt-ink);
  box-shadow: 0 1px 0 rgba(0,0,0,0.02);
}

/* CTA arrow nudge — the only motion on the CTA itself, no glow/bounce
   that would feel salesy. */
.landing-cta { position: relative; }
.landing-cta-arrow {
  display: inline-block;
  transition: transform 0.22s ease;
}
.landing-cta:hover .landing-cta-arrow,
.landing-cta:focus-visible .landing-cta-arrow {
  transform: translateX(4px);
}

/* Phone mock wrapper hosts the floating emojis. The mock keeps its
   existing tilt; the emojis bob around it. */
.landing-mock-wrap {
  position: relative;
  display: inline-block;
}
.landing-float {
  position: absolute;
  font-size: 1.6rem;
  pointer-events: none;
  filter: drop-shadow(0 4px 8px rgba(0,0,0,0.12));
  animation: landing-bob 4s ease-in-out infinite;
}
.landing-float--1 { top: -10px;  left: -22px;  animation-delay: 0s;   }
.landing-float--2 { top: 40%;    right: -28px; animation-delay: 1.1s; font-size: 1.4rem; }
.landing-float--3 { bottom: -8px; left: 20%;   animation-delay: 2.2s; font-size: 1.2rem; }
@keyframes landing-bob {
  0%, 100% { transform: translateY(0)   rotate(-4deg); }
  50%      { transform: translateY(-10px) rotate(6deg); }
}

/* Hero number is split into currency + integer + suffix so the count-up
   only re-renders the integer span; tabular-nums prevents layout jitter. */
.landing-mock-amount {
  display: flex;
  align-items: baseline;
  gap: 0.15rem;
}
.landing-mock-currency {
  font-size: 1.4rem;
  color: var(--bt-primary-ink);
  font-weight: 700;
}
.landing-mock-number {
  font-variant-numeric: tabular-nums;
  display: inline-block;
  min-width: 2.5ch;
  text-align: right;
}

/* Bar fills on first paint instead of appearing pre-filled. */
.landing-mock-fill {
  width: 0;
  animation: landing-bar-fill 1.4s cubic-bezier(0.22, 1, 0.36, 1) 0.25s forwards;
}
@keyframes landing-bar-fill {
  from { width: 0; }
  to   { width: var(--target-width, 38%); }
}

/* Green status dot — was an emoji, swap for a styled element that can pulse
   and theme-match. Keeps the "🟢" intent without the rendering inconsistency
   across iOS/Android. */
.landing-mock-savestate {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}
.landing-mock-savestate-dot {
  width: 9px;
  height: 9px;
  border-radius: 999px;
  background: #22c55e;
  box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.55);
  animation: landing-pulse-dot 2s ease-in-out infinite;
}

/* Glance section — 3 mini-mocks that *show* the product instead of
   describing it. Replaces the old text-heavy "landing-features" cards. */
.landing-glance { margin-bottom: 4rem; }
.landing-glance-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  max-width: 1100px;
  margin: 0 auto;
}
.landing-glance-card {
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius);
  padding: 1.2rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.landing-glance-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--bt-shadow);
}
.landing-glance-mini {
  background: linear-gradient(135deg, var(--bt-primary-50) 0%, var(--bt-accent-100, var(--bt-primary-50)) 100%);
  border-radius: 12px;
  padding: 0.9rem 1rem;
  min-height: 110px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.5rem;
}
.landing-glance-caption {
  font-size: 0.92rem;
  color: var(--bt-ink-muted);
  line-height: 1.45;
}
.landing-glance-caption strong {
  display: block;
  color: var(--bt-ink);
  margin-bottom: 0.15rem;
}

.landing-mini-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--bt-primary-ink);
}
.landing-mini-amount {
  font-family: var(--font-display);
  font-size: 1.6rem;
  color: var(--bt-ink);
  line-height: 1;
}
.landing-mini-bar {
  height: 5px;
  background: rgba(255,255,255,0.55);
  border-radius: 999px;
  overflow: hidden;
}
.landing-mini-bar span {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--bt-primary), var(--bt-accent));
  border-radius: 999px;
}

.landing-mini-input {
  font-family: var(--font-display);
  font-size: 1.4rem;
  color: var(--bt-ink);
  display: flex;
  align-items: baseline;
  gap: 0.3rem;
}
.landing-mini-input-currency {
  font-size: 0.95rem;
  color: var(--bt-primary-ink);
}
.landing-mini-input-caret {
  display: inline-block;
  color: var(--bt-primary);
  font-weight: 400;
  animation: landing-caret-blink 1s steps(2, end) infinite;
  margin-left: 2px;
}
@keyframes landing-caret-blink {
  0%, 49%   { opacity: 1; }
  50%, 100% { opacity: 0; }
}
.landing-mini-chip-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.landing-mini-chip {
  background: rgba(255,255,255,0.7);
  border-radius: 999px;
  padding: 4px 10px;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--bt-ink);
}
.landing-mini-chip--active {
  background: var(--bt-primary);
  color: #fff;
}

.landing-mini-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 0.82rem;
  color: var(--bt-ink);
  padding: 3px 0;
  border-bottom: 1px dashed rgba(0,0,0,0.07);
}
.landing-mini-row:last-child { border-bottom: 0; }
.landing-mini-pill {
  font-family: var(--font-display);
  font-size: 0.82rem;
  font-weight: 700;
  padding: 2px 9px;
  border-radius: 999px;
  font-variant-numeric: tabular-nums;
}
.landing-mini-pill--green {
  background: var(--bt-success-100, #dcfce7);
  color: var(--bt-success-700, #15803d);
}
.landing-mini-pill--red {
  background: var(--bt-warning-100, #fee2e2);
  color: var(--bt-warning-700, #b91c1c);
}

/* Step cards now have an emoji affordance + lift on hover. The body wrap
   lets the title sit on one line with the emoji while the description
   flows underneath. */
.landing-steps li { transition: transform 0.2s ease, box-shadow 0.2s ease; }
.landing-steps li:hover { transform: translateX(3px); box-shadow: var(--bt-shadow); }
.landing-step-body { flex: 1; }
.landing-step-emoji {
  display: inline-block;
  margin-left: 0.35rem;
  font-size: 1.1rem;
  vertical-align: -2px;
}

/* Pricing FREE corner badge — gently rotates in to draw the eye to the
   big zero. Pure CSS, runs once. */
.landing-pricing-card { position: relative; overflow: visible; }
.landing-pricing-badge {
  position: absolute;
  top: -14px;
  right: -10px;
  background: linear-gradient(135deg, var(--bt-success, #22c55e) 0%, #15803d 100%);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 0.95rem;
  letter-spacing: 0.05em;
  padding: 8px 14px;
  border-radius: 999px;
  transform: rotate(8deg);
  box-shadow: 0 8px 18px -6px rgba(21, 128, 61, 0.5);
  animation: landing-badge-wiggle 4.5s ease-in-out infinite;
}
@keyframes landing-badge-wiggle {
  0%, 100% { transform: rotate(8deg)  translateY(0); }
  50%      { transform: rotate(10deg) translateY(-3px); }
}

/* Faq summary gets a subtle hover so it reads as interactive. */
.landing-faq-item summary { transition: color 0.15s ease; }
.landing-faq-item summary:hover { color: var(--bt-primary-ink); }

/* Mobile tweaks for new sections. */
@media (max-width: 900px) {
  .landing-glance-grid { grid-template-columns: 1fr; }
  .landing-float--1 { top: -6px;  left: -10px; }
  .landing-float--2 { right: -14px; }
}

/* ── Landing v3: live ticker, stats strip, before/after ──────────────── */

/* Hero gets two large soft-blob auras that slowly drift behind the mock.
   They're decorative-only (parent has aria-hidden) and pointer-events:
   none so they never intercept clicks on the CTA. */
.landing-hero-visual { position: relative; }
.landing-hero-blob {
  position: absolute;
  border-radius: 50%;
  filter: blur(50px);
  opacity: 0.55;
  pointer-events: none;
  z-index: 0;
}
.landing-hero-blob--a {
  width: 280px; height: 280px;
  top: -40px; left: -30px;
  background: radial-gradient(circle, rgba(234,88,12,0.45), transparent 70%);
  animation: landing-blob-drift 14s ease-in-out infinite;
}
.landing-hero-blob--b {
  width: 220px; height: 220px;
  bottom: -50px; right: -20px;
  background: radial-gradient(circle, rgba(236,72,153,0.35), transparent 70%);
  animation: landing-blob-drift 16s ease-in-out infinite reverse;
  animation-delay: -4s;
}
@keyframes landing-blob-drift {
  0%, 100% { transform: translate(0, 0)     scale(1); }
  33%      { transform: translate(20px, -16px) scale(1.08); }
  66%      { transform: translate(-14px, 20px) scale(0.94); }
}
.landing-mock-wrap { position: relative; z-index: 1; }

/* Phone-app chrome — three dots + title bar — so the mock reads as a
   real app screenshot, not a generic card. */
.landing-mock { padding: 0; overflow: hidden; }
.landing-mock-chrome {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 14px;
  background: var(--bt-surface-alt, #f8f6f3);
  border-bottom: 1px solid var(--bt-border);
}
.landing-mock-chrome-dot {
  width: 9px; height: 9px;
  border-radius: 999px;
  background: var(--bt-border);
}
.landing-mock-chrome-dot:nth-child(1) { background: #f87171; }
.landing-mock-chrome-dot:nth-child(2) { background: #fbbf24; }
.landing-mock-chrome-dot:nth-child(3) { background: #34d399; }
.landing-mock-chrome-title {
  margin-left: auto;
  font-family: var(--font-display);
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--bt-ink-soft);
  letter-spacing: 0.04em;
}
.landing-mock-body {
  padding: 1.4rem 1.5rem;
  position: relative;
}

/* Live ticker toast — slides up from inside the mock when JS fires a
   simulated expense. Pure-CSS in/out: JS just toggles .is-in / .is-out
   so we get smooth slide+fade without timing math in JS. */
.landing-mock-toast {
  position: absolute;
  left: 14px; right: 14px; bottom: 14px;
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--bt-ink);
  color: #fff;
  border-radius: 12px;
  padding: 8px 12px;
  font-size: 0.85rem;
  box-shadow: 0 12px 24px -8px rgba(0,0,0,0.3);
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.32s ease, transform 0.32s cubic-bezier(0.22, 1, 0.36, 1);
}
.landing-mock-toast[hidden] { display: none; }
.landing-mock-toast.is-in  { opacity: 1; transform: translateY(0); }
.landing-mock-toast.is-out { opacity: 0; transform: translateY(-6px); }
.landing-mock-toast-emoji { font-size: 1.1rem; line-height: 1; }
.landing-mock-toast-text  { flex: 1; }
.landing-mock-toast-text strong { font-family: var(--font-display); font-weight: 700; }
.landing-mock-toast-check {
  color: #34d399;
  font-weight: 800;
  font-size: 1.1rem;
}

/* Bar transitions smoothly when JS updates width — the initial 0→38%
   fill animation runs once, then JS-driven changes glide via this
   transition. */
.landing-mock-fill {
  transition: width 0.55s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Stats strip — three giant numbers that count up on first reveal.
   Sits in its own band right under the hero so the eye gets pulled
   downward instead of bouncing back to the CTA. */
.landing-stats {
  margin: 0 -12px 4rem;
  padding: 2rem 1.5rem;
  background: linear-gradient(135deg, var(--bt-primary) 0%, var(--bt-accent) 100%);
  border-radius: var(--bt-radius-lg);
  color: #fff;
  position: relative;
  overflow: hidden;
}
.landing-stats::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 20% 30%, rgba(255,255,255,0.18), transparent 50%),
    radial-gradient(circle at 80% 70%, rgba(255,255,255,0.12), transparent 55%);
  pointer-events: none;
}
.landing-stats-grid {
  position: relative;
  max-width: 880px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
  text-align: center;
}
.landing-stat-number {
  font-family: var(--font-display);
  font-size: clamp(2rem, 5vw, 2.8rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.landing-stat-unit {
  font-size: 0.6em;
  font-weight: 700;
  margin-left: 0.2rem;
  opacity: 0.85;
}
.landing-stat-label {
  margin-top: 0.4rem;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  opacity: 0.92;
}

/* Sebelum / Sesudah comparison — two cards with an arrow between them.
   "Before" is chaotic (emojis scattered, value struck through), "after"
   is calm (one giant number). Lets the user grasp the value prop without
   reading anything. */
.landing-vs { margin-bottom: 4rem; }
.landing-vs-grid {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1rem;
  max-width: 880px;
  margin: 0 auto;
}
.landing-vs-card {
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius-lg);
  padding: 1.5rem 1.4rem;
  text-align: center;
  position: relative;
  min-height: 220px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.75rem;
}
.landing-vs-card--before {
  background: linear-gradient(135deg, #fff5f5 0%, #ffe4e6 100%);
  border-color: rgba(239,68,68,0.15);
}
.landing-vs-card--after {
  background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
  border-color: rgba(34,197,94,0.2);
  box-shadow: 0 12px 30px -12px rgba(34, 197, 94, 0.25);
}
.landing-vs-tag {
  position: absolute;
  top: -12px;
  left: 50%;
  transform: translateX(-50%);
  background: #ef4444;
  color: #fff;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 4px 14px;
  border-radius: 999px;
}
.landing-vs-tag--good { background: #22c55e; }
.landing-vs-chaos {
  font-size: 1.6rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 8px;
}
.landing-vs-chaos span {
  display: inline-block;
  animation: landing-shake 2.4s ease-in-out infinite;
}
.landing-vs-chaos span:nth-child(2) { animation-delay: -0.3s; }
.landing-vs-chaos span:nth-child(3) { animation-delay: -0.6s; }
.landing-vs-chaos span:nth-child(4) { animation-delay: -0.9s; }
.landing-vs-chaos span:nth-child(5) { animation-delay: -1.2s; }
.landing-vs-chaos span:nth-child(6) { animation-delay: -1.5s; }
@keyframes landing-shake {
  0%, 100% { transform: rotate(-6deg) translateY(0); }
  50%      { transform: rotate(6deg)  translateY(-4px); }
}
.landing-vs-zen {
  font-size: 2rem;
  animation: landing-zen-glow 3s ease-in-out infinite;
}
@keyframes landing-zen-glow {
  0%, 100% { transform: scale(1);    filter: drop-shadow(0 0 0 rgba(34,197,94,0)); }
  50%      { transform: scale(1.08); filter: drop-shadow(0 4px 12px rgba(34,197,94,0.45)); }
}
.landing-vs-line {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 700;
  color: #6b7280;
}
.landing-vs-line--big {
  font-size: clamp(2rem, 5vw, 2.6rem);
  color: #15803d;
  letter-spacing: -0.02em;
}
.landing-vs-strike { text-decoration: line-through; text-decoration-thickness: 2px; }
.landing-vs-caption {
  font-size: 0.88rem;
  color: var(--bt-ink-muted);
  line-height: 1.4;
}
.landing-vs-card--after .landing-vs-caption { color: #166534; font-weight: 600; }
.landing-vs-arrow {
  font-family: var(--font-display);
  font-size: 2.4rem;
  font-weight: 800;
  color: var(--bt-primary);
  animation: landing-arrow-pulse 1.8s ease-in-out infinite;
}
@keyframes landing-arrow-pulse {
  0%, 100% { transform: translateX(0); opacity: 0.7; }
  50%      { transform: translateX(6px); opacity: 1; }
}

/* Floating coins around the pricing card — same bob as the hero floats
   but anchored to the card so they read as "value spilling out." */
.landing-pricing-coin {
  position: absolute;
  font-size: 1.6rem;
  pointer-events: none;
  filter: drop-shadow(0 4px 8px rgba(0,0,0,0.12));
  animation: landing-bob 4.5s ease-in-out infinite;
}
.landing-pricing-coin--1 { top: -18px; left: -24px;  animation-delay: 0s; }
.landing-pricing-coin--2 { top: 30%;   right: -28px; animation-delay: 1.2s; font-size: 1.4rem; }
.landing-pricing-coin--3 { bottom: -10px; left: 30%; animation-delay: 2.4s; font-size: 1.2rem; }

/* Staggered card reveals — when a parent .reveal becomes .is-revealed,
   its glance/principle children animate in one after the other instead
   of all at once. Subtle but reads as "polish." */
.landing-glance.reveal .landing-glance-card,
.landing-principle.reveal .landing-principle-card {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
.landing-glance.is-revealed .landing-glance-card,
.landing-principle.is-revealed .landing-principle-card {
  opacity: 1;
  transform: none;
}
.landing-glance.is-revealed .landing-glance-card:nth-child(1)    { transition-delay: 0.05s; }
.landing-glance.is-revealed .landing-glance-card:nth-child(2)    { transition-delay: 0.18s; }
.landing-glance.is-revealed .landing-glance-card:nth-child(3)    { transition-delay: 0.31s; }
.landing-principle.is-revealed .landing-principle-card:nth-child(1) { transition-delay: 0.05s; }
.landing-principle.is-revealed .landing-principle-card:nth-child(2) { transition-delay: 0.18s; }
.landing-principle.is-revealed .landing-principle-card:nth-child(3) { transition-delay: 0.31s; }

/* Mobile: stats strip and vs-grid collapse to single column, blobs shrink
   so they don't overflow the viewport. */
@media (max-width: 900px) {
  .landing-stats-grid {
    grid-template-columns: 1fr;
    gap: 1.25rem;
  }
  .landing-vs-grid {
    grid-template-columns: 1fr;
  }
  .landing-vs-arrow {
    transform: rotate(90deg);
    margin: 0.25rem auto;
  }
  .landing-hero-blob--a { width: 200px; height: 200px; opacity: 0.4; }
  .landing-hero-blob--b { width: 160px; height: 160px; opacity: 0.35; }
  .landing-pricing-coin--2 { right: -10px; }
}

/* Reduced-motion: kill all the new ambient animations. The count-up and
   reveals are JS-gated separately. */
@media (prefers-reduced-motion: reduce) {
  .landing-eyebrow-dot,
  .landing-mock-savestate-dot,
  .landing-float,
  .landing-pricing-badge,
  .landing-pricing-coin,
  .landing-hero-blob,
  .landing-vs-chaos span,
  .landing-vs-zen,
  .landing-vs-arrow,
  .landing-mini-input-caret { animation: none; }
  .landing-mock-fill {
    animation: none;
    width: var(--target-width, 38%);
    transition: none;
  }
  .landing-mock-toast { transition: none; }
  .reveal { opacity: 1; transform: none; transition: none; }
  .landing-glance.reveal .landing-glance-card,
  .landing-principle.reveal .landing-principle-card {
    opacity: 1; transform: none; transition: none;
  }
}

/* ── Post-login delight: subtle motion for the daily app ─────────────
   Goal: feel polished + alive on first impression, never fatigue after
   30 daily uses. One-shot animations are short and quiet; the only
   continuous animation is the "today" pill pulse (it carries signal —
   "you are here"). All gated behind prefers-reduced-motion at the
   bottom of this block. */

/* Hero card sheen — diagonal light sweep that runs once on first paint.
   ::before sits over the gradient and translates across with a soft
   highlight. animation-fill-mode keeps it parked off-screen post-run so
   no idle pixels stay lit. */
.hero-card::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    120deg,
    transparent 30%,
    rgba(255, 255, 255, 0.22) 50%,
    transparent 70%
  );
  transform: translateX(-100%);
  pointer-events: none;
  animation: hero-sheen 1.6s cubic-bezier(0.22, 1, 0.36, 1) 0.25s 1 forwards;
  z-index: 1;
}
.hero-card > * { position: relative; z-index: 2; }
@keyframes hero-sheen {
  to { transform: translateX(100%); }
}

/* Hero metric — gentle zoom-in on first paint, so the number "lands"
   instead of being statically painted. The metric-tick-up animation that
   already exists handles same-page updates; this is purely for arrival. */
.hero-card .metric-xl {
  animation: hero-metric-in 0.55s cubic-bezier(0.34, 1.56, 0.64, 1) 0.1s both;
}
@keyframes hero-metric-in {
  from { opacity: 0; transform: scale(0.88); }
  to   { opacity: 1; transform: scale(1); }
}

/* Streak pill — tiered: ≥7 days gets a sparkle, ≥30 gets a fire halo.
   The JS tags the element with data-streak-tier on render based on
   window.PASAKA_STREAK_DAYS. */
.hero-streak[data-streak-tier="big"]::after,
.hero-streak[data-streak-tier="huge"]::after {
  content: "✨";
  font-size: 0.85rem;
  margin-left: 0.15rem;
  display: inline-block;
  animation: streak-sparkle 1.8s ease-in-out infinite;
}
.hero-streak[data-streak-tier="huge"] {
  background: linear-gradient(135deg, #fff7ed 0%, #fed7aa 100%);
  box-shadow: 0 0 0 1px rgba(234, 88, 12, 0.18), 0 4px 12px -4px rgba(234, 88, 12, 0.35);
}
.hero-streak[data-streak-tier="huge"]::after {
  content: "🔥";
  animation: streak-fire 1.4s ease-in-out infinite;
}
@keyframes streak-sparkle {
  0%, 100% { transform: scale(1)   rotate(0);   opacity: 0.85; }
  50%      { transform: scale(1.2) rotate(12deg); opacity: 1; }
}
@keyframes streak-fire {
  0%, 100% { transform: translateY(0)    scale(1); }
  50%      { transform: translateY(-2px) scale(1.1); }
}
[data-theme="dark"] .hero-streak[data-streak-tier="huge"] {
  background: linear-gradient(135deg, rgba(234,88,12,0.18) 0%, rgba(234,88,12,0.32) 100%);
}

/* Week pills — staggered entrance + soft pulse on "today" so it stays
   the visual anchor without being a glow ad. */
.week-pill {
  animation: week-pill-in 0.45s cubic-bezier(0.22, 1, 0.36, 1) both;
  transition: transform 0.18s ease, box-shadow 0.25s ease;
}
.week-pill:nth-child(1) { animation-delay: 0.00s; }
.week-pill:nth-child(2) { animation-delay: 0.05s; }
.week-pill:nth-child(3) { animation-delay: 0.10s; }
.week-pill:nth-child(4) { animation-delay: 0.15s; }
.week-pill:nth-child(5) { animation-delay: 0.20s; }
.week-pill:nth-child(6) { animation-delay: 0.25s; }
.week-pill:nth-child(7) { animation-delay: 0.30s; }
@keyframes week-pill-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.week-pill.is-today {
  animation:
    week-pill-in 0.45s cubic-bezier(0.22, 1, 0.36, 1) both,
    week-pill-pulse 2.6s ease-in-out infinite 0.6s;
}
@keyframes week-pill-pulse {
  0%, 100% { box-shadow: 0 0 0 2px var(--bt-primary-100), 0 0 0 0   rgba(234, 88, 12, 0.0); }
  50%      { box-shadow: 0 0 0 2px var(--bt-primary-100), 0 0 0 6px rgba(234, 88, 12, 0.18); }
}

/* Cat-pill — when selected (.is-active gets toggled by app.js), the icon
   does a small spring. Lets every category tap feel satisfying. */
.cat-pill .cat-pill-icon { transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1); }
.cat-pill.is-active .cat-pill-icon {
  animation: cat-pill-bounce 0.42s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes cat-pill-bounce {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.3) rotate(-6deg); }
  70%  { transform: scale(0.95) rotate(3deg); }
  100% { transform: scale(1); }
}

/* Quick-amount chips — tap-down spring. Pure :active pseudo, no JS. */
.quick-amounts .quick-amount {
  transition: transform 0.12s ease, background-color 0.15s ease;
}
.quick-amounts .quick-amount:active {
  transform: scale(0.92);
}

/* FAB — gentle "I'm still here" bounce when JS adds .is-attention. JS
   only adds it after ~8s if today's expenses == 0 AND the user is idle.
   Fires 2.5 cycles then auto-removes via JS so it never becomes noise. */
.bt-fab { transition: transform 120ms ease, box-shadow 200ms ease; }
.bt-fab.is-attention {
  animation: fab-attention 1.1s cubic-bezier(0.34, 1.56, 0.64, 1) 2.5;
  box-shadow: 0 0 0 0 rgba(234, 88, 12, 0.45), var(--bt-shadow-lg);
}
@keyframes fab-attention {
  0%   { transform: scale(1)    translateY(0);   box-shadow: 0 0 0 0    rgba(234,88,12,0.45), var(--bt-shadow-lg); }
  40%  { transform: scale(1.08) translateY(-8px); box-shadow: 0 0 0 14px rgba(234,88,12,0),    var(--bt-shadow-lg); }
  60%  { transform: scale(0.98) translateY(0); }
  100% { transform: scale(1)    translateY(0); }
}
.bt-fab:active { transform: scale(0.92); }

/* Ghost preview rows — first-time-hero teaser list fades in one by one
   so the user sees Pasaka start filling itself, not all at once. */
.ghost-preview .ghost-row {
  opacity: 0;
  transform: translateY(6px);
  animation: ghost-in 0.5s ease forwards;
}
.ghost-preview .ghost-row:nth-child(1) { animation-delay: 0.20s; }
.ghost-preview .ghost-row:nth-child(2) { animation-delay: 0.45s; }
.ghost-preview .ghost-row:nth-child(3) { animation-delay: 0.70s; }
@keyframes ghost-in {
  to { opacity: 0.7; transform: translateY(0); }
}

/* Daily rows + mobile cards — initial render fades in with a small
   downward translation. Doesn't re-fire for inline updates (those use
   the existing inline insert animation in app.js). */
.daily-card .day-row,
.daily-cards .daily-card-mobile {
  animation: daily-row-in 0.42s ease both;
}
.daily-card .day-row:nth-child(1)  { animation-delay: 0.02s; }
.daily-card .day-row:nth-child(2)  { animation-delay: 0.04s; }
.daily-card .day-row:nth-child(3)  { animation-delay: 0.06s; }
.daily-card .day-row:nth-child(4)  { animation-delay: 0.08s; }
.daily-card .day-row:nth-child(5)  { animation-delay: 0.10s; }
.daily-card .day-row:nth-child(6)  { animation-delay: 0.12s; }
.daily-card .day-row:nth-child(7)  { animation-delay: 0.14s; }
.daily-card .day-row:nth-child(8)  { animation-delay: 0.16s; }
.daily-card .day-row:nth-child(9)  { animation-delay: 0.18s; }
.daily-card .day-row:nth-child(n+10) { animation-delay: 0.20s; }
.daily-cards .daily-card-mobile:nth-child(1)  { animation-delay: 0.04s; }
.daily-cards .daily-card-mobile:nth-child(2)  { animation-delay: 0.08s; }
.daily-cards .daily-card-mobile:nth-child(3)  { animation-delay: 0.12s; }
.daily-cards .daily-card-mobile:nth-child(4)  { animation-delay: 0.16s; }
.daily-cards .daily-card-mobile:nth-child(n+5) { animation-delay: 0.20s; }
@keyframes daily-row-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Hero CTA — primary "Catat pengeluaran" button gets a subtle lift +
   inner sheen on hover so it reads as the most actionable thing on the
   page (which it is). */
.hero-card .hero-cta {
  position: relative;
  overflow: hidden;
  transition: transform 0.18s ease, box-shadow 0.22s ease;
}
.hero-card .hero-cta::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(120deg, transparent 35%, rgba(255,255,255,0.35) 50%, transparent 65%);
  transform: translateX(-110%);
  transition: transform 0.6s ease;
  pointer-events: none;
}
.hero-card .hero-cta:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 24px -10px rgba(0,0,0,0.25);
}
.hero-card .hero-cta:hover::after {
  transform: translateX(110%);
}

/* Plan tiles — soft lift on hover so adding income/fixed feels like
   touching something solid. Existing layout untouched. */
.plan-tile {
  transition: transform 0.18s ease, box-shadow 0.22s ease, border-color 0.18s ease;
}
.plan-tile:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 24px -12px rgba(0,0,0,0.18);
  border-color: var(--bt-border-strong, var(--bt-border));
}

/* Reduced-motion: kill every ambient/animated rule above. One-shot
   entrance animations get set to instant-in so the layout is still
   correct (no stranded opacity:0 elements). */
@media (prefers-reduced-motion: reduce) {
  .hero-card::before,
  .hero-card .metric-xl,
  .hero-streak[data-streak-tier]::after,
  .week-pill,
  .week-pill.is-today,
  .cat-pill.is-active .cat-pill-icon,
  .quick-amounts .quick-amount,
  .bt-fab.is-attention,
  .ghost-preview .ghost-row,
  .daily-card .day-row,
  .daily-cards .daily-card-mobile,
  .hero-card .hero-cta::after { animation: none !important; }
  .ghost-preview .ghost-row,
  .daily-card .day-row,
  .daily-cards .daily-card-mobile { opacity: 1; transform: none; }
  .hero-card .metric-xl { opacity: 1; transform: none; }
}

/* ── Founder dashboard ─────────────────────────────────────────────── */
.founder-dash .card { background: var(--bt-surface); }

/* ── Programmatic SEO calculator (/calc/gaji-X-juta/) ─────────────────── */
.calc-shell {
  max-width: 620px;
  margin: 0 auto;
  padding: 2rem 0 4rem;
}
.calc-mascot { display: inline-block; margin-bottom: 1rem; }
.calc-h1 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.85rem;
  color: var(--bt-ink);
  margin-bottom: 0.5rem;
}
.calc-lede {
  color: var(--bt-ink-muted);
  margin-bottom: 1.5rem;
}
.calc-card {
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-radius: 18px;
  padding: 1.25rem;
}
.calc-result {
  background: linear-gradient(135deg, var(--bt-primary-50) 0%, var(--bt-accent-100) 100%);
  border-radius: 14px;
  padding: 16px;
  text-align: center;
}
.calc-result-eyebrow {
  font-family: var(--font-arcade);
  font-size: 0.78rem;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--bt-primary-ink);
}
.calc-result-amount {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 2.4rem;
  color: var(--bt-ink);
  margin-top: 4px;
}
.calc-result-sub {
  font-size: 0.85rem;
  color: var(--bt-ink-muted);
  margin-top: 4px;
}
.calc-breakdown {
  margin-top: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.calc-breakdown-row {
  display: flex;
  justify-content: space-between;
}
.calc-breakdown-divider {
  height: 1px;
  background: var(--bt-border);
  margin: 4px 0;
}
.calc-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.calc-chip {
  border: 1px solid var(--bt-border-strong);
  background: var(--bt-surface);
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 0.88rem;
  color: var(--bt-ink);
  text-decoration: none;
  transition: all 0.12s ease;
}
.calc-chip:hover {
  background: var(--bt-primary-50);
  border-color: var(--bt-primary);
  color: var(--bt-ink);
}
.calc-chip.is-active {
  background: var(--bt-primary);
  color: #fff;
  border-color: var(--bt-primary);
}
.calc-cta { display: flex; flex-direction: column; }
.calc-article {
  border-top: 1px solid var(--bt-border);
  padding-top: 1.5rem;
}
.calc-article p { line-height: 1.6; color: var(--bt-ink); }
.calc-formula {
  background: var(--bt-surface-alt);
  border: 1px solid var(--bt-border);
  border-radius: 10px;
  padding: 12px;
  font-family: var(--font-display);
  font-size: 0.92rem;
  color: var(--bt-ink);
  white-space: pre-wrap;
}
@media (min-width: 540px) {
}
@keyframes ledger-saka-bounce {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.18); }
  60%  { transform: scale(0.95); }
  100% { transform: scale(1.06); }
}
@keyframes ledger-coin-fly {
  0% {
    transform: translate(-50%, -50%) scale(0.6);
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  90% {
    opacity: 0.85;
  }
  100% {
    transform: translate(calc(-50% + var(--coin-dx, 0px)), calc(-50% + var(--coin-dy, 0px))) scale(0.35);
    opacity: 0;
  }
}

/* SEO tier chips — landing-page footer link block to the /calc/gaji-N-juta/
   programmatic pages. Builds an internal-link graph for crawlers + lets
   visitors jump straight to "their" calculator. */
.landing-seo-tiers {
  padding: 2.5rem 1rem 3rem;
  max-width: 960px;
  margin: 0 auto;
  text-align: center;
}
/* Compact variant — used at the foot of the landing where the chips are an
   internal-link aid, not a featured section. Smaller heading, left-aligned,
   noticeably less visual weight than .landing-seo-tiers default. */
.landing-seo-tiers--compact {
  padding: 1.5rem 1rem 2rem;
  text-align: left;
}
.landing-seo-tiers--compact .landing-seo-tiers-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  margin-bottom: 0.5rem;
}
.landing-seo-tiers--compact .landing-seo-tier-grid {
  justify-content: flex-start;
  margin-top: 0.5rem;
}
.landing-seo-tier-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 1.25rem;
}
.landing-seo-tier-chip {
  display: inline-block;
  padding: 0.5rem 0.95rem;
  background: var(--bt-surface-alt);
  color: var(--bt-ink);
  border-radius: 999px;
  font-size: 0.92rem;
  font-weight: 600;
  text-decoration: none;
  border: 1px solid var(--bt-border);
  transition: background 0.18s, transform 0.18s, border-color 0.18s;
}
.landing-seo-tier-chip:hover,
.landing-seo-tier-chip:focus-visible {
  background: var(--bt-primary-50);
  border-color: var(--bt-primary);
  color: var(--bt-primary-ink);
  text-decoration: none;
  transform: translateY(-1px);
}

/* PWA install nudge — fixed bottom toast, dismissible. Shown only after the
   user has earned the home-screen install (profile aged ≥3d OR ≥3 expenses).
   `right` is pulled in on mobile so the floating FAB stays clickable in the
   thumb zone — earlier it sat under the nudge at the same anchor. */
.pwa-install-nudge {
  position: fixed;
  left: 12px;
  right: 92px;
  bottom: 80px;
  z-index: 1090;
  display: flex;
  align-items: center;
  gap: 12px;
  background: linear-gradient(135deg, var(--bt-surface) 0%, var(--bt-primary-50) 100%);
  border: 1px solid var(--bt-primary-100);
  border-radius: 16px;
  padding: 12px 14px;
  box-shadow: 0 10px 28px rgba(15, 23, 41, 0.15);
  max-width: 460px;
  margin-left: auto;
  margin-right: auto;
}
@media (min-width: 768px) {
  /* Desktop: no FAB, so the nudge can stretch back to the right edge. */
  .pwa-install-nudge { bottom: 24px; right: 12px; }
}
.pwa-install-mascot { flex-shrink: 0; }
.pwa-install-text { flex-grow: 1; min-width: 0; }
.pwa-install-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  color: var(--bt-ink);
  line-height: 1.2;
}
.pwa-install-sub {
  font-size: 0.82rem;
  color: var(--bt-ink-muted);
  margin-top: 2px;
}
.pwa-install-actions {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex-shrink: 0;
}
.pwa-install-actions .btn { white-space: nowrap; }

/* Respect reduced-motion preference — skip the choreography. */
@media (prefers-reduced-motion: reduce) {
  .ledger-saka-target.saka-grow,
  .ledger-coin,
  .ledger-stage-up-pill { animation: none !important; transition: none !important; opacity: 1 !important; transform: none !important; }
  .ledger-cta-hidden { opacity: 1 !important; transform: none !important; pointer-events: auto !important; }
}

.goal-card { overflow: hidden; }
.goal-photo-wrap {
  width: 100%;
  aspect-ratio: 16/9;
  overflow: hidden;
  transition: filter 600ms ease;
  background: linear-gradient(135deg, var(--bt-warning-100), var(--bt-primary-100));
  display: flex;
  align-items: center;
  justify-content: center;
}
.goal-photo-emoji {
  font-size: 5rem;
  line-height: 1;
  filter: drop-shadow(0 2px 4px rgba(0,0,0,0.08));
}
@media (max-width: 480px) {
}

/* ============================================================================
   UI/UX best-practice baseline (audited 2026-05-12)
   ============================================================================ */

/* ── Tap-target floors. Chips were ~24px tall; WCAG 2.5.5 wants ≥24 with
   spacing, Apple HIG wants ≥44. We split the difference at 36px and keep
   the visual identity tight. ────────────────────────────────────────────── */
.quick-amounts .quick-amount,
.coba-quick button,
.date-chip,
.onboarding-quick-amounts .btn {
  min-height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* ── aria-pressed visual: quick-amount + coba-quick chips reflect the
   currently-selected value via aria-pressed="true". ────────────────────── */
.quick-amounts .quick-amount[aria-pressed="true"],
.coba-quick button[aria-pressed="true"],
.onboarding-quick-amounts .btn[aria-pressed="true"] {
  background: var(--bt-primary);
  color: #fff;
  border-color: var(--bt-primary);
}

/* ── aria-current=page: the active nav link should also be reachable as
   a landmark. Color/active state already styled via .active class; this
   just ensures aria-current carries the same weight. ──────────────────── */
.bt-nav-link[aria-current="page"] {
  background: var(--bt-primary-50);
  color: var(--bt-primary-ink);
}

/* ── Skip link: was already in base.html, just give it a visible state
   on focus. Default 'visually-hidden' until focused. ──────────────────── */
.skip-link {
  position: absolute;
  top: -40px;
  left: 1rem;
  z-index: 2000;
  padding: 0.5rem 1rem;
  background: var(--bt-primary);
  color: #fff;
  border-radius: var(--bt-radius-sm);
  font-weight: 600;
  text-decoration: none;
  transition: top 0.18s ease;
}
.skip-link:focus,
.skip-link:focus-visible {
  top: 1rem;
  outline: none;
  box-shadow: var(--bt-ring);
}

/* Skip-link target. <main> has tabindex="-1" so JS can focus it without
   it being in the regular tab order. Without an outline, the target lands
   focus invisibly — keyboard users hit the skip-link then can't see what
   the focus moved to. :focus-visible only, so programmatic focus from a
   mouse-driven flow (e.g. closing the expense modal) doesn't leave a
   stuck orange ring around the whole content area. */
main:focus-visible {
  outline: none;
  box-shadow: var(--bt-ring);
  border-radius: var(--bt-radius);
}

/* Dashboard summary strip — slim, low-emphasis link to the full monthly
   summary. Replaces the buried "Lihat ringkasan bulan ini" centered link
   that lived under 31 day rows. */
.dashboard-summary-strip { display: block; }
.dashboard-summary-link {
  display: block;
  padding: 0.7rem 0.95rem;
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius);
  text-decoration: none;
  transition: background 0.12s, border-color 0.12s;
}
.dashboard-summary-link:hover {
  background: var(--bt-surface-alt);
  border-color: var(--bt-border-strong);
}
.dashboard-summary-strip-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

/* Coarse-pointer (touch) input has no real :hover — we want the hover
   *visual* (lift, shadow, color tint) to skip on touch, so the user gets
   a stable state until they actually tap. Default browser :hover on touch
   fires sticky after a tap, leaving the previously-tapped row highlighted
   until something else is tapped. */
@media (hover: none) and (pointer: coarse) {
  .daily-table tbody tr.day-row:hover { background: transparent; }
  .bt-fab:hover { transform: none; }
}

/* ── Disabled / aria-busy state: forms that flip a submit button to
   "Menyiapkan…" need a clear visual signal it's not retry-able. ──────── */
button[aria-busy="true"],
.btn[aria-busy="true"] {
  opacity: 0.65;
  cursor: progress;
}
button[disabled],
.btn[disabled] {
  cursor: not-allowed;
}

/* ── Global reduced-motion override. The two existing media blocks only
   covered tick animation + ledger choreography; this catches every
   remaining `transition:` / `animation:` rule for users who opted out. ── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── Smooth scroll for users who haven't opted out (overridden above). ── */
html { scroll-behavior: smooth; }

/* ── Scroll-margin for anchored links (e.g. /#faq from landing). Keeps
   the target from hiding under the fixed navbar. ─────────────────────── */
:target { scroll-margin-top: 80px; }

/* ── Plan tiles — Notion-style inline-edit lists on the dashboard.
   Cells look like plain text at rest; row controls fade in on hover.
   Whole-row click → edit. Enter/blur saves. Esc cancels. ────────────── */
.plan-tile {
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
}
.plan-tile-header {
  padding: 0.65rem 1rem 0.35rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.plan-tile-toggle {
  appearance: none;
  border: 1px solid transparent;
  background: transparent;
  color: var(--bt-ink-soft);
  font: inherit;
  font-size: 0.8rem;
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.65rem;
  border-radius: 999px;
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease, border-color 140ms ease;
}
.plan-tile[data-collapsed="true"] .plan-tile-toggle {
  background: var(--bt-surface-alt);
}
.plan-tile-toggle:hover {
  background: var(--bt-surface-alt);
  border-color: var(--bt-border);
  color: var(--bt-ink);
}
.plan-tile[data-collapsed="true"]:hover .plan-tile-toggle {
  border-color: var(--bt-border);
  color: var(--bt-ink);
}
.plan-tile-toggle:focus-visible {
  outline: 2px solid var(--bt-primary-100);
  outline-offset: 2px;
}
.plan-tile-toggle-chevron {
  display: inline-block;
  font-size: 0.65rem;
  line-height: 1;
  transition: transform 180ms ease;
}
.plan-tile[data-collapsed="false"] .plan-tile-toggle-chevron {
  transform: rotate(180deg);
}
.plan-tile[data-collapsed="true"] .plan-tile-list,
.plan-tile[data-collapsed="true"] .plan-tile-add-trigger,
.plan-tile[data-collapsed="true"] .plan-tile-add {
  display: none !important;
}
.plan-tile[data-collapsed="true"] {
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease;
}
.plan-tile[data-collapsed="true"]:hover {
  background: rgba(234, 88, 12, 0.04);
  border-color: rgba(234, 88, 12, 0.25);
}
[data-theme="dark"] .plan-tile[data-collapsed="true"]:hover {
  background: rgba(255, 255, 255, 0.025);
  border-color: rgba(255, 255, 255, 0.12);
}
.plan-tile[data-collapsed="true"] .plan-tile-header {
  padding-top: 0.7rem;
  padding-bottom: 0.25rem;
}
.plan-tile[data-collapsed="true"] .plan-tile-header .eyebrow {
  padding-top: 0 !important;
}
.plan-tile[data-collapsed="true"] .plan-tile-footer {
  border-top: 0 !important;
  padding-top: 0.25rem;
  padding-bottom: 0.7rem;
  font-size: 1rem;
}
.plan-tile[data-collapsed="true"] .plan-tile-footer .metric {
  font-size: 1.1rem;
}
.plan-tile-list {
  list-style: none;
  margin: 0;
  padding: 0 0.5rem;
  display: flex;
  flex-direction: column;
  gap: 0;
  flex: 1 1 auto;
  min-height: 48px;
}
.plan-tile-list .setup-empty {
  padding: 0.5rem 0.75rem 0.75rem;
  font-style: normal;
}

/* Row at rest: flat, no border, no background. */
.plan-tile-list .setup-row {
  background: transparent;
  border: 0;
  border-radius: 4px;
  border-bottom: 1px solid transparent;
  transition: background 0.08s ease, border-color 0.08s ease;
  cursor: pointer;
}
.plan-tile-list .setup-row + .setup-row {
  border-top: 1px solid var(--bt-border);
}
.plan-tile-list .setup-row:hover {
  background: rgba(234, 88, 12, 0.04);
}
.plan-tile-list .setup-row.is-editing {
  background: rgba(234, 88, 12, 0.06);
  border-color: transparent;
}
.plan-tile-list .setup-row-display {
  padding: 0.45rem 0.6rem;
  gap: 0.5rem;
  min-height: 36px;
}
/* Hide the explicit edit pencil — whole row is the trigger. */
.plan-tile-list .setup-edit-btn { display: none !important; }
/* Trash icon: invisible at rest, fades in on row hover or keyboard focus. */
.plan-tile-list .setup-row-actions {
  opacity: 0;
  transition: opacity 0.12s ease;
}
.plan-tile-list .setup-row:hover .setup-row-actions,
.plan-tile-list .setup-row:focus-within .setup-row-actions {
  opacity: 1;
}
.plan-tile-list .setup-row-actions .btn {
  width: 26px; height: 26px;
  border: 0;
  background: transparent;
  color: var(--bt-ink-soft);
}
.plan-tile-list .setup-row-actions .btn:hover {
  background: var(--bt-danger-100);
  color: var(--bt-danger-700);
}

/* Edit-mode: inputs look like flat text, no border, transparent bg. */
.plan-tile-list .setup-row.is-editing > .setup-row-edit {
  padding: 0.35rem 0.45rem;
  grid-template-columns: 1fr 130px;
  gap: 0.5rem;
}
.plan-tile-list .setup-row-edit .form-control {
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  box-shadow: none;
  padding: 0.25rem 0.4rem;
  font-size: 0.92rem;
}
/* Inside .input-currency, preserve the left padding for the Rp prefix. */
.plan-tile-list .setup-row-edit .input-currency .form-control {
  padding-left: 2rem;
}
.plan-tile-list .setup-row-edit .form-control:focus {
  background: var(--bt-surface);
  border-color: var(--bt-primary-100);
  box-shadow: var(--bt-ring);
  outline: none;
}
.plan-tile-list .setup-row-edit .input-currency::before {
  font-size: 0.85rem;
  opacity: 0.7;
}
/* Save/cancel buttons hidden — Enter saves, Esc cancels, blur saves. */
.plan-tile-list .setup-row-edit-actions { display: none !important; }

/* "+ Tambah" placeholder (Notion's "+ New" row). */
.plan-tile-add-trigger {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  width: 100%;
  background: transparent;
  border: 0;
  border-top: 1px solid var(--bt-border);
  color: var(--bt-ink-soft);
  font: inherit;
  font-size: 0.88rem;
  text-align: left;
  padding: 0.55rem 0.85rem;
  cursor: pointer;
  transition: background 0.08s ease, color 0.08s ease;
}
.plan-tile-add-trigger:hover {
  background: rgba(234, 88, 12, 0.04);
  color: var(--bt-ink);
}
.plan-tile-add-trigger .plan-tile-add-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  font-weight: 700;
  color: var(--bt-ink-soft);
}
.plan-tile-add-trigger:hover .plan-tile-add-icon { color: var(--bt-primary-ink); }

/* Add-form when expanded: same flat look as the edit row. */
.plan-tile-list ~ .plan-tile-add,
.plan-tile-add {
  display: none;
  grid-template-columns: 1fr 130px 32px;
  gap: 0.5rem;
  align-items: center;
  padding: 0.45rem 0.85rem 0.6rem;
  border-top: 1px solid var(--bt-border);
  background: rgba(234, 88, 12, 0.04);
}
.plan-tile-add:not([hidden]) { display: grid; }
/* Cancel "×" button for the inline add form — collapses the form back
   to the "+ Tambah" trigger. Pure ghost button; lives in column 3 of
   the grid. Hidden submit button below keeps Enter-to-submit working. */
.plan-tile-add-cancel {
  appearance: none;
  background: transparent;
  border: 1px solid transparent;
  color: var(--bt-ink-soft);
  width: 32px;
  height: 32px;
  border-radius: var(--bt-radius-sm);
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 140ms ease, color 140ms ease, transform 120ms ease;
}
.plan-tile-add-cancel:hover {
  background: var(--bt-surface-alt);
  color: var(--bt-ink);
}
.plan-tile-add-cancel:active { transform: scale(0.9); }
.plan-tile-add-cancel:focus-visible {
  outline: 2px solid var(--bt-primary-100);
  outline-offset: 2px;
}
@media (max-width: 575.98px) {
  .plan-tile-list ~ .plan-tile-add,
  .plan-tile-add { grid-template-columns: 1fr 110px 32px; }
}
.plan-tile-add .form-control {
  background: var(--bt-surface);
  border: 1px solid transparent;
  border-radius: 4px;
  box-shadow: none;
  padding: 0.3rem 0.5rem;
  font-size: 0.92rem;
}
/* Inside .input-currency, preserve the left padding for the Rp prefix. */
.plan-tile-add .input-currency .form-control {
  padding-left: 2rem;
}
.plan-tile-add .form-control:focus {
  border-color: var(--bt-primary-100);
  box-shadow: var(--bt-ring);
  outline: none;
}

.plan-tile-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.55rem 1rem;
  border-top: 1px solid var(--bt-border);
  font-size: 0.92rem;
}

/* ── Day-cat dot — mobile-only scannable category cue in the date cell.
   When the description column is hidden (<576px), this dot reveals the
   day's primary expense category without expanding the row. ─────────── */
.day-cat-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-left: 0.35rem;
  vertical-align: middle;
  background: var(--cat-other);
}
.day-cat-dot.cat-food          { background: var(--cat-food); }
.day-cat-dot.cat-transport     { background: var(--cat-transport); }
.day-cat-dot.cat-shopping      { background: var(--cat-shopping); }
.day-cat-dot.cat-bills         { background: var(--cat-bills); }
.day-cat-dot.cat-entertainment { background: var(--cat-entertainment); }
.day-cat-dot.cat-health        { background: var(--cat-health); }
/* ============================================================================
   Audit follow-up components — hero bare layout, FAB, no-spend link, streak,
   goal slot, week strip, mobile day cards, count-down feedback, coachmark,
   welcome-back / donation banners, deletion receipt.
   ============================================================================ */

.hero-card-bare,
.first-time-hero {
  background: transparent;
  border: 0;
  box-shadow: none;
  padding: 1.25rem 0 0.25rem;
  text-align: left;
  color: var(--bt-ink);
}
/* Override the gradient-hero text colors (white) for the "bare" variant —
   that variant sits on the page background, so white text would be
   invisible in light mode. Restore ink colors. */
.hero-card-bare .eyebrow,
.first-time-hero .eyebrow {
  color: var(--bt-ink-muted);
}
.hero-card-bare .hero-sub,
.hero-card-bare .text-muted-soft,
.first-time-hero .text-muted-soft {
  color: var(--bt-ink-muted) !important;
}
/* The sheen `::before` is for the gradient hero only — kill it on the
   bare variant to avoid a stray translucent white sweep on light bg. */
.hero-card-bare::before { content: none; }
.first-time-hero .metric-xl {
  font-size: clamp(48px, 12vw, 96px);
  line-height: 1;
  letter-spacing: -2px;
  font-weight: 800;
  color: var(--bt-ink);
}
.first-time-hero .hero-sub { color: var(--bt-ink-muted); font-size: 0.95rem; }
.hero-greeting {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--bt-ink-muted);
  margin-bottom: 0.25rem;
}
.hero-card-bare .metric-xl {
  font-size: clamp(48px, 12vw, 96px);
  line-height: 1;
  letter-spacing: -2px;
  font-weight: 800;
  color: var(--bt-ink);
}
.hero-card-bare.hero-overspent .metric-xl { color: var(--bt-danger-700); }
.hero-card-bare .hero-sub {
  color: var(--bt-ink-muted);
  font-size: 0.95rem;
}
.hero-streak {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.9rem;
  color: var(--bt-ink);
  background: var(--bt-surface-alt);
  border-radius: var(--bt-radius-pill);
  padding: 0.2rem 0.65rem;
}
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.85rem;
}
.hero-nospend-link {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 0.4rem 0.5rem;
  color: var(--bt-ink-muted);
  font-size: 0.9rem;
  cursor: pointer;
  border-radius: var(--bt-radius-sm);
}
.hero-nospend-link:hover, .hero-nospend-link:focus-visible {
  background: var(--bt-surface-alt);
  color: var(--bt-success-700);
  outline: none;
}
.hero-nospend-link[disabled] {
  opacity: 0.6;
  cursor: default;
}

/* Number ticker — visible feedback for amount changes. The previous
   `is-tick` glow rendered invisibly on the light surface; this replaces it. */
.metric.is-ticking {
  background: linear-gradient(90deg, var(--bt-primary-50), transparent);
  border-radius: var(--bt-radius-sm);
  transition: background-color 350ms ease;
}
.metric.is-tick-down { color: var(--bt-warning-700); }
.metric.is-tick-up   { color: var(--bt-success-700); }

/* Persistent FAB — visible on mobile only. Lives in the iOS thumb zone. */
.bt-fab {
  position: fixed;
  bottom: 20px;
  right: 20px;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--bt-primary);
  color: #fff;
  border: 0;
  box-shadow: var(--bt-shadow-lg);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  /* Sit above the PWA install nudge (z-index 1090) and Bootstrap toasts.
     Bootstrap modals use z-index 1055 (backdrop) / 1060 (dialog), so the
     FAB stays below an open modal — which is correct, since the modal
     replaces the FAB as the active action. */
  z-index: 1095;
  transition: transform 120ms ease;
}
.bt-fab:hover { transform: scale(1.04); }
.bt-fab:focus-visible { outline: 3px solid var(--bt-primary-100); outline-offset: 3px; }
.bt-fab svg { width: 24px; height: 24px; }
/* Hide on devices that have a fine pointer (mouse / trackpad / pen).
   Touch users keep the thumb-zone FAB regardless of viewport width — a
   tablet in portrait is still operated with a thumb. */
@media (pointer: fine) {
  .bt-fab { display: none; }
}
@media (display-mode: standalone) {
  .bt-fab { bottom: calc(20px + env(safe-area-inset-bottom)); }
}
/* Hide both FAB and PWA install nudge while any Bootstrap modal is open —
   `body.modal-open` is the official hook. Without this, the FAB at z-index
   1095 would float above the modal backdrop. */
body.modal-open .bt-fab,
body.modal-open .pwa-install-nudge { display: none !important; }

/* Coachmark overlay (first-expense nudge) */
.coachmark-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 41, 0.45);
  z-index: 1040;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 110px;
  animation: coachmark-fade 240ms ease-out;
}
@keyframes coachmark-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.coachmark-card {
  background: var(--bt-surface);
  border-radius: var(--bt-radius-lg);
  box-shadow: var(--bt-shadow-lg);
  padding: 1rem 1.25rem;
  max-width: 320px;
  text-align: center;
  position: relative;
}
.coachmark-arrow {
  font-size: 28px;
  line-height: 1;
  color: var(--bt-primary);
  margin-bottom: 0.4rem;
}
.coachmark-dismiss {
  margin-top: 0.25rem;
  color: var(--bt-ink-muted);
}

/* Welcome-back + donation banners (re-engagement surfaces) */
.welcome-back-banner, .donation-prompt {
  border-radius: var(--bt-radius);
  background: var(--bt-primary-50);
  border-color: var(--bt-primary-100) !important;
}
.donation-prompt { background: var(--bt-accent-50); border-color: var(--bt-accent-100) !important; }

/* Welcome-back tiered cards (medium/heavy variants). The only in-app
   retention surface this product has — sized up so the gap acknowledgement
   feels substantial. */
.welcome-back-card {
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius-lg);
  padding: 1.25rem 1.4rem;
  box-shadow: var(--bt-shadow);
}
.welcome-back-card--medium {
  background: var(--bt-primary-50);
  border-color: var(--bt-primary-100);
}
.welcome-back-card--heavy {
  background: linear-gradient(135deg, var(--bt-primary-50), var(--bt-accent-50));
  border-color: var(--bt-primary-100);
}
.welcome-back-h2 {
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1.2;
  margin: 0;
}
.welcome-back-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.welcome-back-actions .btn { min-height: 44px; }
.welcome-back-recap {
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius);
  padding: 0.7rem 0.9rem;
}
.welcome-back-recap-row {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-top: 0.15rem;
}
[data-theme="dark"] .goal-photo-wrap {
  background: linear-gradient(135deg, #78350f, var(--bt-primary-900));
}

/* Google "Continue with Google" — Google publishes a dark-mode variant
   (near-black surface, light text). Use it so the button doesn't burn
   white on the dark page. */
[data-theme="dark"] .btn-google {
  background: #131314;
  color: #e3e3e3;
  border-color: #3c4043;
}
[data-theme="dark"] .btn-google:hover {
  background: #1f1f20;
  color: #e3e3e3;
  border-color: #5f6368;
}
[data-theme="dark"] .welcome-back-card { background: var(--bt-surface); border-color: var(--bt-border); }
[data-theme="dark"] .welcome-back-card--medium { background: rgba(234,88,12,0.08); }
[data-theme="dark"] .welcome-back-card--heavy { background: rgba(234,88,12,0.10); }
[data-theme="dark"] .welcome-back-recap { background: var(--bt-surface-alt); }

/* Ghost-data preview — first-time-only fake breakdown so the new user's
   dashboard isn't an empty void. Decorative: aria-hidden, no click handlers,
   no DB rows. Disappears when is_first_time flips after the first real log. */
.ghost-preview {
  opacity: 0.42;
  pointer-events: none;
  user-select: none;
  border: 1px dashed var(--bt-border);
  border-radius: var(--bt-radius);
  padding: 0.9rem 1rem;
  background: var(--bt-surface-alt);
}
.ghost-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.ghost-row {
  display: grid;
  grid-template-columns: 56px 1fr auto auto;
  align-items: center;
  gap: 0.6rem;
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--bt-border);
  font-size: 0.92rem;
}
.ghost-row:last-child { border-bottom: 0; }
.ghost-time {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--bt-ink-muted);
  font-size: 0.85rem;
}
.ghost-desc { color: var(--bt-ink); }
.ghost-cat { font-size: 1rem; }
.ghost-amt {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--bt-ink);
  white-space: nowrap;
}
.ghost-footnote {
  margin-top: 0.6rem;
  text-align: center;
  font-style: italic;
}
.eyebrow--soft { background: transparent; color: var(--bt-ink-muted); padding: 0; }
@media (prefers-reduced-motion: no-preference) {
  .ghost-preview { transition: opacity 220ms ease; }
}

/* Weekly strip — 7-day overview below the hero. Each pill is the day
   number; today pulses; future days are muted. */
.week-strip {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
  margin: 0 0 1rem;
}
.week-pill {
  text-align: center;
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius-sm);
  padding: 0.4rem 0.25rem;
  font-size: 0.75rem;
  color: var(--bt-ink-muted);
  cursor: default;
}
.week-pill .week-pill-wd { display: block; font-weight: 700; color: var(--bt-ink); }
.week-pill .week-pill-num { display: block; font-size: 1.1rem; font-weight: 800; color: var(--bt-ink); }
.week-pill .week-pill-mark { display: block; margin-top: 2px; height: 6px; }
.week-pill.is-today { border-color: var(--bt-primary); box-shadow: 0 0 0 2px var(--bt-primary-100); }
.week-pill.is-green .week-pill-mark::before { content: "▲"; color: var(--bt-success-700); font-size: 0.7rem; }
.week-pill.is-red   .week-pill-mark::before { content: "▼"; color: var(--bt-danger-700); font-size: 0.7rem; }
.week-pill.is-future { opacity: 0.45; }

/* Mobile day-cards (replaces the desktop table on small screens) */
.daily-cards { display: none; }
@media (max-width: 575.98px) {
  .daily-table { display: none; }
  .daily-cards { display: flex; flex-direction: column; gap: 8px; padding: 0.75rem; }
  .daily-card-mobile {
    background: var(--bt-surface);
    border: 1px solid var(--bt-border);
    border-radius: var(--bt-radius);
    padding: 0.75rem 0.85rem;
  }
  .daily-card-mobile.is-today {
    border-color: var(--bt-primary);
    background: var(--bt-primary-50);
  }
  .daily-card-mobile.is-future { opacity: 0.5; }
  .daily-card-mobile-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 0.5rem;
    margin-bottom: 0.25rem;
  }
  /* The head is a <button> when the card is expandable. Strip native
     button styles so it reads as part of the card surface. */
  button.daily-card-mobile-toggle {
    width: 100%;
    background: transparent;
    border: 0;
    padding: 0;
    text-align: left;
    color: inherit;
    cursor: pointer;
  }
  button.daily-card-mobile-toggle:focus-visible {
    outline: 2px solid var(--bt-primary);
    outline-offset: 2px;
    border-radius: 4px;
  }
  .daily-card-mobile-head-end {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
  }
  .daily-card-mobile-chev {
    color: var(--bt-ink-soft);
    transition: transform 0.18s ease;
    flex-shrink: 0;
  }
  .daily-card-mobile-toggle[aria-expanded="true"] .daily-card-mobile-chev {
    transform: rotate(180deg);
  }
  .daily-card-mobile-date {
    font-weight: 700;
    color: var(--bt-ink);
  }
  .daily-card-mobile-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    display: inline-block;
    margin-right: 0.25rem;
    vertical-align: middle;
  }
  .daily-card-mobile-dot.is-green { background: var(--bt-success); }
  .daily-card-mobile-dot.is-red   { background: var(--bt-danger); }
  .daily-card-mobile-dot.is-zero  { background: var(--bt-ink-soft); }
  .daily-card-mobile-spent { font-weight: 700; color: var(--bt-danger-700); }
  .daily-card-mobile-left  { font-size: 0.85rem; color: var(--bt-ink-muted); }
  .daily-card-mobile-tags  { margin-top: 0.4rem; display: flex; flex-wrap: wrap; gap: 4px; font-size: 0.75rem; }
  /* Hide the preview pill row once the detail list is open — the same
     transactions appear in the list below, so showing both is noisy.
     `.is-open` is toggled in JS via Bootstrap collapse events so older
     browsers without :has() get the same behaviour. */
  .daily-card-mobile.is-open .daily-card-mobile-tags,
  .daily-card-mobile:has(.daily-card-mobile-detail.show) .daily-card-mobile-tags {
    display: none;
  }
  .daily-card-mobile-detail {
    margin: 0.6rem -0.85rem -0.75rem;
    border-top: 1px solid var(--bt-border);
    background: var(--bt-surface-alt);
    border-radius: 0 0 var(--bt-radius) var(--bt-radius);
  }
  .daily-card-mobile-detail-list { padding: 0; }
  /* CSS grid keeps the description column from being squeezed to a single
     character by the amount + action buttons. Icon spans both rows on the
     left, description+meta stack in the middle, amount + actions stack on
     the right. */
  .daily-card-mobile-detail-list .day-detail-item {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-rows: auto auto;
    column-gap: 10px;
    row-gap: 2px;
    align-items: center;
    padding: 0.6rem 0.85rem;
    border-top: 1px solid var(--bt-border);
  }
  .daily-card-mobile-detail-list .day-detail-item:first-child {
    border-top: 0;
  }
  .daily-card-mobile-detail-list .expense-icon {
    grid-column: 1;
    grid-row: 1 / span 2;
    width: 34px;
    height: 34px;
    align-self: center;
  }
  .daily-card-mobile-detail-list .day-detail-text {
    grid-column: 2;
    grid-row: 1 / span 2;
    min-width: 0;
  }
  .daily-card-mobile-detail-list .day-detail-text .fw-semibold {
    white-space: normal !important;
    overflow: visible !important;
    text-overflow: clip !important;
    font-size: 0.9rem;
    line-height: 1.25;
    word-break: break-word;
  }
  /* The redundant pill-style cat-badge below the description is replaced by
     plain coloured text — the icon background already conveys category. */
  .daily-card-mobile-detail-list .day-detail-text .small {
    margin-top: 2px;
    font-size: 0.72rem;
  }
  .daily-card-mobile-detail-list .day-detail-text .cat-badge {
    background: transparent !important;
    border: 0 !important;
    padding: 0 !important;
    color: var(--bt-ink-muted);
    font-weight: 500;
    text-transform: lowercase;
    font-size: 0.72rem;
  }
  .daily-card-mobile-detail-list .expense-amount {
    grid-column: 3;
    grid-row: 1;
    font-size: 0.9rem;
    font-weight: 700;
    align-self: end;
    white-space: nowrap;
  }
  .daily-card-mobile-detail-list .row-actions {
    grid-column: 3;
    grid-row: 2;
    justify-self: end;
    gap: 4px;
  }
  .daily-card-mobile-detail-list .row-actions .btn {
    padding: 0.3rem 0.45rem;
    line-height: 1;
    min-width: 32px;
    min-height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .daily-card-mobile-detail-add {
    padding: 0.5rem 0.85rem 0.75rem;
    border-top: 1px dashed var(--bt-border);
    margin-top: 0;
  }
  .daily-card-mobile-detail-add .day-add-btn {
    border-style: dashed;
  }
}

/* Delete-expense modal — confirmation preview shows what's about to go. */
.delete-expense-preview {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0.75rem 0.85rem;
  background: var(--bt-surface-alt);
  border: 1px solid var(--bt-border);
  border-radius: var(--bt-radius-sm);
}
.delete-expense-preview-text {
  flex: 1 1 auto;
  min-width: 0;
}
.delete-expense-preview-text .fw-semibold {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.delete-expense-preview .expense-amount {
  flex-shrink: 0;
  font-weight: 700;
}

/* Deletion receipt — shows scale of what will be deleted */
.settings-danger-receipt {
  background: var(--bt-surface-alt);
  border-radius: var(--bt-radius-sm);
  padding: 0.75rem 1rem;
  margin: 0.5rem 0 1rem;
  font-size: 0.9rem;
  color: var(--bt-ink-muted);
}
.settings-danger-receipt strong { color: var(--bt-ink); }

/* Expense modal — split footer for primary + "Save & add another" */
.expense-modal-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* On mobile (coarse pointer + small screen), anchor the modal action buttons
   to the bottom edge so the user's thumb doesn't travel from the keyboard
   to the top of the modal to hit Save. safe-area-inset handles iOS notch /
   home-indicator. Bootstrap's modal-dialog gets a flex column so the
   footer stays sticky inside the modal viewport. */
@media (max-width: 576px) and (pointer: coarse) {
  #expenseModal .modal-dialog {
    margin: 0;
    height: 100%;
    max-width: none;
    display: flex;
    align-items: flex-end;
  }
  #expenseModal .modal-content {
    border-radius: var(--bt-radius-lg) var(--bt-radius-lg) 0 0;
    max-height: 92vh;
    display: flex;
    flex-direction: column;
  }
  #expenseModal .modal-body {
    overflow-y: auto;
    flex: 1 1 auto;
  }
  .expense-modal-footer {
    position: sticky;
    bottom: 0;
    background: var(--bt-surface);
    border-top: 1px solid var(--bt-border);
    padding-bottom: calc(0.75rem + env(safe-area-inset-bottom, 0px));
    z-index: 1;
  }
  .expense-modal-footer > .d-flex { width: 100%; }
  .expense-modal-footer .btn { flex: 1 1 auto; min-height: 48px; }
}

/* ── Theme toggle (navbar) ─────────────────────────────────────────────
   One circular button, sun↔moon icon. Active icon swaps based on the
   `data-theme` attribute on <html>. Persists to localStorage; OS pref
   is the auto fallback when no choice is stored. */
.bt-theme-toggle {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--bt-surface-alt);
  color: var(--bt-ink-muted);
  border: 1px solid var(--bt-border);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.bt-theme-toggle:hover, .bt-theme-toggle:focus-visible {
  background: var(--bt-primary-50);
  color: var(--bt-primary-ink);
  outline: none;
}
.bt-theme-icon { display: none; }
:root[data-theme="light"] .bt-theme-icon-moon { display: block; }
:root[data-theme="dark"]  .bt-theme-icon-sun  { display: block; }

/* ── Touch targets (coarse pointer) ─────────────────────────────────────
   WCAG 2.5.5 and Apple HIG both want ≥44×44px tappable targets. Bootstrap
   defaults land near that on standard text sizes but not on the small chips
   (quick-amounts, categories, date shortcuts) where a mis-tap silently picks
   the wrong category for an expense. Coarse-pointer-only so we don't bloat
   mouse-driven layouts. */
@media (pointer: coarse) {
  .btn-sm,
  .onboarding-quick-amounts .btn,
  [data-quick-cap],
  [data-quick-amount],
  [data-quick-date],
  .cat-picker .cat-pill,
  .category-pill,
  .amount-chip,
  .dropdown-item,
  .bt-lang-select {
    min-height: 44px;
    min-width: 44px;
  }
}

/* ────────────────────────────────────────────────────────────────────
   Happy-vibes layer
   Goal: every authenticated surface feels alive + warm without being
   loud. Universal tap springs, hover lifts, count-ups for numbers,
   animated category bars, gentle celebrations on milestones.
   All gated behind prefers-reduced-motion at the bottom of this block.
   ──────────────────────────────────────────────────────────────────── */

/* Universal button tap spring — every .btn shrinks slightly on press
   so taps feel registered. The transform short-circuits Bootstrap's
   focus/active outlines (which were already there). */
.btn { transition: transform 120ms ease, box-shadow 200ms ease, background-color 140ms ease, border-color 140ms ease; }
.btn:active { transform: scale(0.96); }
.btn-primary:hover { box-shadow: 0 6px 14px -6px rgba(234, 88, 12, 0.45); }

/* Card universal hover lift — applies to every Bootstrap .card on every
   page (settings, summary, plan tiles already overridden). Subtle so it
   doesn't fight the dashboard hero. */
.card {
  transition: transform 180ms ease, box-shadow 220ms ease;
}
main .card:not(.hero-card):not(.daily-card):not(.modal-content):hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 22px -12px rgba(0, 0, 0, 0.14);
}

/* Onboarding mascot — gentle bounce + waggle on first paint, celebrates
   when the user picks a quick amount (JS adds .is-celebrating). */
.onboarding-mascot {
  animation: ob-mascot-in 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
.onboarding-mascot .onboarding-emoji {
  display: inline-block;
  transform-origin: 50% 80%;
  animation: ob-mascot-sway 4.5s ease-in-out 1s infinite;
}
.onboarding-mascot.is-celebrating .onboarding-emoji {
  animation: ob-mascot-celebrate 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes ob-mascot-in {
  from { opacity: 0; transform: translateY(-10px) scale(0.8); }
  to   { opacity: 1; transform: none; }
}
@keyframes ob-mascot-sway {
  0%, 100% { transform: rotate(0); }
  50%      { transform: rotate(6deg); }
}
@keyframes ob-mascot-celebrate {
  0%   { transform: scale(1)   rotate(0deg); }
  35%  { transform: scale(1.3) rotate(-12deg); }
  70%  { transform: scale(0.95) rotate(8deg); }
  100% { transform: scale(1)   rotate(0deg); }
}

/* Onboarding quick-pick buttons — tap pop. Inherits from universal .btn
   but adds a subtle aria-pressed:true glow so the chosen amount carries
   a warm halo. */
.onboarding-quick-amounts .btn[aria-pressed="true"] {
  background: var(--bt-primary);
  color: #fff;
  border-color: var(--bt-primary);
  box-shadow: 0 4px 12px -4px rgba(234, 88, 12, 0.4);
}

/* Onboarding submit — "Mulai →" gets a gentle ready-pulse when the user
   has entered an amount (JS adds .is-ready). */
.onboarding-form .btn-primary.is-ready {
  animation: ob-ready-pulse 2.2s ease-in-out infinite;
}
@keyframes ob-ready-pulse {
  0%, 100% { box-shadow: 0 0 0 0  rgba(234, 88, 12, 0.0), 0 6px 16px -8px rgba(0,0,0,0.15); }
  50%      { box-shadow: 0 0 0 8px rgba(234, 88, 12, 0.18), 0 6px 16px -8px rgba(0,0,0,0.15); }
}

/* Onboarding preview number — slides in from below when revealed by JS. */
.onboarding-preview {
  animation: ob-preview-in 0.42s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes ob-preview-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* Settings cards — stagger fade-in across the grid. */
.settings-grid > section {
  animation: settings-card-in 0.42s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.settings-grid > section:nth-child(1) { animation-delay: 0.05s; }
.settings-grid > section:nth-child(2) { animation-delay: 0.15s; }
.settings-grid > section:nth-child(3) { animation-delay: 0.25s; }
.settings-grid > section:nth-child(4) { animation-delay: 0.35s; }
@keyframes settings-card-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* Monthly summary — metric tiles count up on viewport entry. The JS
   layer in monthly_summary.html observes [data-count-to] and animates
   the textContent; this rule just adds an entrance fade so they feel
   like data "arriving." */
.summary-tile {
  animation: summary-tile-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.summary-tile:nth-child(1) { animation-delay: 0.05s; }
.summary-tile:nth-child(2) { animation-delay: 0.13s; }
.summary-tile:nth-child(3) { animation-delay: 0.21s; }
.summary-tile:nth-child(4) { animation-delay: 0.29s; }
@keyframes summary-tile-in {
  from { opacity: 0; transform: translateY(10px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

/* Per-category breakdown — each row gets a thin animated bar showing
   its share of total spend. The bar fills from 0 → pct on viewport
   entry. Drop the row in via stagger too. */
.summary-cat-row {
  position: relative;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--bt-surface);
  border: 1px solid var(--bt-border);
  margin-bottom: 8px;
  animation: summary-tile-in 0.4s ease both;
  transition: transform 160ms ease, box-shadow 200ms ease;
}
.summary-cat-row:hover {
  transform: translateX(2px);
  box-shadow: 0 6px 14px -8px rgba(0,0,0,0.12);
}
.summary-cat-row:nth-child(1) { animation-delay: 0.05s; }
.summary-cat-row:nth-child(2) { animation-delay: 0.10s; }
.summary-cat-row:nth-child(3) { animation-delay: 0.15s; }
.summary-cat-row:nth-child(4) { animation-delay: 0.20s; }
.summary-cat-row:nth-child(5) { animation-delay: 0.25s; }
.summary-cat-row:nth-child(n+6) { animation-delay: 0.30s; }
.summary-cat-bar {
  position: absolute;
  left: 0; bottom: 0;
  height: 3px;
  width: 0;
  background: linear-gradient(90deg, var(--bt-primary), var(--bt-accent));
  border-bottom-left-radius: 10px;
  border-bottom-right-radius: 10px;
  transition: width 1.1s cubic-bezier(0.22, 1, 0.36, 1);
}
.summary-cat-row.is-revealed .summary-cat-bar { width: var(--bar-pct, 0%); }

/* Share page — the share image gets a sparkle-frame: rotating dashed
   border behind it + a few floating ✨ around the corners. Celebration
   only fires once on page load and on the green state. */
.share-image-wrap {
  position: relative;
  display: inline-block;
}
.share-image-wrap.is-green::before {
  content: "";
  position: absolute;
  inset: -10px;
  border-radius: 28px;
  background: conic-gradient(
    from 0deg,
    rgba(34,197,94,0.0)  0deg,
    rgba(34,197,94,0.55) 90deg,
    rgba(234,88,12,0.55) 180deg,
    rgba(236,72,153,0.55) 270deg,
    rgba(34,197,94,0.0) 360deg
  );
  filter: blur(14px);
  opacity: 0.6;
  animation: share-glow-spin 8s linear infinite;
  z-index: 0;
}
.share-image-wrap img { position: relative; z-index: 1; }
.share-sparkle {
  position: absolute;
  font-size: 1.6rem;
  pointer-events: none;
  filter: drop-shadow(0 4px 8px rgba(0,0,0,0.15));
  animation: share-sparkle-bob 3.5s ease-in-out infinite;
  z-index: 2;
}
.share-sparkle--1 { top: -14px;  left: -14px;  animation-delay: 0s;   }
.share-sparkle--2 { top: 20%;    right: -22px; animation-delay: 1.1s; font-size: 1.2rem; }
.share-sparkle--3 { bottom: -10px; left: 30%;  animation-delay: 2.2s; font-size: 1.3rem; }
@keyframes share-glow-spin {
  to { transform: rotate(360deg); }
}
@keyframes share-sparkle-bob {
  0%, 100% { transform: translateY(0)   rotate(-8deg); }
  50%      { transform: translateY(-8px) rotate(10deg); }
}

/* Coin-burst — reusable effect for celebratory moments. The trigger
   element gets .coin-burst added by JS; coins fly out + fade. JS removes
   the class after animation so it can re-fire. */
.coin-burst-host { position: relative; }
.coin-burst {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: visible;
  z-index: 10;
}
.coin-burst span {
  position: absolute;
  left: 50%;
  top: 50%;
  font-size: 1.4rem;
  opacity: 0;
  animation: coin-fly 1.1s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
.coin-burst span:nth-child(1) { --dx: -60px; --dy: -50px; animation-delay: 0s;    }
.coin-burst span:nth-child(2) { --dx:  60px; --dy: -55px; animation-delay: 0.05s; }
.coin-burst span:nth-child(3) { --dx: -20px; --dy: -75px; animation-delay: 0.10s; }
.coin-burst span:nth-child(4) { --dx:  35px; --dy: -65px; animation-delay: 0.15s; }
.coin-burst span:nth-child(5) { --dx:  -5px; --dy: -90px; animation-delay: 0.20s; }
@keyframes coin-fly {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.4); }
  20%  { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(1) rotate(40deg); }
}

/* Achievement banner — shown on streak milestones (the existing toast
   handles the immediate notice; this is the warmer in-flow version on
   the dashboard hero). */
.hero-achievement {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: linear-gradient(135deg, #fff7ed 0%, #fed7aa 100%);
  color: #9a3412;
  border-radius: var(--bt-radius-pill);
  padding: 0.35rem 0.85rem;
  font-size: 0.9rem;
  font-weight: 700;
  margin-top: 0.5rem;
  box-shadow: 0 4px 12px -4px rgba(234, 88, 12, 0.35);
  animation: hero-achievement-in 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
.hero-achievement-spark {
  display: inline-block;
  animation: streak-sparkle 1.8s ease-in-out infinite;
}
@keyframes hero-achievement-in {
  from { opacity: 0; transform: translateY(-6px) scale(0.85); }
  to   { opacity: 1; transform: none; }
}

/* Empty-state warmth — when an empty-state mascot exists, give it a
   gentle float + a happy color cycle on its background blob. */
.empty-state {
  text-align: center;
}
.empty-state .empty-icon {
  display: inline-block;
  animation: empty-float 3.5s ease-in-out infinite;
}
@keyframes empty-float {
  0%, 100% { transform: translateY(0)    rotate(-2deg); }
  50%      { transform: translateY(-6px) rotate(2deg); }
}

/* Toast happy variant — success toasts get a subtle sparkle pulse on
   their left border so a save *feels* like a small win. */
.bt-toast.success { animation: bt-toast-in 0.18s ease, toast-success-glow 1.4s ease-out; }
@keyframes toast-success-glow {
  0%   { box-shadow: 0 0 0 0   rgba(34,197,94,0.45); }
  100% { box-shadow: 0 0 0 14px rgba(34,197,94,0.0); }
}

/* No-spend ✓ link — extra warm green when clicked (.is-confirmed added
   by JS in monthly.html). */
.hero-nospend-link.is-confirmed {
  color: var(--bt-success-700) !important;
  font-weight: 700;
}

/* Theme toggle — sun/moon does a 360° spin on click. JS adds .is-flipping
   and removes it after the animation. */
#theme-toggle { transition: transform 140ms ease; }
#theme-toggle:active { transform: scale(0.9); }
#theme-toggle.is-flipping .bt-theme-icon {
  animation: theme-spin 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes theme-spin {
  from { transform: rotate(0deg)   scale(0.8); opacity: 0.4; }
  to   { transform: rotate(360deg) scale(1);   opacity: 1; }
}

/* Cat-pill rainbow shine on hover — soft conic-gradient sweep behind the
   icon. Pure cosmetic, kicks the category picker into "fun" territory. */
.cat-pill { position: relative; overflow: hidden; }
.cat-pill::before {
  content: "";
  position: absolute;
  inset: 0;
  background: conic-gradient(
    from 0deg,
    rgba(234,88,12,0.0) 0deg,
    rgba(234,88,12,0.18) 80deg,
    rgba(236,72,153,0.18) 160deg,
    rgba(168,85,247,0.18) 240deg,
    rgba(34,197,94,0.18) 320deg,
    rgba(234,88,12,0.0) 360deg
  );
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms ease;
  z-index: 0;
}
.cat-pill > * { position: relative; z-index: 1; }
.cat-pill:hover::before { opacity: 1; animation: cat-pill-shine 2.2s linear infinite; }
@keyframes cat-pill-shine {
  to { transform: rotate(360deg); }
}

/* Quick-amount chips — a tiny ✨ sparkle peeks out on hover. Uses ::after
   with a content emoji that fades + drifts up on hover only. */
.quick-amounts .quick-amount { position: relative; overflow: visible; }
.quick-amounts .quick-amount::after {
  content: "✨";
  position: absolute;
  top: -8px;
  right: -2px;
  font-size: 0.8rem;
  opacity: 0;
  transform: translateY(4px) scale(0.6);
  transition: opacity 180ms ease, transform 240ms ease;
  pointer-events: none;
}
.quick-amounts .quick-amount:hover::after {
  opacity: 1;
  transform: translateY(-4px) scale(1);
}

/* Streak emoji ladder — extended from the v2 layer. Adds "seed" (1–2)
   and "small" (3–6) tiers with their own micro-icons. Bigger tiers stay
   as defined earlier (✨ for big, 🔥 for huge). */
.hero-streak[data-streak-tier="seed"]::after  { content: "🌱"; }
.hero-streak[data-streak-tier="small"]::after { content: "🌿"; }
.hero-streak[data-streak-tier="seed"]::after,
.hero-streak[data-streak-tier="small"]::after {
  display: inline-block;
  margin-left: 0.25rem;
  animation: streak-sway 3.2s ease-in-out infinite;
}
@keyframes streak-sway {
  0%, 100% { transform: rotate(0); }
  50%      { transform: rotate(10deg); }
}

/* Auth marketing emoji marquee — soft drifting row of category emojis
   along the top of the marketing aside. Decorative; aria-hidden in the
   template so screen readers skip it. */
.auth-emoji-marquee {
  display: flex;
  gap: 1rem;
  font-size: 1.4rem;
  margin-bottom: 1.2rem;
  opacity: 0.85;
  filter: drop-shadow(0 2px 4px rgba(0,0,0,0.06));
}
.auth-emoji-marquee span {
  display: inline-block;
  animation: auth-emoji-bob 3.2s ease-in-out infinite;
}
.auth-emoji-marquee span:nth-child(2) { animation-delay: -0.4s; }
.auth-emoji-marquee span:nth-child(3) { animation-delay: -0.8s; }
.auth-emoji-marquee span:nth-child(4) { animation-delay: -1.2s; }
.auth-emoji-marquee span:nth-child(5) { animation-delay: -1.6s; }
.auth-emoji-marquee span:nth-child(6) { animation-delay: -2.0s; }
.auth-emoji-marquee span:nth-child(7) { animation-delay: -2.4s; }
.auth-emoji-marquee span:nth-child(8) { animation-delay: -2.8s; }
@keyframes auth-emoji-bob {
  0%, 100% { transform: translateY(0)    rotate(-4deg); }
  50%      { transform: translateY(-6px) rotate(6deg); }
}

/* Expense-saved emoji burst — a small flock of emojis erupts from the
   modal save button when JS fires the burst. JS appends spans inline so
   we don't need to pre-render them. */
.save-burst {
  position: absolute;
  pointer-events: none;
  inset: 0;
  z-index: 20;
  overflow: visible;
}
.save-burst span {
  position: absolute;
  left: 50%;
  top: 50%;
  font-size: 1.2rem;
  opacity: 0;
  animation: save-burst-fly 1.2s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
@keyframes save-burst-fly {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.5); }
  25%  { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(-50% + var(--dx, 0)), calc(-50% + var(--dy, -80px))) scale(1.2) rotate(40deg); }
}

/* Hero "vibe" pill — small mood emoji that sits next to the streak pill
   reflecting how the saldo is doing today. Set via data-vibe on the
   hero card by monthly.html JS. */
.hero-vibe {
  display: inline-flex;
  align-items: center;
  background: rgba(255,255,255,0.12);
  border-radius: var(--bt-radius-pill);
  padding: 0.15rem 0.55rem;
  margin-left: 0.4rem;
  font-size: 1rem;
  animation: hero-vibe-bob 3s ease-in-out infinite;
}
.hero-card-bare .hero-vibe { background: var(--bt-surface-alt); }
@keyframes hero-vibe-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-2px); }
}

/* Date chip emoji — make sure the emoji prefix doesn't get cut off and
   pops slightly when the chip becomes active (e.g. user picks "Hari ini"). */
.date-chip span[aria-hidden="true"] {
  display: inline-block;
  margin-right: 2px;
  transition: transform 200ms ease;
}
.date-chip.is-active span[aria-hidden="true"] {
  animation: date-chip-bump 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes date-chip-bump {
  0%   { transform: scale(1); }
  50%  { transform: scale(1.35) rotate(-8deg); }
  100% { transform: scale(1); }
}

/* Plan tile eyebrow emoji — adds a soft bob so the section headers feel
   alive without being noisy. */
.plan-tile-header .eyebrow span[aria-hidden="true"] {
  display: inline-block;
  margin-right: 2px;
  animation: plan-tile-emoji-bob 4s ease-in-out infinite;
}
@keyframes plan-tile-emoji-bob {
  0%, 100% { transform: translateY(0)   rotate(-3deg); }
  50%      { transform: translateY(-2px) rotate(3deg); }
}

/* Settings section header emoji — same gentle bob, longer interval so
   four section emojis don't sync into a single distracting beat. */
.settings-grid .eyebrow span[aria-hidden="true"] {
  display: inline-block;
  margin-right: 2px;
  animation: plan-tile-emoji-bob 5.2s ease-in-out infinite;
}
.settings-grid > section:nth-child(2) .eyebrow span[aria-hidden="true"] { animation-delay: -1.3s; }
.settings-grid > section:nth-child(3) .eyebrow span[aria-hidden="true"] { animation-delay: -2.6s; }
.settings-grid > section:nth-child(4) .eyebrow span[aria-hidden="true"] { animation-delay: -3.9s; }

/* Reduced-motion: kill the new ambient bobs/shines/marquee. The earlier
   reduced-motion block above already handles the rest of this file. */
@media (prefers-reduced-motion: reduce) {
  #theme-toggle.is-flipping .bt-theme-icon,
  .cat-pill:hover::before,
  .quick-amounts .quick-amount::after,
  .hero-streak[data-streak-tier="seed"]::after,
  .hero-streak[data-streak-tier="small"]::after,
  .auth-emoji-marquee span,
  .save-burst span,
  .hero-vibe,
  .date-chip.is-active span[aria-hidden="true"],
  .plan-tile-header .eyebrow span[aria-hidden="true"],
  .settings-grid .eyebrow span[aria-hidden="true"] { animation: none !important; }
  .cat-pill:hover::before { opacity: 0; }
  .quick-amounts .quick-amount:hover::after { opacity: 0; transform: none; }
}

/* ────────────────────────────────────────────────────────────────────
   Monthly summary — celebratory polish
   ──────────────────────────────────────────────────────────────────── */

.summary-page { position: relative; }

/* Header lays out as a vertical flex column so the verdict pill, eyebrow,
   H1 and verdict-line space themselves consistently via `gap`. Bootstrap's
   inline mt-/mb- utilities on these elements were compounding awkwardly
   with the inline-flex pill; we override them to 0 below and let the flex
   gap own the rhythm. */
.summary-header {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.6rem;
  margin-top: 1rem;
}
.summary-header .eyebrow,
.summary-header .summary-h1,
.summary-header .summary-verdict-line { margin: 0; }
.summary-header .summary-h1 { line-height: 1.05; }
.summary-header .summary-verdict-line { margin-top: 0.25rem; }

/* Verdict pill — sits at the top of the header. Green = celebration,
   recovery = encouragement. Both have a soft gradient so the page feels
   like a "results screen," not a report. */
.summary-verdict-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.35rem 0.85rem;
  border-radius: var(--bt-radius-pill);
  animation: summary-pill-in 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
.summary-verdict-pill.is-green {
  background: linear-gradient(135deg, #ecfdf5 0%, #a7f3d0 100%);
  color: #065f46;
  box-shadow: 0 6px 16px -6px rgba(34, 197, 94, 0.4);
}
.summary-verdict-pill.is-recovery {
  background: linear-gradient(135deg, #fff7ed 0%, #fed7aa 100%);
  color: #9a3412;
  box-shadow: 0 6px 16px -6px rgba(234, 88, 12, 0.35);
}
.summary-verdict-pill span[aria-hidden="true"] {
  display: inline-block;
  animation: summary-verdict-spark 2.4s ease-in-out infinite;
}
@keyframes summary-pill-in {
  from { opacity: 0; transform: translateY(-6px) scale(0.85); }
  to   { opacity: 1; transform: none; }
}
@keyframes summary-verdict-spark {
  0%, 100% { transform: scale(1) rotate(0); }
  50%      { transform: scale(1.15) rotate(8deg); }
}

/* H1 entrance bump — the month label scales in slightly so the page feels
   alive when it loads. */
.summary-h1 {
  animation: summary-h1-in 0.55s cubic-bezier(0.22, 1, 0.36, 1) 0.05s both;
}
@keyframes summary-h1-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* Verdict line — the "Hemat Rp X" / "Lewat cap Rp Y" sentence. Green
   gets a warm success ink, recovery stays warm orange. */
.summary-verdict-line {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: 600;
  margin-top: 0.4rem;
  animation: summary-h1-in 0.55s cubic-bezier(0.22, 1, 0.36, 1) 0.18s both;
}
.summary-verdict-line--green    { color: var(--bt-success-700); }
.summary-verdict-line--recovery { color: var(--bt-ink-muted); }
.summary-verdict-line span[aria-hidden="true"] {
  display: inline-block;
  animation: summary-verdict-spark 2.4s ease-in-out infinite;
}

/* Metric tile emoji — inline leader on the eyebrow. The !important on
   position/top/right defends against stale cached CSS that absolute-
   positioned this element (overlapped "TOTAL PENGELUARAN" / "HARI DI
   BAWAH CAP"). Rotation removed from the bob keyframe so the icon's
   bbox never sweeps into adjacent characters. */
.summary-tile-icon {
  position: static !important;
  top: auto !important;
  right: auto !important;
  display: inline-block;
  font-size: 1rem;
  line-height: 1;
  margin-right: 0.3rem;
  vertical-align: -1px;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.08));
  animation: summary-tile-bob 4s ease-in-out infinite;
}
.summary-tile:nth-child(2) .summary-tile-icon { animation-delay: -0.8s; }
.summary-tile:nth-child(3) .summary-tile-icon { animation-delay: -1.6s; }
.summary-tile:nth-child(4) .summary-tile-icon { animation-delay: -2.4s; }
@keyframes summary-tile-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-2px); }
}

/* Medals on the top 3 categories — sized to inline with the label. Gold
   gets a soft glow because it earned it. */
.summary-medal {
  display: inline-block;
  margin-right: 0.25rem;
  font-size: 1.05rem;
  vertical-align: -1px;
  animation: summary-medal-in 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
.summary-medal--gold {
  filter: drop-shadow(0 0 6px rgba(245, 158, 11, 0.55));
}
.summary-medal--silver,
.summary-medal--bronze {
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.12));
}
@keyframes summary-medal-in {
  from { opacity: 0; transform: scale(0.4) rotate(-30deg); }
  to   { opacity: 1; transform: scale(1)   rotate(0); }
}

/* Confetti rain — drops emojis from the top of the page on green
   months. Host is absolute-positioned, pointer-events: none so it never
   intercepts clicks. JS removes the host after 5.5 s. */
.summary-confetti-host {
  position: absolute;
  inset: 0 0 auto 0;
  height: 280px;
  pointer-events: none;
  overflow: hidden;
  z-index: 0;
}
.summary-confetti-host span {
  position: absolute;
  top: -32px;
  left: var(--x, 50%);
  font-size: 1.2rem;
  opacity: 0;
  animation: summary-confetti-fall var(--dur, 3s) ease-in var(--delay, 0s) forwards;
}
@keyframes summary-confetti-fall {
  0%   { opacity: 0; transform: translateY(-20px) rotate(0); }
  10%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(320px) rotate(var(--rot, 180deg)); }
}

/* Reduced motion — kill all the celebration animations but keep the
   pill/medal visible (just instant). */
@media (prefers-reduced-motion: reduce) {
  .summary-verdict-pill,
  .summary-verdict-pill span[aria-hidden="true"],
  .summary-h1,
  .summary-verdict-line,
  .summary-verdict-line span[aria-hidden="true"],
  .summary-tile-icon,
  .summary-medal,
  .summary-confetti-host span { animation: none !important; }
  .summary-confetti-host { display: none; }
}

/* Reduced-motion: kill every ambient/animated rule in this block. */
@media (prefers-reduced-motion: reduce) {
  .onboarding-mascot,
  .onboarding-mascot .onboarding-emoji,
  .onboarding-mascot.is-celebrating .onboarding-emoji,
  .onboarding-form .btn-primary.is-ready,
  .onboarding-preview,
  .settings-grid > section,
  .summary-tile,
  .summary-cat-row,
  .summary-cat-bar,
  .share-image-wrap.is-green::before,
  .share-sparkle,
  .coin-burst span,
  .hero-achievement,
  .hero-achievement-spark,
  .empty-state .empty-icon,
  .bt-toast.success { animation: none !important; }
  .summary-cat-row.is-revealed .summary-cat-bar { transition: none; }
  .btn { transition: none; }
  .btn:active { transform: none; }
  main .card:not(.hero-card):not(.daily-card):not(.modal-content):hover {
    transform: none; box-shadow: none;
  }
}

/* ═════════════════════════════════════════════════════════════════
   METHOD PAGE — /method/ — Narrative story of "Andra"
   A scroll-driven, chapter-based explainer told through the eyes
   of a fictional persona (Andra, 26, staff marketing, gaji 6 jt).
   Each chapter has its own visual centerpiece; the structure goes
   hero → gajian → chaos questions → old way → setup → first
   morning → week diary → Q&A → before/after → CTA.
   ═════════════════════════════════════════════════════════════════ */

.story {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 1rem;
}

.story-chapter {
  position: relative;
  padding: 4.5rem 0 4rem;
  border-bottom: 1px dashed rgba(148, 163, 184, 0.18);
}

.story-chapter:last-child { border-bottom: 0; }

.story-chapter-meta {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin-bottom: 1.2rem;
}

.story-chapter-num {
  font-size: 1.05rem;
  font-weight: 900;
  letter-spacing: 0.04em;
  color: #fff;
  background: linear-gradient(135deg, var(--bt-primary, #ea580c), #f59e0b);
  padding: 0.35rem 0.7rem;
  border-radius: 10px;
  box-shadow: 0 10px 20px -10px rgba(234, 88, 12, 0.5);
}

.story-chapter-date {
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bt-primary-ink, var(--bt-primary));
}

.story-h2 {
  font-size: clamp(1.7rem, 4vw, 2.4rem);
  font-weight: 900;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--bt-ink);
  margin: 0 0 1rem;
}

.story-narrate {
  font-size: 1.08rem;
  line-height: 1.65;
  color: var(--bt-ink-soft, var(--bt-ink));
  max-width: 720px;
  margin: 0 0 2rem;
}

.story-narrate strong { color: var(--bt-ink); }
.story-narrate em { font-style: normal; font-weight: 700; color: var(--bt-primary-ink, var(--bt-primary)); }

.story-callout {
  margin: 2rem auto 0;
  padding: 1.1rem 1.4rem;
  border-radius: 16px;
  background: linear-gradient(135deg, rgba(234, 88, 12, 0.10), rgba(245, 158, 11, 0.08));
  border: 1px solid rgba(234, 88, 12, 0.28);
  text-align: center;
  font-size: 1rem;
  color: var(--bt-ink);
  max-width: 620px;
}

.story-callout strong { color: var(--bt-primary-ink, var(--bt-primary)); font-weight: 800; }

/* ── HERO ─────────────────────────────────────────────────────── */

.story-hero {
  position: relative;
  padding: 4rem 0 3rem;
  text-align: center;
  overflow: hidden;
}

.story-hero-glow {
  position: absolute; inset: 0; pointer-events: none; z-index: 0;
}

.story-orb {
  position: absolute;
  border-radius: 999px;
  filter: blur(70px);
  opacity: 0.55;
  animation: story-orb-drift 14s ease-in-out infinite;
}

.story-orb--a { width: 320px; height: 320px; top: -40px; left: -60px;
  background: radial-gradient(circle, var(--bt-primary, #ea580c) 0%, transparent 70%); }
.story-orb--b { width: 280px; height: 280px; top: 30%; right: -70px;
  background: radial-gradient(circle, #f59e0b 0%, transparent 70%); animation-delay: -4s; opacity: 0.45; }
.story-orb--c { width: 240px; height: 240px; bottom: -60px; left: 30%;
  background: radial-gradient(circle, #fbbf24 0%, transparent 70%); animation-delay: -8s; opacity: 0.4; }

@keyframes story-orb-drift {
  0%, 100% { transform: translate(0, 0) scale(1); }
  33%      { transform: translate(20px, -18px) scale(1.05); }
  66%      { transform: translate(-12px, 14px) scale(0.96); }
}

.story-hero-inner {
  position: relative;
  z-index: 1;
  max-width: 820px;
  margin: 0 auto;
}

.story-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.35rem 0.85rem;
  border-radius: 999px;
  background: rgba(234, 88, 12, 0.1);
  color: var(--bt-primary-ink, var(--bt-primary));
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: 1rem;
}

.story-eyebrow-dot {
  width: 7px; height: 7px;
  border-radius: 999px;
  background: var(--bt-success, #22c55e);
  box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.55);
  animation: story-pulse-dot 1.8s ease-in-out infinite;
}

@keyframes story-pulse-dot {
  0%, 100% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.55); }
  60%      { box-shadow: 0 0 0 8px rgba(34, 197, 94, 0); }
}

.story-h1 {
  font-size: clamp(2.4rem, 5.5vw, 3.8rem);
  font-weight: 900;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--bt-ink);
  margin: 0.5rem 0 1rem;
}

.story-h1-name {
  display: inline-block;
  background: linear-gradient(135deg, var(--bt-primary), #f59e0b);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: story-name-wave 4s ease-in-out infinite;
}

@keyframes story-name-wave {
  0%, 100% { transform: rotate(-1deg); }
  50%      { transform: rotate(1deg); }
}

.story-h1-comma { color: var(--bt-ink); }

.story-h1-accent {
  font-size: 0.65em;
  font-weight: 700;
  color: var(--bt-ink-soft, var(--bt-ink));
  letter-spacing: -0.01em;
}

.story-lede {
  color: var(--bt-ink-soft, var(--bt-ink));
  font-size: 1.1rem;
  line-height: 1.6;
  max-width: 660px;
  margin: 0 auto 2rem;
}

.story-lede strong { color: var(--bt-ink); }

/* Andra orbit — 6 lifestyle emoji rotating around an avatar bubble. */
.story-andra {
  position: relative;
  width: 100%;
  max-width: 420px;
  aspect-ratio: 1 / 1;
  margin: 1rem auto 2rem;
}

.story-andra-orbit {
  position: absolute; inset: 0;
  border-radius: 50%;
  display: grid; place-items: center;
  background: radial-gradient(circle, rgba(255,255,255,0.6) 0%, transparent 70%);
  animation: story-orbit-spin 24s linear infinite;
}

.story-andra-orbit::before,
.story-andra-orbit::after {
  content: "";
  position: absolute;
  inset: 8%;
  border-radius: 50%;
  border: 1.5px dashed rgba(234, 88, 12, 0.22);
}

.story-andra-orbit::after {
  inset: 24%;
  border-style: solid;
  border-color: rgba(234, 88, 12, 0.16);
}

@keyframes story-orbit-spin { to { transform: rotate(360deg); } }

.story-andra-orbit-item {
  position: absolute; top: 50%; left: 50%;
  width: 52px; height: 52px;
  margin: -26px 0 0 -26px;
  border-radius: 50%;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  display: grid; place-items: center;
  font-size: 1.5rem;
  box-shadow: 0 10px 22px -10px rgba(0,0,0,0.2);
  transform: rotate(calc(var(--orbit-i) * 60deg)) translate(160px) rotate(calc(var(--orbit-i) * -60deg));
  animation: story-orbit-counter 24s linear infinite;
}

@keyframes story-orbit-counter {
  to {
    transform: rotate(calc(var(--orbit-i) * 60deg + 360deg)) translate(160px)
               rotate(calc(var(--orbit-i) * -60deg - 360deg));
  }
}

.story-andra-avatar {
  position: absolute;
  top: 50%; left: 50%;
  width: 130px; height: 130px;
  margin: -65px 0 0 -65px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--bt-primary), #f59e0b);
  display: grid;
  place-items: center;
  box-shadow: 0 30px 60px -20px rgba(234, 88, 12, 0.55);
  animation: story-avatar-breath 4s ease-in-out infinite;
}

@keyframes story-avatar-breath {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.04); }
}

.story-andra-avatar-emoji { font-size: 4.5rem; line-height: 1; }

.story-andra-thought {
  position: absolute;
  top: -10px; right: -28px;
  padding: 0.3rem 0.7rem;
  background: var(--bt-surface, #fff);
  border-radius: 999px;
  border: 1px solid var(--bt-border, #e5e7eb);
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--bt-ink);
  box-shadow: 0 6px 14px -6px rgba(0,0,0,0.2);
  animation: story-thought-bob 3s ease-in-out infinite;
}

@keyframes story-thought-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-4px); }
}

/* Progress dots (under the hero). They highlight as the user
   scrolls through chapters (JS does the toggling). */
.story-progress {
  display: inline-flex;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 999px;
  background: rgba(148, 163, 184, 0.10);
  margin-bottom: 1rem;
}

.story-progress-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: rgba(148, 163, 184, 0.4);
  transition: background 0.3s ease, transform 0.3s ease;
}

.story-progress-dot.is-active {
  background: var(--bt-primary, #ea580c);
  transform: scale(1.3);
}

.story-scroll-hint {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--bt-ink-soft, #6b7280);
}

.story-scroll-arrow {
  font-size: 1.2rem;
  color: var(--bt-primary, #ea580c);
  animation: story-bounce-y 1.6s ease-in-out infinite;
}

@keyframes story-bounce-y {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(6px); }
}

/* ── CH1: Gajian notification ──────────────────────────────────── */

.story-gajian {
  display: grid;
  grid-template-columns: minmax(0, 360px) 1fr;
  gap: 2.5rem;
  align-items: center;
  max-width: 820px;
}

.story-notif {
  position: relative;
  padding: 1.1rem 1.2rem 1.2rem;
  border-radius: 22px;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  box-shadow: 0 28px 60px -28px rgba(0,0,0,0.25);
  overflow: hidden;
  animation: story-notif-slide 0.8s cubic-bezier(.2,.8,.2,1) backwards;
  animation-delay: 0.2s;
}

@keyframes story-notif-slide {
  from { opacity: 0; transform: translateY(-30px) scale(0.92); }
  to   { opacity: 1; transform: none; }
}

.story-notif-bar {
  display: flex;
  justify-content: space-between;
  font-size: 0.75rem;
  color: var(--bt-ink-soft, #6b7280);
  font-weight: 700;
  letter-spacing: 0.04em;
  margin-bottom: 0.6rem;
}

.story-notif-bank { font-weight: 800; }

.story-notif-body { text-align: center; padding: 0.5rem 0 0.3rem; }

.story-notif-title {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--bt-ink-soft, #6b7280);
  margin-bottom: 0.3rem;
}

.story-notif-amount {
  font-size: clamp(2rem, 6vw, 2.5rem);
  font-weight: 900;
  color: #15803d;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  animation: story-notif-pop 0.6s ease-out 0.7s backwards;
}

@keyframes story-notif-pop {
  from { opacity: 0; transform: scale(0.5); }
  to   { opacity: 1; transform: scale(1); }
}

.story-notif-sub {
  font-size: 0.85rem;
  color: var(--bt-ink-soft, #6b7280);
  font-weight: 600;
  margin-top: 0.3rem;
}

.story-notif-confetti {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}

.story-confetti-piece {
  position: absolute;
  top: -20px;
  left: var(--cx);
  font-size: 1.2rem;
  animation: story-confetti-fall 2.4s ease-in var(--cd) infinite;
}

@keyframes story-confetti-fall {
  0%   { transform: translateY(0) rotate(0); opacity: 0; }
  20%  { opacity: 1; }
  100% { transform: translateY(220px) rotate(360deg); opacity: 0; }
}

.story-vibe {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1rem;
}

.story-vibe-emoji { font-size: 3.2rem; line-height: 1; animation: story-thought-bob 2s ease-in-out infinite; }

.story-vibe p {
  font-size: 1.4rem;
  font-weight: 800;
  color: var(--bt-ink);
  line-height: 1.3;
  margin: 0;
}

/* ── CH2: Chaos question swirl ─────────────────────────────────── */

.story-chaos {
  position: relative;
  margin: 0 auto;
  max-width: 760px;
}

.story-chaos-stage {
  position: relative;
  height: 460px;
  border-radius: 28px;
  background: linear-gradient(135deg, rgba(234,88,12,0.06), rgba(245,158,11,0.06));
  border: 1px dashed rgba(234, 88, 12, 0.25);
  overflow: hidden;
}

.story-chaos-avatar {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 96px; height: 96px;
  border-radius: 50%;
  background: var(--bt-surface, #fff);
  display: grid;
  place-items: center;
  border: 1px solid var(--bt-border, #e5e7eb);
  box-shadow: 0 14px 30px -14px rgba(0,0,0,0.25);
  z-index: 2;
}

.story-chaos-emoji {
  font-size: 3.4rem;
  line-height: 1;
  animation: story-chaos-shake 2s ease-in-out infinite;
}

@keyframes story-chaos-shake {
  0%, 100% { transform: rotate(0); }
  25%      { transform: rotate(-6deg); }
  75%      { transform: rotate(6deg); }
}

.story-chaos-q {
  position: absolute;
  padding: 0.55rem 0.95rem;
  border-radius: 999px;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--bt-ink);
  box-shadow: 0 12px 24px -16px rgba(0,0,0,0.18);
  animation: story-chaos-float 6s ease-in-out infinite;
  white-space: nowrap;
}

.story-chaos-q--1 { top: 8%;  left: 4%;   animation-delay: 0s; }
.story-chaos-q--2 { top: 16%; right: 6%;  animation-delay: -0.8s; }
.story-chaos-q--3 { top: 36%; left: 2%;   animation-delay: -1.6s; }
.story-chaos-q--4 { top: 38%; right: 4%;  animation-delay: -2.4s; }
.story-chaos-q--5 { bottom: 32%; left: 8%; animation-delay: -3.2s; }
.story-chaos-q--6 { bottom: 24%; right: 12%; animation-delay: -4s; }
.story-chaos-q--7 { bottom: 8%; left: 30%; animation-delay: -4.8s; }
.story-chaos-q--8 { top: 60%; right: 32%; animation-delay: -5.6s; }

@keyframes story-chaos-float {
  0%, 100% { transform: translateY(0) rotate(-1deg); opacity: 0.55; }
  50%      { transform: translateY(-8px) rotate(1deg); opacity: 1; }
}

/* ── CH3: Old-way attempts ─────────────────────────────────────── */

.story-attempts {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
}

.story-attempt {
  padding: 1.3rem 1.1rem;
  border-radius: 16px;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.story-attempt:hover {
  transform: translateY(-3px);
  box-shadow: 0 22px 40px -28px rgba(0,0,0,0.22);
}

.story-attempt-icon {
  width: 48px; height: 48px;
  border-radius: 12px;
  background: rgba(148, 163, 184, 0.12);
  display: grid; place-items: center;
  font-size: 1.6rem;
  margin-bottom: 0.75rem;
}

.story-attempt h3 {
  font-size: 1.02rem;
  font-weight: 800;
  margin: 0 0 0.4rem;
  color: var(--bt-ink);
}

.story-attempt p {
  font-size: 0.88rem;
  color: var(--bt-ink-soft, #6b7280);
  line-height: 1.55;
  margin: 0 0 0.9rem;
}

.story-attempt-fail {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--bt-danger, #dc2626);
  background: rgba(220, 38, 38, 0.10);
  padding: 0.4rem 0.6rem;
  border-radius: 8px;
}

/* ── CH4: Setup auto-play ──────────────────────────────────────── */

.story-setup {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: 2rem;
  align-items: flex-start;
  max-width: 960px;
}

.story-setup-form {
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  border-radius: 22px;
  padding: 1.4rem 1.2rem;
  box-shadow: 0 28px 60px -32px rgba(0,0,0,0.22);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.story-setup-row {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.8rem 0.9rem;
  border-radius: 14px;
  background: rgba(148, 163, 184, 0.06);
  opacity: 0.5;
  transform: translateX(-8px);
  transition: opacity 0.4s ease, transform 0.4s ease, background 0.4s ease, border-color 0.4s ease;
  border: 1px solid transparent;
}

.story-setup-row.is-on {
  opacity: 1;
  transform: none;
  background: linear-gradient(135deg, rgba(234,88,12,0.10), rgba(245,158,11,0.07));
  border-color: rgba(234, 88, 12, 0.25);
  box-shadow: 0 10px 22px -16px rgba(234, 88, 12, 0.4);
}

.story-setup-icon {
  font-size: 1.6rem;
  width: 40px; height: 40px;
  border-radius: 10px;
  display: grid; place-items: center;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
}

.story-setup-meta {
  flex: 1;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
}

.story-setup-label {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--bt-ink);
}

.story-setup-amount {
  font-weight: 800;
  font-size: 1rem;
  color: var(--bt-ink);
  font-variant-numeric: tabular-nums;
}

.story-setup-amount--neg { color: var(--bt-danger, #dc2626); }

.story-setup-currency {
  font-size: 0.78em;
  font-weight: 700;
  opacity: 0.7;
  margin-right: 0.15rem;
}

.story-setup-divider {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bt-ink-soft, #6b7280);
  padding: 0.4rem 0.9rem;
}

.story-setup-divider span {
  display: inline-grid;
  place-items: center;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: rgba(148, 163, 184, 0.18);
  font-size: 0.95rem;
  color: var(--bt-ink);
}

.story-setup-result {
  margin-top: 0.5rem;
  padding: 1rem 1rem 0.8rem;
  border-radius: 16px;
  background: linear-gradient(135deg, rgba(234,88,12,0.10), rgba(245,158,11,0.08));
  border: 1px solid rgba(234, 88, 12, 0.28);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  opacity: 0.5;
  transform: translateY(8px);
  transition: opacity 0.4s ease, transform 0.4s ease;
}

.story-setup-result.is-on { opacity: 1; transform: none; }

.story-setup-result-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 0.92rem;
  color: var(--bt-ink);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.story-setup-result-row--divide {
  justify-content: center;
  color: var(--bt-ink-soft, #6b7280);
  font-size: 0.85rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.story-setup-result-row--final {
  margin-top: 0.4rem;
  padding-top: 0.7rem;
  border-top: 1px solid rgba(234, 88, 12, 0.18);
  font-size: 1.05rem;
}

.story-setup-final-amount {
  font-size: 1.55rem;
  font-weight: 900;
  color: var(--bt-primary, #ea580c);
  letter-spacing: -0.01em;
}

.story-setup-side {
  position: sticky;
  top: 1rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.story-setup-running {
  padding: 1.1rem 1.2rem;
  border-radius: 18px;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  box-shadow: 0 18px 32px -22px rgba(0,0,0,0.18);
}

.story-setup-running-label {
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bt-ink-soft, #6b7280);
  display: block;
  margin-bottom: 0.6rem;
}

.story-setup-running-bar {
  height: 8px;
  border-radius: 999px;
  background: rgba(148, 163, 184, 0.18);
  overflow: hidden;
  margin-bottom: 0.7rem;
}

.story-setup-running-fill {
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--bt-primary, #ea580c), #f59e0b);
  border-radius: 999px;
  transition: width 0.5s ease;
}

.story-setup-running-status {
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--bt-ink);
  display: block;
  min-height: 1.4em;
}

.story-setup-go {
  font-weight: 800;
}

.story-setup-foot {
  line-height: 1.55;
  margin: 0;
}

/* ── CH5: First morning phone ──────────────────────────────────── */

.story-firstmorning {
  display: grid;
  grid-template-columns: 320px 1fr;
  gap: 3rem;
  align-items: center;
  max-width: 880px;
  margin: 0 auto;
}

.story-firstmorning-phone {
  position: relative;
  background: var(--bt-ink, #0b1220);
  border-radius: 38px;
  padding: 14px;
  box-shadow: 0 40px 80px -30px rgba(0,0,0,0.55);
}

.story-phone-notch {
  position: absolute;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  width: 70px;
  height: 18px;
  background: #0b1220;
  border-radius: 0 0 14px 14px;
  z-index: 2;
}

.story-phone-screen {
  background: linear-gradient(180deg, #fef3c7 0%, var(--bt-surface, #fff) 60%);
  border-radius: 24px;
  min-height: 480px;
  padding: 2rem 1.3rem 1.5rem;
  position: relative;
}

.story-phone-clock {
  text-align: center;
  font-weight: 800;
  font-size: 0.85rem;
  color: var(--bt-ink);
  margin: 0.2rem 0 0.8rem;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
}

.story-phone-greeting {
  text-align: center;
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--bt-ink-soft, #6b7280);
  margin-bottom: 1rem;
}

.story-phone-eyebrow {
  text-align: center;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bt-primary-ink, var(--bt-primary));
  margin-bottom: 0.4rem;
}

.story-phone-amount {
  text-align: center;
  font-size: 2.8rem;
  font-weight: 900;
  letter-spacing: -0.02em;
  color: var(--bt-ink);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  margin-bottom: 1rem;
}

.story-phone-currency {
  font-size: 0.5em;
  font-weight: 700;
  opacity: 0.75;
  margin-right: 0.2rem;
}

.story-phone-bar {
  height: 8px;
  border-radius: 999px;
  background: rgba(148, 163, 184, 0.2);
  overflow: hidden;
  margin: 0 0 1.5rem;
}

.story-phone-bar-fill {
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--bt-primary, #ea580c), #f59e0b);
  border-radius: 999px;
  transition: width 1.4s cubic-bezier(.4,.0,.2,1);
}

.story-phone-cta {
  padding: 0.8rem 1rem;
  border-radius: 14px;
  background: linear-gradient(135deg, var(--bt-primary, #ea580c), #f59e0b);
  color: #fff;
  text-align: center;
  font-weight: 800;
  font-size: 0.95rem;
  box-shadow: 0 16px 30px -14px rgba(234, 88, 12, 0.55);
  margin-bottom: 1rem;
}

.story-phone-microcopy {
  text-align: center;
  font-size: 0.78rem;
  color: var(--bt-ink-soft, #6b7280);
  line-height: 1.5;
}

.story-firstmorning-reaction {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  align-items: flex-start;
}

.story-firstmorning-emoji {
  font-size: 3.8rem;
  line-height: 1;
  animation: story-thought-bob 3s ease-in-out infinite;
}

.story-firstmorning-reaction p {
  font-size: 1.15rem;
  line-height: 1.6;
  color: var(--bt-ink);
  margin: 0;
}

.story-firstmorning-reaction strong { color: var(--bt-primary-ink, var(--bt-primary)); font-size: 1.4rem; }

/* ── CH6: Week diary ───────────────────────────────────────────── */

.story-week {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.85rem;
  margin-bottom: 1.5rem;
}

.story-day {
  position: relative;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  border-radius: 16px;
  padding: 0.9rem 0.8rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  opacity: 0;
  transform: translateY(14px);
  animation: story-day-in 0.5s cubic-bezier(.2,.8,.2,1) forwards;
  animation-delay: calc(var(--di) * 110ms + 0.1s);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.story-day:hover {
  transform: translateY(-4px);
  box-shadow: 0 26px 40px -28px rgba(0, 0, 0, 0.22);
}

@keyframes story-day-in {
  to { opacity: 1; transform: none; }
}

.story-day-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 0.78rem;
  font-weight: 800;
  color: var(--bt-ink-soft, #6b7280);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.story-day-num {
  font-size: 1.05rem;
  color: var(--bt-ink);
}

.story-day-amount {
  font-size: 1.1rem;
  font-weight: 900;
  color: var(--bt-ink);
  font-variant-numeric: tabular-nums;
}

.story-day-log {
  list-style: none;
  padding: 0;
  margin: 0.2rem 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.78rem;
}

.story-day-log li {
  display: grid;
  grid-template-columns: 18px 1fr auto;
  gap: 0.4rem;
  align-items: center;
}

.story-day-log span {
  color: var(--bt-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.story-day-log em {
  font-style: normal;
  font-weight: 700;
  color: var(--bt-danger, #dc2626);
  font-variant-numeric: tabular-nums;
}

.story-day-foot {
  margin-top: auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 0.75rem;
  padding-top: 0.5rem;
  border-top: 1px dashed var(--bt-border, #e5e7eb);
}

.story-day-spent { color: var(--bt-ink-soft, #6b7280); font-weight: 700; }

.story-day-pill {
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  font-weight: 800;
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}

.story-day-pill--up   { background: rgba(34, 197, 94, 0.16); color: #15803d; }
.story-day-pill--down { background: rgba(234, 88, 12, 0.16); color: #c2410c; }

.story-day-note {
  grid-column: 1 / -1;
  margin-top: 0.5rem;
  padding: 0.5rem 0.6rem;
  border-radius: 8px;
  background: rgba(234, 88, 12, 0.10);
  font-size: 0.72rem;
  line-height: 1.45;
  color: var(--bt-ink);
}

.story-day--green { box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.10) inset; }
.story-day--red   { box-shadow: 0 0 0 2px rgba(234, 88, 12, 0.15) inset; }

.story-week-summary {
  margin: 0 auto;
  padding: 1.25rem 1.6rem;
  max-width: 580px;
  border-radius: 18px;
  background: linear-gradient(135deg, rgba(34, 197, 94, 0.12), rgba(34, 197, 94, 0.04));
  border: 1px solid rgba(34, 197, 94, 0.30);
  text-align: center;
}

.story-week-summary-num {
  font-size: 2.2rem;
  font-weight: 900;
  color: #15803d;
  font-variant-numeric: tabular-nums;
  margin-bottom: 0.3rem;
}

.story-week-summary-label {
  font-size: 0.92rem;
  color: var(--bt-ink);
  line-height: 1.55;
}

/* ── CH7: Q&A accordion ────────────────────────────────────────── */

.story-qa {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  max-width: 820px;
}

.story-qa-item {
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  border-radius: 14px;
  overflow: hidden;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.story-qa-item[open] {
  border-color: rgba(234, 88, 12, 0.4);
  box-shadow: 0 22px 40px -28px rgba(234, 88, 12, 0.3);
}

.story-qa-item summary {
  list-style: none;
  cursor: pointer;
  padding: 1rem 1.2rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  font-weight: 700;
  color: var(--bt-ink);
}

.story-qa-item summary::-webkit-details-marker { display: none; }

.story-qa-q { line-height: 1.45; }

.story-qa-toggle {
  display: grid;
  place-items: center;
  width: 28px; height: 28px;
  border-radius: 50%;
  background: rgba(234, 88, 12, 0.12);
  color: var(--bt-primary, #ea580c);
  font-weight: 900;
  font-size: 1.1rem;
  flex-shrink: 0;
  transition: transform 0.25s ease, background 0.25s ease;
}

.story-qa-item[open] .story-qa-toggle {
  transform: rotate(45deg);
  background: var(--bt-primary, #ea580c);
  color: #fff;
}

.story-qa-a {
  padding: 0 1.2rem 1.3rem;
  color: var(--bt-ink-soft, var(--bt-ink));
  line-height: 1.6;
  font-size: 0.95rem;
}

.story-qa-a p { margin: 0 0 0.9rem; }

.story-qa-takeaway {
  margin-top: 0.8rem;
  padding: 0.7rem 0.85rem;
  border-radius: 10px;
  background: rgba(234, 88, 12, 0.08);
  font-size: 0.88rem;
  color: var(--bt-ink);
  font-weight: 600;
}

/* Q&A: coffee math viz */
.story-qa-viz {
  margin: 0.6rem 0 0.4rem;
  padding: 0.8rem;
  border-radius: 12px;
  background: rgba(148, 163, 184, 0.08);
}

.story-qa-viz--cof {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  justify-content: center;
}

.story-qa-coin, .story-qa-spend, .story-qa-result {
  padding: 0.55rem 0.8rem;
  border-radius: 12px;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 88px;
  text-align: center;
}

.story-qa-coin-label, .story-qa-result-tag {
  font-size: 0.68rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--bt-ink-soft, #6b7280);
}

.story-qa-coin-num { font-weight: 900; color: var(--bt-ink); font-size: 1rem; }

.story-qa-spend-emoji { font-size: 1.4rem; line-height: 1; }
.story-qa-spend-amount { font-weight: 800; color: var(--bt-danger, #dc2626); }

.story-qa-minus, .story-qa-equals {
  font-weight: 900;
  font-size: 1.2rem;
  color: var(--bt-ink-soft, #6b7280);
}

.story-qa-result--ok {
  background: linear-gradient(135deg, #22c55e, #16a34a);
  color: #fff;
  border-color: transparent;
}

.story-qa-result--ok span:first-child { font-weight: 900; font-size: 1.05rem; }
.story-qa-result--ok .story-qa-result-tag { color: rgba(255,255,255,0.95); }

/* Q&A: date cards (gebetan question) */
.story-qa-viz--date {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.7rem;
}

.story-qa-date-card {
  padding: 0.75rem 0.85rem;
  border-radius: 12px;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.story-qa-date-card span { font-size: 0.78rem; font-weight: 700; color: var(--bt-ink-soft, #6b7280); }
.story-qa-date-card strong { font-size: 1.05rem; font-weight: 900; color: var(--bt-ink); }
.story-qa-date-card small { font-size: 0.78rem; color: var(--bt-ink-soft, #6b7280); }

.story-qa-date-card--locked {
  background: linear-gradient(135deg, rgba(34, 197, 94, 0.12), rgba(34, 197, 94, 0.04));
  border-color: rgba(34, 197, 94, 0.32);
}

.story-qa-date-card--day {
  background: linear-gradient(135deg, rgba(234,88,12,0.08), rgba(245,158,11,0.06));
  border-color: rgba(234, 88, 12, 0.28);
}

/* Q&A: month grid */
.story-qa-month-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
  margin-bottom: 0.7rem;
}

.story-qa-month-cell {
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  font-size: 0.7rem;
  font-weight: 700;
  border-radius: 5px;
  background: rgba(234, 88, 12, 0.10);
  color: var(--bt-primary-ink, var(--bt-primary));
}

.story-qa-month-cell.is-future { background: rgba(148, 163, 184, 0.14); color: var(--bt-ink-soft, #6b7280); }

.story-qa-month-cell.is-mark {
  background: linear-gradient(135deg, var(--bt-primary, #ea580c), #f59e0b);
  color: #fff;
  font-weight: 900;
  transform: scale(1.15);
  box-shadow: 0 6px 14px -4px rgba(234, 88, 12, 0.55);
}

.story-qa-month-callout {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.6rem 0.8rem;
  border-radius: 10px;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
}

.story-qa-month-callout-pill {
  padding: 0.25rem 0.6rem;
  border-radius: 999px;
  background: var(--bt-primary, #ea580c);
  color: #fff;
  font-weight: 800;
  font-size: 0.78rem;
  white-space: nowrap;
  flex-shrink: 0;
}

.story-qa-month-callout p { margin: 0; font-size: 0.88rem; color: var(--bt-ink); }

/* Q&A: shoe meter */
.story-qa-shoe-meter {
  margin-top: 0.4rem;
}

.story-qa-shoe-meter-bar {
  position: relative;
  height: 14px;
  border-radius: 999px;
  background: rgba(148, 163, 184, 0.18);
  overflow: hidden;
}

.story-qa-shoe-meter-fill {
  height: 100%;
  background: linear-gradient(90deg, #22c55e, #84cc16);
  border-radius: 999px;
}

.story-qa-shoe-meter-stops {
  position: relative;
  display: flex;
  justify-content: space-between;
  margin-top: 0.4rem;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--bt-ink-soft, #6b7280);
}

.story-qa-shoe-meter-pin {
  position: absolute;
  top: -32px;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
}

.story-qa-shoe-meter-pin::after {
  content: "▼";
  font-size: 0.7rem;
  color: var(--bt-primary, #ea580c);
}

.story-qa-shoe-meter-tag {
  background: var(--bt-primary, #ea580c);
  color: #fff;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 800;
  white-space: nowrap;
}

/* Q&A: reset (overspend → fresh start) */
.story-qa-viz--reset {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 0.7rem;
  align-items: center;
}

.story-qa-reset-day {
  padding: 0.75rem 0.85rem;
  border-radius: 12px;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.story-qa-reset-day span { font-size: 0.78rem; font-weight: 700; color: var(--bt-ink-soft, #6b7280); }
.story-qa-reset-day strong { font-size: 1.15rem; font-weight: 900; margin: 0.15rem 0; }
.story-qa-reset-day small { font-size: 0.78rem; color: var(--bt-ink-soft, #6b7280); }

.story-qa-reset-day--bad {
  background: linear-gradient(135deg, rgba(220, 38, 38, 0.10), rgba(220, 38, 38, 0.03));
  border-color: rgba(220, 38, 38, 0.30);
}

.story-qa-reset-day--bad strong { color: var(--bt-danger, #dc2626); }

.story-qa-reset-day--new {
  background: linear-gradient(135deg, var(--bt-primary, #ea580c), #f59e0b);
  color: #fff;
  border-color: transparent;
}

.story-qa-reset-day--new span,
.story-qa-reset-day--new small { color: rgba(255, 255, 255, 0.92); }

.story-qa-reset-arrow {
  font-size: 1.5rem;
  font-weight: 900;
  color: var(--bt-primary, #ea580c);
  animation: story-arrow-pulse 1.8s ease-in-out infinite;
}

@keyframes story-arrow-pulse {
  0%, 100% { transform: translateX(0); opacity: 0.5; }
  50%      { transform: translateX(4px); opacity: 1; }
}

/* Q&A: income merge (freelance) */
.story-qa-viz--income {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  align-items: stretch;
}

.story-qa-income-row {
  display: flex;
  justify-content: space-between;
  padding: 0.55rem 0.75rem;
  border-radius: 10px;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  font-weight: 700;
  color: var(--bt-ink);
}

.story-qa-income-row--new {
  background: linear-gradient(135deg, rgba(34, 197, 94, 0.10), rgba(34, 197, 94, 0.03));
  border-color: rgba(34, 197, 94, 0.32);
  animation: story-income-glow 2.4s ease-in-out infinite;
}

@keyframes story-income-glow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.4); }
  50%      { box-shadow: 0 0 0 6px rgba(34, 197, 94, 0); }
}

.story-qa-income-arrow {
  text-align: center;
  font-size: 1.2rem;
  font-weight: 900;
  color: var(--bt-primary, #ea580c);
}

.story-qa-income-result {
  display: flex;
  justify-content: space-between;
  padding: 0.7rem 0.8rem;
  border-radius: 12px;
  background: linear-gradient(135deg, var(--bt-primary, #ea580c), #f59e0b);
  color: #fff;
  font-weight: 900;
}

/* Q&A: savings buckets */
.story-qa-viz--save {
  display: flex;
  gap: 0.7rem;
  flex-wrap: wrap;
}

.story-qa-save-bucket {
  flex: 1;
  min-width: 140px;
  padding: 0.8rem 0.9rem;
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.2rem;
}

.story-qa-save-bucket span { font-size: 1.6rem; line-height: 1; }
.story-qa-save-bucket strong { font-size: 1.05rem; font-weight: 900; color: var(--bt-ink); }
.story-qa-save-bucket small { font-size: 0.78rem; color: var(--bt-ink-soft, #6b7280); line-height: 1.4; }

.story-qa-save-bucket--fixed {
  background: linear-gradient(135deg, rgba(34, 197, 94, 0.10), rgba(34, 197, 94, 0.03));
  border: 1px solid rgba(34, 197, 94, 0.32);
}

.story-qa-save-bucket--bonus {
  background: linear-gradient(135deg, rgba(234, 88, 12, 0.10), rgba(245, 158, 11, 0.06));
  border: 1px solid rgba(234, 88, 12, 0.28);
}

.story-qa-save-total {
  flex-basis: 100%;
  text-align: center;
  padding: 0.7rem;
  border-radius: 10px;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  font-weight: 700;
  color: var(--bt-ink);
  font-size: 0.95rem;
}

.story-qa-save-total strong { color: var(--bt-primary, #ea580c); font-weight: 900; }

/* Q&A: privacy blocks */
.story-qa-viz--privacy {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.6rem;
}

.story-qa-privacy-block {
  padding: 0.8rem 0.7rem;
  border-radius: 12px;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
}

.story-qa-privacy-block span { font-size: 1.6rem; }
.story-qa-privacy-block strong { font-size: 0.9rem; font-weight: 800; color: var(--bt-ink); }
.story-qa-privacy-block small { font-size: 0.75rem; color: var(--bt-ink-soft, #6b7280); line-height: 1.4; }

/* ── CH8: Before/after wallets ─────────────────────────────────── */

.story-wallets {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 1.4rem;
  align-items: stretch;
}

.story-wallet {
  position: relative;
  padding: 1.6rem 1.4rem;
  border-radius: 22px;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
}

.story-wallet--before { background: linear-gradient(135deg, rgba(148, 163, 184, 0.10), rgba(148, 163, 184, 0.03)); }

.story-wallet--after {
  background: linear-gradient(135deg, rgba(34, 197, 94, 0.10), rgba(34, 197, 94, 0.03));
  border-color: rgba(34, 197, 94, 0.32);
  overflow: hidden;
}

.story-wallet-emoji {
  font-size: 2.6rem;
  line-height: 1;
  margin-bottom: 0.5rem;
}

.story-wallet-tag {
  font-size: 0.85rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--bt-ink-soft, #6b7280);
  margin-bottom: 1.1rem;
}

.story-wallet-grid {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.story-wallet-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 0.5rem 0;
  border-bottom: 1px dashed var(--bt-border, #e5e7eb);
  font-size: 0.92rem;
  color: var(--bt-ink-soft, #6b7280);
}

.story-wallet-row:last-child { border-bottom: 0; }
.story-wallet-row strong { color: var(--bt-ink); font-weight: 800; }
.story-wallet-good { color: #15803d !important; }

.story-wallet-vs {
  display: grid;
  place-items: center;
  font-size: 1.4rem;
  font-weight: 900;
  letter-spacing: 0.08em;
  color: var(--bt-primary, #ea580c);
  padding: 0 0.5rem;
}

.story-wallet-sparkle {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}

.story-wallet-sparkle span {
  position: absolute;
  top: 100%;
  left: var(--sx);
  font-size: 1.2rem;
  animation: story-wallet-rise 3s ease-in var(--sd) infinite;
}

@keyframes story-wallet-rise {
  0%   { transform: translateY(0)    rotate(0deg);  opacity: 0; }
  20%  { opacity: 1; }
  100% { transform: translateY(-260px) rotate(360deg); opacity: 0; }
}

.story-yearly {
  margin: 3rem auto 0;
  text-align: center;
  max-width: 620px;
  padding: 2rem 1.5rem;
  border-radius: 24px;
  background: linear-gradient(135deg, rgba(234, 88, 12, 0.10), rgba(245, 158, 11, 0.06));
  border: 1px solid rgba(234, 88, 12, 0.28);
}

.story-yearly-eyebrow {
  display: inline-block;
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bt-primary-ink, var(--bt-primary));
  margin-bottom: 0.5rem;
}

.story-yearly-amount {
  font-size: clamp(2.6rem, 8vw, 3.6rem);
  font-weight: 900;
  color: var(--bt-primary, #ea580c);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  margin-bottom: 0.8rem;
}

.story-yearly-amount span:first-child {
  font-size: 0.5em;
  opacity: 0.85;
  margin-right: 0.25rem;
}

.story-yearly-sub {
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--bt-ink);
  margin: 0;
}

.story-yearly-sub strong { color: var(--bt-primary-ink, var(--bt-primary)); }

/* ── Final CTA ─────────────────────────────────────────────────── */

.story-final {
  position: relative;
  max-width: 720px;
  margin: 0 auto;
  padding: 3rem 1.75rem 2.5rem;
  border-radius: 28px;
  background: linear-gradient(135deg, var(--bt-primary, #ea580c) 0%, #f59e0b 100%);
  color: #fff;
  text-align: center;
  overflow: hidden;
  box-shadow: 0 30px 60px -28px rgba(234, 88, 12, 0.55);
}

.story-final-h2 {
  font-size: clamp(1.7rem, 4vw, 2.3rem);
  font-weight: 900;
  color: #fff;
  margin: 0 0 1rem;
  line-height: 1.2;
}

.story-final-lede {
  color: rgba(255, 255, 255, 0.92);
  font-size: 1.05rem;
  line-height: 1.6;
  margin: 0.5rem auto 1.5rem;
  max-width: 500px;
}

.story-final-cta-row {
  display: flex;
  gap: 0.75rem;
  justify-content: center;
  flex-wrap: wrap;
}

.story-final .btn-primary {
  background: #fff;
  color: var(--bt-primary, #ea580c);
  border-color: #fff;
}

.story-final .btn-primary:hover {
  background: rgba(255, 255, 255, 0.92);
  color: var(--bt-primary, #ea580c);
}

.story-final .btn-outline-secondary {
  border-color: rgba(255, 255, 255, 0.6);
  color: #fff;
}

.story-final .btn-outline-secondary:hover {
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
}

.story-final-microcopy {
  margin: 1.5rem 0 0;
  color: rgba(255, 255, 255, 0.78);
  font-size: 0.85rem;
}

.story-final-spark {
  position: absolute;
  font-size: 1.6rem;
  pointer-events: none;
  animation: story-spark-float 5s ease-in-out infinite;
}

.story-final-spark--1 { top: 12%; left: 8%;  animation-delay: 0s;    }
.story-final-spark--2 { top: 20%; right: 10%; animation-delay: -1.4s; font-size: 1.3rem; }
.story-final-spark--3 { bottom: 18%; left: 14%; animation-delay: -2.8s; font-size: 1.5rem; }
.story-final-spark--4 { bottom: 12%; right: 12%; animation-delay: -4.2s; font-size: 1.2rem; }

@keyframes story-spark-float {
  0%, 100% { transform: translateY(0)   rotate(0deg);  opacity: 0.7; }
  50%      { transform: translateY(-10px) rotate(8deg); opacity: 1; }
}

/* ── Reveal animations for chapters ────────────────────────────── */

.story-chapter.reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.65s ease, transform 0.65s ease;
}

.story-chapter.reveal.is-revealed {
  opacity: 1;
  transform: none;
}

/* ── CH7: Rollover mechanic — chart + 4 scenarios ──────────────── */

.story-rollover {
  display: flex;
  flex-direction: column;
  gap: 1.6rem;
}

.story-rollover-chart {
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  border-radius: 22px;
  padding: 1.4rem 1.4rem 1.6rem;
  box-shadow: 0 28px 60px -32px rgba(0,0,0,0.22);
}

.story-rollover-chart-head {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  margin-bottom: 0.9rem;
}

.story-rollover-chart-title {
  font-size: 0.92rem;
  font-weight: 800;
  color: var(--bt-ink);
}

.story-rollover-chart-sub {
  font-size: 0.8rem;
  color: var(--bt-ink-soft, #6b7280);
  font-weight: 600;
}

.story-rollover-svg {
  width: 100%;
  height: clamp(180px, 30vw, 280px);
  display: block;
}

.story-rollover-chart-x {
  margin-top: 0.6rem;
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--bt-ink-soft, #6b7280);
  text-align: center;
}

.story-rollover-chart-x span:nth-child(4) {
  grid-column: 3 / span 2;
  color: var(--bt-danger, #dc2626);
  font-weight: 800;
}

.story-rollover-chart-pin { white-space: nowrap; }

.story-rollover-scenarios {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.2rem;
}

.story-rollover-card {
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  border-radius: 18px;
  padding: 1.2rem 1.3rem 1.3rem;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.story-rollover-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 24px 50px -28px rgba(0,0,0,0.25);
}

.story-rollover-card--green   { border-color: rgba(34, 197, 94, 0.30); background: linear-gradient(160deg, rgba(34, 197, 94, 0.06), transparent 60%); }
.story-rollover-card--red     { border-color: rgba(220, 38, 38, 0.30); background: linear-gradient(160deg, rgba(220, 38, 38, 0.06), transparent 60%); }
.story-rollover-card--recovery{ border-color: rgba(234, 88, 12, 0.30); background: linear-gradient(160deg, rgba(234, 88, 12, 0.06), transparent 60%); }
.story-rollover-card--warn    { border-color: rgba(245, 158, 11, 0.35); background: linear-gradient(160deg, rgba(245, 158, 11, 0.07), transparent 60%); }

.story-rollover-card-head { display: flex; flex-direction: column; gap: 0.3rem; }

.story-rollover-card-tag {
  display: inline-block;
  align-self: flex-start;
  padding: 0.18rem 0.55rem;
  border-radius: 999px;
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: rgba(148, 163, 184, 0.18);
  color: var(--bt-ink);
}

.story-rollover-card--green   .story-rollover-card-tag { background: rgba(34, 197, 94, 0.18); color: #15803d; }
.story-rollover-card--red     .story-rollover-card-tag { background: rgba(220, 38, 38, 0.16); color: #b91c1c; }
.story-rollover-card--recovery .story-rollover-card-tag { background: rgba(234, 88, 12, 0.16); color: var(--bt-primary-ink, var(--bt-primary)); }
.story-rollover-card--warn    .story-rollover-card-tag { background: rgba(245, 158, 11, 0.20); color: #b45309; }

.story-rollover-card-title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 900;
  line-height: 1.3;
  color: var(--bt-ink);
}

.story-rollover-math {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
  padding: 0.85rem 0.95rem;
  border-radius: 12px;
  background: rgba(148, 163, 184, 0.07);
}

.story-rollover-math-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--bt-ink);
  font-variant-numeric: tabular-nums;
}

.story-rollover-math-label { color: var(--bt-ink-soft, #6b7280); font-weight: 600; }

.story-rollover-math-val--in  { color: #15803d; }
.story-rollover-math-val--out { color: var(--bt-danger, #dc2626); }
.story-rollover-math-val--pos { color: var(--bt-primary, #ea580c); font-weight: 900; }
.story-rollover-math-val--warn { color: #b45309; font-weight: 900; }

.story-rollover-math-row--total {
  padding-top: 0.45rem;
  border-top: 1px dashed rgba(148, 163, 184, 0.35);
  font-size: 0.95rem;
}

.story-rollover-math-row--total .story-rollover-math-label { color: var(--bt-ink); font-weight: 800; }

.story-rollover-card-note {
  margin: 0;
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--bt-ink-soft, var(--bt-ink));
}

/* Mini 3-day week for recovery scenario */
.story-rollover-mini-week {
  display: flex;
  align-items: stretch;
  gap: 0.4rem;
  flex-wrap: wrap;
}

.story-rollover-mini-day {
  flex: 1 1 100px;
  min-width: 100px;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.6rem 0.5rem;
  border-radius: 10px;
  text-align: center;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
}

.story-rollover-mini-label {
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bt-ink-soft, #6b7280);
}

.story-rollover-mini-num {
  font-size: 1rem;
  font-weight: 900;
  color: var(--bt-ink);
  font-variant-numeric: tabular-nums;
}

.story-rollover-mini-foot {
  font-size: 0.7rem;
  color: var(--bt-ink-soft, #6b7280);
  line-height: 1.3;
}

.story-rollover-mini-day--bad   { background: linear-gradient(135deg, rgba(220, 38, 38, 0.10), rgba(220, 38, 38, 0.04)); border-color: rgba(220, 38, 38, 0.30); }
.story-rollover-mini-day--bad   .story-rollover-mini-num { color: var(--bt-danger, #dc2626); }
.story-rollover-mini-day--ok    { background: linear-gradient(135deg, rgba(34, 197, 94, 0.10), rgba(34, 197, 94, 0.04)); border-color: rgba(34, 197, 94, 0.28); }
.story-rollover-mini-day--ok    .story-rollover-mini-num { color: #15803d; }
.story-rollover-mini-day--final {
  background: linear-gradient(135deg, var(--bt-primary, #ea580c), #f59e0b);
  border-color: transparent;
  color: #fff;
}
.story-rollover-mini-day--final .story-rollover-mini-label,
.story-rollover-mini-day--final .story-rollover-mini-num,
.story-rollover-mini-day--final .story-rollover-mini-foot { color: #fff; }

.story-rollover-mini-arrow,
.story-rollover-mini-equals {
  align-self: center;
  font-size: 1.3rem;
  font-weight: 900;
  color: var(--bt-ink-soft, #6b7280);
}

/* Formula footer */
.story-rollover-formula {
  text-align: center;
  padding: 1.5rem 1.4rem;
  border-radius: 18px;
  background: linear-gradient(135deg, rgba(234, 88, 12, 0.08), rgba(245, 158, 11, 0.04));
  border: 1px dashed rgba(234, 88, 12, 0.35);
}

.story-rollover-formula-eyebrow {
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bt-primary-ink, var(--bt-primary));
  margin-bottom: 0.7rem;
}

.story-rollover-formula-code {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.7rem 1rem;
  border-radius: 12px;
  background: var(--bt-surface, #fff);
  border: 1px solid var(--bt-border, #e5e7eb);
  font-family: inherit;
  font-size: 1rem;
  font-weight: 800;
}

.story-rollover-formula-piece {
  padding: 0.3rem 0.7rem;
  border-radius: 8px;
  background: rgba(148, 163, 184, 0.12);
  color: var(--bt-ink);
}

.story-rollover-formula-piece--out {
  background: linear-gradient(135deg, var(--bt-primary, #ea580c), #f59e0b);
  color: #fff;
}

.story-rollover-formula-op {
  font-weight: 900;
  color: var(--bt-ink-soft, #6b7280);
  font-size: 1.2rem;
}

.story-rollover-formula-foot {
  margin: 0.8rem auto 0;
  max-width: 580px;
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--bt-ink-soft, var(--bt-ink));
}

/* ── CH7: Daily-breakdown mock — mirrors the production Rincian
   harian table so the reader sees the exact UI they'll meet on the
   dashboard, with carry-forward rows interleaved between days. ─── */

.story-daily-mock {
  margin: 1.4rem 0 1.4rem;
  border-radius: 18px;
  border: 1px solid var(--bt-border, #e5e7eb);
  background: var(--bt-surface, #fff);
  box-shadow: 0 28px 60px -38px rgba(0,0,0,0.25);
  overflow: hidden;
}

.story-daily-mock-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1rem;
  padding: 1.2rem 1.4rem;
  border-bottom: 1px solid var(--bt-border, #e5e7eb);
}

.story-daily-mock-eyebrow {
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bt-ink-soft, #6b7280);
  margin-bottom: 0.15rem;
}

.story-daily-mock-title {
  font-size: 1.15rem;
  font-weight: 800;
  color: var(--bt-ink);
  margin-bottom: 0.4rem;
}

.story-daily-mock-meta {
  font-size: 0.84rem;
  color: var(--bt-ink-soft, #6b7280);
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  align-items: baseline;
}

.story-daily-mock-meta strong { color: var(--bt-ink); font-weight: 700; margin-right: 0.2rem; }
.story-daily-mock-meta-sep { opacity: 0.5; }

.story-daily-mock-tag {
  padding: 0.25rem 0.6rem;
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  background: rgba(234, 88, 12, 0.12);
  color: var(--bt-primary-ink, var(--bt-primary));
  flex-shrink: 0;
}

.story-daily-mock-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.story-daily-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
  font-variant-numeric: tabular-nums;
}

.story-daily-table thead th {
  text-align: left;
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bt-ink-soft, #6b7280);
  padding: 0.85rem 1rem;
  border-bottom: 1px solid var(--bt-border, #e5e7eb);
  background: var(--bt-surface-alt, rgba(148, 163, 184, 0.05));
  white-space: nowrap;
}

.story-daily-table .story-daily-th-num { text-align: right; }
.story-daily-table thead th:first-child { padding-left: 1.4rem; }
.story-daily-table thead th:last-child { padding-right: 1.4rem; }

.story-flow-tip {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  cursor: help;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
  text-decoration-color: var(--bt-border, #cbd5e1);
}
.story-flow-tip:focus { outline: none; }
.story-flow-tip-q {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.1em;
  height: 1.1em;
  border-radius: 50%;
  background: var(--bt-surface-alt, rgba(148, 163, 184, 0.18));
  color: var(--bt-ink-soft, #6b7280);
  font-size: 0.78em;
  font-weight: 800;
  line-height: 1;
  letter-spacing: 0;
  text-transform: none;
}
.story-flow-tip::after {
  content: attr(data-tip);
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  width: max-content;
  max-width: 240px;
  padding: 0.55rem 0.7rem;
  background: #0b1220;
  color: #f8fafc;
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: 0;
  text-transform: none;
  text-align: left;
  white-space: normal;
  border-radius: 8px;
  box-shadow: 0 6px 20px rgba(15, 23, 42, 0.18);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;
  pointer-events: none;
  z-index: 5;
}
.story-flow-tip::before {
  content: "";
  position: absolute;
  top: calc(100% + 4px);
  right: 0.7rem;
  border: 6px solid transparent;
  border-bottom-color: #0b1220;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.15s ease, visibility 0.15s;
  z-index: 5;
}
.story-flow-tip:hover::after,
.story-flow-tip:focus-visible::after,
.story-flow-tip:hover::before,
.story-flow-tip:focus-visible::before {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.story-flow-tip:focus-visible .story-flow-tip-q {
  outline: 2px solid var(--bt-primary, #ea580c);
  outline-offset: 2px;
}

.story-daily-table tbody td {
  padding: 0.85rem 1rem;
  vertical-align: middle;
  border-top: 1px solid var(--bt-border, #e5e7eb);
}

.story-daily-table tbody td:first-child { padding-left: 1.4rem; }
.story-daily-table tbody td:last-child  { padding-right: 1.4rem; }

.story-daily-row td { color: var(--bt-ink); font-weight: 600; }
.story-daily-row:hover { background: var(--bt-surface-alt, rgba(148, 163, 184, 0.05)); }

.story-daily-row--alert td { background: linear-gradient(0deg, rgba(220, 38, 38, 0.05), rgba(220, 38, 38, 0.02)); }

.story-daily-date {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  font-variant-numeric: tabular-nums;
}

.story-daily-day {
  font-size: 1.05rem;
  font-weight: 900;
  color: var(--bt-ink);
}

.story-daily-dow {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--bt-ink-soft, #6b7280);
}

.story-daily-dow--weekend {
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  background: rgba(234, 88, 12, 0.10);
  color: var(--bt-primary-ink, var(--bt-primary));
}

.story-daily-desc {
  color: var(--bt-ink);
  max-width: 26ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.story-daily-out         { text-align: right; color: var(--bt-danger, #dc2626); font-weight: 700; }
.story-daily-budget    { text-align: right; font-weight: 800; transition: background 0.2s ease, box-shadow 0.2s ease; }
.story-daily-budget--pos { color: #15803d; }
.story-daily-budget--low { color: #b45309; }
.story-daily-saldo       { text-align: right; font-weight: 800; transition: background 0.2s ease, box-shadow 0.2s ease; }
.story-daily-saldo--pos  { color: #15803d; }
.story-daily-saldo--neg  { color: var(--bt-danger, #dc2626); }

.story-daily-saldo:focus-visible { outline: 2px solid var(--bt-primary, #ea580c); outline-offset: -2px; border-radius: 6px; }

.story-daily-saldo.is-linked,
.story-daily-budget.is-linked {
  background: linear-gradient(135deg, rgba(234, 88, 12, 0.18), rgba(245, 158, 11, 0.10));
  box-shadow: inset 0 0 0 2px rgba(234, 88, 12, 0.45);
  border-radius: 6px;
}

.story-daily-bang {
  display: inline-grid;
  place-items: center;
  width: 18px; height: 18px;
  margin-right: 0.35rem;
  border-radius: 50%;
  background: rgba(220, 38, 38, 0.18);
  color: var(--bt-danger, #dc2626);
  font-weight: 900;
  font-size: 0.82rem;
  vertical-align: -2px;
}

.story-daily-carry td {
  padding: 0.55rem 1.4rem;
  border-top: 0;
  background: rgba(148, 163, 184, 0.06);
}

.story-daily-carry-flow {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--bt-ink-soft, #6b7280);
  padding: 0.35rem 0.7rem;
  border-radius: 10px;
  background: var(--bt-surface, #fff);
  border: 1px dashed rgba(148, 163, 184, 0.4);
}

.story-daily-carry-from strong,
.story-daily-carry-to strong {
  color: var(--bt-ink);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.story-daily-carry-arrow {
  width: 36px;
  height: 12px;
  flex-shrink: 0;
}

.story-daily-carry--pos { color: #15803d; }
.story-daily-carry--pos .story-daily-carry-flow { border-color: rgba(34, 197, 94, 0.40); background: rgba(34, 197, 94, 0.05); }
.story-daily-carry--pos .story-daily-carry-arrow { color: #16a34a; }
.story-daily-carry--pos .story-daily-carry-from strong,
.story-daily-carry--pos .story-daily-carry-to strong { color: #15803d; }

.story-daily-carry--neg { color: var(--bt-danger, #dc2626); }
.story-daily-carry--neg .story-daily-carry-flow { border-color: rgba(220, 38, 38, 0.40); background: rgba(220, 38, 38, 0.05); }
.story-daily-carry--neg .story-daily-carry-arrow { color: var(--bt-danger, #dc2626); }
.story-daily-carry--neg .story-daily-carry-from strong,
.story-daily-carry--neg .story-daily-carry-to strong { color: var(--bt-danger, #dc2626); }

.story-daily-mock-foot {
  padding: 1rem 1.4rem;
  background: var(--bt-surface-alt, rgba(148, 163, 184, 0.05));
  border-top: 1px solid var(--bt-border, #e5e7eb);
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--bt-ink);
}

.story-daily-mock-foot strong.text-success { color: #15803d; }

/* ── Mobile ─────────────────────────────────────────────────────── */

@media (max-width: 960px) {
  .story-chapter { padding: 3rem 0; }

  .story-andra { max-width: 320px; }
  .story-andra-orbit-item { transform: rotate(calc(var(--orbit-i) * 60deg)) translate(120px) rotate(calc(var(--orbit-i) * -60deg)); }
  @keyframes story-orbit-counter {
    to {
      transform: rotate(calc(var(--orbit-i) * 60deg + 360deg)) translate(120px)
                 rotate(calc(var(--orbit-i) * -60deg - 360deg));
    }
  }

  .story-gajian,
  .story-setup,
  .story-firstmorning,
  .story-wallets { grid-template-columns: 1fr; gap: 1.5rem; }

  .story-rollover-scenarios { grid-template-columns: 1fr; }
  .story-rollover-mini-arrow,
  .story-rollover-mini-equals { transform: rotate(90deg); align-self: center; }

  .story-daily-mock-head { flex-direction: column; align-items: flex-start; gap: 0.4rem; }

  .story-attempts { grid-template-columns: 1fr 1fr; }

  .story-wallet-vs { padding: 0.4rem 0; font-size: 1.2rem; }

  .story-week {
    grid-template-columns: repeat(2, 1fr);
  }

  .story-setup-side { position: static; }
  .story-firstmorning-phone { margin: 0 auto; max-width: 320px; }

  .story-chaos-stage { height: 380px; }
  .story-chaos-q { font-size: 0.82rem; padding: 0.4rem 0.7rem; }
}

@media (max-width: 560px) {
  .story-week { grid-template-columns: 1fr; }
  .story-attempts { grid-template-columns: 1fr; }
  .story-qa-viz--privacy { grid-template-columns: 1fr; }
  .story-qa-viz--reset { grid-template-columns: 1fr; }
  .story-qa-reset-arrow { transform: rotate(90deg); justify-self: center; }
  .story-chaos-q--4, .story-chaos-q--6 { display: none; }
}

/* ── Dark mode ─────────────────────────────────────────────────── */

[data-theme="dark"] .story-notif,
[data-theme="dark"] .story-attempt,
[data-theme="dark"] .story-setup-form,
[data-theme="dark"] .story-setup-running,
[data-theme="dark"] .story-setup-icon,
[data-theme="dark"] .story-firstmorning-phone .story-phone-screen,
[data-theme="dark"] .story-day,
[data-theme="dark"] .story-chaos-avatar,
[data-theme="dark"] .story-chaos-q,
[data-theme="dark"] .story-qa-item,
[data-theme="dark"] .story-qa-coin,
[data-theme="dark"] .story-qa-spend,
[data-theme="dark"] .story-qa-date-card,
[data-theme="dark"] .story-qa-month-callout,
[data-theme="dark"] .story-qa-reset-day,
[data-theme="dark"] .story-qa-income-row,
[data-theme="dark"] .story-qa-save-total,
[data-theme="dark"] .story-qa-privacy-block,
[data-theme="dark"] .story-rollover-chart,
[data-theme="dark"] .story-rollover-card,
[data-theme="dark"] .story-rollover-mini-day,
[data-theme="dark"] .story-rollover-formula-code,
[data-theme="dark"] .story-wallet {
  background: var(--bt-surface);
  border-color: var(--bt-border);
  color: var(--bt-ink);
}

[data-theme="dark"] .story-flow-tip::after { background: #e5e7eb; color: #0b1220; }
[data-theme="dark"] .story-daily-mock,
[data-theme="dark"] .story-daily-carry-flow {
  background: var(--bt-surface);
  border-color: var(--bt-border);
}
[data-theme="dark"] .story-daily-table thead th { background: var(--bt-surface-alt, rgba(148, 163, 184, 0.10)); }
[data-theme="dark"] .story-daily-row--alert td { background: linear-gradient(0deg, rgba(220, 38, 38, 0.10), rgba(220, 38, 38, 0.03)); }
[data-theme="dark"] .story-daily-saldo--pos,
[data-theme="dark"] .story-daily-budget--pos,
[data-theme="dark"] .story-daily-carry--pos .story-daily-carry-from strong,
[data-theme="dark"] .story-daily-carry--pos .story-daily-carry-to strong { color: #6ee7b7; }
[data-theme="dark"] .story-daily-saldo.is-linked,
[data-theme="dark"] .story-daily-budget.is-linked { background: linear-gradient(135deg, rgba(234, 88, 12, 0.30), rgba(245, 158, 11, 0.18)); }
[data-theme="dark"] .story-daily-mock-foot { background: var(--bt-surface-alt, rgba(148, 163, 184, 0.08)); }
[data-theme="dark"] .story-flow-tip::before { border-bottom-color: #e5e7eb; }
[data-theme="dark"] .story-rollover-math { background: rgba(148, 163, 184, 0.10); }
[data-theme="dark"] .story-rollover-math-val--in { color: #6ee7b7; }
[data-theme="dark"] .story-rollover-mini-day--ok .story-rollover-mini-num { color: #6ee7b7; }
[data-theme="dark"] .story-rollover-formula,
[data-theme="dark"] .story-rollover-formula-piece { background: rgba(234, 88, 12, 0.18); }

[data-theme="dark"] .story-phone-screen {
  background: linear-gradient(180deg, #1f2937 0%, #111827 100%);
}

[data-theme="dark"] .story-day-note { background: rgba(234, 88, 12, 0.18); color: #fed7aa; }

[data-theme="dark"] .story-wallet--before {
  background: linear-gradient(135deg, rgba(148, 163, 184, 0.15), rgba(148, 163, 184, 0.05));
}

[data-theme="dark"] .story-wallet--after {
  background: linear-gradient(135deg, rgba(34, 197, 94, 0.15), rgba(34, 197, 94, 0.04));
  border-color: rgba(34, 197, 94, 0.40);
}

[data-theme="dark"] .story-wallet-good { color: #6ee7b7 !important; }

[data-theme="dark"] .story-setup-result,
[data-theme="dark"] .story-yearly,
[data-theme="dark"] .story-callout {
  background: linear-gradient(135deg, rgba(234, 88, 12, 0.14), rgba(245, 158, 11, 0.06));
  border-color: rgba(234, 88, 12, 0.32);
}

[data-theme="dark"] .story-week-summary {
  background: linear-gradient(135deg, rgba(34, 197, 94, 0.16), rgba(34, 197, 94, 0.04));
  border-color: rgba(34, 197, 94, 0.40);
}

[data-theme="dark"] .story-week-summary-num { color: #6ee7b7; }
[data-theme="dark"] .story-day-pill--up { background: rgba(34, 197, 94, 0.22); color: #6ee7b7; }
[data-theme="dark"] .story-day-pill--down { background: rgba(234, 88, 12, 0.22); color: #fdba74; }
[data-theme="dark"] .story-notif-amount { color: #6ee7b7; }

/* ── Reduced motion ────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  .story-orb,
  .story-andra-orbit,
  .story-andra-orbit-item,
  .story-andra-avatar,
  .story-andra-thought,
  .story-scroll-arrow,
  .story-eyebrow-dot,
  .story-h1-name,
  .story-notif,
  .story-confetti-piece,
  .story-vibe-emoji,
  .story-chaos-emoji,
  .story-chaos-q,
  .story-firstmorning-emoji,
  .story-day,
  .story-arrow-pulse,
  .story-qa-arrow,
  .story-qa-reset-arrow,
  .story-qa-income-row--new,
  .story-wallet-sparkle span,
  .story-final-spark { animation: none; }

  .story-day { opacity: 1; transform: none; }
  .story-chapter.reveal { opacity: 1; transform: none; transition: none; }
  .story-phone-bar-fill { transition: none; }
  .story-setup-running-fill { transition: none; }
  [data-rollover-line] { stroke-dashoffset: 0 !important; transition: none !important; }
  [data-rollover-dots] circle { opacity: 1 !important; transform: none !important; transition: none !important; }
}

