/* =========================================================
   Kasdor – Warp-inspired: editorial, tactile, confident.
   Warm ivory + near-black ink + grainy noise + italic serif accents.
   Light mode (per user constraint), but Warp's soul.
   ========================================================= */

:root {
  --paper:     #F7F6F3;   /* warm off-white base */
  --paper-2:   #F6F4EE;
  --paper-3:   #EEEAE0;
  --ink:       #0F0F0C;   /* near-black */
  --ink-2:     #2C2B26;
  --ink-3:     #66635B;
  --ink-4:     #9A968B;
  --line:      #E6E2D6;
  --line-2:    #CFC9B8;

  --accent:      #FF3D00;   /* brand orange */
  --accent-2:    #FF3D00;   /* same brand orange (unified, no lighter complement) */
  --accent-ink:  #FFFFFF;
  --accent-wash: #FFD4BE;

  --f-display: "Inter Tight", "Inter", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
  --f-sans:    "Inter", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
  --f-serif:   "Fraunces", "Instrument Serif", Georgia, serif;
  --f-mono:    "JetBrains Mono", ui-monospace, Menlo, monospace;

  --radius:     8px;
  --radius-lg:  14px;
  --radius-xl:  20px;

  --shadow:     0 1px 2px rgba(20,20,15,0.05), 0 12px 32px -18px rgba(20,20,15,0.22);
}

/* ---------- palette overrides ---------- */
/* A · White + crimson */
html[data-palette="A"] {
  --paper:   #FFFFFF;
  --paper-2: #F7F4EE;
  --paper-3: #EFEBE0;
  --ink:     #0F0F0C;
  --ink-2:   #2C2B26;
  --ink-3:   #66635B;
  --ink-4:   #9A968B;
  --line:    #E6E2D6;
  --line-2:  #CFC9B8;
  --accent:      #E11D1D;
  --accent-2:    #F04A3A;
  --accent-ink:  #FFFFFF;
  --accent-wash: #FACCC4;
}

/* B · Midnight + hot orange (dark) */
html[data-palette="B"] {
  --paper:   #0C0C0C;
  --paper-2: #161614;
  --paper-3: #1F1E1B;
  --ink:     #F5F1E6;
  --ink-2:   #D4CFBF;
  --ink-3:   #9B967F;
  --ink-4:   #6A6551;
  --line:    #262521;
  --line-2:  #333128;
  --accent:      #FF3D00;
  --accent-2:    #FF8147;
  --accent-ink:  #0C0C0C;
  --accent-wash: #3A1D0C;
}

/* C · White + electric blue */
html[data-palette="C"] {
  --paper:   #FFFFFF;
  --paper-2: #F4F5F8;
  --paper-3: #E9EBF0;
  --ink:     #0E1115;
  --ink-2:   #2A2E36;
  --ink-3:   #5F636D;
  --ink-4:   #93969E;
  --line:    #E3E5EA;
  --line-2:  #C9CCD3;
  --accent:      #2D5BFF;
  --accent-2:    #5A83FF;
  --accent-ink:  #FFFFFF;
  --accent-wash: #D3DDFF;
}

/* D · White + hot pink */
html[data-palette="D"] {
  --paper:   #FFFFFF;
  --paper-2: #F7F3F4;
  --paper-3: #EEE8EB;
  --ink:     #121010;
  --ink-2:   #2E2A2B;
  --ink-3:   #625C5E;
  --ink-4:   #9B9497;
  --line:    #E7E1E4;
  --line-2:  #CFC5CA;
  --accent:      #FF1F7A;
  --accent-2:    #FF5CA0;
  --accent-ink:  #FFFFFF;
  --accent-wash: #FFCEE0;
}

/* E · White + neon lime */
html[data-palette="E"] {
  --paper:   #FFFFFF;
  --paper-2: #F4F6EE;
  --paper-3: #E9ECDC;
  --ink:     #0E110B;
  --ink-2:   #2A2D24;
  --ink-3:   #5F6356;
  --ink-4:   #949789;
  --line:    #E4E6DA;
  --line-2:  #CBCEB9;
  --accent:      #A8E61B;
  --accent-2:    #C8F65C;
  --accent-ink:  #0E110B;
  --accent-wash: #E7F6C2;
}

/* F · White + deep violet */
html[data-palette="F"] {
  --paper:   #FFFFFF;
  --paper-2: #F5F3F9;
  --paper-3: #ECE6F2;
  --ink:     #100E14;
  --ink-2:   #2C2833;
  --ink-3:   #615C6C;
  --ink-4:   #9792A2;
  --line:    #E5E1EC;
  --line-2:  #CCC4D7;
  --accent:      #6B1FE0;
  --accent-2:    #9256F0;
  --accent-ink:  #FFFFFF;
  --accent-wash: #D9C8F8;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--f-sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-feature-settings: "ss01", "cv11";
  /* hard stop the VERTICAL scroll at the top and bottom edges – no
     rubber-band / bounce / pull-to-refresh exposing the body bg beyond
     the page. Y-axis only so the macOS trackpad swipe-left / swipe-
     right gesture still triggers browser back / forward navigation. */
  overscroll-behavior-y: none;
  overscroll-behavior-x: auto;
}

/* grainy noise overlay – tactile Warp-style paper feel */
body::before {
  content: "";
  position: fixed; inset: 0;
  z-index: 1000;
  pointer-events: none;
  opacity: 0.06;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0.7 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; border: none; background: none; color: inherit; }

/* ---------- layout ---------- */
.container {
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
  padding: 0 32px;
}
@media (max-width: 720px) { .container { padding: 0 20px; } }

/* Tighter horizontal padding for nav + footer on mobile so the logos
   sit closer to the screen edge, matching the edge-to-edge feel of
   the hero/CTA dark sections. Body content keeps the wider 20px
   padding for comfortable reading. */
@media (max-width: 720px) {
  .nav-wrap .container,
  .foot .container { padding: 0 6px; }
}

/* ---------- type ---------- */
h1, h2, h3, h4 { margin: 0; font-weight: 500; letter-spacing: -0.025em; color: var(--ink); }
p { margin: 0; }

.display {
  font-family: var(--f-display);
  font-weight: 500;
  letter-spacing: -0.04em;
  line-height: 0.96;
}

/* Responsive line-break helpers used by renderAccent's {brm}/{brd} tokens.
   {brm} (.br-m) breaks ONLY on phones; {brd} (.br-d) breaks ONLY on desktop.
   The German hero + CTA headlines want different wrap points on a phone than
   on desktop; toggling a <br> between display:none and inline suppresses or
   restores its line break. */
.br-m { display: none; }
@media (max-width: 560px) {
  .br-m { display: inline; }
  .br-d { display: none; }
}

.serif-italic {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.015em;
}

.lead {
  font-size: 18px;
  line-height: 1.5;
  color: var(--ink-2);
  max-width: 52ch;
}

.eyebrow {
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--ink-3);
  text-transform: uppercase;
  display: inline-flex; align-items: center; gap: 10px;
}

/* section number labels like Warp's "01 / Product" */
.sec-num {
  font-family: var(--f-mono);
  font-size: 16px;
  color: var(--ink-3);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  display: inline-flex; align-items: center; gap: 14px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 40px;
  width: 100%;
}
.sec-num b { color: var(--ink); font-weight: 500; }
.sec-num .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); }
.sec-num.stage-num { margin-top: 96px; margin-bottom: 8px; padding-bottom: 18px; }

/* ---------- nav ---------- */
.nav-wrap {
  /* fixed so the hero heat-flow can extend to the very top edge,
     letting the nav sit transparently over the animation */
  position: fixed; top: 0; left: 0; right: 0; z-index: 60;
}
.announce {
  background: var(--ink);
  color: var(--paper);
}
.announce-inner {
  display: flex; align-items: center; justify-content: center;
  position: relative;
  min-height: 36px;
  padding: 8px 44px;
  font-size: 13px;
}
.announce-body {
  display: inline-flex; align-items: center; gap: 10px;
  color: rgba(243,238,225,0.92);
  letter-spacing: -0.005em;
  flex-wrap: wrap;
  justify-content: center;
}
.announce-tag {
  color: var(--accent-2);
  font-weight: 500;
}
.announce-sep {
  color: rgba(243,238,225,0.28);
}
.announce-cta {
  color: var(--paper);
  text-decoration: underline;
  text-decoration-color: rgba(243,238,225,0.35);
  text-underline-offset: 3px;
  transition: text-decoration-color .15s ease;
}
.announce-cta:hover { text-decoration-color: var(--accent-2); }
.announce-close {
  position: absolute; right: 16px; top: 50%; transform: translateY(-50%);
  font-size: 18px;
  line-height: 1;
  color: rgba(243,238,225,0.5);
  padding: 4px 8px;
  border-radius: 4px;
  transition: color .15s ease, background .15s ease;
}
.announce-close:hover { color: var(--paper); background: rgba(243,238,225,0.08); }

.nav {
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-bottom: 1px solid transparent;
  transition: background .3s ease, backdrop-filter .3s ease, border-color .3s ease;
}
.nav.scrolled {
  background: color-mix(in oklab, var(--paper) 78%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom-color: var(--line);
}

/* Transparent (top-of-page) state: light text, white-ish controls over the heat-flow */
.nav:not(.scrolled) .nav-logo { color: #ffffff; }
.nav:not(.scrolled) .nav-signin { color: rgba(255, 255, 255, 0.88); }
.nav:not(.scrolled) .nav-signin:hover { color: #ffffff; }
.nav:not(.scrolled) .lang {
  border-color: rgba(255, 255, 255, 0.32);
}
/* Scrolled (white) nav: drop the visible frame around EN/DE – just
   the two buttons + the sliding thumb behind them. */
.nav.scrolled .lang {
  border-color: transparent;
}
.nav:not(.scrolled) .lang button {
  color: rgba(255, 255, 255, 0.72);
}
.nav:not(.scrolled) .lang button:hover { color: #ffffff; }
.nav:not(.scrolled) .lang button.active { color: var(--ink); }
.nav:not(.scrolled) .lang::before { background: #ffffff; }

/* Book a call: white on the transparent nav, orange when scrolled.
   These two rules are specificity (0,2,0), which beats both the
   bare .nav-cta and .btn-primary rules – so they're authoritative
   for the nav CTA in either state. */
.nav:not(.scrolled) .nav-cta {
  background: #ffffff;
  color: var(--ink);
}
.nav:not(.scrolled) .nav-cta:hover {
  background: var(--accent);
  color: var(--accent-ink);
}
.nav.scrolled .nav-cta {
  background: var(--accent);
  color: var(--accent-ink);
}
.nav.scrolled .nav-cta:hover {
  background: color-mix(in oklab, var(--accent) 85%, var(--ink));
}
.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 62px;
  gap: 24px;
}
.nav-logo { display: inline-flex; align-items: center; }
.nav-logo > span { gap: 4px !important; }
.nav-center {
  display: flex; align-items: center; justify-content: center;
  gap: 28px;
}
.nav-link {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  letter-spacing: -0.005em;
  transition: color .15s ease;
}
.nav-link:hover { color: var(--accent); }
.nav-caret { opacity: 0.55; transition: transform .15s ease; }
.nav-link:hover .nav-caret { transform: translateY(1px); opacity: 1; }

.nav-right { display: flex; align-items: center; gap: 16px; justify-self: end; }
.nav-signin {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink-3); /* greyish so it sits softer alongside the orange CTA */
  letter-spacing: -0.005em;
  transition: color .15s ease;
}
.nav-signin:hover { color: var(--ink); }

.nav-cta {
  background: var(--accent);
  color: var(--accent-ink);
  border-radius: 999px;
  padding: 0 18px;
  height: 36px;
  display: inline-flex; align-items: center; gap: 6px;
  font-weight: 500;
  font-size: 13.5px;
  letter-spacing: -0.005em;
  transition: background .25s ease, color .25s ease, transform .15s ease;
}
.nav-cta:hover { background: color-mix(in oklab, var(--accent) 85%, var(--ink)); }

@media (max-width: 1024px) {
  .nav-center { gap: 18px; }
  .nav-right { gap: 10px; }
  .nav-signin { display: none; }
}
@media (max-width: 820px) {
  .nav-center { display: none; }
  .nav-inner { grid-template-columns: auto auto; }
  .announce-inner { font-size: 12px; padding: 8px 36px; }
}
/* Phones (2026-05-29): drop the EN/DE language toggle and surface the
   Log in / Anmelden link in its place — language auto-detects from the
   browser, so a login entry point matters more than manual switching on a
   phone. Also tighten the nav so the (wider, in German) "Gespräch buchen"
   CTA stays fully on-screen. Declared after the 1024px rule above so it wins
   the .nav-signin display battle at phone widths. */
@media (max-width: 560px) {
  /* .nav-right .lang (0,2,0) so it beats the base .lang rule declared later in
     the file regardless of source order. */
  .nav-right .lang { display: none; }
  .nav-signin { display: inline-flex; }
  .nav-inner { gap: 10px; }
  .nav-right { gap: 10px; }
  .nav-cta { padding: 0 12px; }
}
/* Smallest phones (≤375px, e.g. iPhone SE / older Android): the German
   "Gespräch buchen" is long enough to still clip, so tighten a touch more. */
@media (max-width: 375px) {
  .nav-signin { font-size: 13px; }
  .nav-cta { padding: 0 11px; font-size: 13px; }
  .nav-inner { gap: 8px; }
  .nav-right { gap: 8px; }
}

.lang {
  display: inline-flex; align-items: center;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 3px;
  background: transparent;
  height: 36px;
  position: relative;
  isolation: isolate;
}
.lang button {
  font-family: var(--f-mono);
  font-size: 12px;
  font-weight: 500;
  padding: 0 14px;
  height: 28px;
  /* Equal width so EN and DE are visually balanced regardless of the
     font's per-glyph side bearings (mono fonts still differ on width
     bearings — was making the label look shifted inside the thumb). */
  min-width: 40px;
  border-radius: 999px;
  color: var(--ink-3);
  letter-spacing: 0.04em;
  /* justify-content: center explicitly centers the label horizontally;
     without it the default flex-start nudged labels off-center when
     the side bearings around "EN" and "DE" weren't symmetric. */
  display: inline-flex; align-items: center; justify-content: center;
  position: relative;
  z-index: 1;
  transition: color .35s cubic-bezier(.2,.8,.2,1);
}
.lang.lang-pal button { padding: 0 10px; font-size: 10.5px; }
.lang button:hover { color: var(--ink); }
.lang button.active {
  color: var(--paper);
}
/* animated thumb that slides behind active button */
.lang::before {
  content: "";
  position: absolute;
  top: 3px;
  left: var(--thumb-x, 3px);
  width: var(--thumb-w, 0px);
  height: 28px;
  background: var(--ink);
  border-radius: 999px;
  z-index: 0;
  transition: left .35s cubic-bezier(.2,.8,.2,1), width .35s cubic-bezier(.2,.8,.2,1);
  opacity: var(--thumb-opacity, 0);
}


.btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 18px;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
  letter-spacing: -0.005em;
  transition: background .15s ease, color .15s ease, transform .15s ease;
}
.btn-primary {
  background: var(--ink);
  color: var(--paper);
}
.btn-primary:hover { background: var(--accent); }
.btn-primary .arrow { transition: transform .18s ease; }
.btn-primary:hover .arrow { transform: translateX(2px); }
.btn-lg { padding: 14px 22px; font-size: 15px; border-radius: 8px; }

/* Hero CTA: always orange (more specific than .btn-primary, so wins) */
.hero .btn-primary {
  background: var(--accent);
  color: var(--accent-ink);
}
.hero .btn-primary:hover { background: color-mix(in oklab, var(--accent) 85%, var(--ink)); }

/* ---------- hero ---------- */
.hero {
  padding: 0;
  position: relative;
  overflow: hidden;
  background-color: oklch(0.13 0.012 60); /* deep heat-flow base */
  color: var(--paper);
  /* isolate paint so the blurred bg animation doesn't trigger
     repaints in ancestors / siblings (kills the cursor-hover flicker) */
  contain: paint;
  isolation: isolate;
}

/* ============================================================================
   Hero heat-flow = looping VIDEO (2026-05-29).
   The animated CSS heat-flow (.hero::before, blurred gradient with animated
   transform + background-position) was the dominant idle GPU cost — a
   DevTools trace showed ~27-51 RasterTasks PER FRAME at 75fps because the
   blurred surface re-rasterized every frame. Replaced with a hardware-decoded
   28s seamless loop (a literal recording of that exact animation), which runs
   on the GPU's dedicated video-decode block instead of the raster path.
   Pixel-identical motion + orange; near-zero GPU.
   The video covers .hero::before; the ::before is reduced to a STATIC poster
   image as the reduced-motion / load-failure fallback (see override below). */
.hero-heat-video,
.cta-heat-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
  pointer-events: none;
  /* Start hidden and crossfade in once the video is actually playing
     (JS adds .is-playing on the `playing` event). Until then the hero's
     static poster (.hero::before / .cta-wrap::before) shows through, so
     the poster→video hand-off is a soft fade, not a pop. */
  opacity: 0;
  transition: opacity .6s ease;
}
.hero-heat-video.is-playing,
.cta-heat-video.is-playing { opacity: 1; }
/* reduced-motion: hide the video, fall back to the static poster ::before. */
@media (prefers-reduced-motion: reduce) {
  .hero-heat-video, .cta-heat-video { display: none; }
}
/* Hero + CTA heat-flow is a hardware-decoded looping <video>
   (.hero-heat-video / .cta-heat-video, defined above). The ::before is the
   STATIC poster fallback that shows under reduced-motion, if the video fails
   to load, and underneath the video until it crossfades in. There is no
   animated CSS heat-flow anymore — it was the dominant idle GPU cost, so it
   was replaced wholesale by the video (see the note above .hero-heat-video).
   No ::after layer, no blur, no animation: zero per-frame cost. */
.hero::before,
.cta-wrap::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background: url("assets/hero-heatflow-poster.jpg") center / cover no-repeat;
}
.hero-overlay,
.cta-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  /* darken the animated bg by ~32% so white text stays readable
     over the brightest heat-flow highlights. tune this rgba alpha
     if it needs to be more or less heavy. */
  background: rgba(0, 0, 0, 0.32);
}
.hero > .container {
  /* full viewport – nav is now fixed and overlays the top, so we want
     the heat-flow + content to extend edge-to-edge top to bottom */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-top: 94px;  /* 62px nav + 32px breathing room so content clears the nav */
  padding-bottom: 32px;
  position: relative;
  z-index: 2; /* above both the animated bg layers and the overlay */
}

/* Keyframes ported VERBATIM from endor-whisper-smooth – both transform
   AND background-position animate. The bg-position drift across a
   200%/240% sized gradient is half the visual effect; without it the
   animation looks frozen even though the layer is transforming. */
@keyframes heat-flow-a {
  0%   { transform: translate3d(-10%, -8%, 0) rotate(-4deg) scale(1.2); background-position: 0% 30%; }
  25%  { transform: translate3d(-2%, 2%, 0) rotate(2deg) scale(1.35); background-position: 40% 50%; }
  50%  { transform: translate3d(6%, 6%, 0) rotate(8deg) scale(1.25); background-position: 80% 60%; }
  75%  { transform: translate3d(0%, -4%, 0) rotate(4deg) scale(1.4); background-position: 140% 40%; }
  100% { transform: translate3d(-10%, -8%, 0) rotate(-4deg) scale(1.2); background-position: 200% 30%; }
}
@keyframes heat-flow-b {
  0%   { transform: translate3d(8%, 10%, 0) rotate(0deg) scale(1.3); background-position: 100% 0%; }
  33%  { transform: translate3d(-2%, 2%, 0) rotate(-6deg) scale(1.5); background-position: 60% 40%; }
  66%  { transform: translate3d(4%, -6%, 0) rotate(-2deg) scale(1.35); background-position: 30% 80%; }
  100% { transform: translate3d(8%, 10%, 0) rotate(0deg) scale(1.3); background-position: 0% 100%; }
}
.hero-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 56px;
}
.hero-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 56px;
}

.hero .tag {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 7px 14px 7px 10px;
  border: 1px solid rgba(255,255,255,0.14);
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  font-family: var(--f-mono);
  font-size: 12.5px;
  letter-spacing: 0.04em;
  color: rgba(255,255,255,0.88);
  text-transform: uppercase;
  margin-bottom: 32px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.hero .tag .dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 28%, transparent);
}

.hero h1 {
  font-family: var(--f-display);
  font-size: clamp(56px, 8vw, 128px);
  line-height: 0.92;
  letter-spacing: -0.045em;
  font-weight: 500;
  max-width: 22ch;
  color: var(--paper);
  /* warm halo so the white text sits comfortably on the heat-flow bg */
  text-shadow: 0 2px 24px rgba(255, 145, 80, 0.18);
}
.hero h1 em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.02em;
  color: var(--accent);
}


@media (max-width: 720px) {
  .hero-title { padding: 36px 22px 48px; }
}

.hero .lead {
  margin-top: 36px;
  font-size: 20px;
  max-width: 52ch;
  color: rgba(255,255,255,0.78);
}

.hero-cta {
  margin-top: 40px;
  display: flex; align-items: center; gap: 20px;
  flex-wrap: wrap;
}
.hero-cta .meta {
  font-family: var(--f-mono);
  font-size: 12px;
  color: var(--ink-3);
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

/* ---------- marquee ---------- */
.marquee {
  margin-top: 0; /* marquee now sits directly below the dark hero – no gap */
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 18px 0;
  overflow: hidden;
  position: relative;
  white-space: nowrap;
}
.marquee-track {
  display: inline-flex;
  gap: 56px;
  animation: marquee 48s linear infinite;
  will-change: transform;
}
@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
.marquee-item {
  font-family: var(--f-mono);
  font-size: 13px;
  letter-spacing: 0.02em;
  color: var(--ink-2);
  text-transform: uppercase;
  display: inline-flex; align-items: center; gap: 12px;
}
.marquee-item .sep { color: var(--ink-4); }
.marquee-item .val { color: var(--ink); font-family: var(--f-display); font-size: 15px; letter-spacing: -0.01em; text-transform: none; font-weight: 500; }
.marquee-item em { font-family: var(--f-serif); font-style: italic; color: var(--accent); font-size: 15px; letter-spacing: -0.01em; }

/* agent chip variant – dark pills on the light marquee strip */
.marquee-track { gap: 12px; align-items: center; }
.agent-chip {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 8px 16px 8px 8px;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 12px;
  background: #111113;
  color: #F5F3EE;
  font-family: var(--f-mono);
  font-size: 13px;
  letter-spacing: 0.01em;
  text-transform: none;
  white-space: nowrap;
  box-shadow: 0 1px 2px rgba(10,8,6,0.18), 0 6px 20px -10px rgba(10,8,6,0.35);
}
.agent-thumb {
  width: 20px; height: 20px;
  border-radius: 6px;
  flex: 0 0 auto;
  background: var(--c, #E8823A);
  background-image:
    radial-gradient(circle at 30% 25%, rgba(255,255,255,0.35), transparent 45%),
    radial-gradient(circle at 75% 80%, rgba(0,0,0,0.35), transparent 50%),
    linear-gradient(135deg, color-mix(in oklab, var(--c, #E8823A) 100%, white 15%), color-mix(in oklab, var(--c, #E8823A) 70%, black 25%));
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.14), inset 0 -6px 10px rgba(0,0,0,0.35);
  position: relative;
  overflow: hidden;
}
.agent-thumb::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(115deg, transparent 48%, rgba(255,255,255,0.18) 50%, transparent 52%),
    radial-gradient(circle at 80% 20%, rgba(255,255,255,0.4) 0 1px, transparent 2px);
  mix-blend-mode: screen;
}
.agent-name { font-weight: 500; }

/* ---------- section scaffolding ---------- */
.section { padding: 112px 0; position: relative; }
.section-head {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: 64px;
  align-items: end;
  margin-bottom: 64px;
}
@media (max-width: 900px) {
  .section-head { grid-template-columns: 1fr; gap: 24px; }
}
.section-head h2 {
  font-family: var(--f-display);
  /* Aligned to .loop-title so section 1 ('We actually do the work')
     + section 3 ('Fewer hours. More certainty.') read at the same
     scale as section 2 ('Accounts receivable can be effortless'). */
  font-size: clamp(40px, 4.8vw, 64px);
  line-height: 1.02;
  letter-spacing: -0.035em;
  max-width: 22ch;
}
.section-head h2 em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  color: var(--accent);
}
.section-head .lead { max-width: 54ch; font-size: 18px; }

/* ---------- manifesto / whisper ---------- */
.whisper {
  padding: 32px 0 24px;
}
.whisper-card {
  background: var(--ink);
  color: var(--paper);
  border-radius: var(--radius-xl);
  padding: 72px 72px 64px;
  box-shadow: 0 1px 0 rgba(243,238,225,0.04) inset;
}
@media (max-width: 720px) {
  .whisper-card { padding: 48px 32px 44px; border-radius: 24px; }
}
.whisper-main {
  font-family: var(--f-display);
  /* Kept aligned with .section-head h2 (now downsized to match
     .loop-title) so the whisper headline stays the same scale as
     'We actually do the work.' directly below. */
  font-size: clamp(40px, 4.8vw, 64px);
  line-height: 1.02;
  letter-spacing: -0.035em;
  max-width: 22ch;
  font-weight: 500;
  color: var(--paper);
}
.whisper-main em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  color: var(--accent);
  /* Accent now matches the surrounding sans size exactly — no
     optical bump (was 1.08em). User requested all highlighted
     words read at the same scale as their non-highlighted siblings. */
  font-size: 1em;
  line-height: 0.95;
}
.whisper-card p.lead {
  font-family: var(--f-sans);
  font-size: 18px;
  line-height: 1.6;
  font-weight: 400;
  letter-spacing: 0;
  color: rgba(243,238,225,0.78);
  max-width: 64ch;
  margin-top: 28px;
}
.whisper-metrics {
  margin-top: 72px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 56px;
}
.wm {
  display: block;
}
.wm-rule {
  height: 1px;
  background: var(--line);
  margin: 0 0 22px;
}
.wm-value {
  font-family: var(--f-serif);
  font-weight: 400;
  color: var(--ink);
  line-height: 1;
  letter-spacing: -0.01em;
  margin-bottom: 22px;
  display: flex;
  align-items: baseline;
  gap: 4px;
}
.wm-num {
  font-size: clamp(56px, 6.4vw, 88px);
}
.wm-unit {
  font-size: clamp(24px, 2.4vw, 34px);
  color: var(--ink);
}
.wm-label {
  font-family: var(--f-sans);
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.005em;
  margin-bottom: 10px;
}
.wm-note {
  font-family: var(--f-sans);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 38ch;
}
@media (max-width: 880px) {
  .whisper-metrics {
    grid-template-columns: 1fr;
    gap: 40px;
    margin-top: 56px;
  }
}

/* ---------- agents – warp-style split feature grid ---------- */
.agents {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
@media (max-width: 1100px) {
  .agent { padding: 24px 22px; min-height: 200px; }
  .agent .glyph { margin-top: 18px; margin-bottom: 14px; width: 28px; height: 28px; }
  .agent .glyph svg { width: 20px; height: 20px; }
  .agent .name { font-size: 21px; }
  .agent .note { margin-top: 8px; font-size: 13.5px; line-height: 1.45; }
}
@media (max-width: 900px) {
  .agents { grid-template-columns: repeat(2, 1fr); }
  .agent { padding: 22px 20px; min-height: 180px; }
  .agent .glyph { margin-top: 14px; margin-bottom: 12px; }
  .agent .name { font-size: 20px; }
}
@media (max-width: 560px) {
  .agents { grid-template-columns: 1fr; }
  .agent { padding: 20px 18px; min-height: 0; }
  .agent .glyph { margin-top: 10px; margin-bottom: 10px; }
}

.agent {
  background: var(--paper);
  padding: 32px 28px 32px;
  display: flex; flex-direction: column;
  min-height: 240px;
  position: relative;
  transition: background .2s ease;
}
.agent:hover { background: color-mix(in oklab, var(--paper) 95%, var(--accent)); }
.agent .num {
  font-family: var(--f-mono);
  font-size: 11.5px;
  color: var(--ink-3);
  letter-spacing: 0.04em;
}
.agent .glyph {
  width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  color: var(--ink);
  margin-top: 24px;
  margin-bottom: 20px;
}
.agent .glyph svg { width: 22px; height: 22px; }
.agent .name {
  font-family: var(--f-display);
  font-size: 24px;
  font-weight: 500;
  letter-spacing: -0.025em;
  line-height: 1.05;
}
.agent .name em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  color: var(--accent);
}
.agent .note {
  margin-top: 10px;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--ink-2);
  max-width: 32ch;
}

/* ---------- agent-at-work stage ---------- */
.stage {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  background: var(--ink);
  color: var(--paper);
  overflow: hidden;
  position: relative;
}
@media (max-width: 900px) { .stage { grid-template-columns: 1fr; } }

.stage-left {
  padding: 56px 48px 56px;
  display: flex; flex-direction: column; justify-content: space-between;
  min-height: 480px;
  border-right: 1px solid rgba(243,238,225,0.08);
}
.stage-left .eyebrow { color: rgba(243,238,225,0.5); }
.stage-left h3 {
  font-family: var(--f-display);
  font-size: clamp(32px, 3.6vw, 44px);
  line-height: 1.02;
  letter-spacing: -0.03em;
  color: var(--paper);
  margin-top: 28px;
  font-weight: 500;
  max-width: 14ch;
}
.stage-left h3 em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  color: var(--accent-wash);
}
.stage-left .foot {
  font-family: var(--f-mono);
  font-size: 12px;
  color: rgba(243,238,225,0.5);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  margin-top: 40px;
}

.stage-right {
  padding: 32px 32px 40px;
  display: flex; flex-direction: column; gap: 12px;
  background:
    radial-gradient(1200px 320px at -10% -10%, rgba(180,69,42,0.14), transparent 60%),
    var(--ink);
}

.log {
  font-family: var(--f-mono);
  font-size: 12.5px;
  line-height: 1.4;
  color: rgba(243,238,225,0.55);
  letter-spacing: 0.01em;
  display: flex; gap: 12px;
}
.log .t { color: rgba(243,238,225,0.32); flex: none; width: 60px; }

.msg {
  border: 1px solid rgba(243,238,225,0.08);
  background: rgba(243,238,225,0.03);
  border-radius: 10px;
  padding: 14px 16px;
  display: flex; flex-direction: column; gap: 6px;
}
.msg .head {
  display: flex; align-items: center; justify-content: space-between;
  font-family: var(--f-mono);
  font-size: 11.5px;
  color: rgba(243,238,225,0.5);
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.msg .head .who { color: var(--paper); }
.msg .head .pill {
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(229,200,181,0.14);
  color: var(--accent-wash);
  font-size: 10.5px;
  letter-spacing: 0.06em;
}
.msg .body {
  font-family: var(--f-sans);
  font-size: 14px;
  line-height: 1.5;
  color: rgba(243,238,225,0.92);
  letter-spacing: -0.005em;
  text-transform: none;
}
.msg .body em { font-family: var(--f-serif); font-style: italic; color: var(--accent-wash); }

/* attach line for message artifacts */
.msg .attach {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
  align-self: flex-start;
  font-family: var(--f-mono);
  font-size: 11.5px;
  letter-spacing: 0.02em;
  color: rgba(243,238,225,0.55);
  background: rgba(243,238,225,0.04);
  border: 1px solid rgba(243,238,225,0.08);
  border-radius: 6px;
  padding: 5px 9px;
}
.msg .attach .clip { font-size: 11px; opacity: 0.7; }

/* row-style artifacts (cash match, decision, alert) */
.msg .rows {
  display: flex; flex-direction: column;
  margin-top: 2px;
}
.msg .row {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 8px 0;
  border-bottom: 1px dashed rgba(243,238,225,0.08);
  font-size: 13.5px;
  color: rgba(243,238,225,0.85);
}
.msg .row:last-child { border-bottom: none; }
.msg .row .num {
  font-family: var(--f-mono);
  font-size: 13px;
  color: var(--paper);
  letter-spacing: 0;
}
.msg .row-total {
  margin-top: 4px;
  padding-top: 12px;
  border-top: 1px solid rgba(243,238,225,0.14);
  border-bottom: none !important;
  font-weight: 500;
}
.msg .row-total .num { color: var(--paper); }

/* pill tones */
.pill-neutral {
  background: rgba(229,200,181,0.14) !important;
  color: var(--accent-wash) !important;
}
.pill-good {
  background: rgba(123,176,107,0.16) !important;
  color: #c4e0a3 !important;
}
.pill-warn {
  background: rgba(232,161,58,0.16) !important;
  color: #f3c97e !important;
}

/* msg variants – subtle background tint matches tone (no inset edge) */
.msg-good { background: rgba(123,176,107,0.06); border-color: rgba(123,176,107,0.18); }
.msg-warn { background: rgba(232,161,58,0.06); border-color: rgba(232,161,58,0.20); }
.msg-good .row-total .num { color: #c4e0a3; }
.msg-warn .row-total .num { color: #f3c97e; }

/* stage tag (case label) */
.stage-tag {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent-wash);
}

/* stage tabs – labeled, full-width across the top of the stage */
.stage-wrap {
  margin-top: 72px;
  display: flex; flex-direction: column;
  border-radius: var(--radius-xl);
  overflow: hidden;
  background: var(--ink);
}
.stage-tabs {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  background: #161310;
  border-bottom: 1px solid rgba(243,238,225,0.08);
}
.stage-tab {
  position: relative;
  appearance: none;
  background: transparent;
  border: 0;
  border-right: 1px solid rgba(243,238,225,0.06);
  color: rgba(243,238,225,0.55);
  text-align: left;
  padding: 16px 18px 18px;
  cursor: pointer;
  display: flex; flex-direction: column; gap: 6px;
  font-family: var(--f-sans);
  transition: color .2s ease, background .2s ease;
  min-width: 0;
}
.stage-tab:last-child { border-right: 0; }
.stage-tab:hover { color: var(--paper); background: rgba(243,238,225,0.03); }
.stage-tab.is-active { color: var(--paper); background: var(--ink); }
.stage-tab-num {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: rgba(243,238,225,0.4);
}
.stage-tab.is-active .stage-tab-num { color: var(--accent); }
.stage-tab-label {
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.005em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.stage-tab-fill {
  position: absolute;
  left: 0; bottom: 0;
  height: 2px;
  background: var(--accent);
  width: 0;
  animation-name: stage-progress;
  animation-timing-function: linear;
  animation-fill-mode: forwards;
}
@keyframes stage-progress {
  from { width: 0%; }
  to { width: 100%; }
}

@media (max-width: 900px) {
  .stage-tabs { grid-template-columns: repeat(5, minmax(140px, 1fr)); overflow-x: auto; }
  .stage-tab { padding: 12px 14px 14px; }
}

/* fade in fresh content on case switch */
.stage-right > * { animation: stage-fade .35s ease-out both; }
@keyframes stage-fade {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}
.stage-left h3 { animation: stage-fade .4s ease-out both; }

/* ---------- Mahnwesen live demo (stacks below .stage when the active
   case provides a demo payload). All motion is driven by a single 14s
   master timeline so the cursor, the typewriter, the feed-row pulse and
   the send-button morph stay in sync forever. ---------- */
.demo {
  border-top: 1px solid rgba(243,238,225,0.08);
  background:
    radial-gradient(900px 280px at 80% 100%, rgba(180,69,42,0.10), transparent 60%),
    var(--ink);
  padding: 28px 32px 36px;
  position: relative;
  isolation: isolate;
  contain: layout paint;
}
@media (max-width: 720px) { .demo { padding: 22px 18px 28px; } }
.demo-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 20px;
}
.demo-eyebrow {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  color: rgba(243,238,225,0.5);
  text-transform: uppercase;
}
.demo-status {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: rgba(243,238,225,0.55);
  text-transform: uppercase;
}
.demo-status-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 12px rgba(255,61,0,0.55);
  animation: demo-blink 2s ease-in-out infinite;
}
@keyframes demo-blink {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}

.demo-stage {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 24px;
  position: relative;
  min-height: 460px;
}
@media (max-width: 720px) {
  .demo-stage { grid-template-columns: 1fr; min-height: 0; }
}

/* feed (left) */
.demo-feed {
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(243,238,225,0.06);
  border-radius: 12px;
  padding: 14px;
  display: flex; flex-direction: column; gap: 10px;
}
.demo-feed-h {
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  color: rgba(243,238,225,0.4);
  text-transform: uppercase;
  padding: 0 2px 8px;
  border-bottom: 1px solid rgba(243,238,225,0.06);
}
.demo-feed-list {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: 6px;
}
.demo-feed-row {
  padding: 10px 12px;
  border-radius: 8px;
  background: rgba(255,255,255,0.02);
  border: 1px solid rgba(243,238,225,0.05);
  display: flex; flex-direction: column; gap: 4px;
}
.demo-feed-row.is-active {
  animation: demo-row-pulse 14s ease-in-out infinite;
}
@keyframes demo-row-pulse {
  0%, 6%   { background: rgba(255,255,255,0.02); border-color: rgba(243,238,225,0.05); }
  12%, 88% { background: rgba(255,61,0,0.10);    border-color: rgba(255,61,0,0.40);    }
  94%, 100%{ background: rgba(255,255,255,0.02); border-color: rgba(243,238,225,0.05); }
}
.demo-feed-row-top {
  display: flex; align-items: center; justify-content: space-between;
}
.demo-feed-id {
  font-family: var(--f-mono);
  font-size: 11px;
  color: rgba(243,238,225,0.85);
  letter-spacing: 0.02em;
}
.demo-feed-status {
  font-family: var(--f-mono);
  font-size: 9.5px;
  letter-spacing: 0.1em;
  padding: 2px 6px;
  border-radius: 4px;
  text-transform: uppercase;
}
.demo-feed-status--accent  { background: rgba(255,61,0,0.18); color: var(--accent); }
.demo-feed-status--neutral { background: rgba(255,255,255,0.07); color: rgba(243,238,225,0.7); }
.demo-feed-status--ok      { background: rgba(120,200,140,0.16); color: rgb(170,225,180); }
.demo-feed-row-mid {
  font-size: 13px;
  color: var(--paper);
  font-weight: 500;
  letter-spacing: -0.005em;
}
.demo-feed-row-bot {
  display: flex; justify-content: space-between;
  font-family: var(--f-mono);
  font-size: 10.5px;
  color: rgba(243,238,225,0.55);
}

/* compose (right) */
.demo-compose {
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(243,238,225,0.06);
  border-radius: 12px;
  padding: 18px 20px 16px;
  display: flex; flex-direction: column; gap: 14px;
  position: relative;
  min-height: 460px;
}
.demo-compose-h {
  display: flex; flex-direction: column; gap: 4px;
  padding-bottom: 12px;
  border-bottom: 1px solid rgba(243,238,225,0.06);
}
.demo-compose-title {
  font-size: 14px;
  color: var(--paper);
  font-weight: 500;
}
.demo-compose-meta {
  font-family: var(--f-mono);
  font-size: 11px;
  color: rgba(243,238,225,0.55);
}
.demo-controls { display: flex; flex-wrap: wrap; gap: 8px; }
.demo-chip {
  font-family: var(--f-mono);
  font-size: 11px;
  padding: 5px 10px;
  border-radius: 6px;
  background: rgba(255,255,255,0.05);
  color: rgba(243,238,225,0.72);
  letter-spacing: 0.04em;
}
.demo-chip--accent { background: rgba(255,61,0,0.15); color: var(--accent); }

.demo-body {
  flex: 1;
  display: flex; flex-direction: column;
  min-height: 220px;
  padding: 4px 0;
}
.demo-line {
  font-size: 14px;
  line-height: 1.55;
  color: rgba(243,238,225,0.88);
  margin: 0;
  min-height: 1.55em;
  clip-path: inset(0 100% 0 0);
  will-change: clip-path;
}
/* Per-line keyframes: each line stays hidden until cursor is over the
   compose pane, then sweeps in left-to-right. All lines hold visible
   through the click phase and re-hide just before the loop restart so
   the cycle is seamless. */
.demo-line--1  { animation: demo-line-1  14s ease-in-out infinite; }
.demo-line--2  { animation: demo-line-2  14s ease-in-out infinite; }
.demo-line--3  { animation: demo-line-3  14s ease-in-out infinite; }
.demo-line--4  { animation: demo-line-4  14s ease-in-out infinite; }
.demo-line--5  { animation: demo-line-5  14s ease-in-out infinite; }
.demo-line--6  { animation: demo-line-6  14s ease-in-out infinite; }
.demo-line--7  { animation: demo-line-7  14s ease-in-out infinite; }
.demo-line--8  { animation: demo-line-8  14s ease-in-out infinite; }
.demo-line--9  { animation: demo-line-9  14s ease-in-out infinite; }
.demo-line--10 { animation: demo-line-10 14s ease-in-out infinite; }
@keyframes demo-line-1  { 0%, 26% { clip-path: inset(0 100% 0 0); } 30%, 92% { clip-path: inset(0 0 0 0); } 96%, 100% { clip-path: inset(0 100% 0 0); } }
@keyframes demo-line-2  { 0%, 30% { clip-path: inset(0 100% 0 0); } 33%, 92% { clip-path: inset(0 0 0 0); } 96%, 100% { clip-path: inset(0 100% 0 0); } }
@keyframes demo-line-3  { 0%, 34% { clip-path: inset(0 100% 0 0); } 37%, 92% { clip-path: inset(0 0 0 0); } 96%, 100% { clip-path: inset(0 100% 0 0); } }
@keyframes demo-line-4  { 0%, 38% { clip-path: inset(0 100% 0 0); } 41%, 92% { clip-path: inset(0 0 0 0); } 96%, 100% { clip-path: inset(0 100% 0 0); } }
@keyframes demo-line-5  { 0%, 42% { clip-path: inset(0 100% 0 0); } 45%, 92% { clip-path: inset(0 0 0 0); } 96%, 100% { clip-path: inset(0 100% 0 0); } }
@keyframes demo-line-6  { 0%, 46% { clip-path: inset(0 100% 0 0); } 49%, 92% { clip-path: inset(0 0 0 0); } 96%, 100% { clip-path: inset(0 100% 0 0); } }
@keyframes demo-line-7  { 0%, 50% { clip-path: inset(0 100% 0 0); } 53%, 92% { clip-path: inset(0 0 0 0); } 96%, 100% { clip-path: inset(0 100% 0 0); } }
@keyframes demo-line-8  { 0%, 54% { clip-path: inset(0 100% 0 0); } 57%, 92% { clip-path: inset(0 0 0 0); } 96%, 100% { clip-path: inset(0 100% 0 0); } }
@keyframes demo-line-9  { 0%, 58% { clip-path: inset(0 100% 0 0); } 61%, 92% { clip-path: inset(0 0 0 0); } 96%, 100% { clip-path: inset(0 100% 0 0); } }
@keyframes demo-line-10 { 0%, 62% { clip-path: inset(0 100% 0 0); } 65%, 92% { clip-path: inset(0 0 0 0); } 96%, 100% { clip-path: inset(0 100% 0 0); } }

.demo-actions {
  display: flex; justify-content: flex-end;
  padding-top: 12px;
  border-top: 1px solid rgba(243,238,225,0.06);
}
.demo-send {
  position: relative;
  height: 38px;
  min-width: 140px;
  border-radius: 8px;
  background: var(--accent);
  color: var(--paper);
  font-family: var(--f-sans);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.01em;
  overflow: hidden;
  animation: demo-send-bg 14s ease-in-out infinite;
  will-change: transform, background;
}
.demo-send-default,
.demo-send-sent {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  padding: 0 18px;
  white-space: nowrap;
}
.demo-send-default { animation: demo-send-text-default 14s ease-in-out infinite; }
.demo-send-sent    { opacity: 0; color: rgb(170,225,180); animation: demo-send-text-sent 14s ease-in-out infinite; }
@keyframes demo-send-bg {
  0%,  88% { background: var(--accent); transform: scale(1); }
  90%      { background: var(--accent); transform: scale(0.94); }
  91%      { background: var(--accent); transform: scale(1); }
  93%, 100%{ background: rgba(120,200,140,0.18); }
}
@keyframes demo-send-text-default {
  0%, 91% { opacity: 1; }
  93%, 100% { opacity: 0; }
}
@keyframes demo-send-text-sent {
  0%, 91% { opacity: 0; }
  93%, 100% { opacity: 1; }
}

/* cursor – coordinates are pixels relative to .demo-stage's top-left.
   Stage is grid 280|24|1fr so feed is x:0-280, compose starts at x:304. */
.demo-cursor {
  position: absolute;
  top: 0; left: 0;
  width: 22px; height: 22px;
  pointer-events: none;
  z-index: 10;
  filter: drop-shadow(0 2px 6px rgba(0,0,0,0.55));
  animation: demo-cursor-path 14s ease-in-out infinite;
  will-change: transform, opacity;
}
@keyframes demo-cursor-path {
  0%   { transform: translate3d(20px,  460px, 0) scale(1);    opacity: 0; }
  4%   { transform: translate3d(50px,  380px, 0) scale(1);    opacity: 1; }
  10%  { transform: translate3d(120px, 130px, 0) scale(1);    opacity: 1; }  /* hover INV-2041 */
  22%  { transform: translate3d(120px, 130px, 0) scale(1);    opacity: 1; }
  27%  { transform: translate3d(420px, 150px, 0) scale(1);    opacity: 1; }  /* into compose header */
  34%  { transform: translate3d(440px, 240px, 0) scale(1);    opacity: 1; }  /* over body */
  62%  { transform: translate3d(520px, 320px, 0) scale(1);    opacity: 1; }  /* drift during typing */
  86%  { transform: translate3d(820px, 430px, 0) scale(1);    opacity: 1; }  /* over Send */
  89%  { transform: translate3d(820px, 430px, 0) scale(0.82); opacity: 1; }  /* click down */
  91%  { transform: translate3d(820px, 430px, 0) scale(1);    opacity: 1; }  /* click up */
  98%  { transform: translate3d(820px, 430px, 0) scale(1);    opacity: 1; }
  100% { transform: translate3d(40px,  460px, 0) scale(1);    opacity: 0; }
}

@media (max-width: 720px) {
  /* on mobile the layout stacks vertically – pixel-based cursor path
     no longer aligns, so we hide it and let the typewriter + button
     morph carry the demo. */
  .demo-cursor { display: none; }
  .demo-compose { min-height: 0; }
  .demo-body { min-height: 0; }
}

/* ---------- AR loop section (accordion + animated orange card) ---------- */
.loop-section {
  padding: 112px 0;
  background: var(--paper);
}
.loop { display: flex; flex-direction: column; gap: 56px; }
.loop-head { max-width: 760px; }
.loop-title {
  font-family: var(--f-display);
  font-size: clamp(40px, 4.8vw, 64px);
  font-weight: 500;
  letter-spacing: -0.035em;
  line-height: 1.02;
  margin: 0;
  color: var(--ink);
}
.loop-title em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  color: var(--accent);
}
.loop-sub {
  margin: 24px 0 0;
  font-size: 18px;
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 60ch;
}
.loop-grid {
  display: grid;
  /* Image column (now first / left) gets the slightly larger track,
     mirroring the prior layout where the viz card was the dominant
     side – just swapped to the left. */
  grid-template-columns: 1.05fr 1fr;
  gap: 40px;
  align-items: start;
}
@media (max-width: 900px) {
  .loop-grid { grid-template-columns: 1fr; gap: 28px; }
}

/* accordion (left) */
.loop-left { display: flex; flex-direction: column; gap: 10px; }
.loop-step {
  appearance: none;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--paper);
  padding: 14px 20px;
  text-align: left;
  cursor: pointer;
  font-family: var(--f-sans);
  color: var(--ink);
  transition: background .2s ease, border-color .2s ease, color .2s ease;
  display: block;
  width: 100%;
}
.loop-step:hover { background: var(--paper-2); }
.loop-step.is-open {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
.loop-step-head {
  display: grid;
  grid-template-columns: 28px 1fr auto;
  gap: 18px;
  align-items: center;
}
.loop-step-num {
  width: 28px; height: 28px;
  border: 1px solid var(--line);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--ink-3);
  background: var(--paper);
  transition: background .2s ease, color .2s ease, border-color .2s ease;
}
.loop-step.is-open .loop-step-num {
  background: var(--accent);
  color: var(--paper);
  border-color: var(--accent);
}
.loop-step-tt { display: flex; flex-direction: column; gap: 3px; }
.loop-step-title { font-size: 16px; font-weight: 500; letter-spacing: -0.005em; }
.loop-step-sub {
  font-size: 13.5px;
  color: var(--ink-3);
  line-height: 1.45;
}
.loop-step.is-open .loop-step-sub { color: rgba(243,238,225,0.62); }

/* Section 2 (ValueProps) titles should match the section-1 use-case
   labels ("Collections" … "Cash forecasting") for visual continuity.
   Use the same display font, size, weight, and tracking as
   .uc-step-title. Scoped to .vp-section so the base .loop-step-title
   defaults are untouched elsewhere. */
.vp-section .loop-step-tt { gap: 4px; }
.vp-section .loop-step-title {
  font-family: var(--f-display);
  font-size: 21px;
  font-weight: 500;
  letter-spacing: -0.018em;
  line-height: 1.15;
}

/* Section 2 head — two-column layout with the sub on the right.
   Previous attempt used 1fr/1.2fr (Promise's ratio, which has a
   short title) and that shrank the title column too much,
   forcing "Accounts receivable" to wrap to two lines on its own
   ("Accounts / receivable / can be effortless" — 3 lines total).
   New ratio is 1.7fr/1fr — title gets ~63% of the head width,
   enough for "Accounts receivable" to fit on one line at the
   clamp scale, and the sub still has room for ~25 chars/line at
   18px (the 70-char sub wraps to 3 short lines). */
.vp-section .loop-head {
  display: grid;
  grid-template-columns: 1.7fr 1fr;
  gap: 56px;
  align-items: end;
  max-width: none;
}
.vp-section .loop-sub {
  max-width: 44ch;
  font-size: 18px;
  line-height: 1.5;
}
@media (max-width: 900px) {
  .vp-section .loop-head {
    grid-template-columns: 1fr;
    gap: 18px;
    align-items: start;
  }
  .vp-section .loop-sub { max-width: 54ch; }
}

/* Section 2 accordion: number badges removed per user feedback,
   open/close animates smoothly via the grid-template-rows trick.

   Height-locking: the accordion column is forced to the SAME
   HEIGHT as the card column so the right side never extends past
   the left card's bottom edge — regardless of which item is open
   or how long the open body text is. Card column is 1.05fr wide
   and uses aspect-ratio 1/1 → card height = card_col_width =
   total × 1.05/2.05. Accordion column is 1fr wide. For accordion
   height = card height: accordion aspect = (1/2.05) / (1.05/2.05)
   = 1/1.05. So aspect-ratio: 1/1.05 on .loop-left pins the
   accordion's total height to the card's height. */
.vp-section .loop-grid { align-items: stretch; }

.vp-section .loop-left {
  aspect-ratio: 1 / 1.05;
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-height: 0;
}

.vp-section .loop-step {
  flex: 0 0 auto;     /* closed items keep their natural head height */
  min-height: 0;
  /* Override the base 0.2s transitions with a longer, smoother
     curve so the open/close colour swap reads as deliberate.
     flex-grow is also transitioned so the size change when
     toggling between cards animates instead of popping. */
  transition:
    flex-grow .45s cubic-bezier(.22,1,.36,1),
    background .45s cubic-bezier(.22,1,.36,1),
    border-color .45s cubic-bezier(.22,1,.36,1),
    color .45s cubic-bezier(.22,1,.36,1),
    padding .45s cubic-bezier(.22,1,.36,1);
}
.vp-section .loop-step.is-open {
  /* The open item absorbs every remaining pixel in the column,
     so the total stack always equals the locked column height. */
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.vp-section .loop-step.is-open .loop-step-head {
  flex: 0 0 auto;
}
.vp-section .loop-step-head {
  /* No number badge → two columns: title + chevron. */
  grid-template-columns: 1fr auto;
  gap: 16px;
}
.vp-section .loop-step-sub,
.vp-section .loop-step-chev {
  transition: color .45s cubic-bezier(.22,1,.36,1);
}
/* Match Section 1's pattern: when an accordion card is open, its
   toggle chev ("-") takes the brand orange. The base .is-open
   chev rule sets it to a light gray for legibility on dark, but
   Section 2's vertical rhythm + open-card colour mean orange
   reads cleanly here too. Closed-state chev stays muted gray. */
.vp-section .loop-step.is-open .loop-step-chev { color: var(--accent); }
/* Body wrapper — collapsed = 0fr row, opened = 1fr row. The
   inner div has overflow:hidden so the body content is clipped
   while the grid row interpolates between sizes. When the item
   is .is-open, the wrapper also flex-grows to fill whatever
   vertical space the open item has been allocated. */
.vp-section .loop-step-body-wrap {
  display: grid;
  grid-template-rows: 0fr;
  transition:
    grid-template-rows .5s cubic-bezier(.22,1,.36,1),
    opacity .35s ease;
  opacity: 0;
  min-height: 0;
}
.vp-section .loop-step.is-open .loop-step-body-wrap {
  flex: 1 1 0;
}

@media (max-width: 900px) {
  /* Mobile: stack columns; release the aspect-ratio lock so the
     accordion takes its natural height (no card to align to). */
  .vp-section .loop-left { aspect-ratio: auto; display: block; }
  .vp-section .loop-step.is-open { display: block; overflow: visible; }
  .vp-section .loop-step.is-open .loop-step-body-wrap { flex: none; }
}
.vp-section .loop-step.is-open .loop-step-body-wrap {
  grid-template-rows: 1fr;
  opacity: 1;
  transition:
    grid-template-rows .5s cubic-bezier(.22,1,.36,1),
    opacity .35s ease .12s; /* fade in after the row starts opening */
}
.vp-section .loop-step-body-inner {
  overflow: hidden;
  min-height: 0; /* required for grid-rows interpolation to actually animate */
}
.loop-step-chev {
  font-family: var(--f-mono);
  font-size: 18px;
  line-height: 1;
  color: var(--ink-3);
}
.loop-step.is-open .loop-step-chev { color: rgba(243,238,225,0.65); }
.loop-step-body {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid rgba(243,238,225,0.10);
  font-size: 14px;
  line-height: 1.55;
  color: rgba(243,238,225,0.78);
}
.loop-step-body p { margin: 0; }

/* right card with orange heat-flow background */
.loop-right { position: relative; }
.loop-card {
  position: relative;
  border-radius: 24px;
  overflow: hidden;
  background-color: oklch(0.55 0.24 32);
  /* Locked to a 1:1 square so the card stays quadratic at whatever
     width the grid hands it. min-height removed – aspect-ratio
     dictates height now. */
  aspect-ratio: 1 / 1;
  isolation: isolate;
  contain: paint;
  display: flex;
  align-items: center;
  justify-content: center;
}
.loop-card-bg {
  position: absolute;
  inset: -25%;
  pointer-events: none;
  /* STATIC (2026-05-29): this orange glow sits behind the demo cards
     in the Loop / Collections(UseCases) / Integrations(ValueProps)
     sections. Per user: they don't need to move — a fixed "nice shot"
     of the heat-flow is fine here. Removing the animation means the
     blurred gradient rasterizes ONCE and the compositor never touches
     it again (vs re-blurring a 200%x200% layer every frame while these
     sections are on screen). Only the hero keeps the moving heat-flow.
     No will-change: a static layer doesn't need to be force-promoted to
     its own GPU texture — let it paint once into the card. */
  z-index: 0;
}
.loop-card-bg {
  /* warm-only OKLCH stops – no dark anchors, so the card stays
     dominantly orange instead of punching through to ink like the hero.
     Frozen at a fixed background-position; warm-only stops mean any
     position reads as a rich orange wash. */
  background: linear-gradient(
    135deg,
    oklch(0.92 0.10 70 / 0.95) 0%,
    oklch(0.78 0.18 55 / 0.95) 28%,
    oklch(0.65 0.22 38 / 0.95) 58%,
    oklch(0.50 0.22 32 / 0.95) 100%
  );
  background-size: 200% 200%;
  background-position: 60% 45%;
  filter: blur(20px);
  /* animation removed — static heat-flow snapshot. */
}
.loop-card-overlay {
  position: absolute; inset: 0;
  background: rgba(0,0,0,0.08);
  z-index: 1;
  pointer-events: none;
}
/* MOBILE (2026-05-29): on phones the demo cards are full-width and narrow,
   so the desktop 1:1 square makes them too short — the black demo content
   (Send button, "Case resolved", bottom KPIs / forecast labels) gets clipped
   by the card's overflow:hidden. Release the square below 720px and let the
   orange container grow to fit the demo fully; min-height keeps short demos
   from looking cramped. DESKTOP IS UNCHANGED (square preserved >720px). */
@media (max-width: 720px) {
  .loop-card {
    aspect-ratio: auto;
    min-height: 340px;
  }
}
.loop-card-inner {
  position: relative; z-index: 2;
  padding: 36px;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* viz – solid dark product-card chrome, header + body pattern.
   Modeled on the reference screenshot the user shared (Form 1120-S /
   Schedule M-1 card): dark surface, ~12px corners, separated header
   strip with a subtle divider, structured rows underneath. */
.lv {
  background: rgba(15,15,17,0.94);
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 14px;
  padding: 0;
  color: var(--paper);
  width: 100%;
  max-width: 480px;
  animation: lv-fade-in .65s cubic-bezier(.16,1,.3,1) both;
  box-shadow:
    0 20px 50px -22px rgba(20,8,2,0.55),
    0 2px 8px rgba(0,0,0,0.30);
  overflow: hidden;
}
@keyframes lv-fade-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* card header strip (~Form 1120-S row in the reference). Slightly
   lighter than the body so the cap reads as its own surface. */
.lv-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px;
  background: rgba(255,255,255,0.03);
  border-bottom: 1px solid rgba(255,255,255,0.06);
  min-height: 50px;
}
.lv-head-title {
  font-size: 13.5px;
  font-weight: 500;
  color: rgba(255,255,255,0.92);
  letter-spacing: -0.005em;
  display: flex; align-items: center; gap: 10px;
}
.lv-head-sub {
  font-family: var(--f-mono);
  font-size: 11px;
  color: rgba(255,255,255,0.55);
  letter-spacing: 0.04em;
}
.lv-head-menu {
  width: 26px; height: 26px;
  border-radius: 7px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.05);
  display: flex; align-items: center; justify-content: center;
  color: rgba(255,255,255,0.7);
  letter-spacing: 2px;
  font-size: 14px;
  line-height: 0;
}

.lv-body {
  padding: 14px 18px 16px;
}
.lv-foot {
  padding: 12px 18px 14px;
  border-top: 1px solid rgba(255,255,255,0.06);
  display: flex; gap: 8px; align-items: center;
  flex-wrap: wrap;
}

.lv-chip {
  font-family: var(--f-mono);
  font-size: 10.5px;
  padding: 4px 9px;
  border-radius: 5px;
  background: rgba(255,255,255,0.06);
  color: rgba(255,255,255,0.82);
  letter-spacing: 0.04em;
}
.lv-chip-accent { background: rgba(255,61,0,0.18); color: var(--accent); }

/* ===========================================================
   Loop section vizes — refined to match the use-cases polish.
   Shared timing: ucv-row-in keyframe (already defined upstream),
   cubic-bezier(.16, 1, .3, 1) easing, staggered 0.2 / 0.55 / 0.9 /
   1.25s delays so beats feel calm rather than rushed.
   =========================================================== */

/* ---------- 1. CONNECT ---------- */
.lv-cn { padding: 0; }
.lv-cn .lv-body {
  display: flex; flex-direction: column;
  gap: 8px;
}
.lv-cn-row {
  display: grid;
  grid-template-columns: 38px 1fr auto;
  gap: 14px;
  align-items: center;
  padding: 12px 14px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 12px;
  opacity: 0;
  transform: translateY(8px);
  animation: ucv-row-in 0.55s cubic-bezier(.16,1,.3,1) forwards;
}
.lv-cn-row--1 { animation-delay: 0.20s; }
.lv-cn-row--2 { animation-delay: 0.45s; }
.lv-cn-row--3 { animation-delay: 0.70s; }
.lv-cn-row--4 { animation-delay: 0.95s; }
.lv-cn-tile {
  width: 38px; height: 38px;
  border-radius: 9px;
  color: white;
  font-size: 14px;
  font-weight: 800;
  letter-spacing: 0.02em;
  display: flex; align-items: center; justify-content: center;
}
.lv-cn-info { min-width: 0; }
.lv-cn-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--paper);
  letter-spacing: -0.005em;
}
.lv-cn-meta {
  font-size: 11.5px;
  color: rgba(255,255,255,0.55);
  margin-top: 1px;
}
.lv-cn-status {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--f-mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgb(170,225,180);
}
.lv-cn-status-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: rgb(60,180,100);
  box-shadow: 0 0 8px rgba(60,180,100,0.6);
  animation: demo-blink 1.8s ease-in-out infinite;
}

/* ---------- 2. DETECT ---------- */
.lv-det { padding: 0; }
.lv-det .lv-body { padding: 14px 16px 18px; }
.lv-det-row {
  display: grid;
  grid-template-columns: 76px 1fr auto;
  gap: 12px;
  align-items: center;
  padding: 11px 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.05);
  border-radius: 10px;
  margin-bottom: 6px;
  opacity: 0;
  transform: translateY(6px);
  animation: ucv-row-in 0.55s cubic-bezier(.16,1,.3,1) forwards;
}
.lv-det-row:last-child { margin-bottom: 0; }
.lv-det-row--1 { animation-delay: 0.20s; }
.lv-det-row--2 { animation-delay: 0.40s; }
.lv-det-row--3 { animation-delay: 0.60s; }
.lv-det-row--4 { animation-delay: 0.80s; }
.lv-det-row--active {
  background: rgba(255,61,0,0.10);
  border-color: rgba(255,61,0,0.30);
  position: relative;
}
.lv-det-row--active::before {
  content: "";
  position: absolute;
  left: 0; top: 8px; bottom: 8px;
  width: 2px;
  background: var(--accent);
  border-radius: 1px;
}
.lv-det-type {
  font-family: var(--f-mono);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.55);
  padding: 3px 7px;
  background: rgba(255,255,255,0.05);
  border-radius: 4px;
  text-align: center;
}
.lv-det-row--active .lv-det-type {
  background: rgba(255,61,0,0.18);
  color: var(--accent);
}
.lv-det-mid { min-width: 0; }
.lv-det-who {
  font-size: 13px;
  font-weight: 500;
  color: var(--paper);
  letter-spacing: -0.005em;
}
.lv-det-id {
  font-size: 11px;
  color: rgba(255,255,255,0.55);
  margin-top: 1px;
}
.lv-det-tag {
  font-family: var(--f-mono);
  font-size: 10.5px;
  letter-spacing: 0.04em;
  padding: 4px 8px;
  border-radius: 5px;
  background: rgba(255,255,255,0.05);
  color: rgba(255,255,255,0.7);
  white-space: nowrap;
}
.lv-det-tag--accent {
  background: var(--accent);
  color: var(--paper);
  font-weight: 600;
  animation: lv-det-pulse 2s ease-in-out infinite;
}
@keyframes lv-det-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,61,0,0); }
  50%      { box-shadow: 0 0 0 6px rgba(255,61,0,0.18); }
}

/* ---------- 3. DRAFT ---------- */
.lv-dr { padding: 0; }
.lv-dr .lv-body { padding: 14px 16px 18px; display: flex; flex-direction: column; gap: 8px; }
.lv-dr-row {
  padding: 12px 14px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 10px;
  opacity: 0;
  transform: translateY(6px);
  animation: ucv-row-in 0.55s cubic-bezier(.16,1,.3,1) forwards;
}
.lv-dr-row--1 { animation-delay: 0.25s; }
.lv-dr-row--2 { animation-delay: 0.65s; }
.lv-dr-row--3 { animation-delay: 1.05s; }
.lv-dr-top {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 12px;
  margin-bottom: 4px;
}
.lv-dr-to {
  font-size: 12px;
  color: rgba(255,255,255,0.65);
  letter-spacing: -0.005em;
}
.lv-dr-time {
  font-family: var(--f-mono);
  font-size: 10.5px;
  color: rgba(255,255,255,0.45);
  font-variant-numeric: tabular-nums;
}
.lv-dr-subj {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--paper);
  letter-spacing: -0.005em;
  margin-bottom: 8px;
}
.lv-dr-chips {
  display: flex; flex-wrap: wrap; gap: 5px;
}
.lv-dr-chip {
  font-family: var(--f-mono);
  font-size: 10.5px;
  letter-spacing: 0.04em;
  padding: 3px 8px;
  border-radius: 5px;
  background: rgba(255,255,255,0.05);
  color: rgba(255,255,255,0.75);
}
.lv-dr-chip--ready {
  background: rgba(60,180,100,0.16);
  color: rgb(170,225,180);
  font-weight: 600;
}

/* ---------- 4. APPROVE ---------- */
.lv-ap { padding: 0; }
.lv-ap .lv-body { padding: 14px 16px 18px; }
.lv-ap-row {
  display: grid;
  grid-template-columns: 22px 1fr auto;
  gap: 12px;
  align-items: center;
  padding: 10px 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.05);
  border-radius: 9px;
  margin-bottom: 5px;
  opacity: 0;
  transform: translateY(6px);
  animation: ucv-row-in 0.5s cubic-bezier(.16,1,.3,1) forwards;
}
.lv-ap-row--1 { animation-delay: 0.20s; }
.lv-ap-row--2 { animation-delay: 0.40s; }
.lv-ap-row--3 { animation-delay: 0.60s; }
.lv-ap-row--4 { animation-delay: 0.80s; }
.lv-ap-check {
  display: inline-flex; align-items: center; justify-content: center;
}
.lv-ap-check .ucv-tick {
  background: rgb(60,180,100);
  opacity: 0;
  animation: ucv-tick-in 0.45s cubic-bezier(.16,1,.3,1) forwards;
}
.lv-ap-row--1 .ucv-tick { animation-delay: 0.55s; }
.lv-ap-row--2 .ucv-tick { animation-delay: 0.75s; }
.lv-ap-row--3 .ucv-tick { animation-delay: 0.95s; }
.lv-ap-row--4 .ucv-tick { animation-delay: 1.15s; }
.lv-ap-info { min-width: 0; }
.lv-ap-who {
  font-size: 13px;
  font-weight: 500;
  color: var(--paper);
  letter-spacing: -0.005em;
}
.lv-ap-id {
  font-family: var(--f-mono);
  font-size: 10.5px;
  color: rgba(255,255,255,0.55);
  margin-top: 1px;
}
.lv-ap-amt {
  font-family: var(--f-mono);
  font-size: 13px;
  font-weight: 500;
  color: var(--paper);
  font-variant-numeric: tabular-nums;
}
.lv-ap-confirm {
  margin-top: 12px;
  padding: 10px 12px;
  background: rgba(60,180,100,0.10);
  border: 1px solid rgba(60,180,100,0.30);
  border-radius: 9px;
  font-size: 12.5px;
  color: rgb(170,225,180);
  display: flex; align-items: center; gap: 8px;
  font-weight: 500;
  opacity: 0;
  animation: ucv-row-in 0.6s cubic-bezier(.16,1,.3,1) 1.5s forwards;
}

/* ---------- 5. RECONCILE ---------- */
.lv-rc { padding: 0; }
.lv-rc .lv-body { padding: 14px 16px 18px; }
.lv-rc-table-head {
  display: grid;
  grid-template-columns: 1fr 110px 110px;
  gap: 12px;
  padding: 0 12px 8px;
  font-family: var(--f-mono);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.45);
  border-bottom: 1px solid rgba(255,255,255,0.06);
}
.lv-rc-table-head span:nth-child(2),
.lv-rc-table-head span:nth-child(3) { text-align: right; }
.lv-rc-row {
  display: grid;
  grid-template-columns: 1fr 110px 110px;
  gap: 12px;
  padding: 10px 12px;
  font-size: 13px;
  color: rgba(255,255,255,0.85);
  border-bottom: 1px solid rgba(255,255,255,0.05);
  opacity: 0;
  transform: translateY(4px);
  animation: ucv-row-in 0.5s cubic-bezier(.16,1,.3,1) forwards;
}
.lv-rc-row--1 { animation-delay: 0.25s; }
.lv-rc-row--2 { animation-delay: 0.50s; }
.lv-rc-row--3 { animation-delay: 0.75s; }
.lv-rc-acct {
  display: inline-flex; align-items: baseline; gap: 8px;
}
.lv-rc-code {
  font-family: var(--f-mono);
  font-size: 11px;
  color: rgba(255,255,255,0.45);
  letter-spacing: 0.04em;
}
.lv-rc-dr,
.lv-rc-cr {
  text-align: right;
  font-family: var(--f-mono);
  font-variant-numeric: tabular-nums;
  color: var(--paper);
}
.lv-rc-total {
  display: grid;
  grid-template-columns: 1fr 110px 110px;
  gap: 12px;
  padding: 11px 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--paper);
  background: rgba(255,255,255,0.04);
  border-radius: 0 0 8px 8px;
  margin-bottom: 12px;
  opacity: 0;
  animation: ucv-row-in 0.5s cubic-bezier(.16,1,.3,1) 1.0s forwards;
}
.lv-rc-total span:nth-child(2),
.lv-rc-total span:nth-child(3) {
  text-align: right;
  font-family: var(--f-mono);
  font-variant-numeric: tabular-nums;
}
.lv-rc-confirm {
  padding: 10px 12px;
  background: rgba(60,180,100,0.10);
  border: 1px solid rgba(60,180,100,0.30);
  border-radius: 9px;
  font-size: 12.5px;
  color: rgb(170,225,180);
  display: flex; align-items: center; gap: 8px;
  font-weight: 500;
  opacity: 0;
  animation: ucv-row-in 0.6s cubic-bezier(.16,1,.3,1) 1.4s forwards;
}

/* ===========================================================
   ValueProps section — additional space above so it doesn't
   crash into the Loop section above.
   =========================================================== */
.vp-section { padding-top: 0; }

/* ---------- VP1 · INTEGRATIONS LIST ----------
   Vertical list of native integrations. Each row fades in with a
   stagger and its green tick ticks in just after. Whole card
   remounts on a 12s cycle (handled in JS) so the cascade replays. */
.lv-int { padding: 0; }
/* Viewport — fixed height, never moves. Rows are absolutely
   positioned via translateY from a common base; the container
   does not animate. Top padding = 16px is baked into the row's
   "top" CSS so slot 1 (active, translateY 0) lands flush with
   that line. Sized for 5 visible rows at 64px each + 4 gaps. */
.lv-int-viewport {
  position: relative;
  height: 368px;
  overflow: hidden;
  padding: 0 14px;
  box-sizing: border-box;
}
.lv-int-list {
  position: relative;
  width: 100%;
  height: 100%;
}
.lv-int-row {
  position: absolute;
  top: 16px;        /* base — slot 1's rest position */
  left: 0; right: 0;
  display: grid;
  grid-template-columns: 24px 1fr 40px;
  gap: 16px;
  align-items: center;
  padding: 0 16px;
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(255,255,255,0.05);
  border-radius: 12px;
  height: 64px;
  box-sizing: border-box;
  /* All visual state — position, opacity, tile colours, check fill,
     text colour, logo saturation — is bound to the slot class on
     this element. When the slot class changes on a tick, every
     transition fires simultaneously and lands together at ~600ms. */
  transition:
    transform .6s cubic-bezier(.22, 1, .36, 1),
    opacity   .6s cubic-bezier(.22, 1, .36, 1),
    background .6s cubic-bezier(.22, 1, .36, 1),
    border-color .6s cubic-bezier(.22, 1, .36, 1);
  will-change: transform, opacity;
}
.lv-int-check {
  width: 20px; height: 20px;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent;
  border: 1.4px solid rgba(255,255,255,0.32);
  box-sizing: border-box;
  transition:
    background .6s cubic-bezier(.22, 1, .36, 1),
    border-color .6s cubic-bezier(.22, 1, .36, 1),
    box-shadow .6s cubic-bezier(.22, 1, .36, 1);
}
.lv-int-check svg {
  opacity: 0.5;
  transition: opacity .6s cubic-bezier(.22, 1, .36, 1);
}
.lv-int-name {
  font-size: 14.5px;
  font-weight: 500;
  color: rgba(243,238,225,0.65);  /* default = upcoming dim */
  letter-spacing: -0.008em;
  transition: color .6s cubic-bezier(.22, 1, .36, 1);
}
/* Tile = white pill, full-colour PNG inside. Logo opacity +
   saturation are bound to the slot class — full colour at slot 1,
   desaturated + dim in upcoming slots. */
.lv-int-tile {
  width: 40px; height: 40px;
  border-radius: 9px;
  background: #fff;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  padding: 4px;
  box-sizing: border-box;
  flex-shrink: 0;
  transition:
    background .6s cubic-bezier(.22, 1, .36, 1),
    opacity .6s cubic-bezier(.22, 1, .36, 1);
}
.lv-int-tile img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  display: block;
  filter: grayscale(0.5);  /* default = upcoming, desaturated */
  opacity: 0.85;
  transition:
    filter .6s cubic-bezier(.22, 1, .36, 1),
    opacity .6s cubic-bezier(.22, 1, .36, 1),
    transform .6s cubic-bezier(.22, 1, .36, 1);
}
/* Per-brand scale overrides for logos that arrive with more
   internal whitespace than the rest (so they'd otherwise render
   visibly smaller in the fixed tile). Sage in particular has a
   lot of transparent padding around its glyph — scaling to ~1.9
   pushes the glyph out to the tile edges so only a thin white
   border remains. */
.lv-int-tile img[src*="sage-logo"] {
  transform: scale(1.9);
}

/* ---------- Slot states ---------- Step = row (64) + gap (8) = 72.

   slot 0 → exit zone, one row above active (invisible)
   slot 1 → ACTIVE, full state
   slot 2 → next-up, slight dim
   slot 3 → further out, deeper dim
   slot 4 → upcoming
   slot 5 → deepest visible
   slot 6 → entry zone, one row below slot 5 (invisible)

   Rows transition from old slot's styles to new slot's styles
   simultaneously on tick. */

.lv-int-row--slot0 {
  transform: translateY(-72px);
  opacity: 0;
  pointer-events: none;
}

.lv-int-row--slot1 {
  transform: translateY(0);
  opacity: 1;
  background: rgba(255,255,255,0.055);
  border-color: rgba(255,255,255,0.11);
}
.lv-int-row--slot1 .lv-int-check {
  background: rgb(60,180,100);
  border-color: rgb(60,180,100);
  box-shadow: 0 0 0 3px rgba(60,180,100,0.16);
}
.lv-int-row--slot1 .lv-int-check svg { opacity: 1; }
.lv-int-row--slot1 .lv-int-name { color: var(--paper); }
.lv-int-row--slot1 .lv-int-tile img {
  filter: grayscale(0);
  opacity: 1;
}

.lv-int-row--slot2 {
  transform: translateY(72px);
  opacity: 0.85;
}
.lv-int-row--slot2 .lv-int-name { color: rgba(243,238,225,0.75); }

.lv-int-row--slot3 {
  transform: translateY(144px);
  opacity: 0.6;
}
.lv-int-row--slot3 .lv-int-name { color: rgba(243,238,225,0.58); }
.lv-int-row--slot3 .lv-int-tile img {
  filter: grayscale(0.55);
  opacity: 0.78;
}

.lv-int-row--slot4 {
  transform: translateY(216px);
  opacity: 0.35;
}
.lv-int-row--slot4 .lv-int-name { color: rgba(243,238,225,0.42); }
.lv-int-row--slot4 .lv-int-tile img {
  filter: grayscale(0.75);
  opacity: 0.62;
}

.lv-int-row--slot5 {
  transform: translateY(288px);
  opacity: 0.16;
}
.lv-int-row--slot5 .lv-int-name { color: rgba(243,238,225,0.3); }
.lv-int-row--slot5 .lv-int-tile img {
  filter: grayscale(0.85);
  opacity: 0.45;
}

.lv-int-row--slot6 {
  transform: translateY(360px);
  opacity: 0;
  pointer-events: none;
}

/* Bottom fade overlay reinforces the dissolve on slot 5 — without
   it the row at translateY 288 reads as a flat lit row instead of
   "fading into the depth below." */
.lv-int-fade {
  position: absolute;
  inset: auto 0 0 0;
  height: 36%;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgba(15,15,17,0)    0%,
    rgba(15,15,17,0.45) 60%,
    rgba(15,15,17,0.9)  100%
  );
}

/* ---------- VP2 · SUPERCHARGE DASHBOARD ----------
   Big EUR total that counts between two states (high outstanding ↔
   low outstanding via CountTo). Below it, 6 aging-bucket bars that
   morph between two distributions via CSS transition on height. */
.lv-sc { padding: 20px 22px 22px; }
.lv-sc-head {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 6px;
}
.lv-sc-label {
  font-size: 12.5px;
  color: rgba(255,255,255,0.55);
  letter-spacing: -0.005em;
}
.lv-sc-trend {
  display: inline-flex; align-items: center;
  padding: 4px 10px;
  background: rgba(60,180,100,0.15);
  color: rgb(170,225,180);
  border-radius: 999px;
  font-family: var(--f-sans);
  font-size: 11.5px;
  font-weight: 600;
}
.lv-sc-total {
  display: flex; align-items: baseline; gap: 4px;
  font-family: var(--f-display);
  font-weight: 500;
  letter-spacing: -0.03em;
  color: var(--paper);
  font-variant-numeric: tabular-nums;
  margin-bottom: 4px;
}
.lv-sc-cur { font-size: 22px; opacity: 0.7; }
.lv-sc-total .count-up { font-size: 38px; }
.lv-sc-sub {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  margin-bottom: 16px;
  font-variant-numeric: tabular-nums;
}
.lv-sc-chart {
  position: relative;
  height: 200px;
  padding-bottom: 24px;
  border-bottom: 1px solid rgba(255,255,255,0.10);
}
.lv-sc-grid {
  position: absolute;
  inset: 0 0 24px 0;
  pointer-events: none;
}
.lv-sc-grid span {
  position: absolute;
  left: 0; right: 0;
  height: 1px;
  background: rgba(255,255,255,0.05);
}
.lv-sc-grid span:nth-child(1) { top: 0%; }
.lv-sc-grid span:nth-child(2) { top: 50%; }
.lv-sc-grid span:nth-child(3) { top: 100%; }
.lv-sc-bars {
  position: absolute;
  inset: 0 0 24px 0;
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 12px;
  align-items: end;
}
.lv-sc-col {
  display: flex; flex-direction: column; align-items: stretch;
  height: 100%;
  position: relative;
}
.lv-sc-fill {
  width: 100%;
  background: linear-gradient(
    to top,
    var(--accent) 0%,
    color-mix(in oklab, var(--accent) 75%, white) 100%
  );
  border-radius: 6px 6px 4px 4px;
  margin-top: auto;
  /* CORE morph — bar heights smoothly transition between the two
     state distributions whenever React updates the inline style. */
  transition: height 1.2s cubic-bezier(.4, 0, .2, 1);
}
.lv-sc-xl {
  position: absolute;
  bottom: -22px;
  left: 0; right: 0;
  text-align: center;
  font-family: var(--f-mono);
  font-size: 10.5px;
  color: rgba(255,255,255,0.55);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* ---------- VP3 · Exceptions queue (lv-exc) ---------------------
   Identical architecture to .lv-int: fixed-height viewport, rows
   absolutely positioned, slot class controls translateY + opacity +
   background + check-fill + text colour. Container is rock-still;
   only individual rows transition between slot states. 600ms
   ease-out, all properties land together. */
.lv-exc { padding: 0; }
/* Viewport sized to show 4 full rows (slots 1-4) + the top half
   of slot 5 (the "peek" row that hints at what's next in the
   queue). Slot 6 sits below the viewport as the invisible entry
   zone. Height = 16 (top inset) + 4 rows × 72 + 3 gaps × 8 +
   gap before slot 5 (8) + half row (~40) = 376px. */
.lv-exc-viewport {
  position: relative;
  height: 376px;
  overflow: hidden;
  padding: 0 16px;
  box-sizing: border-box;
}
.lv-exc-list {
  position: relative;
  width: 100%;
  height: 100%;
}
.lv-exc-row {
  position: absolute;
  top: 16px;             /* base = slot 1 rest position */
  left: 16px; right: 16px;
  display: grid;
  grid-template-columns: 36px 1fr 22px;
  gap: 14px;
  align-items: center;
  padding: 0 16px;
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(255,255,255,0.05);
  border-radius: 12px;
  height: 72px;
  box-sizing: border-box;
  transition:
    transform .6s cubic-bezier(.22, 1, .36, 1),
    opacity   .6s cubic-bezier(.22, 1, .36, 1),
    background .6s cubic-bezier(.22, 1, .36, 1),
    border-color .6s cubic-bezier(.22, 1, .36, 1);
  will-change: transform, opacity;
}
.lv-exc-ico {
  width: 32px; height: 32px;
  border-radius: 9px;
  display: grid; place-items: center;
  background: rgba(255,255,255,0.05);
  color: rgba(255,255,255,0.72);
  border: 1px solid rgba(255,255,255,0.06);
}
.lv-exc-body { min-width: 0; }
.lv-exc-label {
  font-family: var(--f-tight);
  font-weight: 600;
  font-size: 15.5px;
  color: rgba(243,238,225,0.7);
  letter-spacing: -0.008em;
  line-height: 1.2;
  transition: color .6s cubic-bezier(.22, 1, .36, 1);
}
.lv-exc-detail {
  font-size: 12.5px;
  color: rgba(243,238,225,0.4);
  letter-spacing: -0.002em;
  margin-top: 4px;
  transition: color .6s cubic-bezier(.22, 1, .36, 1);
}
.lv-exc-check {
  width: 22px; height: 22px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: transparent;
  border: 1.4px solid rgba(255,255,255,0.32);
  box-sizing: border-box;
  transition:
    background .6s cubic-bezier(.22, 1, .36, 1),
    border-color .6s cubic-bezier(.22, 1, .36, 1),
    box-shadow .6s cubic-bezier(.22, 1, .36, 1);
}
.lv-exc-check svg {
  opacity: 0.5;
  transition: opacity .6s cubic-bezier(.22, 1, .36, 1);
}

/* ---------- Slot states ---------- Step = row (72) + gap (8) = 80.
   slot 0 = exit (above), 1 = ACTIVE, 2-4 = upcoming, 5 = entry (below) */

.lv-exc-row--slot0 {
  transform: translateY(-80px);
  opacity: 0;
  pointer-events: none;
}

.lv-exc-row--slot1 {
  transform: translateY(0);
  opacity: 1;
  background: rgba(255,255,255,0.055);
  border-color: rgba(255,255,255,0.11);
}
.lv-exc-row--slot1 .lv-exc-label  { color: var(--paper); }
.lv-exc-row--slot1 .lv-exc-detail { color: rgba(243,238,225,0.65); }
.lv-exc-row--slot1 .lv-exc-check {
  /* Match the integrations card's active-check colour + glow
     exactly so the two cascades feel like one design system. */
  background: rgb(60,180,100);
  border-color: rgb(60,180,100);
  box-shadow: 0 0 0 3px rgba(60,180,100,0.16);
}
.lv-exc-row--slot1 .lv-exc-check svg { opacity: 1; }

.lv-exc-row--slot2 {
  transform: translateY(80px);
  opacity: 0.82;
}
.lv-exc-row--slot2 .lv-exc-label  { color: rgba(243,238,225,0.72); }
.lv-exc-row--slot2 .lv-exc-detail { color: rgba(243,238,225,0.48); }

.lv-exc-row--slot3 {
  transform: translateY(160px);
  opacity: 0.5;
}
.lv-exc-row--slot3 .lv-exc-label  { color: rgba(243,238,225,0.55); }
.lv-exc-row--slot3 .lv-exc-detail { color: rgba(243,238,225,0.36); }

.lv-exc-row--slot4 {
  transform: translateY(240px);
  opacity: 0.32;
}
.lv-exc-row--slot4 .lv-exc-label  { color: rgba(243,238,225,0.46); }
.lv-exc-row--slot4 .lv-exc-detail { color: rgba(243,238,225,0.32); }

/* Peek row — sits half-inside the viewport so the user reads it
   as "and there's more queued behind." Strong dim + the bottom
   fade overlay below will mask its lower half. */
.lv-exc-row--slot5 {
  transform: translateY(320px);
  opacity: 0.14;
}
.lv-exc-row--slot5 .lv-exc-label  { color: rgba(243,238,225,0.32); }
.lv-exc-row--slot5 .lv-exc-detail { color: rgba(243,238,225,0.22); }

/* True invisible entry zone — sits fully below the viewport.
   Becomes slot 5 (peek) on next tick. */
.lv-exc-row--slot6 {
  transform: translateY(400px);
  opacity: 0;
  pointer-events: none;
}

/* Bottom fade now extends further up to feather slot 5's lower
   half into the card background — reinforces the "peek" feel. */
.lv-exc-fade {
  position: absolute;
  inset: auto 0 0 0;
  height: 32%;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgba(15,15,17,0)    0%,
    rgba(15,15,17,0.50) 55%,
    rgba(15,15,17,0.92) 100%
  );
}

/* ---------- VP4 · Velocity (lv-vel) -----------------------------
   Replaces the old throughput dashboard. Shows Kasdor reading a
   contract → extracting structured terms → recognizing customer
   pattern → matching an invoice. Phase machine in the component
   drives which elements are visible; CSS only handles the static
   layout, the highlight states, and the entrance transitions. */
.lv-vel {
  padding: 18px 18px 16px;
  /* Deeper base with a soft warm glow from the top-right corner —
     gives the card atmosphere without competing with the document. */
  background:
    radial-gradient(120% 80% at 100% 0%, rgba(255,61,0,0.10) 0%, transparent 55%),
    #0E1311;
  position: relative;
}
.lv-vel-strip {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.09em;
  color: rgba(255,255,255,0.55);
  margin-bottom: 12px;
}
.lv-vel-strip-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px rgba(255,61,0,0.18);
  animation: lv-vel-pulse 1.6s ease-in-out infinite;
}
@keyframes lv-vel-pulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(255,61,0,0.18); }
  50%      { box-shadow: 0 0 0 5px rgba(255,61,0,0.08); }
}

/* Customer header — visually separated from the doc viewport
   below with a clearer panel treatment + larger bottom margin.
   The header is its own surface; the viewport is its own surface. */
.lv-vel-customer {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 12px;
  margin-bottom: 28px;     /* clear visual break to the doc list */
  position: relative;
  box-shadow: 0 1px 0 rgba(255,255,255,0.04) inset;
}
/* Soft hairline divider below the customer header — gives the
   header its own "row" feel and signals the queue below is a
   different surface. */
.lv-vel-customer::after {
  content: "";
  position: absolute;
  left: 16px; right: 16px;
  bottom: -15px;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(255,255,255,0.10) 30%,
    rgba(255,255,255,0.10) 70%,
    transparent 100%
  );
}
.lv-vel-customer-mark {
  width: 34px; height: 34px;
  flex-shrink: 0;
  border-radius: 9px;
  background: linear-gradient(135deg, var(--accent) 0%, #E63300 100%);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 12.5px;
  letter-spacing: -0.01em;
  box-shadow: 0 0 0 1px rgba(255,255,255,0.14) inset,
              0 4px 12px -4px rgba(255,61,0,0.45);
}
.lv-vel-customer-name {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 14.5px;
  color: var(--paper);
  letter-spacing: -0.008em;
  line-height: 1.15;
}
.lv-vel-customer-sub {
  font-family: var(--f-mono);
  font-size: 10px;
  color: rgba(255,255,255,0.5);
  letter-spacing: 0.02em;
  margin-top: 4px;
}

/* Doc viewport — fixed-height container that the chip absolutely
   overlays. Rows are position:absolute inside, positioned via
   slot classes that translateY them into place. Overflow hidden
   so docs rotating up (slot 0) leave the visible area. NO bottom
   fade overlay and NO per-slot dimming — every visible row reads
   equally. */
.lv-vel-doc-viewport {
  position: relative;
  height: 286px;          /* fits 5 rows × 50 + 4 gaps × 9 = 286 */
  overflow: hidden;
}
.lv-vel-doc-list {
  position: relative;
  width: 100%;
  height: 100%;
}
.lv-vel-doc-row {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  display: grid;
  grid-template-columns: 32px 1fr 20px;
  gap: 12px;
  align-items: center;
  padding: 10px 12px;
  background: rgba(255,255,255,0.025);
  border: 1px solid rgba(255,255,255,0.05);
  border-radius: 8px;
  height: 50px;
  box-sizing: border-box;
  transition:
    transform .55s cubic-bezier(.22, 1, .36, 1),
    opacity   .55s cubic-bezier(.22, 1, .36, 1),
    background .45s cubic-bezier(.22, 1, .36, 1),
    border-color .45s cubic-bezier(.22, 1, .36, 1),
    box-shadow .45s cubic-bezier(.22, 1, .36, 1);
  will-change: transform, opacity;
}

/* Slot positions — step = row (50) + gap (9) = 59px.
   slot 1 = active (top of visible area)
   slots 2-5 = upcoming, NOT dimmed
   slot 0 = exit (rotated up, invisible) */
.lv-vel-doc-row--slot0 {
  transform: translateY(-59px);
  opacity: 0;
  pointer-events: none;
}
.lv-vel-doc-row--slot1 { transform: translateY(0); }
.lv-vel-doc-row--slot2 { transform: translateY(59px); }
.lv-vel-doc-row--slot3 { transform: translateY(118px); }
.lv-vel-doc-row--slot4 { transform: translateY(177px); }
.lv-vel-doc-row--slot5 { transform: translateY(236px); }

/* Active row — orange glow + tinted background. Only the row at
   slot 1 (the doc currently being analysed / showing findings). */
.lv-vel-doc-row.is-active {
  background: rgba(255,61,0,0.08);
  border-color: rgba(255,61,0,0.22);
  box-shadow:
    0 0 0 1px rgba(255,61,0,0.12),
    0 0 18px -4px rgba(255,61,0,0.28);
}

.lv-vel-doc-icon {
  width: 32px; height: 32px;
  border-radius: 7px;
  display: grid; place-items: center;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.06);
  color: rgba(255,255,255,0.7);
  transition: background .45s ease, border-color .45s ease, color .45s ease;
}
.lv-vel-doc-row.is-active .lv-vel-doc-icon {
  background: rgba(255,61,0,0.16);
  border-color: rgba(255,61,0,0.32);
  color: rgb(255, 168, 130);
}
.lv-vel-doc-text { min-width: 0; }
.lv-vel-doc-type {
  font-family: var(--f-sans);
  font-weight: 600;
  font-size: 13px;
  color: var(--paper);
  letter-spacing: -0.006em;
  line-height: 1.2;
}
.lv-vel-doc-meta {
  font-size: 11px;
  color: rgba(255,255,255,0.48);
  letter-spacing: -0.002em;
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Green check that appears on the row the same moment the chip
   turns green (findings phase). The check stays attached to the
   row as it rotates up to slot 0 and out of view. Empty by
   default; the JSX renders the SVG only when isFinished. */
.lv-vel-doc-check {
  width: 20px; height: 20px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: transparent;
  transition:
    background .35s cubic-bezier(.22, 1, .36, 1),
    box-shadow .35s cubic-bezier(.22, 1, .36, 1);
}
.lv-vel-doc-row.is-finished .lv-vel-doc-check {
  background: rgb(60, 180, 100);
  box-shadow: 0 0 0 3px rgba(60, 180, 100, 0.18);
}

/* Centered activity chip — white rounded-rectangle, dark text,
   subtle drop shadow. Thicker + larger text than the first pass
   so it reads clearly. The icon tile on the left swaps colour
   between states (orange + spinner while analyzing, green + check
   when findings land) so the chip itself acts as the visible
   "agent is working / agent is done" signal. */
.lv-vel-chip {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 11px 20px 11px 11px;
  background: #fff;
  color: #1B2D1A;
  border-radius: 14px;
  font-family: var(--f-sans);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.006em;
  white-space: nowrap;
  max-width: calc(100% - 28px);
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.04),
    0 16px 40px -10px rgba(0,0,0,0.58),
    0 2px 8px rgba(0,0,0,0.22);
  animation: lv-vel-chip-in .35s cubic-bezier(.22,1,.36,1);
  z-index: 5;
}
@keyframes lv-vel-chip-in {
  from { opacity: 0; transform: translate(-50%, -50%) scale(0.92); }
  to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

/* Analyzing tile — brand-orange gradient square with a white
   loading spinner inside. The rotating ring makes the "analysis
   in progress" beat visible the instant the chip swaps to a
   new document. */
.lv-vel-chip-spinner {
  width: 32px; height: 32px;
  border-radius: 8px;
  background: linear-gradient(135deg, var(--accent) 0%, #E63300 100%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  box-shadow:
    0 0 0 1px rgba(255,255,255,0.18) inset,
    0 0 0 3px rgba(255,61,0,0.16);
}
.lv-vel-chip-spinner::before {
  content: "";
  width: 16px; height: 16px;
  border: 2px solid rgba(255,255,255,0.32);
  border-top-color: #fff;
  border-radius: 50%;
  animation: lv-vel-chip-spin .7s linear infinite;
}
@keyframes lv-vel-chip-spin {
  to { transform: rotate(360deg); }
}

/* Findings tile — green square with a white check inside.
   Same 32×32 dimensions as the analyzing tile so the chip
   width stays steady between states. */
.lv-vel-chip-check {
  width: 32px; height: 32px;
  border-radius: 8px;
  background: rgb(60, 180, 100);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  box-shadow:
    0 0 0 1px rgba(255,255,255,0.16) inset,
    0 0 0 3px rgba(60,180,100,0.16);
}
.lv-vel-chip-check svg { width: 14px; height: 14px; }

/* ---------- VP5 · Visibility (lv-vis) ---------------------------
   Report-style dashboard. Hero "cash collected" headline with vs.-
   prior trend, six-month bar chart, divider, KPI strip below with
   DSO + 30d forecast. Reads like a CFO's monthly review.
   The current-month bar uses a hatched fill so the viewer reads
   it as "in progress, not the final number." */
.lv-vis {
  padding: 22px 24px 20px;
}
.lv-vis-strip {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--f-mono);
  font-size: 10.5px;
  letter-spacing: 0.08em;
  color: rgba(255,255,255,0.6);
  margin-bottom: 14px;
}
.lv-vis-strip-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px rgba(255,61,0,0.18);
  animation: lv-vel-pulse 1.6s ease-in-out infinite;
}

.lv-vis-hero { margin-bottom: 18px; }
.lv-vis-hero-label {
  font-size: 13px;
  color: rgba(255,255,255,0.62);
  margin-bottom: 6px;
  letter-spacing: -0.003em;
}
.lv-vis-hero-row {
  display: flex; align-items: baseline; gap: 12px;
  flex-wrap: wrap;
}
.lv-vis-hero-val {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 38px;
  letter-spacing: -0.03em;
  color: var(--paper);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
/* Match Supercharge's trend pill exactly — same green halo
   (rgba(60,180,100,0.15) background), same pale mint text
   (rgb(170,225,180)), same pill geometry. So the two cards
   feel like part of one design system. */
.lv-vis-hero-trend {
  display: inline-flex; align-items: center;
  padding: 4px 10px;
  background: rgba(60,180,100,0.15);
  color: rgb(170,225,180);
  border-radius: 999px;
  font-family: var(--f-sans);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0;
}

/* Bar chart — 6 monthly bars. Heights derived from data inline
   via style; widths split evenly via flex. Value label sits above
   each bar, month label below. */
/* Chart taller (180px bar area + label row) and month labels live
   OUTSIDE the bar stack now, in a dedicated row beneath each
   column. Heights animate via the existing transition when the
   parent state cycles A↔B. */
.lv-vis-chart {
  display: flex; align-items: stretch;
  gap: 12px;
  height: 196px;
  padding: 14px 2px 0;
}
.lv-vis-col {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: stretch;
}
.lv-vis-bar-stack {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 0;
}
.lv-vis-bar {
  width: 100%;
  background: linear-gradient(
    to top,
    var(--accent) 0%,
    color-mix(in oklab, var(--accent) 70%, white) 100%
  );
  border-radius: 6px 6px 3px 3px;
  /* CORE morph — bar heights smoothly transition between the two
     state snapshots whenever React updates the inline style. */
  transition: height 1.2s cubic-bezier(.4, 0, .2, 1);
}
/* Current-month bar: hatched stripes signal "in-progress /
   month-to-date, not the final number." */
.lv-vis-bar--current {
  background:
    repeating-linear-gradient(
      135deg,
      var(--accent) 0,
      var(--accent) 4px,
      color-mix(in oklab, var(--accent) 50%, transparent) 4px,
      color-mix(in oklab, var(--accent) 50%, transparent) 8px
    );
  opacity: 0.9;
}
.lv-vis-bar-label {
  font-family: var(--f-mono);
  font-size: 10.5px;
  letter-spacing: 0.04em;
  color: rgba(255,255,255,0.45);
  text-align: center;
  margin-top: 10px;
  flex-shrink: 0;
}

.lv-vis-divider {
  height: 1px;
  background: rgba(255,255,255,0.08);
  margin: 18px 0 14px;
}

/* 3-column KPI grid (was 2): DSO · Forecast · At risk. Each
   column is purposefully spare — label, value, single short
   trend chip — so the strip reads at a glance. */
.lv-vis-kpis {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 14px;
}
.lv-vis-kpi { display: flex; flex-direction: column; gap: 4px; }
/* Less technical KPI label: sentence case, sans-serif (not mono
   uppercase). Matches Supercharge's "Outstanding receivables"
   label voice instead of the dashboard-y "AT RISK" / "FORECAST"
   uppercase look. */
.lv-vis-kpi-label {
  font-family: var(--f-sans);
  font-size: 12px;
  letter-spacing: -0.003em;
  color: rgba(255,255,255,0.55);
}
.lv-vis-kpi-val {
  font-family: var(--f-display);
  font-weight: 700;
  font-size: 24px;
  letter-spacing: -0.022em;
  color: var(--paper);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  margin-top: 4px;
}
/* Same pale mint as Supercharge's pill text, but plain inline
   here — three pills in a 3-column strip would be heavy. */
.lv-vis-kpi-trend {
  font-family: var(--f-sans);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: -0.003em;
  color: rgb(170, 225, 180);
  margin-top: 6px;
}

@media (max-width: 720px) {
  .loop-section { padding: 72px 0; }
  /* keep square ratio on mobile too */
  .loop-card-inner { padding: 24px; }
  .lv-pair { grid-template-columns: 1fr; }
  .lv-arrow { transform: rotate(90deg); }
  .lv-vel-hero { font-size: 52px; }
  .lv-vis-hero-val { font-size: 32px; }
  .lv-vis-chart { height: 108px; }
}

/* ---------- Use Cases block (sits inside .does section, above Stage) ---------- */
.uc {
  margin-top: 64px;
  margin-bottom: 32px;
}
.uc-grid {
  display: grid;
  /* Right card is now noticeably larger than the left list, with a
     bigger gap between them per user feedback. Left column shrunk by
     ~1/4 (was 1fr, now 0.8fr); right grew slightly (1.05fr -> 1.25fr). */
  grid-template-columns: 0.8fr 1.25fr;
  gap: 64px;
  align-items: start;
}
@media (max-width: 900px) {
  .uc-grid { grid-template-columns: 1fr; gap: 32px; }
}

/* accordion (left) – cleaner, static (no hover effect per user
   feedback). Display-font titles, no number bubble, soft open state
   via orange left bar + accent title color. */
.uc-left { display: flex; flex-direction: column; gap: 2px; }
.uc-step {
  appearance: none;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  background: transparent;
  padding: 18px 4px 18px 18px;
  text-align: left;
  cursor: pointer;
  font-family: var(--f-sans);
  color: var(--ink);
  transition: none;
  display: block;
  width: 100%;
  position: relative;
}
.uc-step:first-child { border-top: 1px solid var(--line); }
.uc-step:hover { background: transparent; }
.uc-step.is-open {
  background: transparent;
}
.uc-step::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 2px;
  background: transparent;
  transition: background .15s ease;
}
.uc-step.is-open::before { background: var(--accent); }
.uc-step-head {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 16px;
  align-items: center;
}
.uc-step-tt { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.uc-step-title {
  /* Display font for a slightly editorial feel that fits the brand
     voice (Inter Tight 500). Larger so labels read as the main
     content of the left column. */
  font-family: var(--f-display);
  font-size: 21px;
  font-weight: 500;
  letter-spacing: -0.018em;
  line-height: 1.15;
  color: var(--ink);
}
.uc-step.is-open .uc-step-title { color: var(--accent); }
.uc-step-sub {
  font-size: 13.5px;
  color: var(--ink-3);
  line-height: 1.45;
}
/* Sub-line stays in its gray tone whether open or closed – it's the
   always-visible "label" line. Only the body that pops in on click
   gets a different (darker) color so there's a clear visual
   difference between the two. */
.uc-step-chev {
  font-family: var(--f-mono);
  font-size: 20px;
  line-height: 1;
  color: var(--ink-3);
  align-self: center;
}
.uc-step.is-open .uc-step-chev { color: var(--accent); }
.uc-step-body {
  margin-top: 10px;
  font-size: 14px;
  line-height: 1.55;
  /* Darker ink than the gray sub-line above, so the pop-in body is
     visually distinct from the always-visible label. */
  color: var(--ink);
  max-width: 38ch;
}
.uc-step-body p { margin: 0; }

.uc-right .loop-card { width: 100%; }

/* === per-agent vizes (v2 — domain-real, less mono, more anim) === */

/* base override: vizes here use a slightly larger card and softer
   chrome than the Loop vizes so they read as "product surfaces" the
   user could actually mistake for the real thing. */
.uc-right .lv {
  font-family: var(--f-sans);
  max-width: 480px;
  border-radius: 16px;
  background: rgba(18,18,20,0.96);
  border: 1px solid rgba(255,255,255,0.06);
  box-shadow:
    0 24px 60px -24px rgba(20,8,2,0.55),
    0 2px 10px rgba(0,0,0,0.30);
}

/* shared tick */
.ucv-tick {
  display: inline-flex;
  align-items: center; justify-content: center;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: rgb(60,180,100);
  color: white;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
}
.ucv-tick--green { background: rgb(60,180,100); }
.ucv-tick--warn  { background: var(--accent); color: white; font-weight: 700; }

/* shared confirmation toast – used by Collections (and reusable
   anywhere we need a centered "operation succeeded" screen) */
.ucv-toast {
  text-align: center;
  padding: 48px 32px;
  display: flex; flex-direction: column; align-items: center; gap: 12px;
}
.ucv-toast-seal {
  width: 56px; height: 56px;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 6px;
  animation: ucv-toast-seal-in .55s cubic-bezier(.16,1,.3,1) both;
}
@keyframes ucv-toast-seal-in {
  from { opacity: 0; transform: scale(0.6); }
  to   { opacity: 1; transform: scale(1);   }
}
.ucv-toast-title {
  font-size: 19px;
  font-weight: 600;
  color: var(--paper);
  letter-spacing: -0.012em;
  animation: ucv-row-in .5s ease-out .25s both;
}
.ucv-toast-sub {
  font-size: 13px;
  color: rgba(255,255,255,0.65);
  max-width: 30ch;
  animation: ucv-row-in .5s ease-out .4s both;
}

/* CountUp helper – ensure numeric digits don't reflow */
.count-up { font-variant-numeric: tabular-nums; }

/* ---------- 1. Collections (email client) ---------- */
.ucv-mail { padding: 0; }
.ucv-mail-head {
  padding: 18px 20px 14px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}
.ucv-mail-from {
  display: flex; align-items: center; gap: 12px;
  margin-bottom: 12px;
}
.ucv-mail-avatar {
  position: relative;
  width: 38px; height: 38px;
  border-radius: 50%;
  background:
    radial-gradient(120% 100% at 30% 25%, #6b7280 0%, #374151 60%, #1f2937 100%);
  color: white;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.ucv-mail-avatar-initials {
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.02em;
}
.ucv-mail-avatar-badge {
  position: absolute;
  bottom: -2px; right: -2px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: rgb(60,180,100);
  border: 2px solid rgba(18,18,20,1);
  display: flex; align-items: center; justify-content: center;
}
.ucv-mail-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ucv-mail-to {
  font-size: 13px;
  color: rgba(255,255,255,0.7);
}
.ucv-mail-to strong { color: var(--paper); font-weight: 500; }
.ucv-mail-from-line { font-size: 11.5px; color: rgba(255,255,255,0.45); }
.ucv-mail-subj {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--paper);
}
.ucv-mail-body {
  padding: 16px 20px;
  min-height: 150px;
  position: relative;
}
.ucv-mail-line {
  margin: 0 0 4px;
  font-size: 13.5px;
  line-height: 1.5;
  color: rgba(255,255,255,0.88);
  opacity: 0;
  clip-path: inset(0 100% 0 0);
  /* Slower duration + smoother cubic-bezier + simultaneous opacity
     fade so each line glides in instead of snapping. */
  animation: ucv-typeline-reveal 0.85s cubic-bezier(.22, .61, .36, 1) forwards;
  will-change: clip-path, opacity;
}
/* Slightly wider gaps between lines so overlap is comfortable
   instead of crammed; total still settles by ~3.6s. */
.ucv-mail-line--1 { animation-delay: 0.30s; }
.ucv-mail-line--2 { animation-delay: 0.85s; }
.ucv-mail-line--3 { animation-delay: 1.35s; }
.ucv-mail-line--4 { animation-delay: 1.85s; }
.ucv-mail-line--5 { animation-delay: 2.55s; }
.ucv-mail-line--6 { animation-delay: 2.85s; }
@keyframes ucv-typeline-reveal {
  0%   { opacity: 0; clip-path: inset(0 100% 0 0); }
  20%  { opacity: 1; }
  100% { opacity: 1; clip-path: inset(0 0 0 0); }
}
/* Email-style breathing room: blank line after the greeting (line 1)
   and another before the signoff (line 5 = 'Best,' / 'Thanks,').
   Lines 5+6 stay tight together as the signoff block. */
.ucv-mail-line--1 { margin-bottom: 14px; }
.ucv-mail-line--4 { margin-bottom: 14px; }
.ucv-mail-line--5 { margin-bottom: 0; }
.ucv-mail-attach {
  margin-top: 14px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px 8px 8px;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px;
  font-size: 12.5px;
  color: rgba(255,255,255,0.88);
  opacity: 0;
  transform: translateY(8px);
  animation: ucv-attach-slide-in 0.55s cubic-bezier(.22, .61, .36, 1) 3.8s forwards;
}
@keyframes ucv-attach-slide-in {
  to { opacity: 1; transform: translateY(0); }
}
.ucv-mail-attach-ico {
  display: inline-flex;
  align-items: center; justify-content: center;
  width: 28px; height: 28px;
  border-radius: 6px;
  background: rgba(255,61,0,0.20);
  color: var(--accent);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
}
.ucv-mail-attach-name { font-weight: 500; }
.ucv-mail-attach-size { color: rgba(255,255,255,0.5); font-size: 11.5px; }
.ucv-mail-foot {
  position: relative;
  padding: 14px 20px;
  border-top: 1px solid rgba(255,255,255,0.06);
  display: flex; justify-content: flex-end;
}
.ucv-mail-send {
  position: relative;
  min-width: 130px;
  height: 36px;
  border-radius: 8px;
  background: var(--accent);
  color: var(--paper);
  font-weight: 500;
  font-size: 13px;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  /* button compresses briefly when "clicked" by the cursor at 82% of
     the 7.5s compose phase (~6.15s) */
  animation: ucv-mail-send-press 7.5s ease-out forwards;
}
@keyframes ucv-mail-send-press {
  0%, 81% { transform: scale(1); }
  82%, 83% { transform: scale(0.96); }
  84%, 100% { transform: scale(1); }
}
.ucv-mail-send-label {
  display: inline-block;
  /* fades out just after the click compress so the spinner can take
     over the button surface */
  animation: ucv-mail-label-out 7.5s ease-out forwards;
}
@keyframes ucv-mail-label-out {
  0%, 84% { opacity: 1; }
  86%, 100% { opacity: 0; }
}
.ucv-mail-send-spinner {
  position: absolute;
  width: 16px; height: 16px;
  border: 2px solid rgba(255,255,255,0.35);
  border-top-color: rgba(255,255,255,0.98);
  border-radius: 50%;
  opacity: 0;
  /* two simultaneous animations: opacity fade-in tied to the master
     7.5s timeline, plus a continuous spin */
  animation:
    ucv-mail-spinner-in 7.5s ease-out forwards,
    ucv-mail-spinner-spin 0.7s linear infinite;
}
@keyframes ucv-mail-spinner-in {
  0%, 84% { opacity: 0; }
  88%, 100% { opacity: 1; }
}
@keyframes ucv-mail-spinner-spin {
  to { transform: rotate(360deg); }
}

/* Cursor that flies in from below-right and clicks the Send button.
   Anchored to the bottom-right of .ucv-mail-foot, so the resting
   position (transform 0,0) sits roughly over the Send label. */
.ucv-mail-cursor {
  position: absolute;
  bottom: 18px;
  right: 84px;
  width: 22px; height: 22px;
  z-index: 4;
  pointer-events: none;
  opacity: 0;
  filter: drop-shadow(0 2px 6px rgba(0,0,0,0.55));
  animation: ucv-mail-cursor-path 7.5s ease-out forwards;
  will-change: transform, opacity;
}
@keyframes ucv-mail-cursor-path {
  0%, 60%  { opacity: 0; transform: translate(70px, 50px); }
  68%      { opacity: 1; transform: translate(40px, 26px); }
  80%      { opacity: 1; transform: translate(0, 0) scale(1); }
  82%      { opacity: 1; transform: translate(0, 0) scale(0.82); }
  86%      { opacity: 1; transform: translate(0, 0) scale(1); }
  100%     { opacity: 1; transform: translate(0, 0); }
}

/* warn variants for Cash App second screen */
.ucv-bank-check--warn {
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--accent);
  color: white;
  font-weight: 700;
  font-size: 11px;
  display: inline-flex; align-items: center; justify-content: center;
}
.ucv-bank-row--gap {
  background: rgba(255,61,0,0.10) !important;
  border-color: rgba(255,61,0,0.30) !important;
}
.ucv-bank-row-amt--warn { color: var(--accent) !important; }
.ucv-bank-confirm--warn {
  background: rgba(255,61,0,0.10) !important;
  border-color: rgba(255,61,0,0.30) !important;
  color: rgb(255,180,140) !important;
}

/* ---------- 1c. Collections — Slack thread (3rd Collections phase)
   Modeled on the user's screenshot: channel name + badges at top,
   Kasdor message with attached invoice card, then the customer's
   reply slides in highlighted with an orange accent. Closes with
   a green 'Payment expected' verification chip. */
.ucv-slack { padding: 0; }
.ucv-slack-head {
  padding: 14px 18px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}
.ucv-slack-channel {
  display: flex; align-items: center; gap: 8px;
  font-size: 14px;
  font-weight: 600;
  color: var(--paper);
  letter-spacing: -0.005em;
  margin-bottom: 10px;
}
.ucv-slack-hash {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px;
  font-size: 13px;
  font-weight: 700;
  color: rgba(255,255,255,0.55);
}
.ucv-slack-name { color: var(--paper); }
.ucv-slack-badges {
  display: flex; flex-wrap: wrap; gap: 6px;
}
.ucv-slack-badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 10.5px;
  padding: 3px 8px;
  background: rgba(255,255,255,0.06);
  color: rgba(255,255,255,0.78);
  border-radius: 5px;
  letter-spacing: -0.005em;
  white-space: nowrap;
}
.ucv-slack-badge--active {
  background: rgba(60,180,100,0.18);
  color: rgb(170,225,180);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.ucv-slack-badge--platform {
  /* Slack — aubergine */
  background: rgba(74,21,75,0.45);
  color: rgba(255,255,255,0.92);
}
.ucv-slack-badge--teams {
  /* Microsoft Teams — indigo */
  background: rgba(70,78,184,0.45);
  color: rgba(255,255,255,0.92);
}
.ucv-slack-glyph {
  display: inline-block;
  width: 13px; height: 13px;
  object-fit: contain;
}

.ucv-slack-thread {
  padding: 14px 18px 16px;
  display: flex; flex-direction: column;
  gap: 12px;
}
.ucv-slack-msg {
  display: grid;
  grid-template-columns: 32px 1fr;
  gap: 10px;
}
.ucv-slack-msg--out {
  opacity: 0;
  transform: translateY(6px);
  animation: ucv-row-in 0.5s ease-out 0.3s forwards;
}
.ucv-slack-msg--in {
  opacity: 0;
  transform: translateY(6px);
  /* arrives at 4.0s — the "they responded" beat */
  animation: ucv-row-in 0.55s cubic-bezier(.16,1,.3,1) 4.0s forwards;
  /* highlighted reply bubble */
  margin: 4px -4px 0;
  padding: 8px 8px 8px 6px;
  background: rgba(255,61,0,0.06);
  border-left: 3px solid var(--accent);
  border-radius: 0 8px 8px 0;
}
.ucv-slack-avatar {
  width: 32px; height: 32px;
  border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px;
  font-weight: 600;
  color: white;
  overflow: hidden;
}
.ucv-slack-avatar--bot {
  background: transparent;
  padding: 0;
}
.ucv-slack-avatar--bot img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.ucv-slack-avatar--person {
  background: linear-gradient(135deg, #a78bfa 0%, #7c3aed 100%);
  font-size: 11.5px;
  letter-spacing: 0.02em;
}
.ucv-slack-body { min-width: 0; }
.ucv-slack-msg-head {
  display: flex; align-items: baseline; gap: 6px;
  margin-bottom: 3px;
}
.ucv-slack-msg-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--paper);
}
.ucv-slack-msg-bot {
  font-family: var(--f-mono);
  font-size: 9.5px;
  font-weight: 700;
  padding: 1px 5px;
  background: rgba(255,255,255,0.10);
  color: rgba(255,255,255,0.70);
  border-radius: 3px;
  letter-spacing: 0.08em;
}
.ucv-slack-msg-handle {
  font-size: 11.5px;
  color: rgba(255,255,255,0.55);
}
.ucv-slack-msg-time {
  margin-left: auto;
  font-size: 10.5px;
  color: rgba(255,255,255,0.45);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ucv-slack-msg-text {
  font-size: 12.5px;
  line-height: 1.5;
  color: rgba(255,255,255,0.85);
}
.ucv-slack-msg-text--reply {
  color: var(--paper);
  font-weight: 500;
}

.ucv-slack-inv {
  margin-top: 8px;
  padding: 10px 12px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 8px;
  opacity: 0;
  transform: translateY(4px);
  animation: ucv-row-in 0.5s ease-out 1.4s forwards;
}
.ucv-slack-inv-head {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 4px;
}
.ucv-slack-inv-id {
  font-family: var(--f-mono);
  font-size: 11px;
  color: rgba(255,255,255,0.65);
  letter-spacing: 0.04em;
}
.ucv-slack-inv-due {
  font-size: 10.5px;
  color: rgba(255,255,255,0.55);
}
.ucv-slack-inv-amount {
  font-family: var(--f-display);
  font-size: 19px;
  font-weight: 600;
  color: var(--paper);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.ucv-slack-inv-detail {
  font-size: 11.5px;
  color: rgba(255,255,255,0.55);
  margin-top: 2px;
}

.ucv-slack-verify {
  margin-top: 6px;
  padding: 10px 12px;
  background: rgba(60,180,100,0.10);
  border: 1px solid rgba(60,180,100,0.30);
  border-radius: 8px;
  font-size: 12px;
  color: rgb(170,225,180);
  display: flex; align-items: center; gap: 8px;
  font-weight: 500;
  opacity: 0;
  transform: translateY(6px);
  /* fires after the customer reply has had a beat to register */
  animation: ucv-row-in 0.55s cubic-bezier(.16,1,.3,1) 6.0s forwards;
}

/* ---------- 2. Cash Application (bank matching) ---------- */
.ucv-bank { padding: 22px 22px 20px; }
/* Agent attribution strip at the top — makes the multi-agent
   story visible: which Kasdor agent handled the match, and where
   the unhappy-path got routed. Reads "Cash application agent ·
   2 matched · 1 routed to dispute agent" so the user sees
   workload moving between agents, not a passive ERP log. */
.ucv-bank-agent {
  display: flex; align-items: center; gap: 9px;
  padding: 9px 12px;
  margin-bottom: 14px;
  background: rgba(255,61,0,0.05);
  border: 1px solid rgba(255,61,0,0.16);
  border-radius: 8px;
  font-family: var(--f-sans);
  font-size: 11.5px;
  color: rgba(255,255,255,0.78);
  letter-spacing: -0.003em;
}
.ucv-bank-agent strong {
  font-weight: 600;
  color: var(--paper);
}
.ucv-bank-agent-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px rgba(255,61,0,0.18);
  flex-shrink: 0;
}
/* Header now uses the empty right-of-amount space for the payer
   info, instead of dropping the customer line below the amount.
   The right column tops align with the left label so the two
   blocks read in parallel. */
.ucv-bank-head {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 16px;
  align-items: start;
  margin-bottom: 14px;
}
.ucv-bank-head-right {
  text-align: right;
  display: flex; flex-direction: column;
  gap: 2px;
  /* nudge down so the customer name baseline-aligns with the big
     amount number rather than the small 'Incoming payment' label */
  padding-top: 18px;
}
.ucv-bank-from-label {
  font-size: 11.5px;
  color: rgba(255,255,255,0.45);
  letter-spacing: -0.005em;
  margin-bottom: 1px;
}
.ucv-bank-from-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--paper);
  letter-spacing: -0.012em;
}
.ucv-bank-from-meta {
  font-size: 11.5px;
  color: rgba(255,255,255,0.55);
  font-variant-numeric: tabular-nums;
}
.ucv-bank-label {
  font-size: 12.5px;
  color: rgba(255,255,255,0.55);
  letter-spacing: -0.005em;
  margin-bottom: 4px;
}
.ucv-bank-amount {
  display: flex; align-items: baseline; gap: 2px;
  color: var(--paper);
  font-family: var(--f-display);
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.ucv-bank-currency { font-size: 22px; opacity: 0.7; margin-right: 4px; }
.ucv-bank-num { font-size: 38px; font-weight: 500; }
.ucv-bank-cents { font-size: 22px; opacity: 0.7; }
.ucv-bank-divider {
  display: flex; align-items: center;
  gap: 10px;
  margin: 12px 0;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.4);
}
.ucv-bank-divider::before,
.ucv-bank-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: rgba(255,255,255,0.10);
}
.ucv-bank-matches { display: flex; flex-direction: column; gap: 8px; }
.ucv-bank-row {
  display: grid;
  grid-template-columns: 24px 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.05);
  border-radius: 10px;
  font-size: 13px;
  color: rgba(255,255,255,0.88);
  opacity: 0;
  transform: translateY(6px);
  animation: ucv-row-in 1s ease-out forwards;
}
.ucv-bank-row--1 { animation-delay: 0.5s; }
.ucv-bank-row--2 { animation-delay: 1.1s; }
.ucv-bank-row--3 { animation-delay: 1.7s; }
@keyframes ucv-row-in {
  to { opacity: 1; transform: translateY(0); }
}
.ucv-bank-check {
  display: inline-flex; align-items: center; justify-content: center;
}
.ucv-bank-check .ucv-tick {
  background: rgb(60,180,100);
  opacity: 0;
  animation: ucv-tick-in 0.6s cubic-bezier(.16,1,.3,1) forwards;
}
.ucv-bank-row--1 .ucv-tick { animation-delay: 0.9s; }
.ucv-bank-row--2 .ucv-tick { animation-delay: 1.5s; }
.ucv-bank-row--3 .ucv-tick { animation-delay: 2.1s; }
@keyframes ucv-tick-in {
  from { opacity: 0; transform: scale(0.4); }
  to   { opacity: 1; transform: scale(1);   }
}
.ucv-bank-row-amt {
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  color: var(--paper);
}
.ucv-bank-confirm {
  margin-top: 14px;
  padding: 10px 12px;
  background: rgba(60,180,100,0.12);
  border: 1px solid rgba(60,180,100,0.35);
  border-radius: 10px;
  font-size: 12.5px;
  color: rgb(170,225,180);
  display: flex; align-items: center; gap: 8px;
  opacity: 0;
  animation: ucv-row-in 0.6s ease-out 2.6s forwards;
}

/* ---------- 3. Invoice Delivery (logo-left list) ---------- */
.ucv-deliv { padding: 22px 22px 20px; }
.ucv-deliv-h {
  font-size: 12.5px;
  color: rgba(255,255,255,0.55);
  margin-bottom: 16px;
  letter-spacing: -0.005em;
}
/* Row layout left → right: check · customer name · procurement
   system (right-aligned, just left of the logo) · logo on the
   far right. */
.ucv-deliv-row {
  display: grid;
  grid-template-columns: 22px auto 1fr 40px;
  gap: 14px;
  align-items: center;
  padding: 14px 16px;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 12px;
  margin-bottom: 8px;
  opacity: 0;
  transform: translateY(8px);
  animation: ucv-row-in 0.55s ease-out forwards;
}
.ucv-deliv-row:last-child { margin-bottom: 0; }
.ucv-deliv-row--1 { animation-delay: 0.15s; }
.ucv-deliv-row--2 { animation-delay: 0.55s; }
.ucv-deliv-row--3 { animation-delay: 0.95s; }
.ucv-deliv-row--4 { animation-delay: 1.35s; }
.ucv-deliv-check { display: inline-flex; justify-content: center; }
.ucv-deliv-check .ucv-tick {
  opacity: 0;
  animation: ucv-tick-in 0.5s cubic-bezier(.16,1,.3,1) forwards;
}
.ucv-deliv-row--1 .ucv-tick { animation-delay: 0.55s; }
.ucv-deliv-row--2 .ucv-tick { animation-delay: 0.95s; }
.ucv-deliv-row--3 .ucv-tick { animation-delay: 1.35s; }
.ucv-deliv-row--4 .ucv-tick { animation-delay: 1.75s; }
.ucv-deliv-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--paper);
  letter-spacing: -0.005em;
  white-space: nowrap;
}
.ucv-deliv-where {
  font-size: 12px;
  color: rgba(255,255,255,0.6);
  text-align: right;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ucv-deliv-tile {
  width: 38px; height: 38px;
  border-radius: 9px;
  color: white;
  font-size: 14px;
  font-weight: 800;
  letter-spacing: 0.03em;
  display: flex; align-items: center; justify-content: center;
  text-transform: uppercase;
  overflow: hidden;
}
.ucv-deliv-tile--logo {
  background: rgba(255,255,255,0.06);
}
.ucv-deliv-tile--logo img {
  width: 100%; height: 100%;
  object-fit: contain;
  display: block;
}

/* ---------- Billing & Invoicing: inputs → invoice ---------- */
.ucv-bill { padding: 20px 22px 20px; }
.ucv-bill-h {
  font-size: 12.5px;
  color: rgba(255,255,255,0.55);
  margin-bottom: 14px;
  letter-spacing: -0.005em;
}
.ucv-bill-src-wrap { display: flex; flex-wrap: wrap; gap: 7px; }
.ucv-bill-src {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 10px 6px 7px;
  font-size: 12px;
  color: var(--paper);
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 9px;
  white-space: nowrap;
  opacity: 0; transform: translateY(6px);
  animation: ucv-row-in 0.5s ease-out forwards;
}
.ucv-bill-src .ucv-tick { width: 14px; height: 14px; font-size: 9px; }
.ucv-bill-src--1 { animation-delay: 0.10s; }
.ucv-bill-src--2 { animation-delay: 0.25s; }
.ucv-bill-src--3 { animation-delay: 0.40s; }
.ucv-bill-src--4 { animation-delay: 0.55s; }

.ucv-bill-arrow { display: flex; justify-content: center; margin: 12px 0; }
.ucv-bill-arrow span {
  width: 1.5px; height: 18px;
  background: linear-gradient(rgba(255,255,255,0.30), rgba(255,255,255,0.04));
  transform-origin: top; transform: scaleY(0);
  animation: ucv-bill-grow 0.4s ease-out forwards; animation-delay: 0.7s;
}
@keyframes ucv-bill-grow { to { transform: scaleY(1); } }

.ucv-bill-doc {
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 12px;
  padding: 14px 16px;
  opacity: 0; transform: translateY(8px);
  animation: ucv-row-in 0.55s ease-out forwards; animation-delay: 0.85s;
}
.ucv-bill-doc-h {
  display: flex; align-items: baseline; justify-content: space-between;
  padding-bottom: 10px; margin-bottom: 8px;
  border-bottom: 1px solid rgba(255,255,255,0.07);
}
.ucv-bill-doc-id { font-family: var(--f-mono); font-size: 11.5px; color: rgba(255,255,255,0.55); letter-spacing: 0.04em; }
.ucv-bill-doc-cust { font-size: 13px; font-weight: 600; color: var(--paper); }
.ucv-bill-line {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 12.5px; padding: 4px 0;
  opacity: 0; transform: translateY(5px);
  animation: ucv-row-in 0.45s ease-out forwards;
}
.ucv-bill-line--1 { animation-delay: 1.15s; }
.ucv-bill-line--2 { animation-delay: 1.40s; }
.ucv-bill-line--3 { animation-delay: 1.65s; }
.ucv-bill-line-d { color: rgba(255,255,255,0.72); }
.ucv-bill-line-a { font-family: var(--f-mono); color: var(--paper); white-space: nowrap; }
.ucv-bill-total {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 10px; padding-top: 10px;
  border-top: 1px solid rgba(255,255,255,0.07);
  font-size: 12px; color: rgba(255,255,255,0.6);
  opacity: 0; transform: scale(0.96);
  animation: ucv-bill-pop 0.5s cubic-bezier(.16,1,.3,1) forwards; animation-delay: 2.0s;
}
.ucv-bill-total-amt { font-family: var(--f-mono); font-size: 16px; font-weight: 700; color: var(--paper); }
.ucv-bill-issued {
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 12px; font-size: 12px; font-weight: 600; color: rgb(60,180,100);
  opacity: 0; transform: scale(0.96);
  animation: ucv-bill-pop 0.45s cubic-bezier(.16,1,.3,1) forwards; animation-delay: 2.3s;
}
.ucv-bill-issued .ucv-tick { width: 14px; height: 14px; font-size: 9px; }
@keyframes ucv-bill-pop { to { opacity: 1; transform: scale(1); } }

/* ---------- 4. Billing Support (chat thread) ---------- */
.ucv-chat { padding: 18px 20px 16px; }
.ucv-chat-h {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  letter-spacing: -0.005em;
  margin-bottom: 14px;
  display: flex; align-items: center; gap: 8px;
}
.ucv-chat-channel {
  width: 18px; height: 18px;
  object-fit: contain;
  display: block;
  flex-shrink: 0;
}
.ucv-chat-msg {
  display: flex;
  gap: 10px;
  margin-bottom: 12px;
}
.ucv-chat-avatar {
  flex-shrink: 0;
  width: 32px; height: 32px;
  /* Square with subtle rounded corners (was border-radius: 50%
     which clipped the Kasdor logo into a circle). Square tile
     lets the full brand mark show + matches the Slack-style
     avatars in the Collections viz. */
  border-radius: 7px;
  display: flex; align-items: center; justify-content: center;
  color: white;
  font-size: 12px;
  font-weight: 600;
  overflow: hidden;
}
.ucv-chat-avatar--in  { background: rgba(255,255,255,0.12); color: var(--paper); }
.ucv-chat-avatar--out {
  /* The kasdor-favicon.png is already an orange-background + white-
     arches brand mark. Show it as-is (no background, no padding,
     no invert filter) so the actual logo reads, not a white blob. */
  background: transparent;
  padding: 0;
  overflow: hidden;
}
.ucv-chat-avatar--out img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.ucv-chat-bubble {
  flex: 1;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.07);
  border-radius: 12px;
  padding: 10px 14px;
}
.ucv-chat-msg--out .ucv-chat-bubble {
  background: rgba(255,61,0,0.08);
  border-color: rgba(255,61,0,0.20);
  opacity: 0;
  transform: translateY(8px);
  animation: ucv-row-in 0.55s ease-out 1.4s forwards;
}
.ucv-chat-name {
  font-size: 11.5px;
  color: rgba(255,255,255,0.55);
  margin-bottom: 3px;
}
.ucv-chat-body {
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--paper);
}
.ucv-chat-attach {
  margin-top: 10px;
  display: inline-flex;
  align-items: center; gap: 10px;
  padding: 7px 11px 7px 7px;
  background: rgba(0,0,0,0.25);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 8px;
  font-size: 12.5px;
  color: rgba(255,255,255,0.88);
  opacity: 0;
  transform: translateY(8px);
  animation: ucv-attach-pop 5s ease-out 1.9s infinite;
}
@keyframes ucv-attach-pop {
  0%   { opacity: 0; transform: translateY(8px); }
  20%, 100% { opacity: 1; transform: translateY(0); }
}
.ucv-chat-status {
  margin-top: 8px;
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  display: flex; align-items: center; gap: 8px;
  opacity: 0;
  animation: ucv-row-in 0.5s ease-out 2.4s forwards;
}
/* Stronger "Case resolved" stamp at the end of each billing case */
.ucv-chat-resolved {
  margin-top: 14px;
  padding: 10px 12px;
  background: rgba(60,180,100,0.12);
  border: 1px solid rgba(60,180,100,0.32);
  border-radius: 8px;
  font-size: 12.5px;
  color: rgb(170,225,180);
  display: flex; align-items: center; gap: 8px;
  font-weight: 500;
  opacity: 0;
  animation: ucv-row-in 0.5s ease-out 2.8s forwards;
}

/* ---------- 5. Disputes (case workflow) ---------- */
.ucv-disp { padding: 22px 22px 20px; }
.ucv-disp-customer {
  display: flex; align-items: center; gap: 12px;
  padding-bottom: 14px;
  margin-bottom: 16px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}
.ucv-disp-customer-tile {
  width: 38px; height: 38px;
  border-radius: 9px;
  color: white;
  font-size: 16px;
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.ucv-disp-customer-name { font-size: 15px; font-weight: 600; color: var(--paper); }
.ucv-disp-customer-sub { font-size: 12px; color: rgba(255,255,255,0.55); }

/* Flex row of step columns + connector lines. Each step is a dot
   over a label; lines sit between dots with margin-top so they
   align with the vertical CENTER of the dot (not the centroid of
   dot+label). Animation runs strictly in sequence — each next
   thing waits until the previous thing is fully done. */
.ucv-disp-track {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 20px;
  padding: 0 8px;
}
.ucv-disp-step {
  flex-shrink: 0;
  display: flex; flex-direction: column; align-items: center;
  gap: 8px;
}
.ucv-disp-dot {
  width: 22px; height: 22px;
  border-radius: 50%;
  background: rgba(255,255,255,0.08);
  border: 1.5px solid rgba(255,255,255,0.20);
  display: flex; align-items: center; justify-content: center;
  transition: none;
}
.ucv-disp-check { opacity: 0; display: block; }
.ucv-disp-label {
  font-size: 12px;
  text-align: center;
  color: rgba(255,255,255,0.55);
  letter-spacing: -0.005em;
  white-space: nowrap;
}
.ucv-disp-line {
  flex: 1;
  height: 2px;
  /* 22px dot → vertical center at 11px → 2px line top at 10px aligns
     with center of dot column (dots use flex-start, label below) */
  margin-top: 10px;
  background: rgba(255,255,255,0.10);
  border-radius: 1px;
  position: relative;
  overflow: hidden;
}
.ucv-disp-line > span {
  position: absolute; inset: 0;
  background: rgb(60,180,100);
  transform-origin: left;
  transform: scaleX(0);
}

/* Strict sequential timeline:
     0.5s: step 1 dot turns green + check fades in
     1.0s-2.0s: line 1 fills (only after step 1 is done)
     2.0s: step 2 dot turns green + check
     2.5s-3.5s: line 2 fills (only after step 2 is done)
     3.5s: step 3 dot turns green + check
     4.0s+: resolution card slides in
*/
.ucv-disp-step--1 .ucv-disp-dot   { animation: ucv-disp-dot-done 0.35s ease-out 0.5s forwards; }
.ucv-disp-step--1 .ucv-disp-check { animation: ucv-disp-check-in 0.25s ease-out 0.65s forwards; }
.ucv-disp-step--1 .ucv-disp-label { animation: ucv-disp-lbl-done 0.25s ease-out 0.65s forwards; }

.ucv-disp-line--1 > span { animation: ucv-disp-line-fill 1.0s cubic-bezier(.4,0,.2,1) 1.0s forwards; }

.ucv-disp-step--2 .ucv-disp-dot   { animation: ucv-disp-dot-done 0.35s ease-out 2.0s forwards; }
.ucv-disp-step--2 .ucv-disp-check { animation: ucv-disp-check-in 0.25s ease-out 2.15s forwards; }
.ucv-disp-step--2 .ucv-disp-label { animation: ucv-disp-lbl-done 0.25s ease-out 2.15s forwards; }

.ucv-disp-line--2 > span { animation: ucv-disp-line-fill 1.0s cubic-bezier(.4,0,.2,1) 2.5s forwards; }

.ucv-disp-step--3 .ucv-disp-dot   { animation: ucv-disp-dot-done 0.35s ease-out 3.5s forwards; }
.ucv-disp-step--3 .ucv-disp-check { animation: ucv-disp-check-in 0.25s ease-out 3.65s forwards; }
.ucv-disp-step--3 .ucv-disp-label { animation: ucv-disp-lbl-done 0.25s ease-out 3.65s forwards; }

@keyframes ucv-disp-dot-done {
  to { background: rgb(60,180,100); border-color: rgb(60,180,100); }
}
@keyframes ucv-disp-check-in {
  from { opacity: 0; transform: scale(0.5); }
  to   { opacity: 1; transform: scale(1);   }
}
@keyframes ucv-disp-lbl-done {
  to { color: rgb(170,225,180); }
}
@keyframes ucv-disp-line-fill {
  to { transform: scaleX(1); }
}

.ucv-disp-resolution {
  background: rgba(60,180,100,0.10);
  border: 1px solid rgba(60,180,100,0.30);
  border-radius: 10px;
  padding: 14px 16px;
  opacity: 0;
  transform: translateY(8px);
  /* Slides in only AFTER step 3 (Resolved) is checked at 3.65s,
     giving the workflow a clean handoff feel. */
  animation: ucv-row-in 0.65s cubic-bezier(.16,1,.3,1) 4.1s forwards;
}
.ucv-disp-res-label {
  font-size: 11.5px;
  color: rgba(255,255,255,0.55);
  margin-bottom: 4px;
}
.ucv-disp-res-val {
  font-size: 15px;
  color: var(--paper);
  margin-bottom: 8px;
}
.ucv-disp-res-val strong { font-weight: 600; }
.ucv-disp-res-meta {
  font-size: 12px;
  color: rgb(170,225,180);
  display: flex; align-items: center; gap: 8px;
}

/* ---------- 6. Deductions ---------- */
.ucv-ded { padding: 22px 22px 20px; }
.ucv-ded-customer {
  display: flex; align-items: center; gap: 12px;
  margin-bottom: 16px;
}
.ucv-ded-customer-tile {
  width: 38px; height: 38px;
  border-radius: 9px;
  color: white;
  font-size: 13px;
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  letter-spacing: 0.02em;
  overflow: hidden;
}
.ucv-ded-customer-tile--logo {
  background: transparent;
  padding: 0;
}
.ucv-ded-customer-tile--logo img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.ucv-ded-customer-name { font-size: 15px; font-weight: 600; color: var(--paper); }
.ucv-ded-customer-sub { font-size: 12px; color: rgba(255,255,255,0.55); }

.ucv-ded-delta {
  padding: 16px;
  background: rgba(255,61,0,0.08);
  border: 1px solid rgba(255,61,0,0.22);
  border-radius: 12px;
  margin-bottom: 14px;
}
.ucv-ded-delta-label {
  font-size: 12px;
  color: rgba(255,255,255,0.55);
  margin-bottom: 4px;
}
.ucv-ded-delta-num {
  display: flex; align-items: baseline; gap: 2px;
  color: var(--accent);
  font-family: var(--f-display);
  font-weight: 500;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  margin-bottom: 4px;
}
.ucv-ded-currency { font-size: 22px; opacity: 0.7; margin-right: 4px; }
.ucv-ded-delta-num .count-up { font-size: 38px; }
.ucv-ded-cents { font-size: 22px; opacity: 0.7; }
.ucv-ded-delta-sub { font-size: 12px; color: rgba(255,255,255,0.65); }

.ucv-ded-reasons {
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.05);
  border-radius: 10px;
  padding: 4px 14px;
  margin-bottom: 14px;
}
/* Each reason row animates as a single unit on a one-shot timeline
   (no per-amount tick that caused the 'reload' effect the user
   spotted). Row 1 settles ~2.35s, row 2 ~2.85s, confirmation ~3.4s
   — everything stays static through the rest of the 7.5s phase. */
.ucv-ded-reason-row {
  display: flex; justify-content: space-between;
  padding: 10px 0;
  font-size: 13px;
  color: rgba(255,255,255,0.85);
  border-bottom: 1px solid rgba(255,255,255,0.05);
  opacity: 0;
  transform: translateY(4px);
}
.ucv-ded-reason-row:last-child { border-bottom: 0; }
.ucv-ded-reasons > .ucv-ded-reason-row:nth-child(1) {
  animation: ucv-ded-row-in 0.55s cubic-bezier(.16,1,.3,1) 1.8s forwards;
}
.ucv-ded-reasons > .ucv-ded-reason-row:nth-child(2) {
  animation: ucv-ded-row-in 0.55s cubic-bezier(.16,1,.3,1) 2.3s forwards;
}
@keyframes ucv-ded-row-in {
  to { opacity: 1; transform: translateY(0); }
}
.ucv-ded-rec {
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  color: rgb(170,225,180);
  /* color only — the parent row drives the fade-in */
}
.ucv-ded-confirm {
  padding: 10px 12px;
  background: rgba(60,180,100,0.10);
  border: 1px solid rgba(60,180,100,0.30);
  border-radius: 10px;
  font-size: 12.5px;
  color: rgb(170,225,180);
  display: flex; align-items: center; gap: 8px;
  opacity: 0;
  transform: translateY(6px);
  animation: ucv-ded-row-in 0.7s cubic-bezier(.16,1,.3,1) 3.1s forwards;
}
.ucv-ded-confirm--big {
  padding: 14px 16px;
  font-size: 13px;
  line-height: 1.5;
  align-items: flex-start;
}
.ucv-ded-confirm--big strong { color: rgb(190,235,200); font-weight: 600; }
.ucv-ded-delta--good {
  background: rgba(60,180,100,0.10) !important;
  border-color: rgba(60,180,100,0.30) !important;
}
.ucv-ded-delta-num--good { color: rgb(170,225,180) !important; }

/* ---------- 7. Credit Risk ---------- */
.ucv-cr { padding: 22px 22px 20px; }
.ucv-cr-customer {
  display: flex; align-items: center; gap: 12px;
  margin-bottom: 18px;
}
.ucv-cr-customer-tile {
  width: 38px; height: 38px;
  border-radius: 9px;
  color: white;
  font-size: 16px;
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.ucv-cr-customer-name { font-size: 15px; font-weight: 600; color: var(--paper); }
.ucv-cr-customer-sub { font-size: 12px; color: rgba(255,255,255,0.55); }
/* DSO + Limit + Creditreform all on ONE line (3 columns). Stat
   cards tightened (padding, font sizes) so 3 fit cleanly in the
   480px viz card. */
.ucv-cr-row {
  display: grid; grid-template-columns: 1fr 1fr 1fr;
  gap: 8px;
  margin-bottom: 14px;
}
.ucv-cr-stat {
  padding: 12px 12px;
  background: rgba(255,255,255,0.03);
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 11px;
}
.ucv-cr-stat-label {
  font-size: 11px;
  color: rgba(255,255,255,0.55);
  margin-bottom: 4px;
  letter-spacing: -0.005em;
}
.ucv-cr-stat-val {
  display: flex; align-items: baseline; gap: 3px;
  font-family: var(--f-display);
  font-size: 20px;
  font-weight: 600;
  color: var(--paper);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  margin-bottom: 4px;
}
.ucv-cr-stat-eur { font-size: 14px; opacity: 0.75; margin-right: 2px; }
.ucv-cr-stat-unit { font-size: 13px; opacity: 0.75; }
.ucv-cr-stat-delta {
  font-size: 11px;
  font-family: var(--f-sans);
  font-weight: 600;
  white-space: nowrap;
  letter-spacing: -0.005em;
}
/* Semantic delta colors (per metric, the meaning of the direction
   differs — e.g. DSO ↑ is bad, but Limit ↑ is good. So we tag the
   class by meaning, not by arrow direction.) */
.ucv-cr-stat-delta--bad  { color: var(--accent); }
.ucv-cr-stat-delta--good { color: rgb(170,225,180); }

/* Proposed action card – ink-on-paper feel for visual weight */
.ucv-cr-action {
  display: grid;
  grid-template-columns: 32px 1fr;
  gap: 12px;
  padding: 12px 14px;
  background: rgba(255,61,0,0.10);
  border: 1px solid rgba(255,61,0,0.28);
  border-radius: 12px;
  margin-bottom: 10px;
}
.ucv-cr-action-icon {
  width: 32px; height: 32px;
  border-radius: 8px;
  background: var(--accent);
  color: var(--paper);
  display: flex; align-items: center; justify-content: center;
  font-size: 16px;
}
.ucv-cr-action-title {
  font-size: 11.5px;
  color: rgba(255,255,255,0.55);
  margin-bottom: 3px;
  letter-spacing: -0.005em;
}
.ucv-cr-action-text {
  font-size: 13px;
  color: var(--paper);
  font-weight: 500;
  line-height: 1.4;
}

/* Optimization signals card – modeled on the Bang & Olufsen /
   REWE Group screenshot the user shared. Section header has a
   small numeric badge ('6'). Each signal card has a title row
   (heading + chevron), a meta row (category + confidence), body
   text, and Review/Apply buttons. */
.ucv-cr-sigs {
  margin-top: 4px;
}
.ucv-cr-sigs-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 2px 8px;
  font-size: 12px;
  color: rgba(255,255,255,0.65);
  letter-spacing: -0.005em;
}
.ucv-cr-sigs-count {
  font-family: var(--f-mono);
  font-size: 11px;
  color: rgba(255,255,255,0.55);
  padding: 1px 7px;
  background: rgba(255,255,255,0.06);
  border-radius: 4px;
}
.ucv-cr-sig {
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 12px;
  padding: 12px 14px 12px;
}
.ucv-cr-sig-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px;
}
.ucv-cr-sig-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--paper);
  letter-spacing: -0.005em;
}
.ucv-cr-sig-chev {
  color: rgba(255,255,255,0.55);
  font-size: 14px;
  line-height: 1;
}
.ucv-cr-sig-meta {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 12px;
  margin-top: 3px;
  font-size: 11.5px;
  color: rgba(255,255,255,0.55);
}
.ucv-cr-sig-cat { letter-spacing: -0.005em; }
.ucv-cr-sig-conf {
  font-family: var(--f-mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ucv-cr-sig-body {
  margin-top: 10px;
  font-size: 12.5px;
  line-height: 1.5;
  color: rgba(255,255,255,0.82);
}
.ucv-cr-sig-actions {
  display: flex; justify-content: flex-end; gap: 6px;
  margin-top: 12px;
}
.ucv-cr-sig-btn {
  appearance: none;
  border: 0;
  padding: 6px 12px;
  border-radius: 7px;
  font-family: var(--f-sans);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: -0.005em;
  cursor: default;
}
.ucv-cr-sig-btn--ghost {
  background: transparent;
  color: rgba(255,255,255,0.82);
}
.ucv-cr-sig-btn--solid {
  background: var(--paper);
  color: var(--ink);
}

/* ---------- 8. Cash Forecasting ---------- */
.ucv-fc { padding: 22px 22px 18px; }
.ucv-fc-head { margin-bottom: 18px; }
.ucv-fc-label {
  font-size: 12.5px;
  color: rgba(255,255,255,0.55);
  margin-bottom: 6px;
}
.ucv-fc-total {
  display: flex; align-items: baseline;
  gap: 6px;
  color: var(--paper);
  font-family: var(--f-display);
  font-weight: 500;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  margin-bottom: 8px;
}
.ucv-fc-currency { font-size: 26px; opacity: 0.7; }
.ucv-fc-total .count-up { font-size: 44px; }
.ucv-fc-trend { display: flex; align-items: center; gap: 10px; }
.ucv-fc-trend-pill {
  display: inline-flex;
  align-items: center;
  padding: 4px 10px;
  background: rgba(60,180,100,0.15);
  color: rgb(170,225,180);
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 600;
}
.ucv-fc-trend-meta { font-size: 12px; color: rgba(255,255,255,0.55); }
/* Vertical bar chart – 3 columns side by side, each fills from the
   baseline up via CSS height animation. Value sits above each bar
   and rides up with the bar's growth via bottom: var(--h). Subtle
   horizontal gridlines + axis baseline for the finance-dashboard
   feel. */
.ucv-fc-chart {
  position: relative;
  display: flex;
  align-items: stretch;
  gap: 22px;
  height: 200px;
  margin-top: 24px;
  padding: 0 8px 0;
  border-bottom: 1px solid rgba(255,255,255,0.12);
}
.ucv-fc-grid {
  position: absolute;
  inset: 0 8px 0;
  pointer-events: none;
}
.ucv-fc-grid span {
  position: absolute;
  left: 0; right: 0;
  height: 1px;
  background: rgba(255,255,255,0.05);
}
.ucv-fc-grid span:nth-child(1) { top: 0%; }
.ucv-fc-grid span:nth-child(2) { top: 50%; }
.ucv-fc-grid span:nth-child(3) { top: 100%; }

.ucv-fc-col {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  min-width: 0;
}
.ucv-fc-col-track {
  flex: 1;
  position: relative;
}
.ucv-fc-col-fill {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 0;
  background: linear-gradient(
    to top,
    var(--accent) 0%,
    color-mix(in oklab, var(--accent) 75%, white) 100%
  );
  border-radius: 8px 8px 4px 4px;
  animation: ucv-fc-grow-v 1.5s cubic-bezier(.16,1,.3,1) forwards;
  box-shadow: 0 4px 16px -6px rgba(255,61,0,0.45);
}
@keyframes ucv-fc-grow-v {
  to { height: var(--h, 50%); }
}
.ucv-fc-col-val {
  position: absolute;
  left: 0; right: 0;
  bottom: var(--h, 50%);
  margin-bottom: 8px;
  text-align: center;
  font-family: var(--f-display);
  font-size: 13px;
  font-weight: 600;
  color: var(--paper);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.005em;
  opacity: 0;
  animation: ucv-fc-val-in 0.5s ease-out forwards;
}
@keyframes ucv-fc-val-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0);   }
}
.ucv-fc-col-label {
  margin-top: 10px;
  text-align: center;
  font-size: 11.5px;
  color: rgba(255,255,255,0.55);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}


/* ---------- promise ---------- */
.promise-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
@media (max-width: 820px) { .promise-grid { grid-template-columns: 1fr; } }
.prop {
  background: var(--paper);
  /* Tightened vertical padding so the cards read as thinner blocks
     while title + body text sizes stay unchanged. Horizontal
     padding kept at 32px. Vertical: 36/32 -> 26/22 (saves 20px). */
  padding: 26px 32px 22px;
  display: flex; flex-direction: column;
  /* Reduced from 260px (over-tall request earlier) to 200px so
     the cards feel compact. Longer body copies (cards 01 + 06)
     are already widened to use the full card width so they wrap
     in fewer lines — the row may grow slightly on hover for those
     two but base height stays compact. */
  min-height: 200px;
}
.prop .num {
  font-family: var(--f-mono);
  /* Match the existing .sec-num eyebrow size used by the section
     headers ('02 / WHAT WE DO' etc.). */
  font-size: 16px;
  color: var(--accent);
  letter-spacing: 0.02em;
  /* Tightened from 24px so the card height shrinks without
     touching font sizes. */
  margin-bottom: 18px;
  line-height: 1;
}
.prop h4 {
  font-family: var(--f-display);
  font-size: 26px;
  font-weight: 500;
  letter-spacing: -0.025em;
  line-height: 1.08;
}
.prop h4 em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  color: var(--accent);
  /* Accent now matches the surrounding sans size exactly (no
     optical bump — was 1.06em). User requested same-size
     highlighted vs non-highlighted words. */
  font-size: 1em;
}
.prop p {
  margin-top: 12px;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--ink-2);
  /* Width cap removed (was max-width: 38ch). Body now uses the
     full card width so long copy (cards 01 'Knows each customer'
     and 06 'Deploy in days') wraps in ~3 lines instead of 5,
     saving vertical space and letting all rows share the same
     min-height. */
  max-width: none;
  /* Body still takes its layout space so the grid rows stay aligned;
     only opacity / translate animate. See the hover override below. */
  transition: opacity .22s ease, transform .22s ease;
}
/* Hover-to-reveal description: only enabled where the device actually
   has a fine pointer (mouse / trackpad). On touch, the body stays
   visible at all times so mobile users see the same copy as desktop. */
@media (hover: hover) and (pointer: fine) {
  .prop p {
    opacity: 0;
    transform: translateY(6px);
    pointer-events: none;
  }
  .prop:hover p,
  .prop:focus-within p {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
  }
}

/* ---------- faq ---------- */
.faq {
  padding: 112px 0 96px;
  background: var(--paper);
}
/* FAQ container uses the default .container width (1240px) — items
   line up with the other sections (Promise, Whisper, etc.). */
.faq .sec-num { margin: 0 0 40px; }
.faq-title {
  font-family: var(--f-display);
  /* Aligned to .loop-title for consistency with sections 1, 2, 3. */
  font-size: clamp(40px, 4.8vw, 64px);
  font-weight: 500;
  letter-spacing: -0.035em;
  line-height: 1.02;
  color: var(--ink);
  text-align: center;
  margin: 0 auto 56px;
}
.faq-list {
  /* full container width – no narrow centered band */
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.faq-item {
  background: #FFFFFF;
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
  transition: border-color .2s ease, background .2s ease, box-shadow .2s ease;
}
.faq-item:hover { border-color: var(--line-2); }
.faq-item.is-open {
  border-color: var(--line-2);
  box-shadow: 0 1px 2px rgba(20,20,15,0.04), 0 12px 32px -20px rgba(20,20,15,0.12);
}
.faq-q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 16px 28px;
  background: none;
  border: 0;
  cursor: pointer;
  /* use our brand display font (Inter Tight) – same family as
     section headings – instead of mono */
  font-family: var(--f-display);
  font-size: 16px;
  font-weight: 500;
  color: var(--ink);
  letter-spacing: -0.015em;
  text-align: left;
  gap: 24px;
  transition: color .15s ease;
}
.faq-q-text { flex: 1; }
.faq-toggle {
  font-size: 22px;
  line-height: 1;
  color: var(--ink-3);
  transition: color .2s ease;
  flex-shrink: 0;
  font-weight: 300;
  width: 14px;
  text-align: center;
}
.faq-item.is-open .faq-toggle { color: var(--accent); }

/* Max-height collapse, but the actual max-height value is set inline
   by FaqItem from the inner's scrollHeight. That way the transition
   distance matches the real content – no lazy overshoot of a
   hardcoded 1000px target that makes short answers feel slow. */
.faq-a {
  max-height: 0;
  overflow: hidden;
  transition: max-height .45s cubic-bezier(.22, 1, .36, 1);
}
.faq-a-inner {
  /* bottom padding always present – when closed, the row is clipped to
     0 via grid-template-rows: 0fr so padding is invisible. When open,
     it's part of the natural height the row animates to. Keeping it
     constant avoids a jump at the start/end of the transition. */
  padding: 0 28px 22px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-2);
  /* no max-width – answer text stretches across the full item width */
}
@media (max-width: 720px) {
  .faq { padding: 80px 0 64px; }
  .faq-q { padding: 14px 20px; font-size: 15px; gap: 16px; }
  .faq-a-inner { padding: 0 20px 18px; font-size: 14px; }
}

/* ---------- cta ---------- */
.cta-wrap {
  padding: 112px 0;
  position: relative;
  overflow: hidden;
  background-color: oklch(0.13 0.012 60); /* same dark heat-flow base as hero */
  color: var(--paper);
  contain: paint;
  isolation: isolate;
}
.cta-wrap > .container {
  position: relative;
  z-index: 2; /* above the animated bg pseudo-elements and the .cta-overlay */
}
.cta-card {
  /* card chrome stripped – the dark animated bg now lives on .cta-wrap
     and stretches edge-to-edge. .cta-card is now just a content layout
     wrapper that vertically centers within its min-height. */
  background: none;
  color: var(--paper);
  border-radius: 0;
  padding: 0;
  text-align: left;
  position: relative;
  overflow: visible;
  min-height: 280px;
  display: flex; flex-direction: column; align-items: flex-start; justify-content: center;
}
.cta-card::before { display: none; }
.cta-eyebrow {
  position: relative;
  z-index: 2;
  font-family: var(--f-mono);
  font-size: 11.5px;
  color: rgba(243,238,225,0.65);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  display: inline-flex; align-items: center; gap: 10px;
}
.cta-eyebrow .dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent-2);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent-2) 28%, transparent);
}
.cta-card h2 {
  position: relative;
  z-index: 2;
  margin-top: 20px;
  font-family: var(--f-display);
  /* Aligned to .loop-title so the bottom CTA 'Get paid on time,
     without the chase.' reads at the same scale as all the other
     section headlines. */
  font-size: clamp(40px, 4.8vw, 64px);
  line-height: 1.02;
  letter-spacing: -0.035em;
  color: var(--paper);
  max-width: 22ch;
  font-weight: 500;
  text-align: left;
}
.cta-card h2 em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  color: var(--accent-2);
}
.cta-card .lead {
  position: relative;
  z-index: 2;
  margin: 18px 0 0;
  max-width: 48ch;
  font-size: 16.5px;
  color: rgba(243,238,225,0.72);
  text-align: left;
}
.cta-card .btn-primary {
  position: relative;
  z-index: 2;
  margin-top: 28px;
  background: var(--accent);
  color: var(--accent-ink);
}
.cta-card .btn-primary:hover {
  background: color-mix(in oklab, var(--accent) 85%, var(--ink));
  color: var(--accent-ink);
}
.cta-card .mini {
  position: relative;
  z-index: 2;
  margin-top: 14px;
  font-family: var(--f-mono);
  font-size: 11px;
  color: rgba(243,238,225,0.5);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  text-align: left;
}
@media (max-width: 720px) {
  .cta-wrap { padding: 80px 0; }
}

/* ---------- footer ---------- */
.foot {
  position: relative;
  padding: 72px 0 0;
  border-top: 1px solid var(--line);
  overflow: hidden;
}
.foot-top {
  display: grid;
  grid-template-columns: 1.1fr 2.4fr;
  gap: 48px;
  padding-bottom: 48px;
}
/* Mobile (2026-05-29): keep brand + link columns SIDE BY SIDE and
   top-aligned instead of stacking — "Built for security" on the left,
   Company / Legal on the right at the same top edge (per design). The
   security copy wraps narrower in its column; the link columns sit
   top-right. Tightened tracks/gaps so it fits down to ~360px. */
@media (max-width: 500px) {
  .foot-top {
    grid-template-columns: 1.25fr 1fr;
    gap: 18px;
    align-items: start;
  }
  .foot-cols { column-gap: 22px; }
}
.foot-brand { display: flex; flex-direction: column; gap: 10px; }
.foot-tag {
  margin-top: 4px;
  /* tagline aligns with the full logo's left edge (sprout glyph) */
  margin-left: 0;
  white-space: nowrap;
  font-size: 13px;
  color: var(--ink-3); /* match the greyish link color */
  max-width: 26ch;
  line-height: 1.5;
}
.foot-place {
  font-family: var(--f-mono);
  font-size: 11.5px;
  color: var(--ink-3);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.foot-cols {
  display: grid;
  /* spacer + Company + Legal — Security moved to brand cell, Product
     is display:none. Only 3 visible items, so 3 tracks; otherwise the
     trailing column-gap pushes Legal ~56px off the right edge. */
  grid-template-columns: 1fr auto auto;
  row-gap: 24px;
  column-gap: 56px;
  align-items: start;
}
/* No mobile-specific override for .foot-cols — the desktop rule
   (1fr spacer + auto Company + auto Legal) right-packs the link
   columns at every viewport from 320px up. Keeps Company/Legal in
   their 'usual' right-aligned position on phones, tablets, desktop. */
.foot-col-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 14px;
  letter-spacing: -0.005em;
}
.foot-col ul {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: 8px;
}
.foot-col li a {
  font-size: 13.5px;
  color: var(--ink-3);
  transition: color .15s ease;
}
.foot-col li a:hover { color: var(--accent); }

/* Security badge — sits in the brand area on the LEFT, top-aligned
   with the link column titles on the right. */
.foot-security {
  max-width: 260px;
  text-align: left;
}
.foot-security-copy {
  /* font-size 13.5px + line-height 1.55 match the link items.
     padding-top: 5px compensates for the line-box leading — the <a>
     bounding rect starts at the text glyph top (below the leading),
     while the <p> bounding rect starts at the line-box top (above
     the leading). Pushing the <p> down by ~5px brings the first
     glyph in line with 'Careers' / 'Imprint'. */
  margin: 0;
  padding-top: 5px;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink-3); /* match the greyish link color */
  letter-spacing: -0.005em;
  text-transform: none;
}
.foot-security-badges {
  display: flex;
  gap: 22px;
  margin-top: 18px;
  justify-content: flex-start;
}
.foot-badge {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  color: var(--ink-2);
}
.foot-badge svg {
  width: 26px;
  height: 26px;
}
.foot-badge-label {
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--ink-3);
  text-transform: uppercase;
}
@media (max-width: 720px) {
  .foot-security { max-width: none; }
}

/* --- temporary section hides (revisit when there's real content) --- */
/* foot-cols children now in order: [spacer, Product, Company, Legal] —
   Security badge moved out into .foot-brand. */

/* Product column: removed from layout entirely (display: none).
   When Product gets real content, swap to `> * { visibility: hidden }`
   or delete this rule to bring it back. */
.foot-cols .foot-col:nth-child(2) {
  display: none;
}

/* Company column items: [About, Manifesto, Careers, Contact]
   Hide About, Manifesto, and Contact until those pages exist. */
.foot-cols .foot-col:nth-child(3) li:nth-child(1),
.foot-cols .foot-col:nth-child(3) li:nth-child(2),
.foot-cols .foot-col:nth-child(3) li:nth-child(4) {
  display: none;
}

/* Legal column items: [Imprint, Terms, Privacy, DPA]
   Hide Terms (no terms.md content yet) and DPA. */
.foot-cols .foot-col:nth-child(4) li:nth-child(2),
.foot-cols .foot-col:nth-child(4) li:nth-child(4) {
  display: none;
}

.foot-bottom {
  padding: 18px 0 8px;
  border-top: 1px solid var(--line);
  font-family: var(--f-mono);
  font-size: 11.5px;
  color: var(--ink-3);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.foot-region {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.foot-flag {
  display: inline-block;
  height: 12px;
  width: 18px;
  flex-shrink: 0;
  border-radius: 1.5px;
  overflow: hidden;
}

/* Giant striped watermark – huge, overflows the viewport, cropped at the bottom */
.foot-mark {
  position: relative;
  margin-top: -0.05em;
  width: 100%;
  pointer-events: none;
  user-select: none;
  display: flex;
  justify-content: center;
  overflow: hidden;
  /* Container is sized to ~80% of rendered text height (font * 0.78)
     so the bottom of every letter is "slightly cut off" – the original
     design intent – without removing the upper halves of the glyphs.
     Earlier clamp(150, 22vw, 320) was too aggressive (~45% cropped on
     widescreen); earlier clamp(206, 28vw, 366) was the opposite (no
     crop at all on laptop widths). This curve keeps the crop at a
     consistent ~18-22% across the full viewport range. */
  height: clamp(180px, 20vw, 400px);
}
.foot-mark-text {
  font-family: var(--f-display);
  font-weight: 800;
  /* min was 265px which forced the word to overflow on viewports <600px.
     Measured: kasdor at Inter Tight 800 + -0.06em renders ~2.91x font-size
     wide. At 32vw the word is ~93% of viewport — comfortable fit down to
     ~320px viewport. Max restored to 663px (original design) so the
     watermark reads as huge / cropped on widescreen monitors. */
  font-size: clamp(80px, 32vw, 663px);
  letter-spacing: -0.06em;
  line-height: 0.78;
  background-image: repeating-linear-gradient(
    to bottom,
    var(--accent) 0 2px,
    transparent 2px 7px
  );
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  opacity: 0.62;
  padding: 0;
  margin: 0;
  white-space: nowrap;
  display: block;
  transform: translateY(-4%);
}

/* reveal */
.reveal { opacity: 1; transform: none; transition: opacity .6s ease, transform .6s ease; }
.reveal.pre { opacity: 0; transform: translateY(10px); }
.reveal.in  { opacity: 1; transform: none; }

::selection { background: var(--accent); color: var(--accent-ink); }

/* ---------- booking modal ---------- */
.booking-modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px;
}
.booking-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  animation: booking-fade-in .25s ease-out both;
}
.booking-frame {
  position: relative;
  width: 100%;
  /* wider frame so the side padding can be a substantial visible
     strip AND Cal still has enough room for its 3-column layout */
  max-width: 1100px;
  max-height: calc(100vh - 64px);
  background-color: oklch(0.13 0.012 60);
  border-radius: 20px;
  overflow: hidden;
  z-index: 1;
  color: var(--paper);
  /* same compositor isolation as .hero / .cta-wrap — keeps the
     Cal iframe above from forcing repaints of the blurred bg */
  contain: paint;
  isolation: isolate;
  animation: booking-pop-in .35s cubic-bezier(.16, 1, .3, 1) both;
  display: flex;
  flex-direction: column;
}
.booking-frame::before,
.booking-frame::after {
  content: "";
  position: absolute;
  inset: -25%;
  pointer-events: none;
  /* match endor-whisper-smooth source – will-change includes both
     properties the keyframes animate so the browser can plan ahead. */
  will-change: transform, background-position;
  z-index: 0;
}
.booking-frame::before {
  background: linear-gradient(135deg, oklch(0.13 0.012 60) 0%, oklch(0.92 0.10 70 / 0.85) 18%, oklch(0.13 0.012 60) 34%, oklch(0.70 0.21 38 / 0.95) 52%, oklch(0.13 0.012 60) 68%, oklch(0.55 0.24 32 / 0.85) 85%, oklch(0.13 0.012 60) 100%);
  background-size: 200% 200%;
  filter: blur(15px);
  animation: heat-flow-a 14s ease-in-out infinite alternate;
}
.booking-frame::after {
  background: linear-gradient(120deg, transparent 0%, oklch(0.92 0.10 70 / 0.50) 30%, transparent 50%, oklch(0.60 0.22 40 / 0.55) 72%, transparent 100%);
  background-size: 240% 240%;
  filter: blur(20px);
  mix-blend-mode: screen;
  animation: heat-flow-b 20s ease-in-out infinite alternate;
}
.booking-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  /* lighter overlay so the heat-flow stays visibly orange in the side
     padding around the Cal widget (was 0.4 — too dark, killed the
     orange on the L/R edges) */
  background: rgba(0, 0, 0, 0.22);
}
.booking-close {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 3;
  width: 38px;
  height: 38px;
  border: none;
  background: rgba(255, 255, 255, 0.08);
  color: var(--paper);
  border-radius: 999px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  outline: none;
  /* simple background transition only – no transform, no border, no
     focus-ring competing with hover. SVG inside has pointer-events:none
     so hover lives only on the button rect. */
  transition: background .15s ease;
}
.booking-close:hover,
.booking-close:focus-visible { background: rgba(255, 255, 255, 0.22); }
.booking-close:active { background: rgba(255, 255, 255, 0.30); }
.booking-close svg { width: 18px; height: 18px; pointer-events: none; }
.booking-content {
  position: relative;
  z-index: 2;
  /* 70px L/R strips on the 1100px modal. Cal area = 960px, well
     above its 3-column threshold. A touch thicker than the 60px
     'finally!' version per the latest request. */
  padding: 40px 70px 32px;
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}
.booking-header { margin-bottom: 28px; max-width: 60ch; }
.booking-eyebrow {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
  margin: 0 0 12px;
}
.booking-title {
  font-family: var(--f-display);
  font-size: clamp(28px, 3.4vw, 44px);
  font-weight: 500;
  letter-spacing: -0.03em;
  margin: 0;
  color: var(--paper);
  line-height: 1.02;
}
.booking-sub {
  margin: 10px 0 0;
  font-size: 15px;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.72);
}
.booking-cal {
  border-radius: 14px;
  overflow: hidden;
  /* Dark semi-transparent wrapper that frames the Cal iframe on all
     four sides. Padding 30 top/bottom (= X) and 20 L/R (= 2X/3). */
  background: rgba(0, 0, 0, 0.45);
  padding: 30px 20px;
  min-height: 640px;
}
@keyframes booking-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes booking-pop-in {
  from { opacity: 0; transform: translateY(16px) scale(0.97); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
@media (max-width: 720px) {
  /* Mobile full-screen modal. Use DYNAMIC viewport units (dvh) — plain
     100vh on mobile is the *large* viewport (height with the address bar
     hidden), so the frame rendered taller than the visible screen and the
     centered layout pushed the close button up under the browser toolbar
     and the bottom below the fold (couldn't close it). dvh tracks the
     actually-visible area. Anchor the modal at the top (release `bottom`)
     and make it exactly one visible viewport tall; the close button pins
     to the frame's top-right, the calendar scrolls inside. */
  .booking-modal {
    padding: 0;
    inset: 0 0 auto 0;          /* top/left/right: 0, bottom: auto */
    height: 100dvh;
    align-items: stretch;
  }
  .booking-frame {
    border-radius: 0;
    height: 100%;
    max-height: 100dvh;
  }
  .booking-content { padding: 24px 20px 20px; }
  .booking-cal { min-height: 540px; }
}

/* =============================================================================
 * Perf hot-fix follow-up (2026-05-28): pause expensive animations when the
 * booking modal is open.
 *
 * Cal.com's embedded calendar iframe is already heavy on retina (their JS,
 * their DOM, their constant postMessage heartbeat). Stacking our animated
 * heat-flow gradients with `filter: blur(30-40px)` underneath the modal AND
 * inside the booking frame on top of that brings the GPU to its knees on
 * M-series MacBooks — manifests as fan noise and visible screen flicker.
 *
 * When `<body class="modal-open">` is set (BookingModal's effect adds it on
 * mount, removes on unmount), pause the booking-frame heat-flow behind the Cal
 * iframe. (The hero + CTA are now video and the card glows are static, so the
 * booking frame is the only animated gradient left to pause.)
 *
 * `animation-play-state: paused` retains the current frame, so the visual
 * doesn't snap back to t=0 — it just freezes where it is. When the modal
 * closes, the class is removed and animations resume.
 * ===========================================================================*/
body.modal-open .booking-frame::before,
body.modal-open .booking-frame::after {
  animation-play-state: paused !important;
}

/* Also respect user-level reduced-motion preference. Anyone with the OS
 * accessibility setting enabled gets static gradients site-wide. */
@media (prefers-reduced-motion: reduce) {
  .booking-frame::before,
  .booking-frame::after {
    animation: none !important;
  }
}

/* =============================================================================
 * Page Visibility — pause every animation site-wide when the tab is hidden.
 * Hooks into the visibilitychange listener in app.jsx (body.tab-hidden). The
 * universal selector is safe because the user literally can't see the tab, so
 * there's no UX impact; animations resume when the tab is shown again.
 *
 * (Origin: perf hot-fix 3, 2026-05-28 — the GPU-starvation rescue. The other
 * changes from that pass — killing the secondary ::after heat-flow layers and
 * cutting blur radii — were later superseded when the hero + CTA heat-flows
 * became <video> and the card glows became static.)
 * =========================================================================== */
body.tab-hidden *,
body.tab-hidden *::before,
body.tab-hidden *::after {
  animation-play-state: paused !important;
}

/* =============================================================================
 * Perf — Tier 1 (2026-05-28): content-visibility for below-fold sections.
 *
 * Every section below the hero gets `content-visibility: auto`. Browser
 * skips layout + paint for these until the user scrolls them into the
 * viewport (or near it). The `contain-intrinsic-size` placeholder keeps
 * the scroll height stable so scrollbars don't jump on render.
 *
 * Hero stays untouched because it paints immediately.
 *
 * Browser support: Chrome 85+, Edge 85+, Safari 18+, Firefox 125+.
 * Older browsers fall back to normal rendering (no breakage).
 * =========================================================================== */
.whisper,
.section,
.loop-section,
.faq,
.cta-wrap,
.foot {
  content-visibility: auto;
  contain-intrinsic-size: 0 800px;
}

/* =============================================================================
 * Perf — Tier 2 (2026-05-28): pause marquee when scrolled out of viewport.
 *
 * The marquee logo strip scrolls continuously via `marquee` keyframes. With
 * 200+ logos sliding past, this is non-trivial GPU work that runs even when
 * the user has scrolled past the section. IntersectionObserver (wired in
 * sections.jsx) adds .marquee-paused when the element leaves viewport.
 * =========================================================================== */
.marquee.marquee-paused .marquee-track {
  animation-play-state: paused !important;
}

/* =============================================================================
 * Perf — Tier 3 (2026-05-29): universal section-level IO pause.
 *
 * Every top-level section (Hero, Whisper, Does, Loop, ValueProps, UseCases,
 * Faq, CTA, Foot) has a useSectionIOPause(ref) hook in sections.jsx that
 * toggles `.section-paused` when the element leaves the viewport (with
 * 300px rootMargin so the pause lands just past the visible edge).
 *
 * This rule freezes every CSS animation inside a paused section — heat-flow
 * gradients on the hero / CTA / loop card, every stagger / fade / count-up
 * inside the demo viz components, even animated SVG strokes. Browser still
 * paints the current frame (so you don't see a flash of unstyled content
 * on scroll-back) but stops advancing it.
 *
 * Combined with the per-component useGatedInterval hooks, this means:
 *   • Out-of-viewport CSS: animation-play-state: paused (no compositor work)
 *   • Out-of-viewport JS:  setInterval cleared (no React reconciliation)
 *   • In-viewport everywhere: full animation as before
 * =========================================================================== */
/* Selector bug fix (2026-05-29): the PR #9 rule had
   `.section-paused *::before` which matches ::before of any DESCENDANT
   of `.section-paused` — but NOT the ::before of the .section-paused
   element itself. So .hero::before and .cta-wrap::before (the heat-
   flow gradient pseudos that ARE on the paused element directly)
   kept animating after scroll-away. User caught this empirically:
   scroll down, wait, scroll back, and the gradient had "wandered"
   because its animation timer never paused.
   Adding `.section-paused::before` and `.section-paused::after` to
   the selector list fixes it — now the paused element's own pseudos
   freeze too. */
.section-paused,
.section-paused::before,
.section-paused::after,
.section-paused *,
.section-paused *::before,
.section-paused *::after {
  animation-play-state: paused !important;
}
