/* =========================================================================
   Assertify marketing — visual language modeled on testmuai.com
   (warm paper, big Manrope headlines, product frames over soft backdrops,
   dotted-grid pipelines, sticky feature tabs) re-skinned with our indigo.
   ========================================================================= */

/* Self-hosted VARIABLE Manrope (latin + latin-ext, wght 200–800) — replaces the
   render-blocking Google Fonts CDN round-trip. The variable axis covers the 650 /
   750 weights the demo chrome uses; weight 900 clamps to 800 exactly as the old
   css2?wght@…800 URL already did, so headings are unchanged. font-display:swap
   keeps text painting in the fallback immediately (no FOIT). */
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("/fonts/manrope-latin.woff2") format("woff2");
}

:root {
  --paper: #f4f3ee;        /* warm cream base */
  --paper-2: #efeee7;      /* alternating band */
  --paper-3: #eae8df;      /* deeper warm panel */
  --card: #ffffff;
  --ink: #16181d;          /* near-black headings/text */
  --ink-soft: #44474f;
  --muted: #767a85;
  --line: #e6e4da;         /* warm hairline */
  --line-2: #d9d7cc;

  --indigo: #4f46e5;       /* indigo-600 (our accent) */
  --indigo-700: #4338ca;
  --indigo-500: #6366f1;
  --indigo-300: #a5b4fc;
  --indigo-200: #c7d2fe;
  --indigo-100: #e0e7ff;
  --indigo-50: #eef2ff;
  --violet: #7c3aed;

  --dark: #131418;         /* dark accents (terminal, testimonial card) */
  --dark-2: #1c1d22;
  --brand-dark: #1e1b3f;   /* deep indigo — topbar, footer + overscroll gutter (on-brand, not flat black) */
  --brand-dark-2: #262246; /* one step up, for raised chrome on the brand-dark surfaces */
  --on-dark-soft: rgb(255 255 255 / 0.66);

  --ok: #16a34a; --ok-100:#dcfce7;
  --warn:#d97706; --err:#e11d48;

  --r: 16px;               /* default card radius */
  --r-lg: 22px;
  --shadow: 0 18px 50px -28px rgb(20 22 30 / 0.28);
  --shadow-lg: 0 40px 90px -44px rgb(20 22 30 / 0.40);
  --nav-h: 70px;
  --wrap: 1200px;
}

* { box-sizing: border-box; }
html, body { margin: 0; }
/* Root canvas is the deep-indigo brand colour, so the top/bottom rubber-band
   overscroll gutter reads as a seamless extension of the topbar and footer (the
   cream body paints the page itself; only the overscroll gutter shows this). */
html { scroll-behavior: smooth; background-color: var(--dark); }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  font-family: "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  color: var(--ink);
  background: var(--paper);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }

h1, h2, h3, h4 { font-family: "Manrope", sans-serif; letter-spacing: -0.02em; line-height: 1.04; margin: 0; font-weight: 800; }

.wrap { width: min(var(--wrap), calc(100% - 48px)); margin-inline: auto; }
.eyebrow { display: inline-flex; align-items: center; gap: 0.5rem; font-size: 0.82rem; font-weight: 700; letter-spacing: 0.02em; color: var(--indigo); text-transform: none; }
.eyebrow .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--indigo); box-shadow: 0 0 0 4px rgb(79 70 229 / 0.14); animation: eyebrowPulse 2s ease-out infinite; }
/* Live "pulse" on the eyebrow dot — a constant faint halo plus an expanding,
   fading ring. The animated box-shadow overrides the static one above; reduced
   motion falls back to that static halo. */
@keyframes eyebrowPulse {
  0%   { box-shadow: 0 0 0 3px rgb(79 70 229 / 0.16), 0 0 0 0 rgb(79 70 229 / 0.45); }
  70%  { box-shadow: 0 0 0 3px rgb(79 70 229 / 0.16), 0 0 0 9px rgb(79 70 229 / 0); }
  100% { box-shadow: 0 0 0 3px rgb(79 70 229 / 0.16), 0 0 0 9px rgb(79 70 229 / 0); }
}
@media (prefers-reduced-motion: reduce) { .eyebrow .dot { animation: none; } }

/* Dotted-grid texture used on several light sections (shared with the app canvas). */
.dotted { background-image: radial-gradient(rgb(20 22 30 / 0.05) 1px, transparent 1.6px); background-size: 22px 22px; }

/* ----------------------------------------------------------- announcement bar */
.topbar {
  position: relative; overflow: hidden;
  /* SAME surface as the "Ship with confidence" card (.cta-final): a near-black --dark
     base + an indigo radial glow from above; the blueprint grid rides .topbar::before. */
  background-color: var(--dark);
  background-image: radial-gradient(90% 240% at 50% -40%, rgb(99 102 241 / 0.42), transparent 62%);
  color: #fff; font-size: 0.85rem; font-weight: 600;
  display: flex; align-items: center; justify-content: center; gap: 0.6rem;
  padding: 0.55rem 1rem; text-align: center;
}
.topbar::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    linear-gradient(rgb(165 180 252 / 0.09) 1px, transparent 1px),
    linear-gradient(90deg, rgb(165 180 252 / 0.09) 1px, transparent 1px);
  background-size: 34px 34px;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent);
}
.topbar > a { position: relative; z-index: 1; }
.topbar a { display: inline-flex; align-items: center; gap: 0.45rem; color: #fff; }
.topbar .tag { font-size: 0.66rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; padding: 0.18rem 0.5rem; border-radius: 999px; background: linear-gradient(135deg, var(--indigo-500), var(--indigo)); }
.topbar .arr { transition: transform .2s ease; }
.topbar a:hover .arr { transform: translateX(4px); }
/* real Product Hunt logo mark inside the announcement bar */
.topbar__ph { display: inline-flex; align-items: center; line-height: 0; flex: none; }
.topbar__ph svg { display: block; }

/* Product Hunt launch: the announcement bar rides the --dark blueprint surface
   (same as .cta-final + footer; the root canvas is --dark too so the top overscroll
   never shows a seam); the "Check us out" CTA is a bright PH-orange pill on it. */
.topbar--ph a { gap: 0.55rem; flex-wrap: wrap; justify-content: center; row-gap: 0.4rem; }
.topbar--ph .topbar__msg b { font-weight: 800; }
.topbar--ph .topbar__cta { display: inline-flex; align-items: center; gap: 0.35rem; margin-left: 0.2rem;
  background: linear-gradient(135deg, #FF6154, #DA552F); color: #fff; font-weight: 800; padding: 0.24rem 0.78rem;
  border-radius: 999px; box-shadow: 0 6px 16px -8px rgb(218 85 47 / 0.85); transition: transform .15s ease, box-shadow .15s ease; }
.topbar--ph a:hover .topbar__cta { transform: scale(1.05); box-shadow: 0 9px 22px -8px rgb(218 85 47 / 0.95); }
.topbar--ph .topbar__cta .arr { transition: transform .2s ease; }
.topbar--ph a:hover .topbar__cta .arr { transform: translateX(3px); }

/* Product Hunt button (hero secondary CTA) — coral, with the PH logo */
.btn-ph { color: #fff; background: linear-gradient(135deg, #FF6154, #DA552F); box-shadow: 0 10px 24px -12px rgb(218 85 47 / 0.7); }
.btn-ph:hover { transform: translateY(-2px); box-shadow: 0 18px 34px -14px rgb(218 85 47 / 0.85); }
.btn-ph__logo { display: inline-flex; align-items: center; line-height: 0; flex: none; }
.btn-ph__logo svg { display: block; }

/* ----------------------------------------------------------- nav */
.nav {
  position: sticky; top: 0; z-index: 60;
  /* Near-opaque instead of translucent + blur: backdrop-filter on a sticky bar
     with content scrolling under it is recomputed every scroll frame (the single
     most expensive per-frame GPU op here). Over warm paper the difference is
     barely perceptible. A scrolled-state shadow (added via .scrolled in site.js)
     gives the bar the lift that the blur used to imply. */
  background: rgb(244 243 238 / 0.94);
  border-bottom: 1px solid var(--line);
  transition: transform .32s cubic-bezier(.4,0,.2,1), box-shadow .25s ease, background .25s ease;
}
.nav.scrolled { background: rgb(244 243 238 / 0.97); box-shadow: 0 8px 30px -22px rgb(20 22 30 / 0.5); }
/* auto-hide on scroll-down (site.js toggles .nav--hidden), reveal on scroll-up —
   frees vertical space as you read. The sticky feature-tab bar follows it up. */
.nav.nav--hidden { transform: translateY(-100%); }
.nav__in { display: flex; align-items: center; gap: 1.6rem; height: var(--nav-h); }
.brand { display: inline-flex; align-items: center; gap: 0.55rem; font-weight: 800; font-size: 1.18rem; color: var(--indigo); }
.brand .mark { width: 30px; height: 30px; filter: drop-shadow(0 6px 12px rgb(79 70 229 / 0.25)); }
.brand small { display: block; font-size: 0.6rem; font-weight: 700; letter-spacing: 0.08em; color: var(--muted); text-transform: uppercase; margin-top: 1px; }
.nav__links { display: flex; align-items: center; gap: 1.5rem; font-weight: 600; font-size: 0.95rem; }
.nav__links a { color: var(--ink-soft); display: inline-flex; align-items: center; gap: 0.3rem; transition: color .15s ease; }
.nav__links a:hover { color: var(--indigo); }
.nav__spacer { flex: 1; }
.nav__actions { display: flex; align-items: center; gap: 0.8rem; }
/* Theme toggle + language picker cluster, pinned to the far-right corner of the
   FULL-WIDTH bar (outside the 1200px wrap); the wrap reserves right padding
   (below) so the CTAs never slide under it. The picker sits static inside, so
   its `.lang` base rules (relative/inline-flex) anchor the popover correctly. */
.nav .nav__utils { position: absolute; top: 50%; right: clamp(16px, 2vw, 40px); transform: translateY(-50%); z-index: 3;
  display: inline-flex; align-items: center; gap: 0.55rem; }
@media (min-width: 941px) { .nav__in { padding-right: 120px; } }
.nav__signin { font-weight: 700; font-size: 0.95rem; color: var(--ink); }
.nav__signin:hover { color: var(--indigo); }
/* ---- mobile nav: CSS-only hamburger drawer (works with no JS) ----
   A hidden checkbox toggles a max-height drawer. site.js progressively adds
   aria-expanded, Escape-to-close, close-on-link-tap, and reset-on-resize — but
   the menu opens and closes by tap with zero JS, so mobile nav never vanishes. */
.nav__toggle-cb { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; margin: 0; }
.nav__toggle { display: none; }                 /* shown only at <=940px (below) */
/* sign-in / demo: drawer only. Scoped past `.nav__links a` (which sets
   inline-flex) so display:none actually wins on desktop. */
.nav__links a.nav__drawer-only { display: none; }
.nav__toggle-cb:focus-visible ~ .nav__toggle { outline: 2px solid var(--indigo); outline-offset: 2px; }
@media (max-width: 940px) {
  .nav__in { position: relative; flex-wrap: wrap; gap: 0.6rem; }
  .nav__spacer { display: none; }
  .nav__toggle {
    display: inline-grid; place-items: center; width: 44px; height: 44px; margin-left: auto;
    border-radius: 11px; color: var(--ink); cursor: pointer; border: 1px solid transparent;
  }
  .nav__toggle:hover { background: rgb(20 22 30 / 0.05); }
  .nav__toggle .i-close { display: none; }
  .nav__toggle-cb:checked ~ .nav__toggle .i-menu { display: none; }
  .nav__toggle-cb:checked ~ .nav__toggle .i-close { display: block; }
  /* The 5 page links + sign-in/demo collapse into a drawer pinned under the bar. */
  .nav__links {
    position: absolute; top: calc(100% + 1px); left: -24px; right: -24px;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--paper); border-bottom: 1px solid var(--line); box-shadow: var(--shadow);
    max-height: 0; overflow: hidden; transition: max-height .3s ease; z-index: 50;
  }
  .nav__toggle-cb:checked ~ .nav__links { max-height: 75vh; overflow-y: auto; }
  .nav__links a { padding: 0.95rem 24px; border-top: 1px solid var(--line); font-size: 1rem; }
  .nav__links a:first-child { border-top: none; }
  .nav__links a.nav__drawer-only { display: flex; }
  /* De-congest the bar: brand + toggle only. Both CTAs move into the drawer so
     nothing crowds the hamburger. The language picker would collide too — it
     lives in the footer on mobile. */
  .nav__signin, .nav__actions { display: none; }
  .nav .nav__utils { display: none; }
  /* the primary CTA becomes a full-width filled button at the foot of the drawer */
  .nav__links a.nav__cta-primary { margin: 0.6rem 24px 0.75rem; padding: 0.85rem; justify-content: center;
    border: none; border-radius: 12px; color: #fff; font-weight: 800;
    background: linear-gradient(135deg, var(--indigo-500), var(--indigo) 55%, var(--indigo-700));
    box-shadow: 0 10px 24px -12px rgb(79 70 229 / 0.7); }
  .nav__links a.nav__cta-primary:hover { color: #fff; }
}
@media (max-width: 520px) { .nav__signin { display: none; } }
/* Reduced motion: the drawer opens instantly (after the 940px block so it wins). */
@media (prefers-reduced-motion: reduce) { .nav__links { transition: none; } }

/* ----------------------------------------------------------- buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  font-weight: 700; font-size: 0.96rem; padding: 0.72rem 1.25rem; border-radius: 12px;
  cursor: pointer; border: 1px solid transparent; transition: transform .18s ease, box-shadow .2s ease, background .2s ease, border-color .2s ease, color .2s ease;
  white-space: nowrap;
}
.btn .arr { transition: transform .22s cubic-bezier(.34,1.56,.64,1); }
.btn:hover .arr { transform: translateX(4px); }
.btn-primary { color: #fff; background: linear-gradient(135deg, var(--indigo-500), var(--indigo) 55%, var(--indigo-700)); box-shadow: 0 10px 24px -12px rgb(79 70 229 / 0.7); }
.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 18px 34px -14px rgb(79 70 229 / 0.8); }
.btn-dark { color: #fff; background: var(--ink); }
.btn-dark:hover { transform: translateY(-2px); background: #000; box-shadow: 0 16px 30px -16px rgb(0 0 0 / 0.5); }
.btn-ghost { color: var(--ink); background: var(--card); border-color: var(--line-2); }
.btn-ghost:hover { transform: translateY(-2px); border-color: var(--indigo-200); color: var(--indigo-700); box-shadow: var(--shadow); }
.btn-light { color: var(--ink); background: #fff; }
.btn-light:hover { transform: translateY(-2px); box-shadow: 0 16px 30px -14px rgb(0 0 0 / 0.4); }
.btn-lg { padding: 0.85rem 1.5rem; font-size: 1.02rem; }
/* arrow link (underlined, with →) */
.link-arr { display: inline-flex; align-items: center; gap: 0.5rem; font-weight: 700; color: var(--ink); border-bottom: 2px solid var(--ink); padding-bottom: 2px; width: fit-content; }
.link-arr.indigo { color: var(--indigo); border-color: var(--indigo); }
.link-arr .arr { transition: transform .22s ease; }
.link-arr:hover .arr { transform: translateX(5px); }
@media (prefers-reduced-motion: reduce) { .btn, .btn .arr, .link-arr .arr { transition: none; } .btn:hover { transform: none; } }
/* "Split-flap" hover — a button's label rolls up to an identical copy on hover
   (the airport departure-board flip). Labels are wrapped into .flip at runtime
   by the inline script, so this applies to any .btn with no markup changes. */
.flip { display: inline-block; overflow: hidden; height: 1.2em; line-height: 1.2; vertical-align: middle; }
.flip__in { display: flex; flex-direction: column; transition: transform .42s cubic-bezier(.2, .7, .2, 1); }
.flip__in > span { display: block; height: 1.2em; line-height: 1.2; white-space: nowrap; }
.btn:hover .flip__in { transform: translateY(-50%); }
@media (prefers-reduced-motion: reduce) { .flip__in { transition: none; } .btn:hover .flip__in { transform: none; } }

/* ----------------------------------------------------------- section scaffolding */
.section { padding: clamp(3.5rem, 7vw, 6.5rem) 0; }
.section.tight { padding: clamp(2.5rem, 5vw, 4rem) 0; }
.bg-paper-2 { background: var(--paper-2); }
.bg-paper-3 { background: var(--paper-3); }
.sec-head { max-width: 760px; }
.sec-head.center { margin-inline: auto; text-align: center; }
.sec-head h2 { font-size: clamp(2.1rem, 4.6vw, 3.5rem); margin-top: 0.7rem; }
.sec-head p { margin: 1rem 0 0; color: var(--ink-soft); font-size: clamp(1.02rem, 1.6vw, 1.18rem); font-weight: 500; }
/* Two-tone heading: muted line above a bold line (testmu "More Reasons to Love"). */
.h2-twotone { font-size: clamp(2.1rem, 4.6vw, 3.4rem); line-height: 1.05; }
.h2-twotone .mute { display: block; color: var(--muted); font-weight: 700; }

/* ----------------------------------------------------------- hero */
.hero { position: relative; padding: clamp(2.5rem, 5vw, 4.5rem) 0 clamp(3rem, 6vw, 5rem); overflow: hidden; }
.hero__in { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1.15fr); gap: clamp(1.5rem, 4vw, 3rem); align-items: center; }
.hero h1 { font-size: clamp(2.6rem, 6vw, 4.6rem); letter-spacing: -0.03em; }
.hero h1 .hl { color: var(--indigo); }
.hero .lead { margin: 1.5rem 0 0; font-size: clamp(1.08rem, 1.7vw, 1.3rem); color: var(--ink-soft); font-weight: 500; max-width: 36rem; }
.hero .lead b { color: var(--ink); font-weight: 700; }
.hero .cta { margin-top: 2rem; display: flex; flex-wrap: wrap; gap: 0.8rem; }
.hero .micro { margin: 1.1rem 0 0; font-size: 0.9rem; color: var(--muted); font-weight: 600; }
@media (max-width: 920px) { .hero__in { grid-template-columns: 1fr; } .hero__visual { order: 2; } }

/* Hero product montage: a soft indigo-tinted backdrop with the app frame on top
   and small floating UI cards (mirrors testmu's screenshot collage). */
.montage { position: relative; padding: clamp(1rem, 3vw, 2rem); border-radius: var(--r-lg);
  background:
    radial-gradient(120% 120% at 80% 0%, rgb(99 102 241 / 0.18), transparent 60%),
    radial-gradient(100% 100% at 0% 100%, rgb(124 58 237 / 0.12), transparent 55%),
    linear-gradient(160deg, #eceaf6, #f3f2ee);
  border: 1px solid var(--line);
}
.montage::before { content:""; position:absolute; inset:0; border-radius: inherit; background-image: radial-gradient(rgb(20 22 30 / 0.05) 1px, transparent 1.5px); background-size: 20px 20px; opacity:.5; pointer-events:none; }
.montage > * { position: relative; }
.float-card { position: absolute; background: #fff; border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow); padding: 0.6rem 0.75rem; font-size: 0.78rem; font-weight: 600; }
.float-card.tl { top: -14px; left: -14px; }
.float-card.br { bottom: -16px; right: -10px; }
.float-card .row { display: flex; align-items: center; gap: 0.45rem; }
.float-card .ic { color: var(--indigo); }
@media (max-width: 520px) { .float-card { display: none; } }

/* Hero integration orbit: the 3D Assertify icon at the hub with Claude / Jira /
   Slack / GitHub floating around it on faint dashed spokes. (Replaces the app-montage
   collage.) Icons are transparent 3D app-icon PNGs; shadow + float come from CSS. */
.orbit { position: relative; width: min(100%, 500px); margin-inline: auto; aspect-ratio: 1 / 1; }
.orbit::before { content: ""; position: absolute; left: 50%; top: 50%; width: 64%; height: 64%;
  transform: translate(-50%, -50%); border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, rgb(99 102 241 / 0.22), rgb(124 58 237 / 0.10) 46%, transparent 70%);
  filter: blur(10px); }
.orbit__links { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; overflow: visible; }
.orbit__links line { stroke: rgb(99 102 241 / 0.34); stroke-width: 1.5; stroke-dasharray: 1 7;
  stroke-linecap: round; vector-effect: non-scaling-stroke; }
.orb { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 1; }
.orb img { display: block; width: 100%; height: auto; animation: floatOrb 6s ease-in-out infinite; }
.orb--core { width: 46%; }
.orb--core img { filter: drop-shadow(0 24px 42px rgb(76 65 216 / 0.5)); animation-duration: 7.5s; }
.orb--sat { left: var(--x); top: var(--y); width: 22%; z-index: 2; }
.orb--sat img { filter: drop-shadow(0 15px 26px rgb(20 22 30 / 0.28)); }
.orb--claude img { animation-duration: 5.6s; animation-delay: -1.0s; }
.orb--jira   img { animation-duration: 6.6s; animation-delay: -2.3s; }
.orb--slack  img { animation-duration: 6.1s; animation-delay: -0.6s; }
.orb--github img { animation-duration: 5.9s; animation-delay: -1.7s; }
@keyframes floatOrb { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-9px); } }
html.dark .orbit__links line { stroke: rgb(129 140 248 / 0.36); }
html.dark .orbit::before { background: radial-gradient(circle, rgb(99 102 241 / 0.26), rgb(124 58 237 / 0.12) 46%, transparent 70%); }
@media (prefers-reduced-motion: reduce) { .orb img { animation: none; } }

/* ============ "See it work" — the 4-step lifecycle as a PINNED step-scroll.
   Mirrors the platform section (.plat-pin): on desktop + motion the section pins and
   each step holds long enough to read, then cross-fades to the next as you scroll
   (initSteps + pinned paint). The step-tab rail highlights the active step.
   Mobile / reduced-motion: a normal click-tab block, one step at a time. */
.step-pin { position: relative; }
.step-pin__sticky { position: relative; }

/* step tabs (progress rail) */
.stabs { border-bottom: 1px solid var(--line); margin-top: clamp(1.4rem, 3vh, 2.6rem); }
.stabs__in { display: flex; gap: 0.4rem; overflow-x: auto; scrollbar-width: none;
  -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 24px), transparent);
  mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 24px), transparent); }
@media (min-width: 760px) { .stabs__in { -webkit-mask-image: none; mask-image: none; } }
.stabs__in::-webkit-scrollbar { display: none; }
.stab { appearance: none; background: none; border: none; cursor: pointer; padding: 0.95rem 0.9rem; min-height: 44px;
  font: 700 0.95rem "Manrope", sans-serif; color: var(--muted); border-bottom: 2px solid transparent;
  white-space: nowrap; flex: 1; min-width: max-content; display: inline-flex; align-items: center; gap: 0.55rem;
  transition: color .15s ease, border-color .15s ease; }
.stab__n { display: inline-grid; place-items: center; width: 24px; height: 24px; border-radius: 8px; flex: none;
  font-size: 0.82rem; font-weight: 800; color: var(--muted); background: var(--paper-2); border: 1px solid var(--line);
  transition: color .15s ease, background .2s ease, border-color .2s ease, box-shadow .2s ease; }
.stab:hover { color: var(--ink-soft); }
.stab.on { color: var(--ink); border-color: var(--ink); }
.stab.on .stab__n { color: #fff; background: linear-gradient(145deg, #4a41d8, #6d28d9); border-color: transparent;
  box-shadow: 0 6px 14px -4px rgb(76 65 216 / 0.6); }
@media (max-width: 600px) { .stab { flex: 0 0 auto; padding: 0.9rem 0.7rem; } }

/* panels — a VERTICAL stack (step label on top, video below), centered.
   One step shows at a time; there is NO scroll-parked in-between blend (see .is-shown). */
.smod { display: none; }
.smod.on { display: block; animation: fmodIn .28s cubic-bezier(.2, .7, .2, 1) both; }
@media (prefers-reduced-motion: reduce) { .smod.on { animation: none; } }
.smod__in { display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: clamp(1.1rem, 2.6vh, 1.9rem); padding: clamp(1.6rem, 4vh, 3.2rem) 0; max-width: 920px; margin: 0 auto; }

/* step label — title + short lead (the step NUMBER lives in the tab rail, not repeated here) */
.smod__text h3 { font-size: clamp(1.45rem, 2.8vw, 2.15rem); letter-spacing: -0.02em; margin: 0; color: var(--ink); }
.smod__text .lead { margin: 0.55rem auto 0; color: var(--ink-soft); font-size: clamp(1rem, 1.2vw, 1.12rem);
  line-height: 1.55; max-width: 38rem; }

/* media — browser-framed video, centered, shown full-frame (never cropped) */
.smod__visual { position: relative; width: 100%; max-width: 900px; }
.smod__visual::before { content: ""; position: absolute; inset: -7% -5% -13% -5%; z-index: 0; pointer-events: none;
  background: radial-gradient(60% 60% at 50% 42%, rgb(99 102 241 / 0.20), transparent 70%); filter: blur(30px); }
.sbrowser { position: relative; z-index: 1; border-radius: 16px; overflow: hidden; margin: 0 auto;
  border: 1px solid var(--line); background: #fff; box-shadow: var(--shadow-lg); }
.sbar { display: flex; align-items: center; gap: 0.6rem; padding: 0.55rem 0.85rem;
  background: var(--paper-2); border-bottom: 1px solid var(--line); }
.sdots { display: inline-flex; gap: 6px; flex: none; }
.sdots i { width: 10px; height: 10px; border-radius: 50%; }
.sdots i:nth-child(1) { background: #ff5f57; } .sdots i:nth-child(2) { background: #febc2e; } .sdots i:nth-child(3) { background: #28c840; }
.surl { font: 600 0.74rem ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.svid-wrap { position: relative; width: 100%; aspect-ratio: 16 / 9; }
.svid { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: contain; background: #0b0c0f; }

/* pinned mode (JS adds .is-steppin on desktop + motion) — ONE step per scroll, HARD snap.
   Content is anchored toward the TOP (not vertically centered) and kept compact, so there's no
   big gap under the hidden nav and the video isn't cramped at the bottom. The panels box clips
   its overflow so a tall video can't reach the tabs. background-image:none kills the scrolling
   dot-grid — only the pinned sticky's OWN dots (fixed in the viewport) show. */
.step-pin.is-steppin,
html.dark .step-pin.is-steppin { position: relative; background-image: none; }
.step-pin.is-steppin .step-pin__sticky { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden;
  display: flex; flex-direction: column; justify-content: flex-start; gap: clamp(0.3rem, 1vh, 0.7rem);
  padding: clamp(1rem, 4.5vh, 3rem) 0 clamp(0.8rem, 2vh, 1.4rem); }
.step-pin.is-steppin .wrap.section.tight { padding: 0; }
.step-pin.is-steppin .sec-head { margin: 0; }
/* On arrival the head is the SAME size as every other section head (inherits the base
   clamp); once the section PINS (.is-locked, set by JS) it shrinks modestly so the
   step + video fit the viewport. */
.step-pin.is-steppin .sec-head h2 { margin: 0.5rem 0 0;
  transition: font-size 0.4s cubic-bezier(0.2, 0.7, 0.2, 1); }
.step-pin.is-steppin.is-locked .sec-head h2 { font-size: clamp(1.6rem, 3.6vw, 2.9rem); }
.step-pin.is-steppin .sec-head .sub { display: none; }             /* compact header — give the step room */
.step-pin.is-steppin .stabs { position: static; margin-top: 0; background: transparent; }
.step-pin.is-steppin .step-pin__panels { position: relative; flex: 1 1 auto; min-height: 0; overflow: hidden; }
.step-pin.is-steppin .smod { position: absolute; inset: 0; display: block !important;
  opacity: 0; pointer-events: none; animation: none; }             /* hidden steps: instantly gone, no blend
     (animation:none kills the fallback .smod.on fmodIn fill that would otherwise pin step 1 visible) */
.step-pin.is-steppin .smod.is-shown { opacity: 1; pointer-events: auto;
  animation: stepIn .34s cubic-bezier(.2, .7, .2, 1); }
@keyframes stepIn { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .step-pin.is-steppin .smod.is-shown { animation: none; } }
.step-pin.is-steppin .smod__in { padding: clamp(0.4rem, 1.4vh, 1.1rem) 0 0; height: 100%; justify-content: flex-start;
  max-width: none; gap: clamp(0.7rem, 1.8vh, 1.3rem); }
/* height-bound the video so the whole step fits the viewport; the frame shrinks to it (no side bars) */
.step-pin.is-steppin .sbrowser { width: fit-content; max-width: 100%; }
.step-pin.is-steppin .svid-wrap { width: auto; height: clamp(185px, 40vh, 560px); }

/* dark */
html.dark .sbrowser { background: #0f1013; border-color: rgb(255 255 255 / 0.08); }
html.dark .sbar { background: rgb(255 255 255 / 0.05); border-color: rgb(255 255 255 / 0.08); }
html.dark .stab__n { background: rgb(255 255 255 / 0.05); border-color: rgb(255 255 255 / 0.08); }
html.dark .smod__visual::before { background: radial-gradient(58% 58% at 60% 42%, rgb(99 102 241 / 0.26), transparent 70%); }

/* ----------------------------------------------------------- browser/app frame (product mockup) */
.frame { background: #fff; border: 1px solid var(--line); border-radius: 14px; overflow: hidden; box-shadow: var(--shadow-lg); }
.frame__bar { display: flex; align-items: center; gap: 0.55rem; padding: 0.6rem 0.85rem; border-bottom: 1px solid var(--line); background: #faf9f6; }
.frame__dots { display: flex; gap: 0.34rem; }
.frame__dots i { width: 0.6rem; height: 0.6rem; border-radius: 50%; display: block; }
.frame__dots i:nth-child(1){background:#f87171;} .frame__dots i:nth-child(2){background:#fbbf24;} .frame__dots i:nth-child(3){background:#34d399;}
.frame__url { flex: 1; background: #fff; border: 1px solid var(--line); border-radius: 999px; padding: 0.28rem 0.75rem; font: 600 0.74rem ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.frame__live { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.72rem; font-weight: 700; color: var(--indigo-700); }
.frame__live::before { content:""; width:7px; height:7px; border-radius:50%; background:#34d399; animation: pulse 1.7s ease-out infinite; }
@keyframes pulse { 0%{box-shadow:0 0 0 0 rgb(52 211 153/.5);} 70%{box-shadow:0 0 0 6px rgb(52 211 153/0);} 100%{box-shadow:0 0 0 0 rgb(52 211 153/0);} }

/* App body = sidebar + main (used in hero + feature modules) */
.app { display: grid; grid-template-columns: 130px 1fr; min-height: 280px; }
.app__side { border-right: 1px solid var(--line); background: linear-gradient(180deg,#fbfaf7,#f4f3ee); padding: 0.8rem 0.55rem; display: flex; flex-direction: column; gap: 0.55rem; }
.app__brand { display: flex; align-items: center; gap: 0.45rem; font-weight: 800; font-size: 0.8rem; color: var(--indigo); padding: 0.1rem 0.3rem 0.3rem; }
.app__brand img { width: 18px; height: 18px; border-radius: 5px; }
.app__nav { display: flex; flex-direction: column; gap: 0.12rem; }
.app__nav a { display: flex; align-items: center; gap: 0.5rem; padding: 0.38rem 0.5rem; border-radius: 8px; font-size: 0.78rem; font-weight: 650; color: var(--ink-soft); }
.app__nav a.on { background: rgb(79 70 229 / 0.1); color: var(--indigo-700); font-weight: 750; }
.app__nav .i { display: inline-grid; place-items: center; width: 15px; height: 15px; border-radius: 4px; background: rgb(79 70 229 / 0.08); color: var(--indigo); font: 9px/1 ui-monospace,monospace; }
.app__nav a.on .i { background: var(--indigo); color: #fff; }
.app__main { display: flex; flex-direction: column; min-width: 0; }
.app__head { display: flex; align-items: center; gap: 0.55rem; padding: 0.55rem 0.8rem; border-bottom: 1px solid var(--line); }
.app__title { font: 600 0.78rem ui-monospace,monospace; color: var(--ink); }
.app__pass { margin-left: auto; font-size: 0.66rem; font-weight: 800; padding: 0.2rem 0.5rem; border-radius: 999px; background: var(--ok-100); color: #059669; }
.app__run { display: inline-flex; align-items: center; gap: 0.25rem; font-size: 0.7rem; font-weight: 800; color: #fff; padding: 0.25rem 0.55rem; border-radius: 7px; background: linear-gradient(135deg, var(--indigo-500), var(--indigo-700)); }
.app__stage { flex: 1; padding: 0.4rem; background: radial-gradient(rgb(20 22 30/.05) 1px, transparent 1.5px) 0 0/18px 18px, linear-gradient(180deg,#fdfdfb,#f5f4ef); }
.app__stage svg { display: block; width: 100%; height: auto; }
.app__foot { display: flex; flex-wrap: wrap; gap: 0.4rem; padding: 0.55rem 0.8rem; border-top: 1px solid var(--line); }
.app__step { display: inline-flex; align-items: center; gap: 0.32rem; font-size: 0.72rem; font-weight: 650; color: var(--ink-soft); }
.app__step .tick { color: var(--ok); font-weight: 900; }
.app__step.run { color: var(--indigo-700); font-weight: 750; }
.app__spin { width: 11px; height: 11px; border-radius: 50%; border: 2px solid var(--indigo-200); border-top-color: var(--indigo); animation: spin .9s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (max-width: 420px) { .app { grid-template-columns: 52px 1fr; } .app__nav a span:not(.i), .app__brand span, .app__title { display: none; } .app__nav a, .app__brand { justify-content: center; } }
@media (prefers-reduced-motion: reduce) { .app__spin, .frame__live::before { animation: none; } }

/* canvas nodes/edges (shared by hero + Visual Canvas module) */
.edge-base { fill:none; stroke: var(--indigo-200); stroke-width:2.5; stroke-linecap:round; }
.edge-base.ok{stroke:#bbf7d0;} .edge-base.warn{stroke:#fde68a;} .edge-base.err{stroke:#fecdd3;}
.edge-flow { fill:none; stroke: var(--indigo); stroke-width:2.5; stroke-linecap:round; stroke-dasharray:.1 13; animation: dash 1.1s linear infinite; }
.edge-flow.ok{stroke:#16a34a;} .edge-flow.warn{stroke:#d97706;} .edge-flow.err{stroke:#e11d48;}
@keyframes dash { to { stroke-dashoffset:-13.1; } }
.node rect { fill:#fff; stroke: var(--indigo-200); stroke-width:1.5; filter: drop-shadow(0 3px 5px rgb(79 70 229/.15)); }
.node.branch rect{stroke:var(--indigo);stroke-width:2;} .node.ok rect{stroke:#86efac;} .node.warn rect{stroke:#fbbf24;} .node.err rect{stroke:#fda4af;}
.node .t { font: 700 13px "Manrope",sans-serif; fill: var(--ink); }
.node .sdot{fill:var(--indigo);} .node.ok .sdot{fill:#16a34a;} .node.warn .sdot{fill:#d97706;} .node.err .sdot{fill:#e11d48;}
.node .port{fill:#fff;stroke:var(--indigo);stroke-width:1.5;}
@media (prefers-reduced-motion: reduce){ .edge-flow{animation:none;} }

/* terminal mockup (dark) — recorder/CLI teaser */
.term { background: #16171c; border-radius: 12px; overflow: hidden; border: 1px solid #2a2b31; box-shadow: var(--shadow-lg); }
.term__bar { display: flex; align-items: center; gap: 0.5rem; padding: 0.55rem 0.8rem; background: #1d1e24; border-bottom: 1px solid #2a2b31; }
.term__bar i { width: 0.6rem; height: 0.6rem; border-radius: 50%; }
.term__bar i:nth-child(1){background:#f87171;} .term__bar i:nth-child(2){background:#fbbf24;} .term__bar i:nth-child(3){background:#34d399;}
.term__bar span { margin-left: auto; font: 700 0.66rem ui-monospace,monospace; color: #6b7280; letter-spacing: 0.06em; }
.term__body { padding: 1rem 1.1rem; font: 0.84rem/1.7 ui-monospace, SFMono-Regular, Menlo, monospace; color: #e6e7ea; white-space: pre-wrap; word-break: break-word; }
.term__body .p { color: var(--indigo-300); } .term__body .c { color: #6b7280; } .term__body .g { color: #4ade80; } .term__body .cur { display:inline-block; width:8px; height:1.1em; background:var(--indigo-300); vertical-align:-2px; animation: blink 1s step-end infinite; }
@keyframes blink { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce){ .term__body .cur{animation:none;} }

/* ----------------------------------------------------------- teaser strip (Kane CLI style) */
.teaser { display: grid; grid-template-columns: 1fr 1.1fr; gap: clamp(1.5rem, 4vw, 3rem); align-items: center; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-lg); padding: clamp(1.5rem, 3vw, 2.6rem); box-shadow: var(--shadow); }
.teaser h3 { font-size: clamp(1.5rem, 2.6vw, 2.1rem); }
.teaser p { margin: 0.8rem 0 1.2rem; color: var(--ink-soft); font-weight: 500; }
@media (max-width: 760px) { .teaser { grid-template-columns: 1fr; } }

/* ----------------------------------------------------------- trust logos */
.trust__label { display: flex; align-items: center; justify-content: center; gap: clamp(.7rem, 2.4vw, 1.2rem); color: var(--ink-soft); font-size: 0.8rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; margin: 0 0 1.9rem; }
.trust__label::before, .trust__label::after { content: ""; height: 1px; width: clamp(24px, 7vw, 76px); background: var(--line); }
/* Frame the proof strip as its own band so it reads as a distinct section. */
.section.trust { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.trust__logos { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: clamp(1.5rem, 5vw, 3.5rem); }
.trust__logos img { height: 30px; width: auto; opacity: 0.7; filter: grayscale(1) brightness(0.4); }

/* ----------------------------------------------------------- pillar cards (big two-up) */
.pillars { display: grid; grid-template-columns: 1fr 1fr; gap: 1.4rem; margin-top: 2.6rem; }
@media (max-width: 860px) { .pillars { grid-template-columns: 1fr; } }
.pillar { position: relative; border-radius: var(--r-lg); overflow: hidden; border: 1px solid var(--line); background: linear-gradient(180deg, #eceaf6, #e7e9f4); box-shadow: var(--shadow); min-height: 460px; display: flex; flex-direction: column; }
.pillar.alt { background: linear-gradient(180deg, #efeae4, #ece6de); }
.pillar__visual { flex: 1; padding: 1.4rem 1.4rem 0; display: flex; align-items: flex-end; justify-content: center; overflow: hidden; }
.pillar__visual .frame, .pillar__visual .rows { width: 108%; transform: translateY(8%); }
.pillar__body { padding: 1.5rem 1.6rem 1.7rem; background: linear-gradient(180deg, transparent, rgb(255 255 255 / 0.55) 30%, #fff); }
.pillar__body h3 { font-size: clamp(1.4rem, 2.4vw, 1.9rem); }
.pillar__body p { margin: 0.7rem 0 1.1rem; color: var(--ink-soft); font-weight: 500; }

/* ----------------------------------------------------------- pipeline (Planning/Authoring/... ) */
.pipe { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.1rem; margin-top: 2.6rem; }
@media (max-width: 980px) { .pipe { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .pipe { grid-template-columns: 1fr; } }
.stage { background: var(--card); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; box-shadow: var(--shadow); display: flex; flex-direction: column; }
.stage__top { display: flex; align-items: center; gap: 0.6rem; padding: 0.85rem 1rem; font-weight: 800; border-bottom: 1px solid var(--line); }
.stage__top .ic { display: inline-grid; place-items: center; width: 1.7rem; height: 1.7rem; border-radius: 8px; font-size: 0.95rem; }
.stage:nth-child(1) .stage__top { background: linear-gradient(180deg, #eef2ff, #fff); } .stage:nth-child(1) .ic { background: var(--indigo-100); }
.stage:nth-child(2) .stage__top { background: linear-gradient(180deg, #f3ecff, #fff); } .stage:nth-child(2) .ic { background: #e9d8fd; }
.stage:nth-child(3) .stage__top { background: linear-gradient(180deg, #e7f7ee, #fff); } .stage:nth-child(3) .ic { background: #cdeedd; }
.stage:nth-child(4) .stage__top { background: linear-gradient(180deg, #fff1e6, #fff); } .stage:nth-child(4) .ic { background: #ffe0c7; }
.stage__num { margin-left: auto; font: 700 0.7rem ui-monospace,monospace; color: var(--muted); }
.stage__body { padding: 1rem; }
.stage__body h4 { font-size: 1rem; }
.stage__body p { margin: 0.35rem 0 0.8rem; font-size: 0.86rem; color: var(--ink-soft); font-weight: 500; }
.stage__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.4rem; }
.stage__list li { display: flex; align-items: flex-start; gap: 0.45rem; font-size: 0.82rem; color: var(--ink-soft); font-weight: 600; }
.stage__list .tick { color: var(--ok); font-weight: 900; flex: none; }

/* ----------------------------------------------------------- band cards (integrations / deployment) */
.bands { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; margin-top: 1.6rem; }
@media (max-width: 760px) { .bands { grid-template-columns: 1fr; } }
.band-card { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; background: var(--card); border: 1px solid var(--line); border-radius: var(--r); padding: 1.1rem 1.3rem; box-shadow: var(--shadow); }
.band-card b { font-size: 1.02rem; }
.band-card .chips { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.chip { display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.4rem 0.8rem; border-radius: 999px; background: var(--paper); border: 1px solid var(--line); font-size: 0.82rem; font-weight: 650; color: var(--ink-soft); }
.chip img { width: 14px; height: 14px; }
.chip.dot::before { content:""; width:7px; height:7px; border-radius:2px; background: var(--indigo); box-shadow: 0 0 0 3px rgb(79 70 229/.12); }
/* Six integrations read cleaner as a balanced 3-up grid (two equal rows of three)
   than a ragged flex-wrap. Equal columns + centred chips keep it tidy. */
.band-card .chips--grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.band-card .chips--grid .chip { justify-content: center; }

/* ----------------------------------------------------------- sticky feature tabs + modules */
.ftabs { position: sticky; top: var(--nav-h); z-index: 40; background: rgb(244 243 238 / 0.96); border-bottom: 1px solid var(--line); }
/* right-edge fade hints that the tab strip scrolls horizontally on small screens */
.ftabs__in { -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 24px), transparent); mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 24px), transparent); }
@media (min-width: 760px) { .ftabs__in { -webkit-mask-image: none; mask-image: none; } }
.ftabs__in { display: flex; gap: 0.4rem; overflow-x: auto; scrollbar-width: none; }
.ftabs__in::-webkit-scrollbar { display: none; }
.ftab { appearance: none; background: none; border: none; cursor: pointer; padding: 1rem 0.9rem; min-height: 44px; font: 700 0.95rem "Manrope",sans-serif; color: var(--muted); border-bottom: 2px solid transparent; white-space: nowrap; flex: 1; min-width: max-content; transition: color .15s ease, border-color .15s ease; }
.ftab:hover { color: var(--ink-soft); }
.ftab.on { color: var(--ink); border-color: var(--ink); }
@media (max-width: 600px) { .ftab { flex: 0 0 auto; padding: 1rem 0.7rem; } }
.fmod { display: none; }
/* Soft crossfade as a tab panel becomes active (replaces the abrupt display swap).
   display stays block so the nth-of-type backdrop gradients keep landing right. */
.fmod.on { display: block; animation: fmodIn .28s cubic-bezier(.2,.7,.2,1) both; }
@keyframes fmodIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .fmod.on { animation: none; } }
.fmod__in { display: grid; grid-template-columns: 1fr 1.15fr; gap: clamp(1.5rem, 4vw, 3.5rem); align-items: center; padding: clamp(2.5rem, 5vw, 4.5rem) 0; }
@media (max-width: 900px) { .fmod__in { grid-template-columns: 1fr; } }
.fmod h3 { font-size: clamp(1.8rem, 3vw, 2.6rem); margin-top: 0.6rem; }
.fmod .lead { margin: 0.9rem 0 1.3rem; color: var(--ink-soft); font-weight: 500; font-size: 1.05rem; }
.fmod__what { margin: 1.4rem 0 0.7rem; font-size: 0.92rem; font-weight: 700; color: var(--ink); }
.pillset { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.fmod__visual { position: relative; border-radius: var(--r-lg); padding: clamp(1rem, 2.4vw, 2rem); border: 1px solid var(--line); overflow: hidden; display: flex; align-items: center; justify-content: center; min-height: 320px;
  background: radial-gradient(120% 120% at 80% 0%, rgb(99 102 241/.18), transparent 60%), linear-gradient(160deg, #ecebf5, #f3f2ee); }
/* Soft "watercolor" backdrops that vary per module (testmu uses photographic
   landscapes; these evoke the same calm, textured feel with our palette). */
.fmod:nth-of-type(1) .fmod__visual { background: radial-gradient(110% 120% at 78% 4%, rgb(99 102 241/.22), transparent 58%), linear-gradient(155deg, #e9e7f6, #f1f0ec); }
.fmod:nth-of-type(2) .fmod__visual { background: radial-gradient(110% 120% at 22% 6%, rgb(124 58 237/.20), transparent 58%), linear-gradient(155deg, #efe9f6, #f2f0ec); }
.fmod:nth-of-type(3) .fmod__visual { background: radial-gradient(120% 120% at 82% 8%, rgb(79 70 229/.20), transparent 56%), linear-gradient(155deg, #e7eaf7, #f0f1ee); }
.fmod:nth-of-type(4) .fmod__visual { background: radial-gradient(120% 120% at 20% 2%, rgb(225 138 110/.20), transparent 56%), linear-gradient(155deg, #f4ece6, #f2f1ec); }
.fmod:nth-of-type(5) .fmod__visual { background: radial-gradient(120% 120% at 80% 6%, rgb(16 185 129/.16), transparent 56%), linear-gradient(155deg, #e7f1ec, #f1f1ec); }
.fmod:nth-of-type(6) .fmod__visual { background: radial-gradient(120% 120% at 24% 4%, rgb(99 102 241/.20), transparent 56%), linear-gradient(155deg, #e9e8f5, #f1f0ec); }
.fmod__visual::after { content:""; position:absolute; inset:0; pointer-events:none; background-image: radial-gradient(rgb(20 22 30/.04) 1px, transparent 1.5px); background-size: 18px 18px; opacity:.6; }
.fmod__visual > * { position: relative; z-index: 1; width: 100%; }

/* Video slot: a real product clip sits where the mock is. Hidden until its file
   loads (the mock stays as the fallback), so the page never looks broken. */
.fviz__vid { display: none; width: 100%; border-radius: 12px; box-shadow: var(--shadow-lg); background: #fff; }
.fviz.has-video .fviz__vid { display: block; }
.fviz.has-video > *:not(.fviz__vid) { display: none; }

/* -------------------------------------------------- media placeholders
   Tasteful skeleton frame where a real screenshot/clip will be dropped in.
   Wired for lazy-loading: .media-asset[data-src] / <source data-src> are
   promoted to src by initMedia() near the viewport; .media-ph keeps a premium
   look before any asset exists. Once a real asset loads, .has-asset hides the
   skeleton caption and the gradient gives way to the media. */
.media-ph { position: relative; display: block; width: 100%; min-height: clamp(240px, 30vw, 360px);
  background:
    radial-gradient(120% 80% at 15% 0%, rgb(79 70 229 / .07), transparent 60%),
    linear-gradient(135deg, #faf9f6, #f1efe9);
  display: grid; place-items: center; }
.media-ph .media-asset { display: none; width: 100%; height: 100%; object-fit: cover; border-radius: 0; box-shadow: none; background: #fff; }
.media-ph.has-asset .media-asset { display: block; }
.media-ph.has-asset::before, .media-ph.has-asset::after { display: none; }
/* skeleton sweep — calm, paused off-screen via .viz-off like the other paints */
.media-ph::before { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(100deg, transparent 20%, rgb(255 255 255 / .55) 50%, transparent 80%);
  background-size: 220% 100%; animation: mediaSweep 2.6s ease-in-out infinite; opacity: .7; }
.media-ph.viz-off::before { animation: none; }
/* caption: "Screenshot / clip goes here — <label>" pulled from data-ph-label */
.media-ph::after { content: "Screenshot / clip goes here" " — " attr(data-ph-label);
  position: relative; z-index: 1; max-width: 84%; text-align: center;
  font: 700 0.82rem var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  letter-spacing: .01em; color: var(--muted); padding: 0.55rem 0.9rem;
  background: rgb(255 255 255 / .7); border: 1px dashed var(--line); border-radius: 999px; }
@keyframes mediaSweep { 0% { background-position: 130% 0; } 100% { background-position: -30% 0; } }
@media (prefers-reduced-motion: reduce) { .media-ph::before { animation: none; } }
/* inline testimonial inside a module */
.quote { margin: 1.4rem 0 0; }
.quote p { font-size: 1.02rem; color: var(--ink); font-weight: 600; margin: 0; }
.quote p b { color: var(--indigo-700); }
.quote .who { display: flex; align-items: center; gap: 0.6rem; margin-top: 0.7rem; font-size: 0.88rem; }
.quote .who img { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; }
.quote .who b { display: block; } .quote .who span { color: var(--muted); }

/* row-list product visual (test cases / steps / heal) */
.rows { background: #fff; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; box-shadow: var(--shadow); }
.rows__bar { display: flex; align-items: center; gap: 0.5rem; padding: 0.55rem 0.8rem; background: #faf9f6; border-bottom: 1px solid var(--line); font: 600 0.74rem ui-monospace,monospace; color: var(--muted); }
.rows__bar i { width: 9px; height: 9px; border-radius: 50%; } .rows__bar i:nth-child(1){background:#f87171;} .rows__bar i:nth-child(2){background:#fbbf24;} .rows__bar i:nth-child(3){background:#34d399;}
.rows__bar .lbl { margin-left: 0.3rem; }
.rows__bar .rt { margin-left: auto; display: inline-flex; align-items: center; gap: 0.4rem; font-weight: 800; color: var(--indigo-700); }
.rows__bar .rt.rec { color: var(--err); } .rows__bar .rt::before { content:""; width:7px; height:7px; border-radius:50%; background:#34d399; } .rows__bar .rt.rec::before { background:var(--err); }
.rows__body { padding: 0.9rem; display: grid; gap: 0.5rem; }
.row { display: flex; align-items: center; gap: 0.6rem; padding: 0.6rem 0.78rem; border: 1px solid var(--line); border-radius: 10px; font-size: 0.9rem; font-weight: 600; color: var(--ink); box-shadow: 0 2px 6px -4px rgb(20 22 30/.18); }
.row.muted { color: var(--muted); border-style: dashed; box-shadow: none; }
.row.broken { border-color: #fda4af; background: #fff1f2; } .row.broken .sel { color: var(--err); text-decoration: line-through; }
.row.healed { border-color: #86efac; background: #f0fdf4; } .row.healed .sel { color: #15803d; }
.row .ck { color: var(--ok); font-weight: 900; } .row .x { color: var(--err); font-weight: 900; }
.row .n { display: inline-grid; place-items: center; width: 1.4rem; height: 1.4rem; border-radius: 7px; background: var(--indigo-50); color: var(--indigo-700); font-size: 0.76rem; font-weight: 800; }
.row .act { color: var(--muted); font-weight: 800; font-size: 0.7rem; text-transform: uppercase; letter-spacing: .04em; min-width: 3rem; }
.row .act.assert { color: var(--indigo); }
.row .sel { font: 600 0.82rem ui-monospace,monospace; }
.row .tag { margin-left: auto; font-size: 0.68rem; font-weight: 750; padding: 0.2rem 0.55rem; border-radius: 999px; background: var(--indigo-50); color: var(--indigo-700); white-space: nowrap; }
.row .tag.edge{background:#fef3c7;color:#b45309;} .row .tag.val{background:#ffe4e6;color:#be123c;} .row .tag.vis{background:#dcfce7;color:#15803d;}
.row__note { font-size: 0.82rem; color: var(--muted); font-weight: 600; padding: 0 0.3rem; }

/* ----------------------------------------------------------- platform coverage (web + mobile) */
.cov-section { position: relative; overflow: hidden; }
.cov-section::before { content:""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(60% 70% at 18% 0%, rgb(99 102 241/.12), transparent 60%), radial-gradient(60% 80% at 92% 30%, rgb(124 58 237/.10), transparent 58%); }
.cov-section > .wrap { position: relative; }
.cov { margin-top: clamp(2rem, 4vw, 3rem); display: grid; grid-template-columns: 1fr 1.05fr; gap: clamp(1.5rem, 4vw, 3.5rem); align-items: center; }
@media (max-width: 900px) { .cov { grid-template-columns: 1fr; } }

/* segmented platform switcher */
.cov-switch { display: grid; gap: 0.5rem; max-width: 27rem; }
.cov-pill { display: flex; align-items: center; gap: 0.75rem; text-align: left; padding: 0.65rem 0.85rem; border-radius: 14px;
  background: var(--card); border: 1px solid var(--line); box-shadow: var(--shadow); cursor: pointer; color: var(--ink);
  transition: transform .2s ease, border-color .2s ease, box-shadow .2s ease, background .2s ease; }
.cov-pill:hover { transform: translateY(-2px); border-color: var(--indigo-200); }
.cov-pill.on { border-color: transparent; background: linear-gradient(135deg, var(--indigo-700), var(--violet)); color: #fff; box-shadow: 0 18px 40px -20px rgb(79 70 229/.6); }
.cov-pill__ic { flex: none; width: 38px; height: 38px; display: grid; place-items: center; border-radius: 10px; background: var(--indigo-50); color: var(--indigo); transition: background .2s ease, color .2s ease; }
.cov-pill.on .cov-pill__ic { background: rgb(255 255 255/.16); color: #fff; }
.cov-pill__ic svg { width: 21px; height: 21px; }
.cov-pill__txt { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.cov-pill__txt b { font-size: 1rem; font-weight: 750; }
.cov-pill__txt span { font-size: 0.78rem; font-weight: 600; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cov-pill.on .cov-pill__txt span { color: rgb(255 255 255/.78); }
/* "Coming soon" platforms: greyed + not selectable, with an indigo soon pill so
   the roadmap still reads. They never get .on while disabled. */
.cov-pill.is-soon { cursor: default; box-shadow: none; }
.cov-pill.is-soon:hover { transform: none; border-color: var(--line); }
.cov-pill.is-soon .cov-pill__ic { background: var(--line); color: var(--muted); }
.cov-pill.is-soon .cov-pill__txt b { color: var(--muted); }
.cov-pill__soon { margin-left: auto; align-self: center; flex: none; font-size: 0.64rem; font-weight: 800;
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--indigo); background: var(--indigo-50);
  border: 1px solid var(--indigo-200); padding: 0.22rem 0.52rem; border-radius: 999px; white-space: nowrap; }

/* per-platform copy (only the active one shown) */
.cov-detail { display: none; margin-top: 1.5rem; }
.cov-detail.on { display: block; animation: covFade .35s ease both; }
.cov-detail h3 { font-size: clamp(1.3rem, 2.4vw, 1.7rem); }
.cov-detail p { margin: 0.6rem 0 0; color: var(--ink-soft); font-weight: 500; font-size: 1.02rem; }
.cov-detail .stage__list { margin-top: 1.1rem; max-width: 30rem; }
.cov__cta { margin-top: 1.6rem; }
@keyframes covFade { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .cov-detail.on, .cov-device.on, .cov-touch, .cov-rec::before { animation: none; } }

/* morphing device stage */
.cov-stage { position: relative; display: grid; place-items: center; min-height: clamp(520px, 58vw, 580px); }
.cov-device { grid-area: 1 / 1; width: 100%; display: flex; justify-content: center; opacity: 0; visibility: hidden; transform: scale(.97); transition: opacity .4s ease, transform .4s ease, visibility .4s; }
.cov-device.on { opacity: 1; visibility: visible; transform: none; }

/* web: browser frame */
.cov-web { width: 100%; max-width: 440px; }
.cov-web .rows__bar { border-radius: 0; }
.cov-web .rows__body { padding: 0.9rem; }

/* phone mockups — custom modern flagship frames (iPhone 16 Pro · Galaxy S25
   Ultra) drawn in CSS so they always look current and we control the polish.
   The floating cards, the live touch, and the REC chip show what's actually
   happening: AI driving native gestures on a real, screen-recorded device. */
.cov-phonewrap { position: relative; width: max-content; margin-inline: auto; }
.cov-glow { position: absolute; z-index: 0; width: 122%; height: 80%; left: 50%; top: 52%;
  transform: translate(-50%, -50%); pointer-events: none; filter: blur(24px);
  background: radial-gradient(58% 52% at 50% 45%, rgb(99 102 241 / .32), rgb(124 58 237 / .12) 55%, transparent 72%); }
.cov-device[data-plat="android"] .cov-glow {
  background: radial-gradient(58% 52% at 50% 45%, rgb(26 163 74 / .28), rgb(34 197 94 / .1) 55%, transparent 72%); }

.phone { position: relative; z-index: 2; width: 250px; padding: 12px; border-radius: 52px;
  background: linear-gradient(150deg, #4a4d56 0%, #1b1d23 30%, #131419 62%, #2c2f37 100%);
  box-shadow:
    inset 0 0 0 1.5px rgb(255 255 255 / .08),
    inset 0 2px 1px rgb(255 255 255 / .22),
    inset 0 -3px 3px rgb(0 0 0 / .55),
    0 44px 64px -30px rgb(16 18 26 / .62),
    0 20px 38px -24px rgb(16 18 26 / .5); }
.phone__screen { position: relative; border-radius: 40px; overflow: hidden; aspect-ratio: 9 / 19.5;
  background: #000; box-shadow: inset 0 0 0 1px rgb(0 0 0 / .5); }

/* iPhone: Dynamic Island */
.phone--ios .phone__island { position: absolute; z-index: 6; top: 22px; left: 50%; transform: translateX(-50%);
  width: 84px; height: 26px; border-radius: 999px; background: #07070a; }
.phone--ios .phone__island::after { content: ""; position: absolute; right: 11px; top: 50%; transform: translateY(-50%);
  width: 8px; height: 8px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #2a3b5a, #05060a 70%); box-shadow: 0 0 0 1px rgb(80 120 200 / .25); }

/* Galaxy: squarer body + centered punch-hole */
.phone--android { width: 248px; padding: 9px; border-radius: 44px;
  background: linear-gradient(150deg, #34373f 0%, #121318 55%, #26282f 100%); }
.phone--android .phone__screen { border-radius: 34px; aspect-ratio: 9 / 20; }
.phone--android .phone__punch { position: absolute; z-index: 6; top: 13px; left: 50%; transform: translateX(-50%);
  width: 11px; height: 11px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #233049, #04050a 72%); box-shadow: 0 0 0 2px rgb(0 0 0 / .4); }

/* subtle side rails */
.phone__btn { position: absolute; z-index: 1; border-radius: 4px; background: linear-gradient(180deg, #41444c, #1d2026); }
.phone--ios .phone__btn.act { left: -2px; top: 96px; width: 3px; height: 28px; }
.phone--ios .phone__btn.vup { left: -2px; top: 138px; width: 3px; height: 40px; }
.phone--ios .phone__btn.vdn { left: -2px; top: 188px; width: 3px; height: 40px; }
.phone--ios .phone__btn.pwr { right: -2px; top: 150px; width: 3px; height: 64px; }
.phone--android .phone__btn.vup { right: -2px; top: 104px; width: 3px; height: 40px; }
.phone--android .phone__btn.vdn { right: -2px; top: 150px; width: 3px; height: 40px; }
.phone--android .phone__btn.pwr { left: -2px; top: 150px; width: 3px; height: 50px; }

/* floating context cards — add depth + explain the mechanism */
.cov-tag { position: absolute; z-index: 8; display: flex; align-items: center; gap: 9px; max-width: 196px;
  padding: 9px 12px; border-radius: 14px; background: rgb(255 255 255 / .86);
  -webkit-backdrop-filter: blur(10px) saturate(1.4); backdrop-filter: blur(10px) saturate(1.4);
  border: 1px solid rgb(255 255 255 / .75);
  box-shadow: 0 20px 42px -18px rgb(20 22 30 / .45), 0 3px 8px -3px rgb(20 22 30 / .2); }
.cov-tag__ic { flex: none; width: 30px; height: 30px; border-radius: 9px; display: grid; place-items: center;
  color: #fff; background: linear-gradient(135deg, var(--indigo-500), var(--indigo-700)); }
.cov-device[data-plat="android"] .cov-tag__ic { background: linear-gradient(135deg, #1aa34a, #15803d); }
.cov-tag__ic svg { width: 17px; height: 17px; }
.cov-tag__tx { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.cov-tag__tx b { font-size: .82rem; font-weight: 750; color: var(--ink); }
.cov-tag__tx span { font-size: .7rem; font-weight: 600; color: var(--muted); }
.cov-tag--cloud { top: -16px; left: -8px; }
.cov-tag--ai { bottom: 12px; right: -12px; }

/* in-screen REC chip — "screen recording of every run" */
.cov-rec { margin-left: auto; display: inline-flex; align-items: center; gap: 5px;
  font: 800 10px ui-monospace, monospace; letter-spacing: .04em; color: #b91c1c;
  background: #fee2e2; padding: 4px 9px; border-radius: 999px; }
.cov-rec::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: #ef4444; animation: covRec 1.5s ease-in-out infinite; }

/* live AI touch on the active gesture row */
.cov-step.is-live { position: relative; border-color: var(--indigo-200); box-shadow: 0 6px 18px -8px rgb(79 70 229 / .4); }
.cov-touch { position: absolute; right: 38px; top: 50%; width: 22px; height: 22px; border-radius: 50%;
  transform: translateY(-50%); background: rgb(79 70 229 / .9); pointer-events: none; animation: covTap 1.8s ease-out infinite; }
.cov-device[data-plat="android"] .cov-touch { background: rgb(26 163 74 / .92); }

@keyframes covRec { 0%, 100% { opacity: 1; } 50% { opacity: .2; } }
@keyframes covTap {
  0% { box-shadow: 0 0 0 0 rgb(79 70 229 / .5); opacity: .9; }
  70% { box-shadow: 0 0 0 16px rgb(79 70 229 / 0); opacity: .5; }
  100% { box-shadow: 0 0 0 0 rgb(79 70 229 / 0); opacity: .9; } }

/* the live "screen" rendered inside the phone */
.cov-screen { position: absolute; inset: 0; display: flex; flex-direction: column; background: linear-gradient(180deg, #ffffff, #f6f5f1); font-family: inherit; }
.cov-sb { display: flex; align-items: center; justify-content: space-between; padding: 26px 30px 8px; font-size: 15px; font-weight: 800; color: var(--ink); }
.cov-screen--ios .cov-sb { padding-top: 30px; }
.cov-sig { display: inline-flex; align-items: center; gap: 3px; font-size: 12px; font-weight: 800; }
.cov-sig i { width: 4px; height: 11px; border-radius: 1px; background: var(--ink); display: inline-block; }
.cov-apphdr { display: flex; align-items: center; gap: 10px; padding: 8px 20px 14px; }
.cov-appic { font-size: 20px; line-height: 1; }
.cov-appname { font-weight: 800; font-size: 17px; color: var(--ink); }
.cov-steps { flex: 1; display: flex; flex-direction: column; gap: 9px; padding: 4px 12px; }
.cov-step { display: flex; align-items: center; gap: 7px; background: #fff; border: 1px solid var(--line); border-radius: 14px; padding: 10px 9px; box-shadow: 0 6px 16px -10px rgb(20 22 30 / .22); font-size: 13px; font-weight: 650; color: var(--ink); }
.cov-step .g { font: 800 9.5px ui-monospace, monospace; letter-spacing: .02em; color: var(--muted); min-width: 30px; }
.cov-step .ck { color: var(--ok); font-weight: 900; font-size: 15px; min-width: 20px; text-align: center; }
.cov-step .t { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cov-step .b { margin-left: auto; font-size: 10px; font-weight: 800; padding: 3px 8px; border-radius: 999px; white-space: nowrap; }
.cov-step .b.ok { background: #dcfce7; color: #15803d; }
.cov-step .b.mut, .cov-step .b.ind { background: var(--indigo-50); color: var(--indigo-700); }
.cov-home { width: 130px; height: 5px; border-radius: 999px; background: var(--ink); opacity: .8; margin: 10px auto 14px; }
.cov-nav { display: flex; align-items: center; justify-content: center; gap: 52px; padding: 12px 0 18px; }
.cov-nav span { width: 16px; height: 16px; border: 2px solid var(--muted); }
.cov-nav span:nth-child(1) { border-radius: 50%; }
.cov-nav span:nth-child(2) { border-radius: 3px; }
.cov-nav span:nth-child(3) { transform: rotate(45deg); border-radius: 3px; }
@media (max-width: 900px) { .cov-stage { min-height: 560px; } }

/* ----------------------------------------------------------- stats */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.1rem; }
@media (max-width: 760px) { .stats { grid-template-columns: repeat(2, 1fr); } }
.stat { text-align: center; padding: 1.5rem 1rem; }
.stat b { display: block; font-size: clamp(2.2rem, 5vw, 3.4rem); font-weight: 800; letter-spacing: -0.03em; color: var(--ink); line-height: 1; }
.stat b .u { color: var(--indigo); }
.stat span { display: block; margin-top: 0.5rem; font-size: 0.92rem; font-weight: 600; color: var(--muted); }

/* ----------------------------------------------------------- dark credibility / testimonial */
/* indigo/violet brand card — deliberately a different colour from the near-black
   ".cta-final" that sits right below it, so the testimonial reads as its own block. */
.cred { position: relative; border-radius: var(--r-lg); overflow: hidden; background: linear-gradient(145deg, #4a41d8 0%, #6d28d9 100%); color: #fff; padding: clamp(2.2rem, 5vw, 3.6rem); box-shadow: var(--shadow-lg); }
.cred::before { content:""; position:absolute; inset:0; background: radial-gradient(85% 120% at 88% -10%, rgb(255 255 255/.18), transparent 55%), radial-gradient(80% 120% at 0% 110%, rgb(0 0 0/.24), transparent 55%); pointer-events:none; }
.cred__in { position: relative; display: grid; grid-template-columns: 200px 1fr; gap: clamp(1.5rem, 4vw, 2.6rem); align-items: center; }
@media (max-width: 720px) { .cred__in { grid-template-columns: 1fr; } }
.cred__photo { aspect-ratio: 1; border-radius: 18px; overflow: hidden; border: 1px solid rgb(255 255 255/.15); max-width: 200px; }
.cred__photo img { width: 100%; height: 100%; object-fit: cover; }
.cred blockquote { margin: 0; font-size: clamp(1.2rem, 2.4vw, 1.7rem); font-weight: 600; line-height: 1.35; letter-spacing: -0.01em; color: rgb(255 255 255 / 0.85); }
.cred blockquote b { color: #fff; font-weight: 800; }
.cred .who { margin-top: 1.2rem; display: flex; flex-direction: column; gap: 0.1rem; }
.cred .who b { font-weight: 800; }
.cred .who span { color: rgb(255 255 255 / 0.72); font-size: 0.92rem; font-weight: 600; }
.cred .who a { display: inline-flex; align-items: center; gap: 0.4rem; margin-top: 0.5rem; color: #fff; font-weight: 700; width: fit-content; }
.cred .who a svg { width: 18px; height: 18px; fill: currentColor; }

/* ----------------------------------------------------------- reasons grid */
.reasons { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.1rem; margin-top: 2.6rem; }
@media (max-width: 920px) { .reasons { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .reasons { grid-template-columns: 1fr; } }
.reason { background: var(--card); border: 1px solid var(--line); border-radius: var(--r); padding: 1.5rem 1.4rem; box-shadow: var(--shadow); transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease; }
.reason:hover { transform: translateY(-3px); border-color: var(--indigo-200); box-shadow: var(--shadow-lg); }
.reason .ic { display: inline-grid; place-items: center; width: 2.6rem; height: 2.6rem; border-radius: 12px; background: linear-gradient(135deg, var(--indigo-50), var(--indigo-100)); border: 1px solid var(--indigo-100); font-size: 1.3rem; margin-bottom: 1rem; }
.reason h4 { font-size: 1.12rem; }
.reason p { margin: 0.45rem 0 0; color: var(--ink-soft); font-size: 0.92rem; font-weight: 500; }
.reason.badge { background: linear-gradient(160deg, var(--indigo-50), #fff); border-color: var(--indigo-100); }
.reason.badge .k { font-size: 0.72rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--indigo); }

/* ----------------------------------------------------------- pricing */
.plans { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.1rem; margin-top: 2.6rem; align-items: stretch; }
.plans--5 { grid-template-columns: repeat(5, 1fr); }
/* Two paid tiers + Enterprise — three even columns, centered on a tidy width. */
.plans--3 { grid-template-columns: repeat(3, 1fr); max-width: 64rem; margin-inline: auto; }
@media (max-width: 1200px) { .plans--5 { grid-template-columns: repeat(3, 1fr); max-width: 60rem; margin-inline: auto; } }
@media (max-width: 900px) { .plans--3 { grid-template-columns: 1fr; max-width: 26rem; } }
@media (max-width: 1040px) { .plans { grid-template-columns: repeat(2, 1fr); max-width: 44rem; margin-inline: auto; } .plans--5 { grid-template-columns: repeat(2, 1fr); max-width: 44rem; } }
@media (max-width: 560px) { .plans { grid-template-columns: 1fr; max-width: 24rem; } .plans--5 { grid-template-columns: 1fr; max-width: 24rem; } }
.plans__note { margin: 1.4rem auto 0; text-align: center; color: var(--muted); font-size: 0.92rem; font-weight: 500; }
.plans__note a { color: var(--indigo); font-weight: 700; }
/* paper cards: solid, focused centre with the outer edges very gently receding —
   a barely-there vignette so each card reads like a lit sheet of paper, not a flat
   box. Squarer corners lean into the "paper" feel. Kept deliberately subtle. */
.plan { position: relative; display: flex; flex-direction: column;
  background: radial-gradient(118% 100% at 50% 38%, transparent 50%, rgb(20 22 30 / 0.05) 100%), var(--card);
  border: 1px solid var(--line); border-radius: 11px; padding: 1.7rem; box-shadow: var(--shadow); }
html.dark .plan { background: radial-gradient(120% 100% at 50% 34%, rgb(255 255 255 / 0.045), transparent 56%), var(--card); }
.plan.featured { border-color: var(--indigo); box-shadow: 0 26px 60px -26px rgb(79 70 229/.45); }
.plan__name { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; min-height: 1.9rem; }
.plan__name h3 { font-size: 1.2rem; }
.plan .tag { font-size: 0.62rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: #fff; background: var(--indigo); padding: 0.28rem 0.5rem; border-radius: 999px; }
.plan .price { margin: 1rem 0 0; font-size: 2.6rem; font-weight: 800; letter-spacing: -0.03em; line-height: 1; }
.plan .price .per { font-size: 0.92rem; font-weight: 600; color: var(--muted); }
.plan .price.custom { font-size: 2.1rem; }
.plan .for { margin: 0.5rem 0 0; color: var(--muted); font-size: 0.9rem; font-weight: 500; }
.plan ul { list-style: none; padding: 1.3rem 0 0; margin: 1.3rem 0 1.5rem; display: grid; gap: 0.7rem; border-top: 1px solid var(--line); }
.plan li { display: flex; gap: 0.55rem; align-items: flex-start; font-size: 0.92rem; color: var(--ink-soft); font-weight: 500; }
.plan li.inherit { color: var(--indigo-700); font-weight: 700; }
.plan li .ck { color: var(--indigo); font-weight: 900; flex: none; }
.plan .btn { margin-top: auto; width: 100%; }

/* ----------------------------------------------------------- faq (two-column) */
.faq { display: grid; grid-template-columns: 0.8fr 1.4fr; gap: clamp(1.5rem, 4vw, 3rem); align-items: start; }
@media (max-width: 820px) { .faq { grid-template-columns: 1fr; } }
.faq__head h2 { font-size: clamp(2rem, 4vw, 3rem); }
.faq__list { display: grid; gap: 0; }
.faq__list details { border-bottom: 1px solid var(--line); padding: 0.3rem 0; }
.faq__list summary { cursor: pointer; list-style: none; display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 1.15rem 0.2rem; font-weight: 700; font-size: 1.05rem; color: var(--ink); }
.faq__list summary::-webkit-details-marker { display: none; }
.faq__list summary::after { content: "+"; font: 700 1.4rem ui-monospace,monospace; color: var(--indigo); transition: transform .2s ease; }
.faq__list details[open] summary::after { transform: rotate(45deg); }
.faq__list p { margin: -0.2rem 0.2rem 1.2rem; color: var(--ink-soft); font-weight: 500; max-width: 52ch; }
.faq__list a { color: var(--indigo); font-weight: 700; }

/* ----------------------------------------------------------- enterprise + final CTA */
.ent { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.5rem, 4vw, 3rem); background: var(--card); border: 1px solid var(--line); border-radius: var(--r-lg); padding: clamp(1.8rem, 4vw, 3rem); box-shadow: var(--shadow); align-items: center; }
@media (max-width: 800px) { .ent { grid-template-columns: 1fr; } }
.ent h2 { font-size: clamp(1.8rem, 3.4vw, 2.6rem); }
.ent p { margin: 0.8rem 0 1.4rem; color: var(--ink-soft); font-weight: 500; }
.ent__list { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; }
@media (max-width: 480px) { .ent__list { grid-template-columns: 1fr; } }
.ent__list li { display: flex; gap: 0.5rem; align-items: flex-start; font-size: 0.92rem; font-weight: 600; color: var(--ink-soft); }
.ent__list .ck { color: var(--indigo); font-weight: 900; }

.cta-final { position: relative; overflow: hidden; border-radius: var(--r-lg); background: var(--dark); color: #fff; text-align: center; padding: clamp(2.8rem, 6vw, 4.6rem); box-shadow: var(--shadow-lg); }
.cta-final::before { content:""; position:absolute; inset:0; z-index: 0; background: radial-gradient(90% 120% at 50% -10%, rgb(99 102 241/.4), transparent 60%); pointer-events:none; }
/* blueprint: a fine indigo graph-paper grid, faded to the edges by a radial mask
   so it's densest (most "drafted") through the centre. Very subtle. */
.cta-final::after { content:""; position:absolute; inset:0; z-index: 0; pointer-events:none;
  background-image:
    linear-gradient(rgb(165 180 252 / 0.09) 1px, transparent 1px),
    linear-gradient(90deg, rgb(165 180 252 / 0.09) 1px, transparent 1px);
  background-size: 34px 34px;
  -webkit-mask-image: radial-gradient(115% 92% at 50% 46%, #000 26%, transparent 80%);
          mask-image: radial-gradient(115% 92% at 50% 46%, #000 26%, transparent 80%); }
.cta-final > * { position: relative; z-index: 1; }
/* the glossy 3D app icon crowns the closing card — glowing off the dark panel + a
   slow float for life; drop-shadow (not box-shadow) hugs the icon's transparent silhouette. */
.cta-final__logo { display: flex; justify-content: center; margin-bottom: clamp(0.4rem, 1.6vw, 1.1rem); }
.cta-final__logo img { width: clamp(160px, 24vw, 280px); height: auto;
  filter: drop-shadow(0 26px 46px rgb(76 65 216 / 0.5)); animation: float3d 6s ease-in-out infinite; will-change: transform; }
@keyframes float3d { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-11px); } }
@media (prefers-reduced-motion: reduce) { .cta-final__logo img { animation: none; } }
.cta-final h2 { font-size: clamp(2.1rem, 5vw, 3.4rem); }
.cta-final p { margin: 1rem auto 1.8rem; max-width: 40rem; color: var(--on-dark-soft); font-weight: 500; }
.cta-final .cta { display: flex; justify-content: center; flex-wrap: wrap; gap: 0.8rem; }

/* ----------------------------------------------------------- waitlist form */
.wl { max-width: 640px; margin: 2.4rem auto 0; background: var(--card); border: 1px solid var(--line); border-radius: var(--r); padding: clamp(1.4rem, 3vw, 2rem); box-shadow: var(--shadow); display: grid; gap: 1.1rem; }
.wl__row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; }
@media (max-width: 560px) { .wl__row { grid-template-columns: 1fr; } }
.wl__field { display: grid; gap: 0.4rem; }
.wl__label { font-size: 0.86rem; font-weight: 700; color: var(--ink); }
.wl__opt { font-weight: 600; color: var(--muted); }
.wl__input { width: 100%; padding: 0.7rem 0.85rem; border: 1px solid var(--line); border-radius: 10px; background: var(--paper); color: var(--ink); font: inherit; font-size: 0.95rem; transition: border-color .18s ease, box-shadow .18s ease, background .18s ease; }
.wl__input::placeholder { color: var(--muted); }
.wl__input:focus { outline: none; border-color: var(--indigo); background: var(--card); box-shadow: 0 0 0 4px rgb(79 70 229 / 0.12); }
.wl__input.is-invalid { border-color: var(--err); box-shadow: 0 0 0 4px rgb(225 29 72 / 0.1); }
textarea.wl__input { resize: vertical; min-height: 86px; }
/* reserve the error line permanently so showing/clearing it never shifts the
   form layout (empty keeps its height instead of collapsing to display:none). */
.wl__err { font-size: 0.8rem; font-weight: 600; color: var(--err); min-height: 1.05rem; line-height: 1.3; }
.wl__submit { width: 100%; justify-content: center; margin-top: 0.2rem; }
.wl__note { margin: 0; padding: 0.85rem 1rem; border-radius: 10px; font-weight: 600; font-size: 0.92rem; text-align: center; }
.wl__note.ok { background: var(--ok-100); color: #15803d; border: 1px solid rgb(22 163 74 / 0.3); }
.wl__note.bad { background: #fff1f2; color: var(--err); border: 1px solid rgb(225 29 72 / 0.3); }

/* ----------------------------------------------------------- footer */
/* Dark footer — mirrors the dark topbar (page reads dark → light → dark) so the
   bottom overscroll (html background is --dark) blends into it instead of
   showing a beige-to-black seam. */
footer { position: relative; overflow: hidden; color: #fff; padding: clamp(3rem, 6vw, 4.5rem) 0 2.5rem;
  /* matches the topbar + .cta-final: --dark base with an indigo glow, blueprint grid on ::before */
  background-color: var(--dark);
  background-image: radial-gradient(80% 130% at 50% -8%, rgb(99 102 241 / 0.32), transparent 60%); }
footer::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    linear-gradient(rgb(165 180 252 / 0.08) 1px, transparent 1px),
    linear-gradient(90deg, rgb(165 180 252 / 0.08) 1px, transparent 1px);
  background-size: 34px 34px;
  -webkit-mask-image: radial-gradient(120% 100% at 50% 22%, #000 24%, transparent 82%);
          mask-image: radial-gradient(120% 100% at 50% 22%, #000 24%, transparent 82%); }
footer > * { position: relative; z-index: 1; }
.foot { position: relative; display: grid; grid-template-columns: 1.8fr repeat(4, 1fr); gap: 2rem 1.5rem; }
@media (max-width: 860px) { .foot { grid-template-columns: 1fr 1fr; padding-bottom: 3.25rem; } }
@media (max-width: 520px) { .foot { grid-template-columns: 1fr; } }
footer .brand { color: #fff; }
.foot__brand p { margin: 0.9rem 0 1.1rem; max-width: 26rem; color: rgb(255 255 255 / 0.6); font-size: 0.92rem; }
.foot__brand .copy { color: rgb(255 255 255 / 0.4); font-size: 0.85rem; display: block; }
.foot__col h4 { font-size: 0.74rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: rgb(255 255 255 / 0.5); margin: 0 0 0.9rem; }
.foot__col a { display: block; padding: 0.3rem 0; color: rgb(255 255 255 / 0.72); font-weight: 600; font-size: 0.92rem; }
.foot__col a:hover { color: #fff; }
/* Back-to-top button, bottom-right of the footer. #top + the global smooth-scroll
   mirror the footer brand link — no JS needed. */
.foot__top { position: absolute; right: 0; bottom: 0; display: inline-flex; align-items: center; justify-content: center; width: 2.6rem; height: 2.6rem; border-radius: 12px; color: #fff; background: rgb(255 255 255 / 0.06); border: 1px solid rgb(255 255 255 / 0.14); transition: transform .2s ease, background .2s ease, border-color .2s ease; }
.foot__top:hover { background: rgb(255 255 255 / 0.12); border-color: rgb(255 255 255 / 0.3); transform: translateY(-2px); }
.foot__top svg { width: 18px; height: 18px; }

/* ----------------------------------------------------------- legal subpages helper */
.subpage { min-height: calc(100vh - var(--nav-h)); padding: clamp(3rem, 6vw, 5rem) 0; }
.subpage .about { display: grid; grid-template-columns: 240px 1fr; gap: 2.4rem; align-items: center; margin-top: 1.6rem; }
@media (max-width: 720px) { .subpage .about { grid-template-columns: 1fr; max-width: 32rem; } }
.subpage .about .photo { aspect-ratio: 1; border-radius: 18px; overflow: hidden; box-shadow: var(--shadow); }
.subpage .about .photo img { width: 100%; height: 100%; object-fit: cover; }
.subpage .about p { margin: 0 0 1rem; color: var(--ink-soft); font-size: 1.05rem; }
.subpage .about b { color: var(--ink); }
.subpage .about a.li { display: inline-flex; align-items: center; gap: 0.5rem; color: var(--indigo); font-weight: 700; }
.subpage .about a.li svg { width: 20px; height: 20px; fill: currentColor; }

/* ----------------------------------------------------------- Jira closed-loop */
.loop { display: grid; grid-template-columns: 1fr 1.05fr; gap: clamp(1.5rem, 4vw, 3.5rem); align-items: center; }
@media (max-width: 900px) { .loop { grid-template-columns: 1fr; } }
.loop__visual { position: relative; border-radius: var(--r-lg); padding: clamp(1.1rem, 2.6vw, 1.8rem); border: 1px solid var(--line); overflow: hidden;
  background: radial-gradient(120% 120% at 80% 0%, rgb(38 132 255 / 0.14), transparent 58%), linear-gradient(160deg, #e9edf6, #f2f1ec); }
.loop__visual::after { content:""; position:absolute; inset:0; pointer-events:none; background-image: radial-gradient(rgb(20 22 30/.04) 1px, transparent 1.5px); background-size: 18px 18px; opacity:.55; }
.loop__visual > * { position: relative; }
/* ticket + comment cards */
.tkt { background: #fff; border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow); padding: 0.9rem 1rem; }
.tkt__head { display: flex; align-items: center; gap: 0.5rem; font-size: 0.78rem; font-weight: 700; color: var(--muted); }
.tkt__head img { width: 16px; height: 16px; }
.tkt__key { color: #2684ff; font-weight: 800; }
.tkt__title { margin: 0.45rem 0 0.65rem; font-size: 1rem; font-weight: 700; color: var(--ink); }
.tkt__row { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.tkt__assignee { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.78rem; font-weight: 650; color: var(--ink-soft); }
.tkt__bot { display: inline-grid; width: 20px; height: 20px; border-radius: 6px; overflow: hidden; flex: none; box-shadow: 0 0 0 1px rgb(20 22 30 / 0.06); }
.tkt__bot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tkt__status { margin-left: auto; font-size: 0.66rem; font-weight: 800; letter-spacing: .03em; padding: 0.2rem 0.5rem; border-radius: 5px; }
.tkt__status.todo { background: #e4e6ea; color: #5a6473; }
.tkt__status.done { background: var(--ok-100); color: #15803d; }
.loop__arrow { display: flex; align-items: center; justify-content: center; gap: 0.5rem; padding: 0.55rem 0; color: var(--indigo); font-weight: 700; font-size: 0.82rem; }
.loop__arrow::before, .loop__arrow::after { content:""; height: 1px; flex: 1; background: linear-gradient(90deg, transparent, var(--indigo-200)); }
.cmt { background: #fff; border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow); padding: 0.85rem 1rem; }
.cmt__head { display: flex; align-items: center; gap: 0.5rem; font-size: 0.8rem; }
.cmt__av { display: inline-grid; width: 22px; height: 22px; border-radius: 6px; overflow: hidden; flex: none; box-shadow: 0 0 0 1px rgb(20 22 30 / 0.06); }
.cmt__av img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cmt__who { font-weight: 800; color: var(--ink); }
.cmt__when { color: var(--muted); font-weight: 600; }
.cmt__body { margin: 0.55rem 0 0; font-size: 0.88rem; color: var(--ink-soft); font-weight: 500; line-height: 1.5; }
.cmt__body b { color: #15803d; font-weight: 800; }
.cmt__tags { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: 0.6rem; }
.cmt__tag { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.68rem; font-weight: 700; padding: 0.2rem 0.5rem; border-radius: 999px; background: var(--paper); border: 1px solid var(--line); color: var(--ink-soft); }

/* ----------------------------------------------------------- integrations grid */
.intg-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-top: 2.4rem; }
@media (max-width: 820px) { .intg-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 560px) { .intg-grid { grid-template-columns: repeat(2, 1fr); } }
.intg { display: flex; align-items: center; gap: 0.7rem; background: var(--card); border: 1px solid var(--line); border-radius: var(--r); padding: 0.95rem 1.1rem; box-shadow: var(--shadow);
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease; }
.intg:hover { transform: translateY(-2px); border-color: var(--indigo-200); box-shadow: var(--shadow-lg); }
.intg img { width: 24px; height: 24px; flex: none; }
.intg b { font-size: 0.92rem; font-weight: 700; color: var(--ink); }
.intg span { display: block; font-size: 0.74rem; font-weight: 600; color: var(--muted); margin-top: 1px; }
.intg__more { display: flex; align-items: center; justify-content: center; color: var(--muted); font-weight: 700; font-size: 0.9rem; border-style: dashed; }

/* ----------------------------------------------------------- AI agent team */
.team-roster { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-top: 2.4rem; }
@media (max-width: 980px) { .team-roster { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 540px) { .team-roster { grid-template-columns: 1fr; } }
.agent { background: var(--card); border: 1px solid var(--line); border-radius: var(--r); padding: 1.4rem; box-shadow: var(--shadow); transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease; }
.agent:hover { transform: translateY(-3px); border-color: var(--indigo-200); box-shadow: var(--shadow-lg); }
.agent__ic { display: inline-grid; place-items: center; width: 2.6rem; height: 2.6rem; border-radius: 12px; background: linear-gradient(135deg, var(--indigo-50), var(--indigo-100)); border: 1px solid var(--indigo-100); font-size: 1.3rem; margin-bottom: 0.9rem; }
.agent__role { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.agent__role h4 { font-size: 1.04rem; }
.agent__badge { font-size: 0.6rem; font-weight: 800; letter-spacing: 0.05em; text-transform: uppercase; color: var(--indigo); background: rgb(79 70 229 / 0.09); padding: 0.16rem 0.45rem; border-radius: 999px; }
.agent p { margin: 0.5rem 0 0; color: var(--ink-soft); font-size: 0.9rem; font-weight: 500; }
.team-verify { margin: 1.8rem auto 0; max-width: 48rem; text-align: center; color: var(--ink-soft); font-weight: 600; font-size: 1.02rem; }
.team-verify b { color: var(--ink); }

/* "replaces" band — hires you skip + tools you retire (strikethrough chips) */
.replaces { display: grid; grid-template-columns: 1fr 1fr; gap: 1.6rem 2.4rem; margin-top: 2.8rem; padding-top: 2rem; border-top: 1px solid var(--line); }
@media (max-width: 720px) { .replaces { grid-template-columns: 1fr; } }
.replaces .stack-label { margin: 0 0 0.9rem; }
.strikes { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.strike { display: inline-flex; align-items: center; gap: 0.45rem; padding: 0.4rem 0.85rem; border-radius: 999px; background: var(--card); border: 1px solid var(--line); font-size: 0.85rem; font-weight: 650; color: var(--muted); text-decoration: line-through; text-decoration-color: rgb(244 63 94 / 0.55); text-decoration-thickness: 2px; }
.strike::before { content: ""; width: 7px; height: 7px; border-radius: 2px; background: #f43f5e; box-shadow: 0 0 0 3px rgb(244 63 94 / 0.12); flex: none; }
.replaces__then { margin: 1.1rem 0 0; display: inline-flex; align-items: center; gap: 0.5rem; font-weight: 800; font-size: 1.05rem; color: var(--indigo-700); }
.replaces__then img { width: 24px; height: 24px; border-radius: 7px; }
.team-note { margin: 2rem 0 0; text-align: center; color: var(--muted); font-weight: 600; font-size: 0.92rem; }
.team-note b { color: var(--ink-soft); }

/* ----------------------------------------------------------- MCP / Claude Code */
.mcp { display: grid; grid-template-columns: 1fr 1.05fr; gap: clamp(1.5rem, 4vw, 3.5rem); align-items: center; }
@media (max-width: 900px) { .mcp { grid-template-columns: 1fr; } }
.mcp-card { background: var(--dark); border-radius: var(--r-lg); border: 1px solid #2a2b31; box-shadow: var(--shadow-lg); overflow: hidden; }
.mcp-card__bar { display: flex; align-items: center; gap: 0.6rem; padding: 0.85rem 1rem; border-bottom: 1px solid #2a2b31; }
.mcp-card__bar img { width: 22px; height: 22px; border-radius: 6px; }
.mcp-card__name { font-weight: 800; color: #fff; }
.mcp-card__on { margin-left: auto; display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.68rem; font-weight: 800; letter-spacing: 0.03em; color: #4ade80; background: rgb(74 222 128 / 0.12); padding: 0.2rem 0.55rem; border-radius: 999px; }
.mcp-card__on::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: #4ade80; }
.mcp-card__url { padding: 0.55rem 1rem; font: 600 0.72rem ui-monospace, SFMono-Regular, Menlo, monospace; color: #7c8190; border-bottom: 1px solid #2a2b31; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mcp-card__tools { padding: 0.5rem; display: grid; gap: 0.15rem; }
.mcp-tool { display: flex; align-items: center; gap: 0.6rem; padding: 0.5rem 0.7rem; border-radius: 8px; font: 600 0.84rem ui-monospace, SFMono-Regular, Menlo, monospace; color: #e6e7ea; }
.mcp-tool:hover { background: #1d1e24; }
.mcp-tool .d { width: 6px; height: 6px; border-radius: 50%; background: var(--indigo-300); flex: none; }
.mcp-tool .ck { margin-left: auto; color: #4ade80; font-weight: 900; font-size: 0.8rem; }
.mcp-tool .more { color: #6b7280; font-weight: 600; padding-left: 1.2rem; }
.mcp__pills { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1.3rem; }

/* "retire" chips with a brand logo instead of the red dot (recognisable at a glance) */
.strike--logo::before { display: none; }
.strike--logo img { width: 16px; height: 16px; flex: none; object-fit: contain; }

/* =========================================================================
   MOTION & POLISH LAYER  (added 2026-06-24)
   Scroll-reveal, hero load-in, off-screen animation pausing, focus rings,
   scroll-spy, tab/menu a11y, and touch/responsive hardening.

   GATING (the safety contract): every JS-driven entrance below is scoped to
   html.js-reveal, which a synchronous <head> script adds ONLY when
   IntersectionObserver is supported AND prefers-reduced-motion is not set.
   So with no JS, an old browser, or reduced motion, all content is fully
   visible and static by default — the start state never hides anything.
   site.js also un-hides everything if its engine fails to initialize.
   ========================================================================= */

/* ---- scroll reveal (engine = the IntersectionObserver in site.js) ---- */
.js-reveal [data-reveal],
.js-reveal [data-reveal-children] > * {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .6s cubic-bezier(.22,.61,.36,1), transform .6s cubic-bezier(.22,.61,.36,1);
}
.js-reveal [data-reveal].is-in,
.js-reveal [data-reveal-children] > *.is-in { opacity: 1; transform: none; }
/* lighter lift for image rows so width:auto logos never nudge layout horizontally */
.js-reveal [data-reveal="soft"],
.js-reveal [data-reveal-children="soft"] > * { transform: translateY(10px); }
@media (prefers-reduced-motion: reduce) {
  .js-reveal [data-reveal],
  .js-reveal [data-reveal-children] > * { opacity: 1 !important; transform: none !important; transition: none !important; }
}

/* ---- hero load-in cascade (CSS only — keyed off the same early flag, NOT the
   observer, since the hero is above the fold and must never start blank) ---- */
.js-reveal .hero__copy > * { opacity: 0; animation: heroRise .7s cubic-bezier(.22,.61,.36,1) both; }
.js-reveal .hero__copy > h1     { animation-delay: .05s; }
.js-reveal .hero__copy > .lead  { animation-delay: .15s; }
.js-reveal .hero__copy > .cta   { animation-delay: .26s; }
.js-reveal .hero__copy > .micro { animation-delay: .35s; }
.js-reveal .hero__visual { opacity: 0; animation: heroRise .8s cubic-bezier(.22,.61,.36,1) .2s both; }
/* float cards: one combined declaration (pop in once, then the gentle idle float)
   so the two animations don't clobber each other in the cascade */
.js-reveal .float-card.tl { opacity: 0; animation: cardPop .5s ease .8s both, floatY 6s ease-in-out 1.3s infinite; }
.js-reveal .float-card.br { opacity: 0; animation: cardPop .5s ease .95s both, floatY 7s ease-in-out 1.5s infinite; }
@keyframes heroRise { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
@keyframes cardPop  { from { opacity: 0; transform: translateY(10px) scale(.96); } to { opacity: 1; transform: none; } }
@keyframes floatY   { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@media (prefers-reduced-motion: reduce) {
  .js-reveal .hero__copy > *, .js-reveal .hero__visual,
  .js-reveal .float-card.tl, .js-reveal .float-card.br { opacity: 1 !important; animation: none !important; transform: none !important; }
}

/* ---- pause forever-running paint animations when scrolled off-screen ----
   The .viz-off class is added by site.js only while an element is out of view;
   with no JS it is never present, so the dashes/pulses keep flowing as before
   (graceful, not frozen). These follow the existing prefers-reduced-motion
   blocks, which already set animation:none for RM users (so RM still wins,
   and .viz-off is never added for them anyway). */
.frame.viz-off .edge-flow,
.frame.viz-off .frame__live::before,
.frame.viz-off .app__spin,
.eyebrow.viz-off .dot,
.term.viz-off .cur,
.montage.viz-off .float-card { animation-play-state: paused; }

/* ---- keyboard focus rings (real interactive controls only) ---- */
a:focus-visible, button:focus-visible, .btn:focus-visible, .ftab:focus-visible,
summary:focus-visible, .foot__top:focus-visible, .link-arr:focus-visible,
details[name="faq"] summary:focus-visible { outline: 2px solid var(--indigo); outline-offset: 2px; }
.topbar a:focus-visible, footer a:focus-visible, .foot__top:focus-visible,
.cred a:focus-visible, .cta-final a:focus-visible, .mcp-card:focus-visible { outline-color: var(--indigo-300); }

/* ---- scroll-spy active nav link (set by site.js) ---- */
.nav__links a.is-current { color: var(--indigo); }

/* ---- the sticky feature-tab bar rides up with the auto-hidden nav so it never
   leaves a floating gap where the bar used to be ---- */
.ftabs { transition: top .32s cubic-bezier(.4,0,.2,1); }
html.nav-up .ftabs { top: 0; }

/* ---- native offset so in-page anchors don't land under the sticky bar ---- */
section[id], #top { scroll-margin-top: calc(var(--nav-h) + 12px); }

/* ---- touch / hover hardening: don't leave cards stuck "lifted" after a tap,
   and neutralize the lift transforms for reduced-motion users ---- */
@media (hover: none) {
  .btn:hover, .reason:hover, .intg:hover, .agent:hover, .foot__top:hover, .pillar:hover { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .reason:hover, .intg:hover, .agent:hover, .foot__top:hover { transform: none; }
}

/* ---- FAQ answer: a soft fade/slide on the answer text as it opens (the
   <details> height itself snaps as usual; RM users get the instant default) ---- */
@media (prefers-reduced-motion: no-preference) {
  .faq__list details[open] p { animation: faqIn .28s ease both; }
  @keyframes faqIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
}

/* ---- narrow-screen hardening ---- */
/* long monospace selectors in the product mockups must not push horizontal scroll */
.row { min-width: 0; }
.row .sel { min-width: 0; overflow-wrap: anywhere; }
/* float cards collapse against .hero overflow:hidden once the hero stacks (<=920px),
   not only at <=520px — otherwise they clip awkwardly in the 521–920px band */
@media (max-width: 920px) { .float-card { display: none; } }
/* keep the SVG mockup node labels legible when the frames shrink on phones */
@media (max-width: 560px) { .node .t { font-size: 15px; } .app__stage svg { min-height: 0; } }
/* single-column footer: don't let the absolute back-to-top button cover Legal links */
@media (max-width: 520px) { .foot { padding-bottom: 3.5rem; } }

/* ===========================================================================
   Claude × Assertify — hero float card + the "brain / hands" partnership band
   =========================================================================== */
/* hero: eyebrow now leads the headline (headings reset to margin:0), so add a gap */
.hero__copy .eyebrow { margin-bottom: 0.9rem; }
/* hero: the plain-English ask, in a Claude-branded float card */
.float-card.claude { border-color: rgb(217 119 87 / 0.40); }
.float-card .cl { width: 15px; height: 15px; flex: none; }
/* keep the floating chips above the app frame so they're never clipped behind it */
.montage .float-card { z-index: 4; }

/* the partnership section */
.cx { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr); gap: clamp(1.5rem, 4vw, 3.5rem); align-items: center; }
@media (max-width: 900px) { .cx { grid-template-columns: 1fr; } .cx-chat { order: 2; } }
.cx__copy h2 { font-size: clamp(2rem, 4.4vw, 3.2rem); letter-spacing: -0.02em; margin-top: 0.7rem; line-height: 1.06; }
.cx__copy > p { margin: 1.1rem 0 0; color: var(--ink-soft); font-size: clamp(1.02rem, 1.6vw, 1.18rem); font-weight: 500; max-width: 34rem; }

/* brain / hands split */
.cx-split { display: grid; grid-template-columns: 1fr 1fr; gap: 0.8rem; margin-top: 1.6rem; }
@media (max-width: 480px) { .cx-split { grid-template-columns: 1fr; } }
.cx-half { background: var(--card); border: 1px solid var(--line); border-radius: 14px; padding: 1rem 1.05rem; box-shadow: var(--shadow); }
.cx-half__top { display: flex; align-items: center; gap: 0.5rem; font-weight: 800; color: var(--ink); font-size: 0.92rem; margin-bottom: 0.65rem; }
.cx-logo { width: 20px; height: 20px; border-radius: 6px; flex: none; }
.cx-half ul { list-style: none; display: grid; gap: 0.42rem; margin: 0; padding: 0; }
.cx-half li { position: relative; padding-left: 1.1rem; font-size: 0.86rem; font-weight: 550; color: var(--ink-soft); }
.cx-half li::before { content: ""; position: absolute; left: 0; top: 0.5em; width: 6px; height: 6px; border-radius: 2px; background: var(--indigo); box-shadow: 0 0 0 3px rgb(79 70 229 / 0.12); }
.cx-cta { margin-top: 1.6rem; }

/* the Claude chat card — plain-English in, real tests out */
.cx-chat { background: var(--card); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow-lg); overflow: hidden; }
.cx-chat__bar { display: flex; align-items: center; gap: 0.6rem; padding: 0.85rem 1rem; border-bottom: 1px solid var(--line); background: var(--paper); }
.cx-chat__bar img { width: 24px; height: 24px; }
.cx-chat__name { font-weight: 800; color: var(--ink); }
.cx-chat__tag { margin-left: auto; display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.68rem; font-weight: 800; letter-spacing: 0.03em; color: #b45309; background: rgb(217 119 87 / 0.12); padding: 0.2rem 0.55rem; border-radius: 999px; }
.cx-chat__tag::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: #d97757; }
.cx-chat__body { padding: 1rem; display: grid; gap: 0.7rem; }
.cx-msg { font-size: 0.9rem; font-weight: 500; line-height: 1.5; padding: 0.7rem 0.85rem; border-radius: 14px; }
.cx-msg--me { justify-self: end; max-width: 88%; background: var(--indigo-50); border: 1px solid var(--indigo-100); color: var(--ink); border-bottom-right-radius: 5px; }
.cx-msg--ai { justify-self: start; width: 100%; background: var(--paper-2); border: 1px solid var(--line); color: var(--ink); border-bottom-left-radius: 5px; }
.cx-run { margin-top: 0.6rem; display: grid; gap: 0.2rem; }
.cx-tool { display: flex; align-items: center; gap: 0.55rem; padding: 0.4rem 0.55rem; border-radius: 8px; background: var(--card); border: 1px solid var(--line); font: 600 0.8rem ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--ink); }
.cx-tool .d { width: 6px; height: 6px; border-radius: 50%; background: var(--indigo-300); flex: none; }
.cx-tool .p { color: var(--muted); font-weight: 600; }
.cx-tool .ck { margin-left: auto; color: var(--ok); font-weight: 800; }
.cx-tool.ok { border-color: rgb(22 163 74 / 0.30); background: var(--ok-100); }
.cx-chat__foot { display: flex; align-items: center; gap: 0.5rem; padding: 0.8rem 1rem; border-top: 1px solid var(--line); background: var(--paper); font-size: 0.82rem; font-weight: 650; color: var(--ink-soft); }
.cx-chat__foot .ck { color: var(--ok); font-weight: 900; }

/* ===================================================== Claude × Assertify — synchronized duo
   Replaces the old flat .cx-chat with a dark Claude terminal + light Assertify window that
   build in lockstep. Reuses .term / .frame / .app / .cx-tool / .edge-* / .node chrome and the
   cardPop / floatY / dash / blink / pulse / spin keyframes already in this file.
   NOTE: the old .cx-chat* rules above stay in place (harmless / unused now). */

/* --- the duo grid (occupies the right cell of the existing .cx 2-col grid) --- */
.cx-duo { display: grid; grid-template-columns: 1fr 52px 1.12fr; align-items: stretch; gap: 0;
  min-height: 360px; min-width: 0; }                 /* min-height pins layout: streaming rows never shift it */
.cx-duo > * { min-width: 0; }                        /* let panes shrink instead of overflowing the column */
.cx-pane { display: flex; min-width: 0; }            /* let .term / .frame stretch to full pane height */
.cx-pane > .term, .cx-pane > .frame { width: 100%; }

.cx-duo__foot { grid-column: 1 / -1; margin: 1rem 0 0; border: 1px solid var(--line);
  border-radius: 12px; padding: 0.7rem 0.95rem; background: var(--paper); }

/* --- Claude pane: dark term chrome + terracotta "connected" badge --- */
.cx-pane--claude .term__bar { background: #1d1e24; }
.cx-pane--claude .term__bar .cx-logo { width: 16px; height: 16px; border-radius: 4px; flex: none; }
.cx-pane--claude .cx-pane__name { font: 700 0.72rem ui-monospace, SFMono-Regular, Menlo, monospace; color: #cdd0d6; }
.cx-pane--claude .term__bar .cx-chat__tag { margin-left: auto; }   /* reuse the terracotta connected pill */
.cx-pane--claude .term__body { display: grid; gap: 0.55rem; padding: 0.9rem 1rem; }
.cx-msg--term { background: #232429; border-color: #2f3037; color: #e6e7ea; max-width: 100%;
  justify-self: stretch; border-bottom-right-radius: 14px; }

/* MCP tool rows on the dark term bg (reuse .cx-tool look; recolor for dark) */
.cx-tool--dark { background: #1b1c21; border-color: #2a2b31; color: #e6e7ea; }
.cx-tool--dark .p { color: #8b8f99; }
.cx-tool--dark .ck { opacity: 0; transition: opacity 0.2s ease; color: #4ade80; }  /* check hidden until row resolves */

/* --- the beam --- */
.cx-beam { position: relative; min-width: 0; }
.cx-beam__svg { position: absolute; inset: 0; margin: auto 0; height: 12px; width: 100%; overflow: visible; }
.cx-beam__track { stroke: var(--indigo-100); stroke-width: 2; stroke-linecap: round; stroke-dasharray: 0.1 9; }
.cx-beam__pulse { stroke: var(--indigo); stroke-width: 3; stroke-linecap: round;
  stroke-dasharray: 14 100; stroke-dashoffset: 114; opacity: 0; }

/* --- node / edge pre-states only while the JS-driven sequence is armed --- */
.js-reveal .cx-duo:not(.is-live) .cx-node { opacity: 0; }
.js-reveal .cx-duo:not(.is-live) .cx-edge { stroke-dasharray: 220; stroke-dashoffset: 220; }
.js-reveal .cx-duo:not(.is-live) .cx-edge-flow { opacity: 0; }
.js-reveal .cx-duo:not(.is-live) .cx-step { opacity: 0.35; }
.js-reveal .cx-duo:not(.is-live) .cx-tool--dark { opacity: 0; transform: translateY(6px); }
.js-reveal .cx-duo:not(.is-live) .cx-msg--term { opacity: 0; transform: translateY(6px); }

/* shared transition surfaces */
.cx-tool--dark, .cx-msg--term { transition: opacity 0.4s ease, transform 0.4s ease,
  background 0.4s ease, border-color 0.4s ease; }
.cx-step { transition: opacity 0.35s ease; }
.cx-node { transform-box: fill-box; transform-origin: center; }

/* --- the LIVE cascade: everything below is delays off the single .is-live class --- */
.cx-duo.is-live .cx-msg--term { opacity: 1; transform: none; }

.cx-duo.is-live .cx-tool--dark { opacity: 1; transform: none; }
.cx-duo.is-live .cx-tool--dark[data-cx-row="0"] { transition-delay: 0.60s; }
.cx-duo.is-live .cx-tool--dark[data-cx-row="1"] { transition-delay: 1.30s; }
.cx-duo.is-live .cx-tool--dark[data-cx-row="2"] { transition-delay: 2.00s; }
.cx-duo.is-live .cx-tool--dark[data-cx-row="3"] { transition-delay: 2.70s; }
/* row check-marks appear shortly after each row lands */
.cx-duo.is-live .cx-tool--dark[data-cx-row="0"] .ck { opacity: 1; transition-delay: 1.00s; }
.cx-duo.is-live .cx-tool--dark[data-cx-row="1"] .ck { opacity: 1; transition-delay: 1.70s; }
.cx-duo.is-live .cx-tool--dark[data-cx-row="2"] .ck { opacity: 1; transition-delay: 2.40s; }
/* final row flips green */
.cx-duo.is-live .cx-tool--final { transition-delay: 2.70s; }
.cx-duo.is-live .cx-tool--final.cx-go-green { background: rgb(74 222 128 / 0.12); border-color: rgb(74 222 128 / 0.35); }
.cx-duo.is-live .cx-tool--final .ck { opacity: 1; transition-delay: 3.30s; }

/* nodes pop in, edges draw, steps light — each synced to its tool row */
.cx-duo.is-live .cx-node[data-cx-node="0"] { animation: cxNodePop 0.34s cubic-bezier(.22,.61,.36,1) 0.70s both; }
.cx-duo.is-live .cx-node[data-cx-node="1"] { animation: cxNodePop 0.34s cubic-bezier(.22,.61,.36,1) 1.40s both; }
.cx-duo.is-live .cx-node[data-cx-node="2"] { animation: cxNodePop 0.34s cubic-bezier(.22,.61,.36,1) 2.10s both; }
.cx-duo.is-live .cx-node[data-cx-node="3"] { animation: cxNodePop 0.34s cubic-bezier(.22,.61,.36,1) 2.80s both; }
.cx-duo.is-live .cx-edge[data-cx-edge="0"] { animation: cxEdgeDraw 0.45s ease 1.40s both; }
.cx-duo.is-live .cx-edge[data-cx-edge="1"] { animation: cxEdgeDraw 0.45s ease 2.10s both; }
.cx-duo.is-live .cx-edge[data-cx-edge="2"] { animation: cxEdgeDraw 0.45s ease 2.80s both; }
.cx-duo.is-live .cx-step[data-cx-step="0"] { opacity: 1; transition-delay: 0.85s; }
.cx-duo.is-live .cx-step[data-cx-step="1"] { opacity: 1; transition-delay: 1.55s; }
.cx-duo.is-live .cx-step[data-cx-step="2"] { opacity: 1; transition-delay: 2.25s; }

/* the green-path flow turns on only at the finale (the dash anim is already infinite via .edge-flow) */
.cx-duo.is-live .cx-edge-flow { opacity: 1; transition: opacity 0.4s ease 3.30s; }

/* the beam fires once per tool call — JS toggles .cx-beam.fire (it re-triggers the
   play-once anim). Opacity is driven by the keyframe (fade in → sweep → fade out) —
   NOT a static opacity:1 — so the pulse vanishes between calls and after the finale
   instead of leaving a frozen dash sitting in the gutter. */
.cx-beam.fire .cx-beam__pulse { animation: cxBeam 0.32s ease-out 1; }

/* --- new keyframes (everything else reused) --- */
@keyframes cxBeam     { 0% { opacity: 0; stroke-dashoffset: 114; } 15% { opacity: 1; } 82% { opacity: 1; } 100% { opacity: 0; stroke-dashoffset: 0; } }
@keyframes cxNodePop  { from { opacity: 0; transform: scale(.9); } to { opacity: 1; transform: scale(1); } }
@keyframes cxEdgeDraw { from { stroke-dashoffset: 220; } to { stroke-dashoffset: 0; } }

/* --- responsive: stack to one column, beam becomes a short vertical connector --- */
@media (max-width: 900px) {
  .cx-duo { grid-template-columns: 1fr; min-height: 0; gap: 0; }
  .cx-beam { height: 38px; }
  .cx-beam__svg { width: 14px; height: 100%; left: 0; right: 0; margin: 0 auto; inset: 0;
    transform: rotate(90deg); transform-origin: center; }
}

/* --- viz-off: pause the only at-rest loops when the duo is scrolled away --- */
.cx-duo.viz-off .cx-edge-flow,
.cx-duo.viz-off .frame__live::before,
.cx-duo.viz-off .cx-beam__pulse { animation-play-state: paused; }

/* --- reduced motion: render the fully-built, passing end state with zero motion ---
   The :not(.is-live) hide rules only apply under .js-reveal (set only when motion is wanted),
   so reduced-motion / no-JS already shows everything. These extra guards make it bulletproof. */
@media (prefers-reduced-motion: reduce) {
  .cx-duo .cx-node, .cx-duo .cx-msg--term, .cx-duo .cx-tool--dark { opacity: 1 !important; transform: none !important; animation: none !important; }
  .cx-duo .cx-tool--dark .ck { opacity: 1 !important; }
  .cx-duo .cx-edge { stroke-dasharray: none !important; stroke-dashoffset: 0 !important; animation: none !important; }
  .cx-duo .cx-edge-flow { opacity: 1 !important; }
  .cx-duo .cx-step { opacity: 1 !important; }
  .cx-duo .cx-tool--final { background: rgb(74 222 128 / 0.12); border-color: rgb(74 222 128 / 0.35); }
  .cx-beam__pulse { display: none; }
}

/* --- full-width Claude×Assertify layout: header on top, the duo as a full-width showcase,
       detail cards below (the duo needs the whole wrap width so both windows stay legible) --- */
.cx-flow { display: flex; flex-direction: column; gap: clamp(1.6rem, 3vw, 2.6rem); }
.cx-head { display: grid; grid-template-columns: 1.15fr 0.85fr; gap: clamp(1.2rem, 3vw, 2.5rem); align-items: end; }
.cx-head .eyebrow { margin-bottom: 0.6rem; }
.cx-head__lead h2 { font-size: clamp(2rem, 4.4vw, 3.2rem); letter-spacing: -0.02em; line-height: 1.06; }
.cx-head__aside p { margin: 0; color: var(--ink-soft); font-size: clamp(1.02rem, 1.4vw, 1.12rem); font-weight: 500; }
.cx-head__aside .cx-cta { margin-top: 1.1rem; }
@media (max-width: 760px) { .cx-head { grid-template-columns: 1fr; align-items: start; gap: 1rem; } }
/* detail cards span full width below the showcase; fill them with a 2-col bullet list */
.cx-flow .cx-split { margin-top: 0; }
.cx-flow .cx-half ul { grid-template-columns: 1fr 1fr; gap: 0.5rem 1.2rem; }
@media (max-width: 560px) { .cx-flow .cx-half ul { grid-template-columns: 1fr; } }

/* =========================================================================
   PRODUCT-HUNT RELAUNCH LAYER (added 2026-07-02)
   PH launch bar + official badge, the "Claude+Assertify+Jira = QA department"
   equation, videos & tutorials, seamless logo marquee, scroll-progress bar,
   aurora backdrop, cursor spotlight, count-up, 3D tilt, subtle grain.
   Everything is progressive enhancement and honours prefers-reduced-motion.
   ========================================================================= */

/* ---- scroll-progress "assertion bar": a thin gradient line that fills as you
   read (width set by site.js). A cheap, on-brand "instrumented" cue. ---- */
.scrollbar { position: fixed; inset: 0 0 auto 0; height: 3px; z-index: 80; pointer-events: none; }
.scrollbar i { display: block; height: 100%; width: 0;
  background: linear-gradient(90deg, var(--indigo-500), var(--indigo), var(--violet));
  box-shadow: 0 0 10px rgb(79 70 229 / 0.5); transition: width .1s linear; }

/* ---- Product Hunt launch bar (launch week — dismissible; hidden until site.js
   un-hides it, so a placeholder link never shows with JS off) ---- */
.ph-bar { display: flex; align-items: center; justify-content: center; gap: 0.85rem; flex-wrap: wrap;
  padding: 0.6rem 1rem; text-align: center; position: relative; z-index: 65;
  background: linear-gradient(90deg, #DA552F, #FF6154); color: #fff;
  font: 600 0.88rem/1.4 "Manrope", sans-serif; }
.ph-bar[hidden] { display: none; }
.ph-bar__pulse { flex: none; width: 9px; height: 9px; border-radius: 50%; background: #fff;
  box-shadow: 0 0 0 0 rgb(255 255 255 / 0.7); animation: phPing 1.6s ease-out infinite; }
.ph-bar__msg b { font-weight: 800; }
.ph-bar__cta { background: #fff; color: #DA552F; font-weight: 800; padding: 0.34rem 0.85rem;
  border-radius: 999px; white-space: nowrap; transition: transform .15s ease; }
.ph-bar__cta:hover { transform: scale(1.05); }
.ph-bar__close { background: none; border: 0; color: #fff; font-size: 20px; line-height: 1;
  cursor: pointer; padding: 0 0.2rem; opacity: 0.8; }
.ph-bar__close:hover { opacity: 1; }
@keyframes phPing { 0% { box-shadow: 0 0 0 0 rgb(255 255 255 / 0.7); } 70% { box-shadow: 0 0 0 9px rgb(255 255 255 / 0); } 100% { box-shadow: 0 0 0 0 rgb(255 255 255 / 0); } }
@media (prefers-reduced-motion: reduce) { .ph-bar__pulse { animation: none; } }

/* official PH badge in the hero — hidden until its SVG actually loads (it 404s
   until the post is live / the post_id is filled in), so it never shows broken. */
.ph-embed { display: inline-block; margin-top: 1.3rem; }
.ph-embed[hidden] { display: none; }
.ph-embed img { width: 250px; height: 54px; }

/* ---- aurora / mesh-gradient backdrop (hero + QA-department) ---- */
.aurora { position: absolute; inset: -25% -12%; z-index: 0; pointer-events: none; filter: blur(46px); opacity: 0.9;
  background:
    radial-gradient(40% 50% at 18% 28%, rgb(99 102 241 / 0.22), transparent 60%),
    radial-gradient(42% 52% at 82% 18%, rgb(124 58 237 / 0.18), transparent 60%),
    radial-gradient(46% 56% at 62% 82%, rgb(99 102 241 / 0.14), transparent 60%);
  animation: auroraDrift 24s ease-in-out infinite alternate; }
.aurora--2 { opacity: 0.7; }
@keyframes auroraDrift { 0% { transform: translate3d(-2%, -1%, 0) scale(1); } 100% { transform: translate3d(3%, 2%, 0) scale(1.08); } }
.aurora.viz-off { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .aurora { animation: none; } }

/* ---- cursor spotlight: a soft radial that tracks the pointer (site.js sets
   --mx / --my). Painted behind content via ::after; content is lifted to z-index:1.
   Applied to every major section for a consistent page-wide effect. */
[data-spotlight] { position: relative; }
[data-spotlight]::after { content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 50%), rgb(99 102 241 / 0.16), transparent 62%); }
.cred[data-spotlight]::after, .cta-final[data-spotlight]::after {
  background: radial-gradient(320px circle at var(--mx, 50%) var(--my, 50%), rgb(255 255 255 / 0.12), transparent 62%); }
/* lift each spotlit section's content above the glow — the generic `> .wrap` covers
   almost every section; the two dark cards carry data-spotlight on themselves. */
[data-spotlight] > .wrap,
.cred[data-spotlight] .cred__in,
.cta-final[data-spotlight] > * { position: relative; z-index: 1; }

/* ---- visible custom Product Hunt badge (hero) — coral, always shown, glow pulse.
   Does NOT depend on the official self-refreshing SVG, so it can't 404/blank pre-launch. */
.ph-badge { display: inline-flex; align-items: center; gap: 0.6rem; margin-top: 1.3rem;
  padding: 0.45rem 0.95rem 0.45rem 0.5rem; border-radius: 12px; text-decoration: none; color: #fff;
  background: linear-gradient(135deg, #FF6154, #DA552F); box-shadow: 0 10px 24px -12px rgb(218 85 47 / 0.7);
  transition: transform .18s ease, box-shadow .2s ease; animation: phGlow 2.8s ease-in-out infinite; }
.ph-badge:hover { transform: translateY(-2px); box-shadow: 0 16px 32px -12px rgb(218 85 47 / 0.85); }
.ph-badge__up { flex: none; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 9px;
  background: rgb(255 255 255 / 0.18); font-size: 0.8rem; font-weight: 800; }
.ph-badge__txt { display: flex; flex-direction: column; line-height: 1.12; text-align: left; }
.ph-badge__k { font-size: 0.62rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; opacity: 0.85; }
.ph-badge__txt b { font-size: 0.95rem; font-weight: 800; }
@keyframes phGlow { 0%, 100% { box-shadow: 0 10px 24px -12px rgb(218 85 47 / 0.6); } 50% { box-shadow: 0 12px 30px -10px rgb(218 85 47 / 0.9); } }
@media (prefers-reduced-motion: reduce) { .ph-badge { animation: none; } }

/* ===================================================== Claude + Assertify + Jira = QA department */
.qadept { position: relative; overflow: hidden; }
.qa-eq-title { line-height: 1.12; }
.qa-eq-title .hl { color: var(--indigo); }

/* Assertify — the hero card: the product is the star, brain/loop/report plug in
   below. Indigo gradient so it reads as the main feature regardless of theme. */
.qa-hero { position: relative; z-index: 1; overflow: hidden; margin-top: clamp(2rem, 4vw, 3rem);
  display: flex; align-items: center; gap: clamp(1.2rem, 3vw, 2.2rem);
  background: linear-gradient(135deg, var(--indigo-700), var(--violet)); color: #fff;
  border-radius: var(--r-lg); padding: clamp(1.6rem, 3.5vw, 2.6rem) clamp(1.6rem, 3.5vw, 2.8rem);
  box-shadow: 0 30px 70px -30px rgb(79 70 229 / 0.6); }
.qa-hero::before { content:""; position:absolute; inset:0; pointer-events:none;
  background: radial-gradient(80% 140% at 92% -12%, rgb(255 255 255/.18), transparent 55%); }
.qa-hero__mark { position: relative; flex: 0 0 auto; width: clamp(4.2rem, 9vw, 6rem); height: clamp(4.2rem, 9vw, 6rem);
  border-radius: 22px; display: grid; place-items: center;
  background: rgb(255 255 255 / 0.14); border: 1px solid rgb(255 255 255 / 0.24); box-shadow: inset 0 1px 0 rgb(255 255 255/.2); }
.qa-hero__mark img { width: 58%; height: 58%; object-fit: contain; }
.qa-hero__body { position: relative; min-width: 0; }
.qa-hero__badge { display: inline-flex; align-items: center; font-size: 0.72rem; font-weight: 800; letter-spacing: 0.05em; text-transform: uppercase;
  color: #fff; background: rgb(255 255 255 / 0.16); border: 1px solid rgb(255 255 255 / 0.26); padding: 0.24rem 0.72rem; border-radius: 999px; }
.qa-hero h3 { margin-top: 0.7rem; font-size: clamp(1.35rem, 3vw, 2.05rem); line-height: 1.1; }
.qa-hero p { margin: 0.6rem 0 0; max-width: 46rem; color: rgb(255 255 255 / 0.86); font-weight: 500; font-size: clamp(0.98rem, 1.4vw, 1.08rem); }

/* The trio that plugs into Assertify — brain (Claude), loop (Jira), report (Slack). */
.qa-trio { position: relative; z-index: 1; margin-top: 1rem; display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
.qa-piece { position: relative; overflow: hidden;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  padding: 1.4rem; box-shadow: var(--shadow);
  transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease; }
.qa-piece:hover { transform: translateY(-4px); border-color: var(--indigo-200); box-shadow: var(--shadow-lg); }
.qa-piece__ic { width: 2.9rem; height: 2.9rem; border-radius: 14px; display: grid; place-items: center;
  background: linear-gradient(135deg, var(--indigo-50), var(--indigo-100)); border: 1px solid var(--indigo-100); margin-bottom: 1rem; }
.qa-piece__ic img { width: 26px; height: 26px; border-radius: 7px; }
.qa-piece__ic--plain { background: #fff; border-color: var(--line); }
.qa-piece h4 { font-size: 1.08rem; }
.qa-piece p { margin: 0.5rem 0 1rem; color: var(--ink-soft); font-size: 0.9rem; font-weight: 500; }
.qa-piece__tag { display: inline-flex; align-items: center; font-size: 0.7rem; font-weight: 800; letter-spacing: 0.03em;
  text-transform: uppercase; color: var(--indigo-700); background: var(--indigo-50); border: 1px solid var(--indigo-100);
  padding: 0.28rem 0.6rem; border-radius: 999px; }
@media (max-width: 720px) {
  .qa-hero { flex-direction: column; text-align: center; }
  .qa-hero__body { display: flex; flex-direction: column; align-items: center; }
  .qa-hero p { margin-inline: auto; }
  .qa-trio { grid-template-columns: 1fr; }
}

/* ===================================================== seamless logo marquee (trust) */
.marquee { overflow: hidden; position: relative; margin-top: 1.6rem;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.marquee__track { display: flex; align-items: center; width: max-content;
  animation: marquee 34s linear infinite; }
.marquee__track img { flex: none; height: 34px; width: auto; margin-inline-end: clamp(2rem, 6vw, 5rem); opacity: 0.72; filter: grayscale(1) brightness(0.4); transition: opacity .3s ease, filter .3s ease; }
.marquee__track img:hover { opacity: 1; filter: grayscale(1) brightness(0.12); }
.marquee:hover .marquee__track, .marquee.viz-off .marquee__track { animation-play-state: paused; }
@keyframes marquee { to { transform: translateX(-33.3333%); } }
@media (prefers-reduced-motion: reduce) {
  .marquee { -webkit-mask-image: none; mask-image: none; }
  .marquee__track { animation: none; width: auto; flex-wrap: wrap; justify-content: center; gap: clamp(1.5rem, 5vw, 3.5rem); }
  .marquee__track img { margin-inline-end: 0; }
}

/* ===================================================== videos & tutorials */
.tuts { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.1rem; margin-top: 2.6rem; }
@media (max-width: 980px) { .tuts { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .tuts { grid-template-columns: 1fr; max-width: 26rem; margin-inline: auto; } }
.tut { display: flex; flex-direction: column; background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  overflow: hidden; box-shadow: var(--shadow); transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease; }
.tut:hover { transform: translateY(-3px); border-color: var(--indigo-200); box-shadow: var(--shadow-lg); }
.tut__thumb.media-ph { min-height: clamp(150px, 20vw, 190px); border-bottom: 1px solid var(--line); }
.tut__thumb.media-ph::after { content: none; }   /* no "screenshot goes here" caption in the tutorials grid */
.tut__play { position: relative; z-index: 1; width: 46px; height: 46px; border-radius: 50%; display: grid; place-items: center;
  background: rgb(255 255 255 / 0.92); color: var(--indigo); font-size: 0.95rem; box-shadow: 0 10px 24px -10px rgb(20 22 30 / 0.4); }
.tut__thumb.media-ph.has-asset .tut__play, .tut__thumb.media-ph.has-asset .tut__len { display: none; }
.tut__len { position: absolute; right: 0.6rem; bottom: 0.6rem; z-index: 1; font: 800 0.7rem ui-monospace, monospace;
  color: #fff; background: rgb(20 22 30 / 0.7); padding: 0.16rem 0.45rem; border-radius: 6px; }
.tut__meta { padding: 1rem 1.1rem 1.2rem; }
.tut__meta h4 { font-size: 1rem; }
.tut__meta p { margin: 0.4rem 0 0; color: var(--ink-soft); font-size: 0.85rem; font-weight: 500; }

/* ---- feature-tab video wrapper (mock is the fallback; real clip swaps in) ---- */
.fviz { position: relative; width: 100%; }
.fviz > .rows, .fviz > .frame, .fviz > .term { width: 100%; }

/* ---- count-up stats: tabular figures so the number doesn't jitter while counting ---- */
.stat b { font-variant-numeric: tabular-nums; }

/* ---- 3D tilt cards (site.js sets the transform on pointer-fine devices) ---- */
[data-tilt] { transition: transform .18s cubic-bezier(.22,.61,.36,1), box-shadow .2s ease, border-color .2s ease; }

/* ---- subtle film grain over the page for a tactile, editorial finish ---- */
body::after { content: ""; position: fixed; inset: 0; z-index: 2; pointer-events: none; opacity: 0.02;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 120px 120px; }

/* keep hover-lift transforms off touch + reduced-motion for the new cards too */
@media (hover: none) { .qa-piece:hover, .tut:hover { transform: none; } }
@media (prefers-reduced-motion: reduce) { .qa-piece:hover, .tut:hover { transform: none; } }

/* ===================================================== the economics (Claude × MCP value)
   A dark "formula" card — Claude plan + Assertify = a QA department — with a payoff
   figure band, then the four differentiators reusing the .reason cards. The formula
   card is ALWAYS dark (like .cred) so the money moment reads the same in either theme. */
.val { position: relative; overflow: hidden; }
.val-formula { position: relative; z-index: 1; overflow: hidden; margin-top: clamp(2rem, 4vw, 2.8rem);
  background: var(--dark); color: #fff; border-radius: var(--r-lg); box-shadow: var(--shadow-lg);
  padding: clamp(1.7rem, 4vw, 2.8rem); }
.val-formula::before { content:""; position:absolute; inset:0; pointer-events:none;
  background: radial-gradient(80% 120% at 88% -8%, rgb(99 102 241/.34), transparent 55%),
              radial-gradient(70% 100% at 4% 108%, rgb(124 58 237/.26), transparent 55%); }
.val-formula > * { position: relative; }

.val-formula__eq { display: grid; grid-template-columns: 1fr auto 1fr auto 1fr; align-items: stretch;
  gap: clamp(0.6rem, 1.6vw, 1.2rem); }
.val-term { display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem;
  background: rgb(255 255 255 / 0.04); border: 1px solid rgb(255 255 255 / 0.1); border-radius: var(--r);
  padding: clamp(1.1rem, 2.2vw, 1.5rem); }
.val-term__ic { width: 3rem; height: 3rem; border-radius: 13px; display: grid; place-items: center; flex: none;
  background: rgb(255 255 255 / 0.1); border: 1px solid rgb(255 255 255 / 0.14); }
.val-term__ic img { width: 28px; height: 28px; object-fit: contain; }
/* Assertify term shows the real brand logo tile edge-to-edge (logo.png is a
   finished gradient tile), not the grey icon-on-tile the other terms use. */
.val-term__ic--brand { background: none; border: none; }
.val-term__ic--brand img { width: 100%; height: 100%; object-fit: contain; }
.val-term__ic--win { background: rgb(99 102 241 / 0.22); border-color: rgb(99 102 241 / 0.4); font-size: 1.5rem; }
.val-term b { font-size: 1.06rem; font-weight: 800; }
.val-term span { color: var(--on-dark-soft); font-size: 0.9rem; font-weight: 500; line-height: 1.4; }
.val-term--win { background: linear-gradient(160deg, rgb(99 102 241 / 0.2), rgb(124 58 237 / 0.08));
  border-color: rgb(99 102 241 / 0.42); box-shadow: 0 24px 50px -30px rgb(99 102 241 / 0.7); }
.val-term--win b { color: #fff; }
.val-op { align-self: center; font-size: clamp(1.4rem, 3vw, 2rem); font-weight: 700; color: var(--indigo-300); opacity: 0.85; }

/* payoff figure band under the formula */
.val-figs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-top: clamp(1.4rem, 3vw, 2rem);
  padding-top: clamp(1.4rem, 3vw, 2rem); border-top: 1px solid rgb(255 255 255 / 0.12); }
.val-fig { text-align: center; }
.val-fig b { display: block; font-size: clamp(2rem, 5vw, 3rem); font-weight: 800; letter-spacing: -0.03em; line-height: 1;
  font-variant-numeric: tabular-nums;
  background: linear-gradient(120deg, #fff 30%, var(--indigo-300)); -webkit-background-clip: text; background-clip: text; color: transparent; }
.val-fig > span { display: block; margin-top: 0.6rem; color: var(--on-dark-soft); font-size: 0.9rem; font-weight: 600; }

/* the four differentiators reuse .reason; just the grid wrapper here */
.val-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.1rem; margin-top: clamp(1.4rem, 3vw, 2rem); }
@media (max-width: 980px) { .val-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .val-grid { grid-template-columns: 1fr; max-width: 26rem; margin-inline: auto; } }

/* stack the formula on narrow screens: terms full-width, operators rotate to point down */
@media (max-width: 720px) {
  .val-formula__eq { grid-template-columns: 1fr; }
  .val-term { flex-direction: row; align-items: center; flex-wrap: wrap; }
  .val-term__ic { margin-right: 0.2rem; }
  .val-term b { flex: 1 1 auto; }
  .val-term span { flex: 1 1 100%; }
  .val-op { justify-self: center; }
  .val-figs { grid-template-columns: 1fr; gap: 1.3rem; text-align: center; }
}

/* =========================================================================
   DARK THEME  —  html.dark overrides. The site ships DARK BY DEFAULT: a
   pre-paint <head> script sets html.dark (or .light from a saved choice) before
   the stylesheet loads, and the footer sun/moon toggle flips + persists it.
   Most surfaces are token-driven, so this palette cascades widely; the rest are
   the hardcoded light surfaces (nav, product-mockup chrome, brand-logo filters)
   patched to their dark-app equivalents.
   ========================================================================= */
html.dark {
  color-scheme: dark;
  --paper: #0f1013;        /* base canvas */
  --paper-2: #15161b;      /* alternating band */
  --paper-3: #1a1b21;      /* deeper panel */
  --card: #191a20;         /* elevated card */
  --ink: #f2f3f5;
  --ink-soft: #b4b7c0;
  --muted: #878b96;
  --line: #292b33;
  --line-2: #383b46;
  --dark: #1a1c22;         /* dark-feature cards (cred / cta-final) lift above the page */
  /* In dark mode the cream-era deep indigo (#1e1b3f) reads as a harsh purple stripe
     over the near-black page. Retint to a near-black with just a whisper of indigo so
     the topbar/footer/overscroll sit harmoniously — still "not flat black". */
  --brand-dark: #181726;
  --brand-dark-2: #201f33;
  --on-dark-soft: rgb(255 255 255 / 0.66);
  /* the lightest indigo tints double as "light wash" backgrounds → make them
     translucent indigo so chips/icons read on dark (the real indigo accent
     colours 300/500/600/700 are left intact for gradients + accent text). */
  --indigo-50: rgb(99 102 241 / 0.13);
  --indigo-100: rgb(99 102 241 / 0.24);
  --indigo-200: rgb(99 102 241 / 0.40);
  --shadow: 0 18px 50px -28px rgb(0 0 0 / 0.6);
  --shadow-lg: 0 40px 90px -44px rgb(0 0 0 / 0.72);
}
html.dark body { background: var(--paper); }

/* dotted backdrop → faint LIGHT dots on dark (were dark dots for a light page) */
html.dark .dotted { background-image: radial-gradient(rgb(255 255 255 / 0.05) 1px, transparent 1.6px); }

/* sticky chrome — cream translucent bars → dark translucent */
html.dark .nav { background: rgb(15 16 19 / 0.86); }
html.dark .nav.scrolled { background: rgb(15 16 19 / 0.95); box-shadow: 0 8px 30px -22px rgb(0 0 0 / 0.85); }
html.dark .ftabs { background: rgb(15 16 19 / 0.95); }

/* brand-logo strips: darkened for a light bg → lighten for dark so they show */
html.dark .trust__logos img,
html.dark .marquee__track img { filter: grayscale(1) brightness(0) invert(0.72); opacity: 0.62; }
html.dark .marquee__track img:hover { opacity: 1; filter: grayscale(1) brightness(0) invert(1); }

/* integration-grid brand marks: the monochrome-dark ones (GitHub near-black,
   Slack aubergine) vanish on the dark card → lift to a soft white. The colour
   logos (GitLab / Jira / Figma / Discord) already pop, so they're left intact. */
html.dark .intg img[src*="github"],
html.dark .intg img[src*="slack"] { filter: brightness(0) invert(0.92); }

/* accent-text chips whose ink was dark indigo → lift to light indigo */
html.dark .qa-piece__tag,
html.dark .plan li.inherit { color: var(--indigo-300); }
html.dark .qa-piece__ic--plain { background: rgb(255 255 255 / 0.9); border-color: rgb(255 255 255 / 0.14); }

/* product-mockup chrome → dark app surfaces (the app itself ships a dark theme) */
html.dark .frame,
html.dark .frame__url,
html.dark .rows,
html.dark .tkt,
html.dark .cmt,
html.dark .float-card,
html.dark .fviz__vid,
html.dark .media-ph .media-asset,
html.dark .cov-step { background: #1b1c22; border-color: var(--line); }
html.dark .frame__bar,
html.dark .rows__bar { background: #202127; border-color: var(--line); }
html.dark .app__side { background: linear-gradient(180deg, #1c1d23, #16171c); }
html.dark .row.broken { background: rgb(225 29 72 / 0.14); border-color: rgb(244 63 94 / 0.4); }
html.dark .wl__note.bad { background: rgb(225 29 72 / 0.14); }

/* mockup CONTAINERS (large light gradient panels) → dark. Descendant selectors
   (html.dark .fmod .fmod__visual) out-specify the per-nth light rules above. */
html.dark .fmod .fmod__visual { background: radial-gradient(120% 120% at 80% 0%, rgb(99 102 241/.20), transparent 60%), linear-gradient(160deg, #1b1c22, #141519); }
html.dark .pillar { background: linear-gradient(180deg, #1a1b22, #16171c); }
html.dark .pillar__body { background: linear-gradient(180deg, transparent, rgb(0 0 0 / 0.25) 30%, #16171c); }
html.dark .stage .stage__top { background: linear-gradient(180deg, rgb(99 102 241 / 0.16), #16171c); }
html.dark .stage .ic { background: rgb(99 102 241 / 0.24); }
html.dark .cov-screen { background: linear-gradient(180deg, #1b1c22, #141519); }
/* hero canvas: darker than the node fill (#1b1c22) so the flow nodes still read */
html.dark .app__stage { background: radial-gradient(rgb(255 255 255 / 0.05) 1px, transparent 1.5px) 0 0/18px 18px, linear-gradient(180deg, #141519, #0e0f12); }
/* hero montage backing panel (light gradient) → dark with the indigo/violet glow */
html.dark .montage { background: radial-gradient(120% 120% at 80% 0%, rgb(99 102 241 / 0.22), transparent 60%), radial-gradient(100% 100% at 0% 100%, rgb(124 58 237 / 0.16), transparent 55%), linear-gradient(160deg, #17181e, #101116); }
html.dark .montage::before { background-image: radial-gradient(rgb(255 255 255 / 0.05) 1px, transparent 1.5px); }

/* pipeline SVG node cards (white fill) → dark */
html.dark .node rect,
html.dark .node .port { fill: #1b1c22; }

/* reasons "badge" card gradient (…, #fff) → dark */
html.dark .reason.badge { background: linear-gradient(160deg, rgb(99 102 241 / 0.14), var(--card)); }

/* -------- footer theme toggle (sun/moon) -------- */
.theme-toggle { display: inline-flex; align-items: center; gap: 0.5rem; margin-top: 1.1rem;
  padding: 0.42rem 0.5rem 0.42rem 0.85rem; border-radius: 999px; cursor: pointer;
  background: rgb(255 255 255 / 0.06); border: 1px solid rgb(255 255 255 / 0.14); color: #fff;
  font: 700 0.78rem "Manrope", sans-serif; transition: background .2s ease, border-color .2s ease; }
.theme-toggle:hover { background: rgb(255 255 255 / 0.12); border-color: rgb(255 255 255 / 0.3); }
.theme-toggle__track { position: relative; width: 2.9rem; height: 1.55rem; border-radius: 999px; flex: none;
  background: rgb(255 255 255 / 0.16); border: 1px solid rgb(255 255 255 / 0.18); transition: background .2s ease; }
.theme-toggle__knob { position: absolute; top: 1px; left: 1px; width: 1.3rem; height: 1.3rem; border-radius: 50%;
  display: grid; place-items: center; background: #fff; color: #131418;
  transition: transform .22s cubic-bezier(.2,.7,.2,1); }
.theme-toggle__knob svg { width: 13px; height: 13px; }
.theme-toggle__knob .i-sun { display: none; }
.theme-toggle__knob .i-moon { display: block; }
/* light mode: knob slides right, shows the sun */
html.light .theme-toggle__track { background: rgb(99 102 241 / 0.35); }
html.light .theme-toggle__knob { transform: translateX(1.35rem); color: #d97706; }
html.light .theme-toggle__knob .i-sun { display: block; }
html.light .theme-toggle__knob .i-moon { display: none; }

/* -------- nav theme toggle (compact icon button) --------
   Mirrors the app sign-in page's theme toggle: a bordered, blurred square with a
   single sun/moon glyph that shows the TARGET action (sun while dark → "go
   light", moon while light → "go dark"). Sized/rounded to sit as a tidy pair
   with the language pill on its right. The footer keeps its own labelled
   knob-track toggle (above) untouched. */
.theme-btn { display: inline-grid; place-items: center; width: 2.4rem; height: 2.4rem; padding: 0;
  border: 1px solid rgb(15 23 42 / 0.10); border-radius: 12px; background: rgb(255 255 255 / 0.9); color: #44474f;
  box-shadow: 0 1px 2px rgb(20 22 30 / 0.06); cursor: pointer;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  transition: color .14s ease, border-color .14s ease, background .14s ease, transform .12s ease; }
.theme-btn:hover { color: var(--indigo); border-color: var(--indigo-200); background: #fff; transform: translateY(-1px); }
.theme-btn svg { width: 1.1rem; height: 1.1rem; }
/* default (dark theme): show the sun ("go light"); light theme: show the moon. */
.theme-btn .i-sun { display: block; }
.theme-btn .i-moon { display: none; }
html.light .theme-btn .i-sun { display: none; }
html.light .theme-btn .i-moon { display: block; }
/* dark chrome: translucent-on-dark, matching the nav language pill beside it. */
html.dark .theme-btn { border-color: rgb(255 255 255 / 0.14); background: rgb(255 255 255 / 0.06); color: #c4c8d2; box-shadow: none; }
html.dark .theme-btn:hover { color: #a5b4fc; border-color: rgb(129 140 248 / 0.5); background: rgb(255 255 255 / 0.12); }
@media (prefers-reduced-motion: reduce) { .theme-btn { transition: color .14s ease, border-color .14s ease, background .14s ease; } }

/* ---- Light-mode frame: match the cream "app bar" ----------------------------
   In DARK mode the topbar/footer/overscroll gutter are the --dark chrome and
   read as a seamless dark frame. In LIGHT mode that dark chrome clashed with the
   cream nav — a hard dark→cream seam on scroll up/down. So in light mode the
   frame follows the SAME cream surface as the body/nav: one continuous light
   page, no transition. (Dark mode is untouched.) The Product-Hunt orange CTA and
   indigo "SOON" pill still pop against the cream. */
html.light { background-color: var(--paper); }             /* overscroll gutter */

html.light .topbar { background-color: var(--paper); background-image: none;
  color: var(--ink); border-bottom: 1px solid var(--line); }
html.light .topbar a { color: var(--ink); }
/* keep the SOON pill's text white on its indigo fill (the topbar text goes ink
   in light mode, which would otherwise darken the tag). */
html.light .topbar .tag { color: #fff; }
html.light .topbar::before { background-image:
    linear-gradient(rgb(20 22 30 / 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgb(20 22 30 / 0.05) 1px, transparent 1px); }

html.light footer { background-color: var(--paper); background-image: none;
  color: var(--ink); border-top: 1px solid var(--line); }
html.light footer::before { background-image:
    linear-gradient(rgb(20 22 30 / 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgb(20 22 30 / 0.05) 1px, transparent 1px); }
html.light footer .brand { color: var(--ink); }
html.light .foot__brand p { color: var(--ink-soft); }
html.light .foot__brand .copy { color: var(--muted); }
html.light .foot__col h4 { color: var(--muted); }
html.light .foot__col a { color: var(--ink-soft); }
html.light .foot__col a:hover { color: var(--ink); }
html.light .foot__top { color: var(--ink); background: rgb(20 22 30 / 0.05); border-color: var(--line); }
html.light .foot__top:hover { background: rgb(20 22 30 / 0.09); border-color: var(--line-2); }
html.light .foot__controls .lang__btn { background: var(--card); border-color: var(--line); color: var(--ink); }
html.light .foot__controls .lang__btn:hover { background: var(--paper-2); border-color: var(--line-2); }
html.light .foot__controls .lang__arrow { color: var(--muted); }
/* the theme toggle's base style is white-on-dark for the dark footer; on the
   cream light-mode footer that pill + its "Light" label vanish. Match the
   language-picker treatment: solid card fill, hairline border, ink text. */
html.light .foot__controls .theme-toggle { background: var(--card); border-color: var(--line); color: var(--ink); }
html.light .foot__controls .theme-toggle:hover { background: var(--paper-2); border-color: var(--line-2); }
@media (prefers-reduced-motion: reduce) { .theme-toggle__knob { transition: none; } }

/* ---------------------------------------------------------------- v28 feedback pass: calmer chrome, no top hairlines */
.nav { border-bottom: none; }
.mcp__note { margin: 1.8rem 0 0; font-weight: 600; color: var(--ink-soft); font-size: 1.02rem; }
.mcp__note b { color: var(--indigo); }
.trust__note { text-align: center; color: var(--muted); font-size: 0.8rem; font-weight: 600; margin: 1.5rem auto 0; }

/* ---------------------------------------------------------------- v31: razor-whoosh sheen
   Replaces the magnetic drift + split-flap flip (both removed) with a single clean
   light-streak that sweeps across the main buttons on hover. Same auto-sweep is
   restored on the announcement bar to draw the eye to it. */
.btn { position: relative; overflow: hidden; }
.btn::after { content: ""; position: absolute; top: -60%; left: 0; width: 100%; height: 220%; z-index: 2; pointer-events: none;
  background: linear-gradient(90deg, transparent 16%, rgb(255 255 255 / 0.10) 34%, rgb(255 255 255 / 0.55) 50%, rgb(255 255 255 / 0.10) 66%, transparent 84%);
  filter: blur(6px);
  transform: translateX(-115%) skewX(-26deg); }
.btn:hover::after, .btn:focus-visible::after { animation: blade 0.95s cubic-bezier(0.3, 0.55, 0.35, 1); }
@keyframes blade { from { transform: translateX(-115%) skewX(-26deg); } to { transform: translateX(115%) skewX(-26deg); } }

/* a broad, skewed, soft-edged blade of light that glides across once, then rests —
   wide + blurred so it reads as a sheen, not a thin line or a passing train. */
.topbar--ph { position: relative; overflow: hidden; }
.topbar--ph::after { content: ""; position: absolute; top: -40%; left: 0; height: 180%; width: 175px; z-index: 2; pointer-events: none;
  background: linear-gradient(90deg, transparent, rgb(255 255 255 / 0.10) 32%, rgb(255 255 255 / 0.44) 50%, rgb(255 255 255 / 0.10) 68%, transparent);
  filter: blur(8px);
  transform: translateX(-200px) skewX(-26deg);
  animation: topbarBlade 7.8s cubic-bezier(0.22, 0.61, 0.36, 1) 1.2s infinite; }
@keyframes topbarBlade {
  0%   { transform: translateX(-200px) skewX(-26deg); }
  27%  { transform: translateX(calc(100vw + 200px)) skewX(-26deg); }
  100% { transform: translateX(calc(100vw + 200px)) skewX(-26deg); }
}
@media (prefers-reduced-motion: reduce) {
  .btn:hover::after, .btn:focus-visible::after { animation: none; }
  .topbar--ph::after { animation: none; opacity: 0; }
}

/* ---------------------------------------------------------------- v33: platform scrollytelling
   Pin the feature section and cross-fade its panels as you scroll through the tabs
   (JS adds .is-platpin on desktop+motion; otherwise it's a normal click-tab block). */
.plat-pin.is-platpin { position: relative; }
.plat-pin.is-platpin .plat-pin__sticky { position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden;
  display: flex; flex-direction: column; justify-content: center; gap: clamp(0.4rem, 1.4vh, 1.1rem);
  padding: calc(var(--nav-h) + 0.5rem) 0 1.6rem; }
.plat-pin.is-platpin .wrap.section.tight { padding: 0; }
.plat-pin.is-platpin .ftabs { position: static; top: auto; background: transparent; }
.plat-pin.is-platpin .plat-pin__panels { position: relative; min-height: 50vh; }
/* HARD SNAP — exactly one panel shown at a time (no scroll-parked cross-fade blend).
   Hidden panels are opacity:0 instantly; only the shown one animates in (stepIn). */
.plat-pin.is-platpin .fmod { position: absolute; inset: 0; display: block !important; opacity: 0;
  pointer-events: none; animation: none; }
.plat-pin.is-platpin .fmod.is-shown { opacity: 1; pointer-events: auto;
  animation: stepIn .34s cubic-bezier(.2, .7, .2, 1); }
@media (prefers-reduced-motion: reduce) { .plat-pin.is-platpin .fmod.is-shown { animation: none; } }
.plat-pin.is-platpin .fmod__in { padding: 0; height: 100%; align-content: center; }
.plat-pin.is-platpin .fmod__visual { max-height: 52vh; }
.plat-pin.is-platpin .frame, .plat-pin.is-platpin .rows, .plat-pin.is-platpin .term { max-height: 48vh; }

/* custom dropdown (progressive-enhances the native <select>): opens BELOW, dark-themed,
   proper arrow padding — replaces the native popup that rendered light and overlaid on top. */
.csel { position: relative; }
.csel__native { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; margin: 0; }
.csel__btn { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; text-align: left; cursor: pointer; }
.csel__label { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.csel__label.is-placeholder { color: var(--muted); }
.csel__arrow { flex: none; display: grid; place-items: center; color: var(--muted); transition: transform 0.22s cubic-bezier(0.2, 0.7, 0.2, 1); }
.csel__arrow svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.3; stroke-linecap: round; stroke-linejoin: round; }
.csel.is-open .csel__arrow { transform: rotate(180deg); color: var(--indigo); }
.csel__btn.is-invalid { border-color: var(--err); box-shadow: 0 0 0 4px rgb(225 29 72 / 0.1); }
.csel__list { position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 60; padding: 0.35rem;
  border-radius: 12px; border: 1px solid var(--line-2); background: var(--card); box-shadow: var(--shadow-lg);
  max-height: min(60vh, 20rem); overflow-y: auto; transform-origin: top center; animation: cselIn 0.16s cubic-bezier(0.2, 0.7, 0.2, 1); }
/* JS (initSelect) flips the menu upward + clamps max-height to the free space when the
   field sits near the bottom of the viewport, so every option always renders. */
.csel.is-up .csel__list { top: auto; bottom: calc(100% + 6px); transform-origin: bottom center; animation-name: cselInUp; }
@keyframes cselIn { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
@keyframes cselInUp { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.csel__opt { padding: 0.58rem 0.7rem; border-radius: 8px; font-size: 0.95rem; font-weight: 600; color: var(--ink); cursor: pointer; }
.csel__opt.is-placeholder { color: var(--muted); }
.csel__opt:hover, .csel__opt.kb { background: var(--indigo-50); color: var(--indigo-700); }
.csel__opt.on { background: rgb(79 70 229 / 0.14); color: var(--indigo-700); }
@media (prefers-reduced-motion: reduce) { .csel__list { animation: none; } .csel__arrow { transition: none; } }

/* ---------------------------------------------------------------- v37: book-a-demo modal
   The demo form is no longer a page section — it lives in an overlay opened by any
   [data-open-demo] trigger. `.is-open` is the JS path; `:target` is a no-JS fallback. */
.modal { position: fixed; inset: 0; z-index: 200; display: none; align-items: flex-start; justify-content: center;
  padding: clamp(0.8rem, 4vh, 2.4rem) 1rem; overflow-y: auto; overscroll-behavior: contain; }
.modal.is-open, .modal:target { display: flex; }
.modal__backdrop { position: fixed; inset: 0; background: rgb(10 11 20 / 0.55); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); }
.modal__panel { position: relative; z-index: 1; width: min(460px, 100%); margin: auto;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow-lg);
  padding: clamp(1.25rem, 3.5vw, 1.75rem); animation: modalIn 0.3s cubic-bezier(0.2, 0.7, 0.2, 1); }
.modal:target .modal__panel { animation: modalIn 0.3s cubic-bezier(0.2, 0.7, 0.2, 1); }
@keyframes modalIn { from { opacity: 0; transform: translateY(16px) scale(0.985); } to { opacity: 1; transform: none; } }
.modal__head { margin-bottom: 1rem; }
.modal__head h2 { font-size: clamp(1.4rem, 3vw, 1.75rem); margin: 0.4rem 0 0.35rem; }
.modal__head p { margin: 0; color: var(--ink-soft); font-size: 0.9rem; line-height: 1.4; }
/* inside the modal the form is NOT its own card — the panel already is one */
.modal .wl { max-width: none; margin: 0; background: none; border: none; box-shadow: none; padding: 0; gap: 0.7rem; }
.modal .wl__row { gap: 0.7rem; }
.modal .wl__field { gap: 0.28rem; }
.modal .wl__label { font-size: 0.8rem; }
.modal .wl__input { padding: 0.52rem 0.7rem; font-size: 0.9rem; border-radius: 9px; }
.modal textarea.wl__input { min-height: 58px; }
.modal .wl__err { font-size: 0.75rem; min-height: 0.9rem; }
.modal .wl__submit { margin-top: 0.15rem; }
.modal__close { position: absolute; top: 0.7rem; right: 0.7rem; display: grid; place-items: center; width: 2rem; height: 2rem;
  border-radius: 9px; border: 1px solid var(--line); background: var(--paper); color: var(--ink-soft); cursor: pointer;
  transition: transform 0.15s ease, background 0.15s ease, color 0.15s ease, border-color 0.15s ease; }
.modal__close:hover { background: var(--paper-3); color: var(--ink); border-color: var(--line-2); transform: rotate(90deg); }
.modal__close svg { width: 16px; height: 16px; }
body.modal-open { overflow: hidden; }
html.dark .modal__close { background: rgb(255 255 255 / 0.05); border-color: rgb(255 255 255 / 0.14); color: var(--on-dark-soft); }
html.dark .modal__close:hover { background: rgb(255 255 255 / 0.12); color: #fff; }
@media (prefers-reduced-motion: reduce) { .modal__panel { animation: none; } .modal__close:hover { transform: none; } }

/* ---------------------------------------------------------------- v38: PH launch countdown
   Pre-launch the orange CTA pill holds a live d/h/m/s countdown. tabular-nums keeps
   the digits from jittering the pill width as they tick. */
/* sized to match the "Soon" tag pill — same height + type scale, never bigger */
.topbar__cta--count { gap: 0.34rem; padding: 0.18rem 0.55rem; cursor: default; }
.cd { display: inline-flex; align-items: baseline; gap: 0.3rem; font-variant-numeric: tabular-nums; }
.cd__seg { font-size: 0.56rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; opacity: 0.9; }
.cd__seg b { font-weight: 800; font-size: 0.68rem; letter-spacing: 0.005em; }
/* PH logo now sits inline just before the word "Product" */
.topbar__msg .topbar__ph { vertical-align: middle; margin: 0 0.34rem 0 0.12rem; position: relative; top: -0.05em; }

/* ---------------------------------------------------------------- v38: split-flap heading reveal
   Section <h2>s settle in like an airport departure board — each letter spins
   through random glyphs then locks, left→right. A hidden "ghost" copy of the final
   character reserves the cell width so the line NEVER reflows (no wobble/dizziness).
   Reduced-motion + no-IntersectionObserver skip it and show plain text. */
/* each word's letter-cells ride together so a word never breaks mid-glyph; the
   line only wraps at the real whitespace text nodes between words */
.flap-w { display: inline-block; white-space: nowrap; }
/* Clip only the x-axis (hides wider scramble glyphs past the reserved width);
   keep y visible so letter descenders (y, p, g) + punctuation aren't cut off.
   `clip` on one axis is honoured alongside `visible` on the other (unlike
   `hidden`, which would force the visible axis to `auto`). */
.flap-c { position: relative; display: inline-block; overflow-x: clip; overflow-y: visible; vertical-align: bottom; }
.flap-c__g { visibility: hidden; }                          /* final glyph — reserves exact width */
.flap-c__r { position: absolute; left: 0; right: 0; top: 0; text-align: center; white-space: nowrap; }
.flap-c.is-flipping .flap-c__r { color: var(--indigo); }    /* spinning letters glow indigo, settle to ink */
@media (prefers-reduced-motion: reduce) { .flap-c.is-flipping .flap-c__r { color: inherit; } }

/* ---------------------------------------------------------------- v41: typewriter testimonial
   The founder quote types itself out char-by-char when it scrolls in. Un-typed
   letters keep their layout (visibility:hidden) so the card never reflows; a blinking
   caret rides the frontier. RM / no-IO show the full quote at once. */
.cred blockquote.tw .tw-c { visibility: hidden; }
.cred blockquote.tw .tw-c.on { visibility: visible; }
.cred blockquote.tw .tw-c.caret { border-right: 2px solid currentColor; margin-right: -2px; }
.cred blockquote.tw.is-typing .tw-c.caret { animation: twBlink 1.05s step-end infinite; }
@keyframes twBlink { 0%, 100% { border-color: currentColor; } 50% { border-color: transparent; } }
@media (prefers-reduced-motion: reduce) {
  .cred blockquote.tw .tw-c { visibility: visible; }
  .cred blockquote.tw .tw-c.caret { border-right: 0; margin-right: 0; }
}

/* ---------------------------------------------------------------- v42: language picker
   Flags only (no country names) — a PLACEHOLDER: it does not translate yet. initLang
   builds it into every [data-lang] slot (nav top-right + footer). Styled to match the
   app's custom <select>. */
.lang { position: relative; display: inline-flex; }
/* Trigger mirrors the app login picker's button: a white rounded pill with an
   emoji flag and a static down chevron (no rotation, muted colour). */
.lang__btn { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.4rem 0.6rem; cursor: pointer;
  border: 1px solid rgb(15 23 42 / 0.10); border-radius: 12px; background: rgb(255 255 255 / 0.9); color: var(--ink);
  box-shadow: 0 1px 2px rgb(20 22 30 / 0.06);
  transition: border-color .15s ease, background .15s ease; }
.lang__btn:hover { background: #fff; }
/* Emoji flag — sized like the app's text-2xl glyph. */
.lang__flag { display: inline-flex; align-items: center; justify-content: center; font-size: 1.5rem; line-height: 1; }
.lang__arrow { display: grid; place-items: center; color: var(--muted); }
.lang__arrow svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
/* Popover mirrors the app login picker exactly: a 5-column grid of flag tiles,
   the active one an indigo-tinted tile with an inset ring + a corner check. */
.lang__list { position: absolute; top: calc(100% + 6px); right: 0; z-index: 80; padding: 0.5rem;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.375rem;
  border-radius: 16px; border: 1px solid var(--line-2); background: var(--card); box-shadow: var(--shadow-lg);
  transform-origin: top right; animation: cselIn .16s cubic-bezier(.2, .7, .2, 1); }
.lang__list[hidden] { display: none; }
/* 40px tiles to match the app login picker's measured tile size exactly. */
.lang__opt { position: relative; display: grid; place-items: center; width: 40px; height: 40px; padding: 0;
  border: 0; background: none; border-radius: 12px; cursor: pointer;
  transition: background .12s ease, box-shadow .12s ease; }
.lang__opt:hover, .lang__opt.kb { background: var(--paper-2); }
.lang__opt.on { background: var(--indigo-50); box-shadow: inset 0 0 0 1px var(--indigo-200); }
.lang__check { position: absolute; top: -5px; right: -5px; width: 16px; height: 16px; display: grid; place-items: center;
  border-radius: 50%; background: var(--indigo); color: #fff; box-shadow: 0 0 0 2px var(--card);
  opacity: 0; transform: scale(.5); transition: opacity .12s ease, transform .12s ease; }
.lang__check svg { width: 10px; height: 10px; fill: none; stroke: currentColor; stroke-width: 3.2; stroke-linecap: round; stroke-linejoin: round; }
.lang__opt.on .lang__check { opacity: 1; transform: scale(1); }
/* footer variant: a translucent chip on the dark footer, list opens upward */
.foot__controls { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin-top: 1.1rem; }
.foot__controls .theme-toggle { margin-top: 0; }
.foot__controls .lang__btn { background: rgb(255 255 255 / 0.06); border-color: rgb(255 255 255 / 0.14); color: #fff; }
.foot__controls .lang__btn:hover { background: rgb(255 255 255 / 0.12); border-color: rgb(255 255 255 / 0.3); }
.foot__controls .lang__arrow { color: rgb(255 255 255 / 0.6); }
.foot__controls .lang__list { top: auto; bottom: calc(100% + 6px); left: 0; right: auto; transform-origin: bottom left; }
/* dark theme: the base trigger + selected-tile styles are tuned for the light
   cream nav (white pill, near-white indigo-50 tile). On dark they read as a
   glaring white box and a bright tile — swap in a dark-appropriate treatment.
   The always-dark footer picker keeps its own style (scoped to .nav__lang). */
html.dark .nav__lang .lang__btn { background: rgb(255 255 255 / 0.06); border-color: rgb(255 255 255 / 0.14); box-shadow: none; }
html.dark .nav__lang .lang__btn:hover { background: rgb(255 255 255 / 0.12); border-color: rgb(255 255 255 / 0.28); }
html.dark .nav__lang .lang__arrow { color: rgb(255 255 255 / 0.55); }
html.dark .lang__opt:hover, html.dark .lang__opt.kb { background: rgb(255 255 255 / 0.06); }
html.dark .lang__opt.on { background: rgb(99 102 241 / 0.18); box-shadow: inset 0 0 0 1px rgb(129 140 248 / 0.5); }
@media (prefers-reduced-motion: reduce) { .lang__list { animation: none; } .lang__arrow { transition: none; } }
