/*
  styles.css - Finzura marketing site.

  WHY THIS FILE EXISTS
  ────────────────────
  The landing page used to be one 49KB index.html with the Tailwind CDN script
  and a large inline <style> block. That CDN build is a development tool: it
  ships ~300KB of JavaScript, compiles classes in the browser on every load, and
  flashes unstyled content before it finishes. Fine for a prototype, wrong for
  the first thing a prospective user ever sees.

  THE RULE THAT MATTERS MOST
  ──────────────────────────
  Every token in the :root block below is copied verbatim from the light theme
  in web/src/index.css (the `:root:not(.dark)` block). Not "close to". Identical.
  The marketing page and the app render the same colours because they are the
  same numbers.

  If you change a colour in web/src/index.css, change it here too. If the two
  ever drift, the handoff from landing page to app stops feeling continuous and
  that is the entire point of this file.
*/

/* ══════════════════════════════════════════════════════════════════════════
   TOKENS - mirrored from web/src/index.css
   ══════════════════════════════════════════════════════════════════════════ */
:root {
  /* Surfaces. Background is a faint cool-tinted white, never pure #fff, so the
     cards have something to lift against. Cards themselves are pure white. */
  --background:         oklch(0.985 0.008 210);
  --foreground:         oklch(0.24 0.04 220);
  --card:               oklch(1 0 0);
  --card-foreground:    oklch(0.24 0.04 220);
  --muted:              oklch(0.95 0.012 210);
  --muted-foreground:   oklch(0.52 0.035 220);
  --accent:             oklch(0.92 0.035 175);
  --accent-foreground:  oklch(0.28 0.06 200);
  --border:             oklch(0.88 0.02 210);
  --ring:               oklch(0.55 0.1 190);
  --primary:            oklch(0.36 0.08 210);
  --primary-foreground: oklch(0.985 0.008 210);

  /* Brand + money colours. --peso is the green used for positive amounts,
     --danger the red used for negative ones, exactly as in the app. */
  --brand:      #0f4c5c;
  --brand-dark: #0a3540;
  --peso:       #087f5b;
  --danger:     #c2413b;

  /* Chart colours double as the accent palette, same as the app. --chart-1 is
     the teal used for hero figures like the spendable balance. */
  --chart-1: oklch(0.6 0.12 184);
  --chart-2: oklch(0.6 0.14 145);
  --chart-3: oklch(0.62 0.13 85);
  --chart-5: oklch(0.58 0.13 285);

  /* Ambient page-glow colours as RGB triplets, matching the .page-glow-*
     classes in the app. Used for the soft washes behind each section. */
  --glow-teal:    20, 184, 166;
  --glow-amber:   251, 191, 36;
  --glow-violet:  139, 92, 246;
  --glow-emerald: 16, 185, 129;
  --glow-rose:    244, 63, 94;

  --radius: 0.5rem;

  --font-sans: 'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* Display face. Marketing only, never used for UI, labels, or numbers.
     To remove the serif entirely, set this to var(--font-sans) and the whole
     page falls back to Geist with no other edits required. */
  --font-display: 'Instrument Serif', Georgia, serif;

  --maxw: 1120px;
}

/* ══════════════════════════════════════════════════════════════════════════
   BASE
   ══════════════════════════════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;
  /* Offset so anchor targets are not hidden behind the sticky nav. */
  scroll-padding-top: 90px;
}

body {
  background: var(--background);
  color: var(--foreground);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

.container { max-width: var(--maxw); margin: 0 auto; padding: 0 24px; }
.center { text-align: center; }

/* Screen-reader-only text, used for form labels that are visually implied. */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Keyboard users get a visible focus ring everywhere. Mouse users do not. */
:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
  border-radius: calc(var(--radius) * 0.6);
}

/* Skip link: first tab stop on the page, hidden until focused. */
.skip-link {
  position: absolute; top: -100px; left: 16px; z-index: 200;
  background: var(--brand); color: #fff;
  padding: 10px 18px; border-radius: var(--radius);
  font-size: 0.85rem; font-weight: 600; text-decoration: none;
}
.skip-link:focus { top: 16px; }

/* ══════════════════════════════════════════════════════════════════════════
   TYPOGRAPHY
   ══════════════════════════════════════════════════════════════════════════ */
h1, h2, h3 { font-weight: 700; letter-spacing: -0.02em; line-height: 1.1; }
h1 { font-size: clamp(2.5rem, 6vw, 4.2rem); }
h2 { font-size: clamp(1.9rem, 4vw, 2.9rem); }
h3 { font-size: 1.05rem; letter-spacing: -0.01em; }

/* The one serif moment. Applied to an <em> inside a headline. */
h1 em, h2 em, .display-em {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--brand);
}

.lede {
  font-size: 1.1rem;
  color: var(--muted-foreground);
  max-width: 52ch;
}
.lede.center { margin-inline: auto; }

/*
  .eyebrow - lifted straight from the app's section labels, the ones that read
  FINANCIAL PULSE · OCT 1-15, 2026 and WEALTH SNAPSHOT. Uppercase, wide
  tracking, brand teal. This is the strongest single piece of visual continuity
  between the landing page and the product, so it is used on every section.
*/
.eyebrow {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--chart-1);
  margin-bottom: 14px;
}
.eyebrow.center { text-align: center; }

.muted { color: var(--muted-foreground); }
.fine  { font-size: 0.8rem; color: var(--muted-foreground); }

/* Money figures. Tabular numerals keep digits in vertical alignment, which is
   what makes a column of amounts look like a ledger rather than a sentence. */
.num {
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  font-weight: 700;
}
.num-pos { color: var(--peso); }
.num-neg { color: var(--danger); }
.num-hero {
  font-size: clamp(2rem, 4vw, 2.6rem);
  color: var(--chart-1);
}

/* ══════════════════════════════════════════════════════════════════════════
   BUTTONS
   ══════════════════════════════════════════════════════════════════════════ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 11px 20px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-family: inherit;
  font-size: 0.92rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.18s ease, box-shadow 0.18s ease,
              transform 0.18s ease, border-color 0.18s ease;
}

/*
  .btn-glow keeps its original name from the old inline stylesheet so existing
  markup and muscle memory still work. The treatment changed from a gold glow on
  near-black to the app's solid brand teal, which is what the real primary
  button looks like in the product.
*/
.btn-glow {
  background: var(--brand);
  color: #fff;
  box-shadow: 0 1px 2px rgba(10, 53, 64, 0.18);
}
.btn-glow:hover {
  background: var(--brand-dark);
  box-shadow: 0 6px 18px rgba(15, 76, 92, 0.26);
  transform: translateY(-1px);
}
.btn-glow:active { transform: translateY(0); }

.btn-outline {
  background: var(--card);
  color: var(--foreground);
  border-color: var(--border);
}
.btn-outline:hover {
  border-color: var(--chart-1);
  color: var(--brand);
  transform: translateY(-1px);
}

.btn-ghost { background: none; color: var(--muted-foreground); padding: 11px 12px; }
.btn-ghost:hover { color: var(--brand); }

.btn-lg    { padding: 14px 28px; font-size: 1rem; }
.btn-block { display: flex; width: 100%; }

/* ══════════════════════════════════════════════════════════════════════════
   CHIPS, PILLS, CARDS
   ══════════════════════════════════════════════════════════════════════════ */

/* .chip mirrors the app's status pills, the "On pace for Oct 1-15, 2026" and
   "14d left" markers on the dashboard. */
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 13px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card);
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--muted-foreground);
}
.chip-teal {
  border-color: color-mix(in oklch, var(--chart-1) 35%, transparent);
  background: color-mix(in oklch, var(--chart-1) 8%, var(--card));
  color: var(--brand);
}
.chip-dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--chart-1);
  flex-shrink: 0;
}

/*
  .glass also keeps its old name. On the near-black page it was a frosted
  translucent panel. Here it is the app's actual card: white, one hairline
  border, a shadow soft enough to read as lift rather than drop.
*/
.glass {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) * 2);
  box-shadow: 0 1px 2px rgba(15, 35, 45, 0.04),
              0 8px 24px -12px rgba(15, 35, 45, 0.12);
}
.glass-hover { transition: transform 0.22s ease, box-shadow 0.22s ease; }
.glass-hover:hover {
  transform: translateY(-4px);
  box-shadow: 0 2px 4px rgba(15, 35, 45, 0.05),
              0 18px 40px -16px rgba(15, 35, 45, 0.2);
}

/* Tinted feature cards. The soft lavender and mint gradients come from the
   Split Track stat cards in the app. */
.tint-violet  { background: linear-gradient(145deg, rgba(var(--glow-violet), 0.08), var(--card) 65%); }
.tint-teal    { background: linear-gradient(145deg, rgba(var(--glow-teal), 0.08), var(--card) 65%); }
.tint-amber   { background: linear-gradient(145deg, rgba(var(--glow-amber), 0.1), var(--card) 65%); }
.tint-emerald { background: linear-gradient(145deg, rgba(var(--glow-emerald), 0.08), var(--card) 65%); }

/* Square icon tile that sits at the top of each feature card. */
.ic-tile {
  width: 38px; height: 38px;
  display: flex; align-items: center; justify-content: center;
  border-radius: calc(var(--radius) * 1.2);
  flex-shrink: 0;
}
.ic-teal    { background: rgba(var(--glow-teal), 0.12);    color: #0d9488; }
.ic-amber   { background: rgba(var(--glow-amber), 0.16);   color: #b45309; }
.ic-violet  { background: rgba(var(--glow-violet), 0.12);  color: #7c3aed; }
.ic-emerald { background: rgba(var(--glow-emerald), 0.12); color: #047857; }
.ic-rose    { background: rgba(var(--glow-rose), 0.1);     color: #be123c; }

/* ══════════════════════════════════════════════════════════════════════════
   AMBIENT GLOW - mirrors the app's .page-glow-* system
   ══════════════════════════════════════════════════════════════════════════ */
.glow-teal, .glow-gold, .glow-purple {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  z-index: 0;
}
.glow-teal   { background: radial-gradient(ellipse at center, rgba(var(--glow-teal), 0.14) 0%, rgba(var(--glow-teal), 0.05) 45%, transparent 72%); }
.glow-gold   { background: radial-gradient(ellipse at center, rgba(var(--glow-amber), 0.14) 0%, rgba(var(--glow-amber), 0.05) 45%, transparent 72%); }
.glow-purple { background: radial-gradient(ellipse at center, rgba(var(--glow-violet), 0.12) 0%, rgba(var(--glow-violet), 0.04) 45%, transparent 72%); }

.gradient-line {
  height: 1px;
  max-width: var(--maxw);
  margin: 0 auto;
  background: linear-gradient(90deg, transparent, var(--border), transparent);
}

/* ══════════════════════════════════════════════════════════════════════════
   SCROLL REVEAL
   ══════════════════════════════════════════════════════════════════════════ */
.reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
.reveal.visible { opacity: 1; transform: none; }

/* ══════════════════════════════════════════════════════════════════════════
   SCROLL-DRIVEN PRODUCT ANIMATIONS
   Used by the scrollytelling sections. All are inert until script.js adds the
   trigger class when the section scrolls into view, so nothing animates early.
   Count-up figures ([data-countup]) are driven entirely in JS and need no CSS.
   ══════════════════════════════════════════════════════════════════════════ */

/* Pay-period ring: offset animates from empty (276) to its target when filled. */
[data-ring-fill] { transition: stroke-dashoffset 1.1s cubic-bezier(0.22, 1, 0.36, 1); }

/* MP2 curve: the stroke draws itself left to right. dasharray/offset are set in
   JS from the path's own length so the effect scales to any path. */
[data-draw] {
  transition: stroke-dashoffset 1.4s cubic-bezier(0.33, 1, 0.68, 1);
}
[data-area] { transition: opacity 0.8s ease 0.4s; }
[data-area].is-drawn { opacity: 1 !important; }

/* Trackers progress bar: width is set inline to 0 and animated to its target
   via the data-fill percentage (the inline transition handles the easing). */

/* Reduced motion: show every end state immediately, no travel. The JS also
   short-circuits, but this guarantees the visual even if JS is slow or absent. */
@media (prefers-reduced-motion: reduce) {
  [data-ring-fill] { stroke-dashoffset: var(--ring-target, 193) !important; }
  [data-draw] { stroke-dashoffset: 0 !important; }
  [data-area] { opacity: 1 !important; }
}

/* ══════════════════════════════════════════════════════════════════════════
   NAV
   ══════════════════════════════════════════════════════════════════════════ */
.nav {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in oklch, var(--background) 82%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}
.nav-inner {
  display: flex; align-items: center; justify-content: space-between;
  height: 64px; gap: 20px;
}
.logo {
  display: inline-flex; align-items: center; gap: 9px;
  font-size: 1.05rem; font-weight: 700; letter-spacing: -0.02em;
  color: var(--foreground); text-decoration: none;
}
.logo-mark {
  width: 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  /* The real logo SVG carries its own navy rounded-square background, so this
     container stays transparent (no competing gradient box behind it). */
  background: transparent;
}
.logo-mark svg { display: block; }
.nav-links { display: flex; gap: 26px; }
.nav-links a {
  color: var(--muted-foreground); text-decoration: none;
  font-size: 0.9rem; font-weight: 500;
  transition: color 0.15s ease;
}
.nav-links a:hover { color: var(--brand); }
.nav-actions { display: flex; align-items: center; gap: 8px; }

/* Announcement strip above the nav. */
.announce {
  background: color-mix(in oklch, var(--accent) 70%, var(--background));
  color: var(--accent-foreground);
  font-size: 0.82rem;
  text-align: center;
  padding: 9px 16px;
  border-bottom: 1px solid var(--border);
}

/* ══════════════════════════════════════════════════════════════════════════
   SECTIONS
   ══════════════════════════════════════════════════════════════════════════ */
.section { position: relative; padding: 92px 0; overflow: hidden; }
.section-head { max-width: 640px; margin: 0 auto 52px; text-align: center; }
.section > .container { position: relative; z-index: 1; }

/* ══════════════════════════════════════════════════════════════════════════
   HERO
   ══════════════════════════════════════════════════════════════════════════ */
.hero { position: relative; padding: 76px 0 92px; overflow: hidden; }
.hero-copy { max-width: 720px; margin: 0 auto; text-align: center; }
.hero-ctas {
  display: flex; gap: 12px; flex-wrap: wrap;
  justify-content: center; margin-top: 28px;
}

/* Tilt scene holds the dashboard mockup plus the floating peso pills. */
.hero-visual {
  position: relative;
  max-width: 880px;
  margin: 72px auto 0;
  perspective: 1400px;
}
.tilt-scene { position: relative; transform-style: preserve-3d; }

/*
  .pill - the floating category markers borrowed from the Kimi sample and the
  Copilot Money reference, re-denominated in pesos and real Philippine
  merchants. They sit outside the card on desktop and are hidden on mobile,
  where there is no room for them to float without colliding.
*/
.pill {
  position: absolute; z-index: 3;
  display: flex; align-items: center; gap: 8px;
  padding: 9px 15px;
  border-radius: 999px;
  background: var(--card);
  border: 1px solid var(--border);
  box-shadow: 0 10px 28px -10px rgba(15, 35, 45, 0.28);
  font-size: 0.8rem; font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  transform: rotate(var(--rot, 0deg));
  animation: bob 6s ease-in-out infinite;
}
.pill .pill-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.pill-in  { color: var(--peso); }
.pill-out { color: var(--danger); }
.pill-mp2 { color: #b45309; }

.float-a { top: -26px; left: -18px; --rot: -5deg; }
.float-b { top: 16%; right: -30px; --rot: 6deg; animation-delay: 1.2s; }
.float-c { bottom: 10%; left: -34px; --rot: 4deg; animation-delay: 2.1s; }
.float-d { bottom: -22px; right: 8%; --rot: -6deg; animation-delay: 0.7s; }

@keyframes bob {
  0%, 100% { transform: rotate(var(--rot)) translateY(0); }
  50%      { transform: rotate(var(--rot)) translateY(-9px); }
}

/*
  .device-frame keeps its name from the old stylesheet. It wraps the product
  mockup, and later the real screen recording once that exists.
*/
.device-frame {
  position: relative;
  border-radius: calc(var(--radius) * 2.4);
  border: 1px solid var(--border);
  background: var(--card);
  box-shadow: 0 2px 6px rgba(15, 35, 45, 0.05),
              0 40px 80px -32px rgba(15, 35, 45, 0.3);
  overflow: hidden;
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform 0.3s ease-out;
  will-change: transform;
}

/* ── Dashboard mockup, drawn in markup so it needs no image asset ─────────── */
.dash { padding: 22px; }
.dash-bar {
  display: flex; align-items: center; gap: 7px;
  padding-bottom: 14px; margin-bottom: 18px;
  border-bottom: 1px solid var(--border);
}
.dash-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--border); }
.dash-crumb {
  margin-left: auto; font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--muted-foreground);
}
.dash-label {
  font-size: 0.68rem; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--muted-foreground);
}
.dash-hero { display: flex; align-items: center; gap: 26px; flex-wrap: wrap; }
.dash-ring { flex-shrink: 0; }
.dash-chips { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }

.dash-stats {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 10px; margin-top: 22px;
}
.dash-stat {
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) * 1.4);
  padding: 12px 14px;
  background: var(--background);
}
.dash-stat .num { font-size: 0.98rem; margin-top: 4px; display: block; }

/* ══════════════════════════════════════════════════════════════════════════
   SCOPE STRIP - honest capability facts, not invented social proof
   ══════════════════════════════════════════════════════════════════════════ */
.scope {
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  background: var(--muted);
  padding: 30px 0;
}
.scope-row {
  display: flex; justify-content: center; align-items: center;
  gap: 14px 40px; flex-wrap: wrap;
}
.scope-item {
  display: inline-flex; align-items: center; gap: 9px;
  font-size: 0.88rem; font-weight: 500; color: var(--foreground);
}
.scope-item svg { color: var(--chart-1); flex-shrink: 0; }

/* ══════════════════════════════════════════════════════════════════════════
   PAIN CARDS
   ══════════════════════════════════════════════════════════════════════════ */
.pain-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.pain-card { padding: 26px 24px; }
.pain-card p { color: var(--foreground); font-size: 0.95rem; }
.pain-card .pain-when {
  display: block; margin-bottom: 10px;
  font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--muted-foreground);
}

/* ══════════════════════════════════════════════════════════════════════════
   BENTO GRID
   ══════════════════════════════════════════════════════════════════════════ */
.bento-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.bento-wide { grid-column: span 2; }
.bento-card { padding: 24px; display: flex; flex-direction: column; gap: 12px; }
.bento-card h3 { margin-top: 2px; }
.bento-card p { font-size: 0.89rem; color: var(--muted-foreground); }

/*
  .screenshot-placeholder keeps its name. Every one of these is a TODO: capture
  the real screen in light mode so it reads as a bright artifact on the page.
  See FUTURE_UPGRADES.md item M5.
*/
.screenshot-placeholder {
  display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 8px;
  padding: 20px;
  border: 1.5px dashed color-mix(in oklch, var(--chart-1) 32%, transparent);
  border-radius: calc(var(--radius) * 1.6);
  background: color-mix(in oklch, var(--chart-1) 4%, var(--background));
  color: var(--muted-foreground);
  font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.04em; text-align: center;
  margin-top: auto;
}

/* ══════════════════════════════════════════════════════════════════════════
   SPLIT SHOWCASE
   ══════════════════════════════════════════════════════════════════════════ */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 56px; align-items: center; }
.split.reverse .split-copy   { order: 2; }
.split.reverse .split-visual { order: 1; }
.split-copy p:not(.eyebrow) { color: var(--muted-foreground); margin: 16px 0 20px; max-width: 46ch; }

.tick-list { list-style: none; }
.tick-list li {
  position: relative;
  padding: 7px 0 7px 30px;
  font-size: 0.94rem;
}
.tick-list li::before {
  content: '';
  position: absolute; left: 2px; top: 14px;
  width: 14px; height: 8px;
  border-left: 2px solid var(--chart-1);
  border-bottom: 2px solid var(--chart-1);
  transform: rotate(-45deg);
}

/* ══════════════════════════════════════════════════════════════════════════
   ZURA CHAT
   ══════════════════════════════════════════════════════════════════════════ */
.chat-card { padding: 18px; max-width: 400px; }
.chat-head {
  display: flex; align-items: center; gap: 11px;
  padding-bottom: 14px; margin-bottom: 16px;
  border-bottom: 1px solid var(--border);
}
.chat-avatar {
  width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  border-radius: calc(var(--radius) * 1.4);
  background: linear-gradient(135deg, rgba(var(--glow-violet), 0.9), var(--chart-1));
  color: #fff; font-weight: 700; font-size: 0.8rem;
}
.chat-log { display: flex; flex-direction: column; gap: 10px; min-height: 270px; }

.chat-bubble { display: none; max-width: 82%; }
.chat-bubble.show { display: block; animation: chat-in 0.38s ease forwards; }
.chat-bubble.from-user { align-self: flex-end; }
.chat-bubble.from-zura { align-self: flex-start; }

.bubble {
  padding: 10px 14px;
  border-radius: calc(var(--radius) * 2.2);
  font-size: 0.85rem;
  line-height: 1.5;
}
.from-user .bubble {
  background: var(--brand);
  color: #fff;
  border-bottom-right-radius: var(--radius);
}
.from-zura .bubble {
  background: var(--muted);
  border: 1px solid var(--border);
  color: var(--foreground);
  border-bottom-left-radius: var(--radius);
}
.bubble .hl { color: var(--brand); font-weight: 600; }
.bubble .sub { color: var(--muted-foreground); }

@keyframes chat-in {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

.chat-input {
  display: flex; align-items: center; gap: 10px;
  margin-top: 14px; padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) * 1.4);
  background: var(--background);
  font-size: 0.82rem;
  color: var(--muted-foreground);
}
.caret {
  width: 2px; height: 14px; margin-left: auto;
  background: var(--chart-1);
  animation: blink 1.1s step-end infinite;
}
@keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }

/* Zura suggestion chips, matching the real ones on the app's Zura screen. */
.sugg-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; }
.sugg {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 13px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card);
  font-size: 0.78rem;
  color: var(--foreground);
}
.sugg .sugg-kind { color: var(--muted-foreground); font-size: 0.72rem; }

/* ══════════════════════════════════════════════════════════════════════════
   ROADMAP + QUOTES
   ══════════════════════════════════════════════════════════════════════════ */
.soon-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
.soon-card {
  padding: 18px 14px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 9px;
}
.soon-card p { font-size: 0.8rem; font-weight: 500; color: var(--muted-foreground); }

.quote-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }

/* ══════════════════════════════════════════════════════════════════════════
   FINAL CTA
   ══════════════════════════════════════════════════════════════════════════ */
.cta-box {
  position: relative; z-index: 1;
  max-width: 680px; margin: 0 auto;
  padding: 56px 40px;
  text-align: center;
  border-radius: calc(var(--radius) * 3);
  border: 1px solid var(--border);
  background: linear-gradient(160deg,
              color-mix(in oklch, var(--accent) 55%, var(--card)),
              var(--card) 70%);
  box-shadow: 0 30px 70px -40px rgba(15, 35, 45, 0.4);
}

/* ══════════════════════════════════════════════════════════════════════════
   FOOTER
   ══════════════════════════════════════════════════════════════════════════ */
.footer { border-top: 1px solid var(--border); padding: 40px 0 32px; background: var(--muted); }
.footer-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 18px; flex-wrap: wrap;
}
.footer-links { display: flex; gap: 20px; }
.footer-links a {
  font-size: 0.82rem; color: var(--muted-foreground); text-decoration: none;
}
.footer-links a:hover { color: var(--brand); }
.footer-fine {
  max-width: 620px; margin: 26px auto 0;
  text-align: center; font-size: 0.72rem;
  color: var(--muted-foreground); line-height: 1.6;
}

/* ══════════════════════════════════════════════════════════════════════════
   REQUEST ACCESS OVERLAY
   ══════════════════════════════════════════════════════════════════════════ */
#access-overlay {
  display: none;
  position: fixed; inset: 0; z-index: 100;
  align-items: center; justify-content: center;
  padding: 20px;
  background: rgba(15, 35, 45, 0.45);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
#access-overlay.open { display: flex; }

.modal { width: 100%; max-width: 400px; padding: 28px; }
.modal-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 12px; margin-bottom: 22px;
}
.modal-close {
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  border: none; border-radius: var(--radius);
  background: none; color: var(--muted-foreground); cursor: pointer;
}
.modal-close:hover { background: var(--muted); color: var(--foreground); }

.field { display: block; margin-bottom: 16px; }
.field-label {
  display: block; margin-bottom: 7px;
  font-size: 0.8rem; font-weight: 500; color: var(--foreground);
}
.field input {
  width: 100%;
  padding: 11px 13px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
  font-family: inherit; font-size: 0.92rem;
  color: var(--foreground);
}
.field input::placeholder { color: var(--muted-foreground); opacity: 0.7; }
.field input:focus { outline: 2px solid var(--ring); outline-offset: 0; border-color: transparent; }

.form-error {
  margin-top: 10px;
  font-size: 0.8rem;
  color: var(--danger);
}
.is-hidden { display: none; }

.modal-success { text-align: center; padding: 10px 0; }
.success-mark {
  width: 46px; height: 46px; margin: 0 auto 14px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: color-mix(in oklch, var(--chart-1) 14%, var(--card));
  color: var(--peso);
}

/* ══════════════════════════════════════════════════════════════════════════
   HERO ANIMATION
   A nine second loop that compresses one full pay period into a single view:
   an expense is logged through Zura, the balance reacts to it, then the period
   closes and carries the remainder forward.

   That last beat is the whole reason this is animated rather than recorded.
   A screen recording cannot show a period roll-over, because in real life the
   transition takes two weeks.
   ══════════════════════════════════════════════════════════════════════════ */
.dash { position: relative; overflow: hidden; }

/* The figure shifts to brand teal while it counts, so the change reads as
   caused by the expense rather than as a number randomly rearranging. */
[data-balance] { transition: color 0.3s ease; }
.dash.is-ticking [data-balance] { color: var(--brand); }

[data-ring] { transition: stroke-dashoffset 0.9s cubic-bezier(0.22, 1, 0.36, 1); }

.dash-feed { list-style: none; margin-top: 18px; border-top: 1px solid var(--border); }
.feed-row {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 0;
  font-size: 0.86rem;
  border-bottom: 1px solid var(--border);
}
.feed-ic { width: 26px; height: 26px; border-radius: calc(var(--radius) * 0.9); }
.feed-name { flex: 1; }
.feed-row.is-new { animation: feed-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) both; }

@keyframes feed-in {
  from { opacity: 0; transform: translateY(-10px); }
  to   { opacity: 1; transform: none; }
}

.zura-toast {
  position: absolute; left: 22px; right: 22px; bottom: 18px;
  display: flex; align-items: center; gap: 10px;
  padding: 11px 14px;
  border-radius: calc(var(--radius) * 1.6);
  background: var(--brand);
  color: #fff;
  font-size: 0.84rem; font-weight: 500;
  box-shadow: 0 12px 30px -10px rgba(10, 53, 64, 0.5);
  opacity: 0; transform: translateY(14px);
  transition: opacity 0.35s ease, transform 0.35s ease;
  pointer-events: none;
}
.zura-toast.is-on { opacity: 1; transform: none; }
.zura-badge {
  width: 22px; height: 22px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.22);
  font-size: 0.7rem; font-weight: 700;
}

.dash-rollover {
  position: absolute; inset: auto 0 0 0;
  display: flex; align-items: center; justify-content: center; gap: 9px;
  padding: 14px;
  background: color-mix(in oklch, var(--chart-2) 16%, var(--card));
  border-top: 1px solid color-mix(in oklch, var(--chart-2) 35%, transparent);
  font-size: 0.85rem;
  transform: translateY(100%);
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
.dash-rollover.is-on { transform: none; }
.rollover-mark { display: flex; color: var(--peso); }

/* ══════════════════════════════════════════════════════════════════════════
   RESPONSIVE
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 900px) {
  .bento-grid, .pain-grid { grid-template-columns: repeat(2, 1fr); }
  .bento-wide { grid-column: span 2; }
  .split { grid-template-columns: 1fr; gap: 36px; }
  .split.reverse .split-copy,
  .split.reverse .split-visual { order: 0; }
  .soon-grid { grid-template-columns: repeat(2, 1fr); }
  .nav-links { display: none; }
}

@media (max-width: 640px) {
  .section { padding: 64px 0; }
  .hero { padding: 48px 0 64px; }
  .hero-visual { margin-top: 48px; }
  .bento-grid, .pain-grid, .quote-grid { grid-template-columns: 1fr; }
  .bento-wide { grid-column: span 1; }
  .dash-stats { grid-template-columns: 1fr; }
  .footer-inner { flex-direction: column; text-align: center; }
  .cta-box { padding: 40px 24px; }

  /* The nav has to stay on one line, so the lowest-value item gives way first.
     Sign in is still reachable from the footer on every page. */
  .container { padding: 0 18px; }
  .announce { font-size: 0.76rem; padding: 8px 14px; }
  .nav-actions .btn-ghost { display: none; }
  .nav-inner { height: 58px; }
  .btn { padding: 10px 15px; font-size: 0.85rem; }
  .btn-lg { padding: 13px 22px; font-size: 0.94rem; }
  .hero-ctas .btn { width: 100%; }

  /* The floating pills need room to float. On a phone there is none, so they
     are removed rather than overlapped on top of the mockup. */
  .pill { display: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   REDUCED MOTION
   Respects the OS-level "reduce motion" setting. Everything still renders,
   it simply arrives without travelling. The reveal elements are forced
   visible so nothing is stuck at opacity 0.
   ══════════════════════════════════════════════════════════════════════════ */
@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;
  }
  .reveal { opacity: 1; transform: none; }
  .device-frame { transform: none !important; }

  /* The hero loop does not run at all, so its two transient elements would
     otherwise sit frozen on screen. The dashboard still shows the finished
     state, which carries the same information without moving. */
  .zura-toast, .dash-rollover { display: none; }
}
