/* ════════════════════════════════════════════════════════════════════════
   Landing page — public marketing site.

   Effects are hand-ported from Animate UI / React Bits into plain CSS +
   vanilla JS: no React, no Tailwind, no build step. Every animation runs on
   transform/opacity only, and the whole motion layer switches off under
   prefers-reduced-motion.

   Paired with /assets/js/landing.js.
   ════════════════════════════════════════════════════════════════════════ */

:root {
    --ink:        #0f172a;
    --ink-2:      #1e293b;
    --muted:      #64748b;
    --muted-2:    #94a3b8;
    --line:       #e2e8f0;
    --line-soft:  #eef2f7;
    --surface:    #ffffff;
    --canvas:     #f8fafc;

    --brand:      #4f6ef7;
    --brand-2:    #7c3aed;
    --grad:       linear-gradient(135deg, #4f6ef7, #7c3aed);

    --shadow-sm:  0 1px 2px rgba(15,23,42,.04);
    --shadow-md:  0 8px 24px rgba(15,23,42,.06);
    --shadow-lg:  0 18px 44px rgba(15,23,42,.10);
    --shadow-xl:  0 28px 70px rgba(15,23,42,.14);

    /* Gentle curves. The previous --ease-out (.16,1,.3,1) is an expo-out: it
       covers most of its distance almost instantly, which is what made the
       page feel snappy and hard. These settle instead of snapping. */
    --ease:       cubic-bezier(.4,0,.2,1);
    --ease-out:   cubic-bezier(.33,1,.68,1);
}

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

body {
    font-family: 'Inter', sans-serif;
    background: var(--canvas);
    color: var(--ink-2);
    -webkit-font-smoothing: antialiased;
    overflow-x: hidden;
}
a { text-decoration: none; }
::selection { background: rgba(79,110,247,.16); }

/* ══ MOTION PRIMITIVES ══════════════════════════════════════════════════
   Ported from Animate UI's "Motion Effect" and React Bits' "Blur Text" /
   "Split Text". JS adds .is-in when the element scrolls into view. */

/* Scoped to .js (set inline in <head>) so that with JavaScript disabled
   nothing is ever left invisible — the page simply renders static. */
.js [data-reveal] {
    opacity: 0;
    transform: translate3d(0, 16px, 0);
    /* Fade + slide only. A blur filter here read as the page going out of
       focus while scrolling, and it is expensive to composite besides. */
    transition:
        opacity   .9s var(--ease-out),
        transform .9s var(--ease-out);
    transition-delay: var(--reveal-delay, 0ms);
    will-change: opacity, transform;
}
.js [data-reveal="left"]  { transform: translate3d(-18px, 0, 0); }
.js [data-reveal="right"] { transform: translate3d(18px, 0, 0); }
.js [data-reveal="scale"] { transform: scale(.97); }

.js [data-reveal].is-in {
    opacity: 1;
    transform: none;
}
/* Once it has played, stop reserving a compositor layer. */
.js [data-reveal].is-done { will-change: auto; }

/* Word-by-word reveal (React Bits "Split Text" / "ScrollReveal").
   Words start at the library's baseOpacity of 0.1 rather than 0, so a heading
   is always legible — it resolves rather than materialises. The library's
   blur is deliberately omitted: blurring text on scroll reads as the page
   going out of focus. */
.split-word {
    display: inline-block;
    opacity: .1;
    transform: translate3d(0, .3em, 0);
    transition:
        opacity   .9s var(--ease-out),
        transform .9s var(--ease-out);
    transition-delay: var(--word-delay, 0ms);
}
.split-ready .split-word { opacity: 1; transform: none; }

/* Mask-wipe: the eyebrow label slides up from behind a clip. */
.rise-mask  { display: inline-block; overflow: hidden; vertical-align: bottom; padding-bottom: 2px; }
.rise-inner { display: inline-block; transform: translateY(110%); transition: transform 1.05s var(--ease-out); }
[data-rise].rise-ready .rise-inner { transform: none; }

/* ScrollFloat (React Bits): characters rise, un-squash and fade in, scrubbed
   to scroll. JS writes the transform each frame — CSS only sets the resting
   state so a heading is readable before the script runs. */
.float-word { display: inline-block; white-space: nowrap; }
/* An element animated whole (the gradient brand name) — the transform sits
   on this wrapper so the background-clip inside it stays intact. */
.float-atom { display: inline-block; }
.float-char {
    display: inline-block;
    transform-origin: 50% 0%;
    will-change: transform, opacity;
}
/* Hidden only once JS has taken over, so no-JS keeps the plain heading. */
.js [data-float] .float-char { opacity: 0; }

/* ══ SHINE SWEEP (React Bits "Shiny Text" / shine buttons) ══════════════ */
.shine { position: relative; overflow: hidden; isolation: isolate; }
.shine::after {
    content: '';
    position: absolute; top: 0; bottom: 0;
    left: -140%; width: 60%;
    background: linear-gradient(
        100deg,
        transparent 0%,
        rgba(255,255,255,.42) 50%,
        transparent 100%);
    transform: skewX(-18deg);
    pointer-events: none;
}
.shine:hover::after { animation: shineSweep .85s var(--ease-out); }
@keyframes shineSweep { to { left: 140%; } }

/* Gradient text that slowly drifts (Animate UI "Gradient Text"). */
.grad-text {
    background: linear-gradient(115deg, #4f6ef7, #7c3aed, #4f6ef7, #06b6d4, #4f6ef7);
    background-size: 280% 100%;
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
    animation: gradDrift 9s ease-in-out infinite;
}
@keyframes gradDrift {
    0%, 100% { background-position:   0% 50%; }
    50%      { background-position: 100% 50%; }
}

/* ══ MAGNETIC BUTTON (React Bits "Magnet") ══════════════════════════════
   JS writes --mx/--my; CSS does the moving so it stays on the compositor. */
.magnetic {
    transform: translate3d(var(--mx, 0px), var(--my, 0px), 0);
    transition: transform .35s var(--ease-out), box-shadow .25s var(--ease),
                opacity .2s var(--ease);
}
.magnetic.is-pulling { transition: transform .08s linear; }

/* ══ NAV ════════════════════════════════════════════════════════════════ */
nav {
    position: sticky; top: 0; z-index: 100;
    background: rgba(255,255,255,.72);
    backdrop-filter: blur(16px) saturate(180%);
    -webkit-backdrop-filter: blur(16px) saturate(180%);
    border-bottom: 1px solid transparent;
    padding: 0 2rem;
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    height: 72px;
    transition: height .3s var(--ease), background .3s var(--ease),
                border-color .3s var(--ease), box-shadow .3s var(--ease);
}
nav.is-stuck {
    height: 62px;
    background: rgba(255,255,255,.9);
    border-bottom-color: var(--line);
    box-shadow: 0 1px 24px rgba(15,23,42,.05);
}
.nav-brand { display: flex; align-items: center; gap: 10px; justify-self: start; }
.nav-brand img { transition: transform .3s var(--ease); }
.nav-brand:hover img { transform: scale(1.04); }

.nav-links { display: flex; align-items: center; gap: 4px; justify-self: center; }
.nav-link-item {
    position: relative;
    padding: 8px 14px; border-radius: 9px;
    font-size: .875rem; font-weight: 500; color: #475569;
    transition: color .2s var(--ease);
}
.nav-link-item::after {
    content: '';
    position: absolute; left: 14px; right: 14px; bottom: 3px;
    height: 2px; border-radius: 2px;
    background: var(--grad);
    transform: scaleX(0); transform-origin: left;
    transition: transform .3s var(--ease-out);
}
.nav-link-item:hover { color: var(--ink-2); }
.nav-link-item:hover::after { transform: scaleX(1); }

.nav-actions { display: flex; align-items: center; gap: 10px; justify-self: end; }
.btn-primary {
    padding: 10px 22px; border-radius: 10px;
    font-size: .875rem; font-weight: 700;
    background: var(--grad);
    color: #fff; border: none; cursor: pointer;
    box-shadow: 0 6px 18px rgba(79,110,247,.26);
    transition: box-shadow .25s var(--ease), opacity .2s var(--ease);
    display: inline-flex; align-items: center; gap: 7px;
}
.btn-primary:hover { color: #fff; box-shadow: 0 10px 26px rgba(79,110,247,.36); }

/* ══ HERO ═══════════════════════════════════════════════════════════════ */
.hero-wrap { position: relative; overflow: hidden; background: #fff; }


/* CSS aurora — the colour wash sitting under the dot field. */
.hero-aurora { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.hero-aurora span {
    position: absolute; display: block;
    border-radius: 50%;
    filter: blur(70px);
    opacity: .5;
    will-change: transform;
}
.hero-aurora span:nth-child(1) {
    width: 540px; height: 540px; top: -190px; left: -120px;
    background: radial-gradient(circle, rgba(79,110,247,.36), transparent 70%);
    animation: auroraA 19s ease-in-out infinite;
}
.hero-aurora span:nth-child(2) {
    width: 460px; height: 460px; top: -120px; right: -110px;
    background: radial-gradient(circle, rgba(124,58,237,.30), transparent 70%);
    animation: auroraB 23s ease-in-out infinite;
}
.hero-aurora span:nth-child(3) {
    width: 400px; height: 400px; bottom: -200px; left: 42%;
    background: radial-gradient(circle, rgba(6,182,212,.22), transparent 70%);
    animation: auroraC 27s ease-in-out infinite;
}
@keyframes auroraA { 50% { transform: translate3d(90px, 60px, 0) scale(1.14); } }
@keyframes auroraB { 50% { transform: translate3d(-80px, 70px, 0) scale(1.1); } }
@keyframes auroraC { 50% { transform: translate3d(-60px, -50px, 0) scale(1.18); } }

/* Interactive dot field (React Bits "DotGrid"). Dots light up and are pushed
   aside by the cursor, and a click sends a shock wave through them. Masked
   so the field fades out before it reaches the hero's edges. */
.hero-dots {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    pointer-events: none;
    opacity: 0;
    transition: opacity .9s var(--ease);
    mask-image: radial-gradient(ellipse 82% 68% at 50% 38%, #000 42%, transparent 82%);
    -webkit-mask-image: radial-gradient(ellipse 82% 68% at 50% 38%, #000 42%, transparent 82%);
}
.hero-dots.is-live { opacity: 1; }

/* Static fallback grid when the canvas cannot run. */
.hero-grid {
    position: absolute; inset: 0; pointer-events: none;
    background-image:
        linear-gradient(rgba(15,23,42,.045) 1px, transparent 1px),
        linear-gradient(90deg, rgba(15,23,42,.045) 1px, transparent 1px);
    background-size: 56px 56px;
    mask-image: radial-gradient(ellipse 80% 62% at 50% 34%, #000 35%, transparent 78%);
    -webkit-mask-image: radial-gradient(ellipse 80% 62% at 50% 34%, #000 35%, transparent 78%);
    transition: opacity .6s var(--ease);
}
/* Once the dot field is running the static grid is redundant. */
.hero-wrap.dots-on .hero-grid { opacity: 0; }

.hero {
    position: relative; z-index: 2;
    max-width: 1140px; margin: 0 auto;
    padding: 104px 2rem 84px;
    text-align: center;
}
.hero-badge {
    display: inline-flex; align-items: center; gap: 8px;
    background: rgba(255,255,255,.7);
    border: 1px solid rgba(79,110,247,.22);
    box-shadow: 0 2px 10px rgba(79,110,247,.08);
    backdrop-filter: blur(8px);
    color: var(--brand); font-size: .74rem; font-weight: 700;
    padding: 6px 16px 6px 12px; border-radius: 99px;
    margin-bottom: 30px; text-transform: uppercase; letter-spacing: .07em;
}
.hero-badge .pulse-dot {
    width: 7px; height: 7px; border-radius: 50%;
    background: #10b981; position: relative; flex: none;
}
.hero-badge .pulse-dot::after {
    content: ''; position: absolute; inset: 0; border-radius: 50%;
    background: #10b981; animation: pulseRing 2.2s var(--ease-out) infinite;
}
@keyframes pulseRing {
    0%   { transform: scale(1);   opacity: .7; }
    100% { transform: scale(3.2); opacity: 0;  }
}

.hero h1 {
    font-size: clamp(2.5rem, 5.6vw, 4.15rem);
    font-weight: 900; line-height: 1.06;
    letter-spacing: -.035em; margin-bottom: 24px;
    color: var(--ink);
}
.hero-sub {
    font-size: 1.12rem; color: var(--muted); max-width: 600px;
    margin: 0 auto 42px; line-height: 1.75;
}
.hero-cta {
    display: flex; align-items: center; justify-content: center;
    gap: 14px; flex-wrap: wrap; margin-bottom: 26px;
}
.btn-hero {
    display: inline-flex; align-items: center; gap: 9px;
    padding: 16px 38px; border-radius: 14px;
    font-size: 1rem; font-weight: 700;
    background: var(--grad);
    color: #fff;
    box-shadow: 0 10px 30px rgba(79,110,247,.34);
}
.btn-hero:hover { color: #fff; box-shadow: 0 16px 42px rgba(79,110,247,.44); }
.btn-hero-outline {
    display: inline-flex; align-items: center; gap: 9px;
    padding: 16px 32px; border-radius: 14px;
    font-size: 1rem; font-weight: 600;
    background: rgba(255,255,255,.75);
    backdrop-filter: blur(8px);
    color: #475569;
    border: 1.5px solid var(--line);
    transition: border-color .25s var(--ease), color .25s var(--ease),
                background .25s var(--ease), transform .25s var(--ease-out);
}
.btn-hero-outline:hover {
    border-color: rgba(79,110,247,.55); color: var(--brand);
    background: #fff; transform: translateY(-2px);
}

.hero-note {
    font-size: .8rem; color: var(--muted-2);
    display: flex; align-items: center; justify-content: center;
    gap: 20px; flex-wrap: wrap;
}
.hero-note span { display: inline-flex; align-items: center; gap: 6px; }

.hero-scroll {
    margin-top: 54px;
    display: inline-flex; flex-direction: column; align-items: center; gap: 7px;
    color: var(--muted-2); font-size: .7rem; font-weight: 600;
    text-transform: uppercase; letter-spacing: .12em;
}
.hero-scroll i { font-size: 1rem; animation: scrollNudge 2.1s var(--ease-out) infinite; }
@keyframes scrollNudge {
    0%, 100% { transform: translateY(0);   opacity: .55; }
    50%      { transform: translateY(6px); opacity: 1;   }
}

/* ══ STATS BAR — divided rail ═══════════════════════════════════════════
   Five numbers floating in a row read as an afterthought. Each one now sits
   in its own column of a ruled rail with an accent icon above it, so the
   band has structure without becoming another row of cards. */
.stats-bar {
    background: linear-gradient(180deg, #fff 0%, #fbfcfe 100%);
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    padding: 0 2rem;
    position: relative;
}
.stats-bar::before {
    content: ''; position: absolute; top: -1px; left: 50%; transform: translateX(-50%);
    width: min(680px, 80%); height: 1px;
    background: linear-gradient(90deg, transparent, rgba(79,110,247,.5), transparent);
}
.stats-inner {
    max-width: 1140px; margin: 0 auto;
    display: grid; grid-template-columns: repeat(5, 1fr);
}
.stat-item {
    --accent-rgb: 79, 110, 247;
    position: relative;
    padding: 36px 18px 34px;
    text-align: center;
    transition: background .35s var(--ease);
}
/* Hairline between columns, faded at both ends so it never hits the border. */
.stat-item + .stat-item::before {
    content: ''; position: absolute; left: 0; top: 24px; bottom: 24px; width: 1px;
    background: linear-gradient(180deg, transparent, var(--line) 20%, var(--line) 80%, transparent);
}
.stat-item:hover { background: rgba(var(--accent-rgb), .045); }

.stat-ico {
    width: 36px; height: 36px; border-radius: 11px; margin: 0 auto 14px;
    display: flex; align-items: center; justify-content: center;
    font-size: .92rem;
    color: rgb(var(--accent-rgb));
    background: rgba(var(--accent-rgb), .12);
    box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), .14);
    transition: transform .4s var(--ease-out), box-shadow .4s var(--ease);
}
.stat-item:hover .stat-ico {
    transform: translateY(-3px) scale(1.07) rotate(-3deg);
    box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), .3),
                0 8px 18px rgba(var(--accent-rgb), .22);
}

.stat-num {
    font-size: 2.35rem; font-weight: 900; letter-spacing: -.05em;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    background: linear-gradient(140deg, rgb(var(--accent-rgb)), rgba(var(--accent-rgb), .62));
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
}
.stat-lbl {
    font-size: .8rem; color: var(--muted); margin-top: 10px;
    font-weight: 600; line-height: 1.5;
}

@media (max-width: 900px) {
    .stats-inner { grid-template-columns: repeat(3, 1fr); }
    .stat-item + .stat-item::before { display: none; }
    .stat-item { padding: 28px 14px; }
}
@media (max-width: 520px) {
    .stats-inner { grid-template-columns: repeat(2, 1fr); }
    .stat-num { font-size: 1.95rem; }
}

/* ══ SECTIONS ═══════════════════════════════════════════════════════════ */
.section { max-width: 1140px; margin: 0 auto; padding: 96px 2rem; }
.section-label {
    text-align: center; font-size: .73rem; font-weight: 800;
    color: var(--brand); text-transform: uppercase; letter-spacing: .13em;
    margin-bottom: 12px;
}
.section-title {
    text-align: center; font-size: clamp(1.7rem, 3.1vw, 2.35rem);
    font-weight: 800; letter-spacing: -.028em; margin-bottom: 15px;
    color: var(--ink);
}
.section-sub {
    text-align: center; font-size: .96rem; color: var(--muted);
    max-width: 540px; margin: 0 auto 58px; line-height: 1.75;
}

/* ══ FEATURES ═══════════════════════════════════════════════════════════
   Eighteen identical white boxes said nothing about what each module is.
   Every card now carries its own accent, on the same system as the bento —
   gradient icon chip, rule that draws across the top, tint that follows the
   cursor, and a lift shadow in that card's own colour.

   The BorderGlow rides on top of that, now lit in each card's own accent
   instead of a single fixed violet. */
.features-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
@media (max-width: 1024px) { .features-grid { grid-template-columns: repeat(2,1fr); } }
@media (max-width: 640px)  { .features-grid { grid-template-columns: 1fr; } }

.feature-card {
    --accent-rgb: 79, 110, 247;
    --gx: 50%; --gy: 50%;

    /* BorderGlow state, written by JS from cursor proximity and angle. */
    --glow: 0;
    --cursor-angle: 45deg;
    --cone: 22;                /* half-width of the lit arc, as % of the rim */
    --card-br: 18px;
    --glow-pad: 26px;

    position: relative;
    display: flex; flex-direction: column;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: var(--card-br);
    padding: 28px 26px 26px;
    /* Visible, so the halo can bleed past the card. The cursor tint is still
       contained because a background is clipped by border-radius anyway. */
    overflow: visible;
    box-shadow: 0 1px 2px rgba(15,23,42,.04), 0 8px 22px rgba(15,23,42,.04);
    transition: transform .45s var(--ease-out), box-shadow .45s var(--ease),
                border-color .35s var(--ease);
}


/* Accent tint following the cursor. */
.feature-card::after {
    content: '';
    position: absolute; inset: 0; z-index: 0;
    border-radius: inherit; pointer-events: none;
    background: radial-gradient(300px circle at var(--gx) var(--gy),
        rgba(var(--accent-rgb), .085), transparent 66%);
    opacity: 0;
    transition: opacity .4s var(--ease);
}
.feature-card:hover::after { opacity: 1; }

.feature-card:hover {
    transform: translateY(-5px);
    /* Kept faint: the lit arc is the highlight, so a strongly tinted border
       underneath it just reads as a second competing line. */
    border-color: rgba(var(--accent-rgb), .18);
    box-shadow: 0 2px 4px rgba(15,23,42,.04), 0 20px 42px rgba(var(--accent-rgb), .17);
}

.feature-icon {
    width: 50px; height: 50px; border-radius: 15px;
    display: flex; align-items: center; justify-content: center;
    font-size: 1.3rem; margin-bottom: 18px; flex: none;
    color: rgb(var(--accent-rgb));
    background: linear-gradient(140deg, rgba(var(--accent-rgb), .17), rgba(var(--accent-rgb), .06));
    box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), .16);
    transition: transform .4s var(--ease-out), background .4s var(--ease),
                color .4s var(--ease), box-shadow .4s var(--ease);
}
/* The chip fills solid on hover — the moment that makes the card feel alive. */
.feature-card:hover .feature-icon {
    color: #fff;
    background: linear-gradient(145deg, rgb(var(--accent-rgb)), rgba(var(--accent-rgb), .76));
    box-shadow: 0 10px 22px rgba(var(--accent-rgb), .34);
    transform: translateY(-2px) scale(1.06) rotate(-3deg);
}

.feature-card h3 {
    font-size: 1rem; font-weight: 800; margin-bottom: 9px;
    color: var(--ink); letter-spacing: -.015em;
}
.feature-card p { font-size: .865rem; color: var(--muted); line-height: 1.7; }
.feature-card > *:not(.bg-edge-light) { position: relative; z-index: 1; }

/* ── BorderGlow (React Bits) ─────────────────────────────────────────────
   Gated on mask support: unmasked, these gradients paint as a hard ring
   around the whole card, which is worse than no effect. Inert otherwise. */
.bg-edge-light { display: none; }

@supports (mask-image: conic-gradient(#000, #fff)) {

    /* The rim: a gradient border masked to an arc facing the cursor.
       The padding-box layer MUST be opaque — it covers the card interior so
       only the 1.6px border is left showing. Transparent there let the accent
       gradient flood the whole card. It sits at z-index 0, behind the text,
       which is what lets an opaque fill be used at all. */
    .feature-card::before {
        content: '';
        /* -1px, not 0. An absolutely positioned box resolves inset against the
           PADDING box, so inset:0 sat one pixel inside the card's own 1px
           border — the accent ring and the grey border drew as two offset
           lines, mismatched at the corners because the radii differ too.
           Pulling it out by the border width makes the two coincide, so the
           lit arc covers the grey border instead of sitting beside it. */
        position: absolute; inset: -1px; z-index: 0;
        border-radius: inherit;
        border: 1.6px solid transparent;
        pointer-events: none;
        background:
            linear-gradient(#fff 0 100%) padding-box,
            linear-gradient(135deg,
                rgba(var(--accent-rgb), 1),
                rgba(var(--accent-rgb), .45) 45%,
                rgba(var(--accent-rgb), 1)) border-box;
        -webkit-mask-image: conic-gradient(from var(--cursor-angle) at center,
            #000 calc(var(--cone) * 1%),
            transparent calc((var(--cone) + 16) * 1%),
            transparent calc((100 - var(--cone) - 16) * 1%),
            #000 calc((100 - var(--cone)) * 1%));
        mask-image: conic-gradient(from var(--cursor-angle) at center,
            #000 calc(var(--cone) * 1%),
            transparent calc((var(--cone) + 16) * 1%),
            transparent calc((100 - var(--cone) - 16) * 1%),
            #000 calc((100 - var(--cone)) * 1%));
        opacity: var(--glow);
        transition: opacity .3s var(--ease);
    }

    /* Halo bleeding outside the card, on its own larger element so the mask
       does not clip it. Sits behind the card. */
    .feature-card > .bg-edge-light {
        display: block;
        position: absolute; inset: calc(var(--glow-pad) * -1);
        z-index: -1; pointer-events: none;
        border-radius: calc(var(--card-br) + var(--glow-pad));
        -webkit-mask-image: conic-gradient(from var(--cursor-angle) at center,
            #000 3%, transparent 12%, transparent 88%, #000 97%);
        mask-image: conic-gradient(from var(--cursor-angle) at center,
            #000 3%, transparent 12%, transparent 88%, #000 97%);
        opacity: var(--glow);
        transition: opacity .3s var(--ease);
    }
    /* Radius is the CARD's — inheriting the inflated one drew a second,
       rounder ring cutting across every corner. */
    .feature-card > .bg-edge-light::before {
        content: '';
        position: absolute; inset: var(--glow-pad);
        border-radius: var(--card-br);
        box-shadow:
            0 0 4px 0   rgba(var(--accent-rgb), .55),
            0 0 18px 0  rgba(var(--accent-rgb), .3),
            0 0 54px 2px rgba(var(--accent-rgb), .13);
    }
}

/* ══ HOW IT WORKS — full-width timeline rows ════════════════════════════
   Three columns per row — node, copy, supporting detail — so every row
   spans the section and there is no dead column. Still no cards: the only
   chrome is the rail, the node and a hairline between rows. */
.how-bg {
    background:
        radial-gradient(ellipse 50% 40% at 10% 0%, rgba(79,110,247,.055), transparent 62%),
        radial-gradient(ellipse 50% 40% at 92% 100%, rgba(124,58,237,.05), transparent 62%),
        #fff;
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
}

.timeline { position: relative; max-width: 1040px; margin: 0 auto; }

.timeline-rail {
    position: absolute; left: 27px; top: 38px; bottom: 42px;
    width: 2px; border-radius: 2px;
    background: var(--line);
    z-index: 0;                 /* strictly behind every row */
}
.timeline-fill {
    position: absolute; inset: 0; border-radius: inherit;
    background: linear-gradient(180deg, #4f6ef7 0%, #7c3aed 55%, #06b6d4 100%);
    transform: scaleY(0); transform-origin: top;
    will-change: transform;
}
html:not(.js) .timeline-fill { transform: scaleY(1); }

/* Two rows: the step label runs across both content columns, so the title
   and the supporting points start on exactly the same line. That alignment
   is structural — no hand-tuned padding holding the columns level. */
.tl-step {
    --accent-rgb: 79, 110, 247;
    position: relative; z-index: 2;
    display: grid;
    grid-template-columns: 56px minmax(0, 1.08fr) minmax(0, .92fr);
    grid-template-rows: auto 1fr;
    column-gap: 40px;
    align-items: start;
    padding: 34px 0 36px;
}
.tl-step + .tl-step { border-top: 1px solid var(--line-soft); }

.tl-node {
    grid-area: 1 / 1 / 3 / 2;
    position: relative; z-index: 2;   /* the rail must never cross the number */
    width: 56px; height: 56px; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: 1.02rem; font-weight: 900;
    background: #fff; color: #b3bdcc;
    box-shadow: inset 0 0 0 2px var(--line);
    transition: background .55s var(--ease-out), color .45s var(--ease),
                box-shadow .55s var(--ease-out), transform .55s var(--ease-out);
}
.tl-step.is-active .tl-node {
    background: linear-gradient(145deg, rgb(var(--accent-rgb)), rgba(var(--accent-rgb), .74));
    color: #fff;
    box-shadow: inset 0 0 0 2px rgba(var(--accent-rgb), 0),
                0 10px 24px rgba(var(--accent-rgb), .38);
    transform: scale(1.06);
}

.tl-body { grid-area: 2 / 2 / 3 / 3; min-width: 0; }
.tl-label {
    grid-area: 1 / 2 / 2 / 4;
    display: inline-flex; align-items: center; gap: 8px; justify-self: start;
    font-size: .7rem; font-weight: 800; letter-spacing: .15em; text-transform: uppercase;
    color: #a9b3c4; margin-bottom: 12px;
    transition: color .45s var(--ease);
}
.tl-step.is-active .tl-label { color: rgb(var(--accent-rgb)); }
.tl-label i { font-size: .9rem; }

.tl-title {
    font-size: 1.46rem; font-weight: 800; letter-spacing: -.028em;
    color: var(--ink); margin-bottom: 11px; line-height: 1.25;
}
.tl-desc { font-size: .95rem; color: var(--muted); line-height: 1.78; }

/* Supporting detail fills the right half of every row, starting level with
   the title because both sit in grid row 2. */
.tl-points {
    grid-area: 2 / 3 / 3 / 4;
    list-style: none; padding: 0; margin: 0;
    display: flex; flex-direction: column; gap: 12px;
}
.tl-points li {
    display: flex; align-items: flex-start; gap: 11px;
    font-size: .875rem; color: #475569; line-height: 1.6;
}
.tl-points i {
    flex: none; margin-top: 1px;
    width: 22px; height: 22px; border-radius: 7px;
    display: flex; align-items: center; justify-content: center;
    font-size: .68rem;
    color: rgb(var(--accent-rgb));
    background: rgba(var(--accent-rgb), .12);
    box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), .16);
    transition: transform .4s var(--ease-out);
}
.tl-step:hover .tl-points i { transform: scale(1.08); }

@media (max-width: 900px) {
    /* Points drop under the copy: three rows, two columns. */
    .tl-step {
        grid-template-columns: 56px minmax(0, 1fr);
        grid-template-rows: auto auto auto;
        column-gap: 24px; padding: 28px 0 30px;
    }
    .tl-node   { grid-area: 1 / 1 / 4 / 2; }
    .tl-label  { grid-area: 1 / 2 / 2 / 3; }
    .tl-body   { grid-area: 2 / 2 / 3 / 3; }
    .tl-points { grid-area: 3 / 2 / 4 / 3; margin-top: 18px; }
}
@media (max-width: 640px) {
    .timeline-rail { left: 21px; }
    .tl-step { grid-template-columns: 44px minmax(0, 1fr); column-gap: 18px; }
    .tl-node { width: 44px; height: 44px; font-size: .9rem; }
    .tl-title { font-size: 1.18rem; }
    .tl-desc, .tl-points li { font-size: .88rem; }
}

/* ══ MODULES — tab strip over one panel ═════════════════════════════════
   The list sat beside the panel as twelve rows, which left the panel's
   column dead below it; stretching the panel only moved that gap inside.
   The strip runs across the top instead, so the panel is full width and its
   own content sets the height — nothing to pad out. */
.mods { display: block; }

/* ── Tab strip ── */
.mods-list {
    display: flex; flex-wrap: wrap; justify-content: center;
    gap: 8px; margin-bottom: 26px;
}
.mod-item {
    --accent-rgb: 79, 110, 247;
    display: inline-flex; align-items: center; gap: 8px;
    padding: 9px 17px; border-radius: 99px;
    border: none; background: #fff;
    box-shadow: inset 0 0 0 1px var(--line);
    font-family: inherit; font-size: .82rem; font-weight: 600;
    color: #56637a; cursor: pointer; white-space: nowrap;
    transition: background .25s var(--ease), color .25s var(--ease),
                box-shadow .25s var(--ease), transform .25s var(--ease-out);
}
.mod-item > i:first-child { font-size: .9rem; color: rgb(var(--accent-rgb)); transition: color .25s var(--ease); }
.mod-item .mod-chev { display: none; }
.mod-item:hover {
    color: var(--ink-2);
    box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), .4);
    transform: translateY(-1px);
}
.mod-item:focus-visible { outline: 2px solid rgb(var(--accent-rgb)); outline-offset: 2px; }
.mod-item.is-active {
    background: rgb(var(--accent-rgb)); color: #fff; font-weight: 700;
    box-shadow: 0 8px 20px rgba(var(--accent-rgb), .3);
}
.mod-item.is-active > i:first-child { color: #fff; }

/* ── Panel: full width, two columns inside ── */
.mods-panels { display: grid; }
.mod-panel {
    --accent-rgb: 79, 110, 247;
    grid-area: 1 / 1;
    display: grid;
    grid-template-columns: minmax(0, 1.06fr) minmax(0, .94fr);
    grid-template-areas: "main side" "foot foot";
    column-gap: 46px;
    border-radius: 22px;
    padding: 38px 38px 30px;
    background:
        radial-gradient(110% 140% at 100% 0%, rgba(var(--accent-rgb), .09), transparent 58%),
        linear-gradient(160deg, rgba(var(--accent-rgb), .05), rgba(var(--accent-rgb), .015));
    box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), .13);
    opacity: 0; visibility: hidden; pointer-events: none;
    transform: translateY(10px);
    transition: opacity .4s var(--ease), transform .45s var(--ease-out), visibility .4s;
}
.mod-panel.is-active { opacity: 1; visibility: visible; pointer-events: auto; transform: none; }
html:not(.js) .mod-panel { opacity: 1; visibility: visible; transform: none; }
html:not(.js) .mods-panels { display: flex; flex-direction: column; gap: 16px; }

.mod-main { grid-area: main; min-width: 0; }
.mod-side { grid-area: side; min-width: 0; }

.mod-panel-icon {
    width: 58px; height: 58px; border-radius: 17px;
    display: flex; align-items: center; justify-content: center;
    font-size: 1.5rem; margin-bottom: 20px;
    color: #fff;
    background: linear-gradient(145deg, rgb(var(--accent-rgb)), rgba(var(--accent-rgb), .72));
    box-shadow: 0 12px 26px rgba(var(--accent-rgb), .34);
}
.mod-panel h4 {
    font-size: 1.5rem; font-weight: 800; letter-spacing: -.03em;
    color: var(--ink); margin-bottom: 12px; line-height: 1.22;
}
.mod-panel p { font-size: .95rem; color: var(--muted); line-height: 1.78; }

.mod-side-label {
    font-size: .68rem; font-weight: 800; letter-spacing: .15em; text-transform: uppercase;
    color: rgb(var(--accent-rgb));
    margin-bottom: 14px; padding-top: 4px;
}
.mod-tags { display: flex; flex-direction: column; gap: 9px; }
.mod-tag {
    display: flex; align-items: center; gap: 10px;
    font-size: .855rem; font-weight: 600; color: #475569;
    padding: 9px 14px; border-radius: 11px;
    background: #fff;
    box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), .16);
}
.mod-tag::before {
    content: ''; flex: none;
    width: 6px; height: 6px; border-radius: 50%;
    background: rgb(var(--accent-rgb));
}

.mod-foot {
    grid-area: foot;
    margin-top: 30px; padding-top: 22px;
    border-top: 1px solid rgba(var(--accent-rgb), .16);
    display: flex; align-items: center; justify-content: space-between;
    gap: 14px; flex-wrap: wrap;
    font-size: .82rem; font-weight: 600; color: var(--muted);
}
.mod-foot > span { display: inline-flex; align-items: center; gap: 8px; }
.mod-foot > span > i { color: rgb(var(--accent-rgb)); font-size: .95rem; }
.mod-cta {
    display: inline-flex; align-items: center; gap: 7px;
    font-size: .82rem; font-weight: 700;
    color: rgb(var(--accent-rgb));
    transition: gap .25s var(--ease);
}
.mod-cta:hover { gap: 12px; color: rgb(var(--accent-rgb)); }

@media (max-width: 820px) {
    .mods-list { justify-content: flex-start; }
    .mod-panel {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas: "main" "side" "foot";
        padding: 30px 24px 26px;
    }
    .mod-side { margin-top: 26px; }
    .mod-panel h4 { font-size: 1.28rem; }
}

/* ══ PRICING ════════════════════════════════════════════════════════════ */
.pricing-bg {
    background: linear-gradient(180deg, #fff 0%, var(--canvas) 100%);
    border-top: 1px solid var(--line-soft); border-bottom: 1px solid var(--line-soft);
}
.pricing-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; max-width: 1140px; margin: 0 auto; }
@media (max-width: 1024px) { .pricing-grid { grid-template-columns: repeat(2,1fr); } }
@media (max-width: 560px)  { .pricing-grid { grid-template-columns: 1fr; } }

.pricing-card {
    position: relative; background: #fff;
    border: 1.5px solid var(--line); border-radius: 20px;
    padding: 30px 26px; display: flex; flex-direction: column;
    box-shadow: var(--shadow-sm);
    transition: transform .3s var(--ease-out), box-shadow .3s var(--ease),
                border-color .3s var(--ease);
}
.pricing-card:hover { transform: translateY(-6px); box-shadow: var(--shadow-lg); border-color: #cbd5e1; }

/* Popular card: slowly rotating conic gradient border. */
.pricing-card.popular {
    border-color: transparent;
    box-shadow: 0 18px 46px rgba(124,58,237,.18);
}
.pricing-card.popular::before {
    content: '';
    position: absolute; inset: -1.5px;
    border-radius: inherit;
    background: conic-gradient(from var(--ring, 0deg),
        #4f6ef7, #7c3aed, #06b6d4, #7c3aed, #4f6ef7);
    animation: ringSpin 6s linear infinite;
    z-index: 0;
}
.pricing-card.popular::after {
    content: '';
    position: absolute; inset: 0;
    border-radius: inherit; background: #fff;
    z-index: 0;
}
.pricing-card.popular > * { position: relative; z-index: 1; }
@keyframes ringSpin { to { --ring: 360deg; } }
@property --ring { syntax: '<angle>'; initial-value: 0deg; inherits: false; }

.pricing-pop-tag {
    position: absolute; top: -12px; left: 50%; transform: translateX(-50%);
    background: var(--grad); color: #fff;
    font-size: .68rem; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
    padding: 5px 15px; border-radius: 99px; white-space: nowrap;
    box-shadow: 0 4px 14px rgba(124,58,237,.35);
    z-index: 2;
}
.pricing-icon { width: 48px; height: 48px; border-radius: 14px; display: flex; align-items: center; justify-content: center; font-size: 1.3rem; margin-bottom: 15px; }
.pricing-name  { font-size: 1.06rem; font-weight: 800; color: var(--ink-2); }
.pricing-cycle { font-size: .75rem; color: var(--muted-2); margin-bottom: 15px; }
.pricing-amount {
    font-size: 2.5rem; font-weight: 900; color: var(--ink);
    line-height: 1; letter-spacing: -.03em;
    font-variant-numeric: tabular-nums;
}
.pricing-amount sup { font-size: 1.1rem; font-weight: 700; top: -.7em; margin-right: 1px; }
.pricing-per  { font-size: .72rem; color: var(--muted-2); margin: 7px 0 18px; }
.pricing-feats { list-style: none; padding: 0; margin: 0 0 24px; flex: 1; }
.pricing-feats li { display: flex; align-items: flex-start; gap: 9px; font-size: .84rem; color: #475569; padding: 6px 0; }
.pricing-feats li i { color: #10b981; font-size: .9rem; margin-top: 2px; flex-shrink: 0; }
.pricing-btn {
    display: flex; align-items: center; justify-content: center; gap: 8px;
    width: 100%; padding: 12px; border-radius: 11px;
    font-size: .875rem; font-weight: 700;
    transition: opacity .2s var(--ease), transform .2s var(--ease-out), box-shadow .25s var(--ease);
}
.pricing-btn-primary { background: var(--grad); color: #fff; box-shadow: 0 6px 18px rgba(79,110,247,.28); }
.pricing-btn-primary:hover { color: #fff; box-shadow: 0 10px 26px rgba(79,110,247,.4); }
.pricing-btn-outline { background: transparent; color: #334155; border: 1.5px solid var(--line); }
.pricing-btn-outline:hover { border-color: rgba(79,110,247,.5); color: var(--brand); }
.pricing-btn:hover { transform: translateY(-2px); }
.pricing-note { text-align: center; font-size: .82rem; color: var(--muted-2); margin-top: 38px; }

/* ══ TRIAL CTA ══════════════════════════════════════════════════════════ */
.trial-wrap { padding: 0 2rem 96px; }
.trial-banner {
    max-width: 860px; margin: 0 auto;
    /* Three stops rather than two, oversized and slowly drifting, so the
       surface is always gently moving instead of being a flat block. */
    background: linear-gradient(135deg, #4f6ef7 0%, #6b53f0 46%, #8b3ff0 100%);
    border-radius: 28px; padding: 66px 48px 58px;
    text-align: center; color: #fff;
    position: relative; overflow: hidden; isolation: isolate;
    /* Inset hairline gives the panel an edge instead of bleeding into the page. */
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,.22),
        inset 0 0 0 1px rgba(255,255,255,.12),
        0 30px 70px rgba(79,110,247,.3);
}
/* No hover response on the panel itself. It is a banner, not a control —
   the button inside it is the only thing you can act on, so it is the only
   thing that should react. The panel's life comes from its own ambient
   motion instead. */

.trial-banner > * { position: relative; z-index: 1; }
.trial-banner h2 { font-size: clamp(1.7rem, 3.1vw, 2.15rem); font-weight: 900; margin-bottom: 15px; letter-spacing: -.02em; }
.trial-banner p  { font-size: .98rem; opacity: .88; margin: 0 auto 34px; max-width: 490px; line-height: 1.7; }
.btn-white {
    display: inline-flex; align-items: center; gap: 9px;
    padding: 15px 36px; border-radius: 13px;
    font-size: .98rem; font-weight: 700;
    background: #fff; color: var(--brand);
    box-shadow: 0 10px 30px rgba(15,23,42,.18);
    transition: box-shadow .25s var(--ease);
}
.btn-white:hover {
    color: var(--brand);
    transform: translateY(-2px);
    box-shadow: 0 18px 42px rgba(15,23,42,.28);
}

/* Perks as translucent pills — loose low-opacity text under a big headline
   read as an afterthought. */
.trial-perks { display: flex; justify-content: center; gap: 10px; flex-wrap: wrap; margin-top: 30px; }
.trial-perk {
    display: inline-flex; align-items: center; gap: 7px;
    font-size: .79rem; font-weight: 600;
    padding: 7px 14px; border-radius: 99px;
    color: rgba(255,255,255,.95);
    background: rgba(255,255,255,.12);
    box-shadow: inset 0 0 0 1px rgba(255,255,255,.16);
    transition: background .3s var(--ease);
}
.trial-perk:hover { background: rgba(255,255,255,.2); }
.trial-perk i { font-size: .85rem; color: rgba(255,255,255,.85); }

/* Aurora canvas (React Bits). Sits under the content, over the gradient.

   Screen blend, not normal. The shader writes colour = intensity * ramp, so
   wherever the band is faint the colour is near-black while its alpha is
   still partial — composited normally that paints dark murk across the
   panel. The library assumes a dark page behind it, where that never shows.
   Screen can only lighten, so the faint areas contribute nothing and the
   bright band still reads. */
.banner-aurora {
    position: absolute; inset: 0; z-index: 0;
    width: 100%; height: 100%;
    border-radius: inherit; pointer-events: none;
    mix-blend-mode: screen;
    opacity: 0; transition: opacity 1.2s var(--ease);
}
.banner-aurora.is-live { opacity: .9; }

/* Where it is supported, plus-lighter is truly additive — even cleaner than
   screen for a light effect laid over colour. */
@supports (mix-blend-mode: plus-lighter) {
    .banner-aurora { mix-blend-mode: plus-lighter; }
    .banner-aurora.is-live { opacity: .75; }
}

/* ══ FOOTER ═════════════════════════════════════════════════════════════ */
.footer-wrap { border-top: 1px solid var(--line); background: #fff; }
footer {
    padding: 36px 2rem;
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap; gap: 12px;
    font-size: .81rem; color: var(--muted-2);
    max-width: 1140px; margin: 0 auto;
}

/* ══ NAV HOVER BACKGROUND (Animate UI "Hover Background") ═══════════════
   One pill slides between links instead of each link lighting separately. */
.nav-links { position: relative; }
.nav-pill {
    position: absolute; top: 50%; left: 0;
    height: 34px; width: 0;
    transform: translate3d(var(--px, 0px), -50%, 0);
    border-radius: 9px;
    background: rgba(79,110,247,.1);
    opacity: 0;
    transition: transform .34s var(--ease-out), width .34s var(--ease-out),
                opacity .22s var(--ease);
    pointer-events: none;
    z-index: 0;
}
.nav-links.is-hovering .nav-pill { opacity: 1; }
.nav-link-item { z-index: 1; }


/* ══ GRAIN ══════════════════════════════════════════════════════════════
   A little film grain stops the large gradients from banding. */
.grain::after {
    content: '';
    position: absolute; inset: 0;
    pointer-events: none; z-index: 1;
    opacity: .5;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.045'/%3E%3C/svg%3E");
}

/* ══ SCROLL PROGRESS ════════════════════════════════════════════════════ */
.scroll-progress {
    position: fixed; top: 0; left: 0; z-index: 200;
    height: 3px; width: 100%;
    transform: scaleX(0); transform-origin: left;
    background: linear-gradient(90deg, #4f6ef7, #7c3aed, #06b6d4);
    pointer-events: none;
}

/* ══ HERO ROTATING WORD ═════════════════════════════════════════════════ */
.hero-rotate-line {
    font-size: 1.06rem; font-weight: 700; color: var(--muted);
    margin: -8px 0 22px;
    display: flex; align-items: baseline; justify-content: center; gap: .4em;
    flex-wrap: wrap;
}
.hero-rotate {
    display: inline-grid;
    vertical-align: bottom;
    text-align: left;
}
.hero-rotate > span {
    grid-area: 1 / 1;
    opacity: 0;
    transform: translateY(.45em);
    transition: opacity .45s var(--ease-out), transform .45s var(--ease-out);
    background: var(--grad);
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
    white-space: nowrap;
}
.hero-rotate > span.is-on { opacity: 1; transform: none; }
.hero-rotate > span.is-out { opacity: 0; transform: translateY(-.45em); }

/* ══ APP MOCKUP ═════════════════════════════════════════════════════════
   A pure-CSS picture of the product — no screenshots to keep in sync. */
.mock-wrap { position: relative; max-width: 940px; margin: 58px auto 0; padding: 0 .5rem; }

.app-mock {
    position: relative;
    border-radius: 16px;
    background: #fff;
    border: 1px solid var(--line);
    box-shadow: var(--shadow-xl);
    overflow: hidden;
    transform: perspective(1800px) rotateX(4deg);
    transform-origin: center top;
}
.app-mock-bar {
    display: flex; align-items: center; gap: 7px;
    padding: 10px 14px;
    background: #f8fafc;
    border-bottom: 1px solid var(--line);
}
.app-mock-bar .dot { width: 10px; height: 10px; border-radius: 50%; background: #e2e8f0; flex: none; }
.app-mock-bar .dot:nth-child(1) { background: #fca5a5; }
.app-mock-bar .dot:nth-child(2) { background: #fcd34d; }
.app-mock-bar .dot:nth-child(3) { background: #86efac; }
.app-mock-url {
    margin-left: 10px; flex: 1;
    display: inline-flex; align-items: center; gap: 6px;
    max-width: 320px; padding: 4px 12px; border-radius: 99px;
    background: #fff; border: 1px solid var(--line);
    font-size: .68rem; color: var(--muted-2);
}

/* The screenshot itself. Aspect ratio is fixed so the hero never reflows
   while the image loads. */
.app-mock-shot {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 1906 / 951;
    background: #f8fafc;
}

/* Floating notification chips around the mockup */
.mock-float {
    position: absolute; z-index: 3;
    display: inline-flex; align-items: center; gap: 8px;
    padding: 9px 14px; border-radius: 12px;
    background: rgba(255,255,255,.92);
    backdrop-filter: blur(10px);
    border: 1px solid var(--line);
    box-shadow: var(--shadow-lg);
    font-size: .74rem; font-weight: 700; color: var(--ink-2);
    white-space: nowrap;
}
.mock-float i { font-size: .9rem; }
.mock-float-1 { top: 16%;  left: -18px;  animation: floatY 6.5s ease-in-out infinite; }
.mock-float-2 { top: 44%;  right: -22px; animation: floatY 7.5s ease-in-out infinite .7s; }
.mock-float-3 { bottom: 12%; left: 4%;   animation: floatY 8s   ease-in-out infinite 1.4s; }
@keyframes floatY { 50% { transform: translateY(-11px); } }

/* ══ MARQUEE (React Bits "Logo Loop") ═══════════════════════════════════ */
.marquee {
    position: relative; overflow: hidden;
    padding: 22px 0;
    background: #fff;
    border-bottom: 1px solid var(--line);
    mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}
.marquee-track { display: flex; width: max-content; gap: 12px; animation: marqueeRun 42s linear infinite; }
.marquee:hover .marquee-track { animation-play-state: paused; }
.marquee-track.reverse { animation-direction: reverse; animation-duration: 52s; margin-top: 12px; }
@keyframes marqueeRun { to { transform: translate3d(-50%, 0, 0); } }
.marquee-chip {
    display: inline-flex; align-items: center; gap: 8px;
    padding: 9px 18px; border-radius: 99px;
    border: 1px solid var(--line); background: var(--canvas);
    font-size: .82rem; font-weight: 600; color: #475569;
    white-space: nowrap;
}
.marquee-chip i { font-size: .9rem; }

/* ══ BENTO — light, per-card accent ═════════════════════════════════════
   Premium on a light surface comes from depth and restraint, not glow: each
   card owns an accent colour that drives its icon chip, the rule that draws
   across its top on hover, the tint that follows the cursor, and the colour
   of its lifted shadow. --accent-rgb is set per tile in the markup. */
.bento-section {
    position: relative;
    overflow: hidden;
    background:
        radial-gradient(ellipse 62% 48% at 50% -6%, rgba(79,110,247,.09), transparent 62%),
        radial-gradient(ellipse 45% 40% at 88% 108%, rgba(124,58,237,.07), transparent 65%),
        linear-gradient(180deg, #ffffff 0%, #f6f7fc 100%);
    border-top: 1px solid var(--line-soft);
    border-bottom: 1px solid var(--line-soft);
}
/* A faint dot field, faded out at the edges, so the background is not flat. */
.bento-section::before {
    content: '';
    position: absolute; inset: 0; pointer-events: none;
    background-image: radial-gradient(rgba(15,23,42,.06) 1px, transparent 1px);
    background-size: 26px 26px;
    mask-image: radial-gradient(ellipse 72% 58% at 50% 42%, #000 25%, transparent 76%);
    -webkit-mask-image: radial-gradient(ellipse 72% 58% at 50% 42%, #000 25%, transparent 76%);
}
.bento-section > * { position: relative; z-index: 1; }

.bento {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-auto-rows: 1fr;
    gap: 20px;
}

.bento-tile {
    --accent-rgb: 79, 110, 247;
    --gx: 50%; --gy: 50%;

    position: relative;
    display: flex; flex-direction: column;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 22px;
    padding: 30px 28px;
    overflow: hidden;
    box-shadow: 0 1px 2px rgba(15,23,42,.04), 0 10px 26px rgba(15,23,42,.045);
    transform: perspective(1200px)
               rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))
               translate3d(0, var(--lift, 0px), 0);
    transition: transform .45s var(--ease-out), box-shadow .45s var(--ease),
                border-color .35s var(--ease);
    transform-style: preserve-3d;
}
.bento-tile.is-tilting { transition: transform .12s linear, box-shadow .45s var(--ease); }

/* Accent rule that draws across the top edge on hover. */
.bento-tile::before {
    content: '';
    position: absolute; top: 0; left: 26px; right: 26px; height: 3px;
    border-radius: 0 0 4px 4px;
    background: linear-gradient(90deg,
        rgba(var(--accent-rgb), .25), rgb(var(--accent-rgb)), rgba(var(--accent-rgb), .25));
    transform: scaleX(0); transform-origin: center;
    transition: transform .5s var(--ease-out);
    z-index: 2;
}
.bento-tile:hover::before { transform: scaleX(1); }

/* Accent tint following the cursor across the card. */
.bento-tile::after {
    content: '';
    position: absolute; inset: 0; z-index: 0;
    border-radius: inherit; pointer-events: none;
    background: radial-gradient(340px circle at var(--gx) var(--gy),
        rgba(var(--accent-rgb), .09), transparent 66%);
    opacity: 0;
    transition: opacity .4s var(--ease);
}
.bento-tile:hover::after { opacity: 1; }

.bento-tile:hover {
    --lift: -6px;
    border-color: rgba(var(--accent-rgb), .32);
    box-shadow:
        0 2px 4px rgba(15,23,42,.04),
        0 24px 50px rgba(var(--accent-rgb), .18);
}

.bento-icon {
    width: 50px; height: 50px; border-radius: 15px; flex: none;
    display: flex; align-items: center; justify-content: center;
    font-size: 1.3rem; margin-bottom: 18px;
    color: rgb(var(--accent-rgb));
    background: linear-gradient(140deg, rgba(var(--accent-rgb), .17), rgba(var(--accent-rgb), .06));
    box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), .16);
    transition: transform .4s var(--ease-out), box-shadow .4s var(--ease);
}
.bento-tile:hover .bento-icon {
    transform: translateY(-2px) scale(1.06) rotate(-3deg);
    box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), .3),
                0 10px 22px rgba(var(--accent-rgb), .22);
}

.bento-tile h4 {
    font-size: 1.06rem; font-weight: 800; color: var(--ink);
    margin-bottom: 10px; letter-spacing: -.018em; line-height: 1.3;
}
.bento-tile p { font-size: .865rem; color: var(--muted); line-height: 1.7; flex: 1; }

.bento-big {
    font-size: 3.5rem; font-weight: 900; letter-spacing: -.05em; line-height: .9;
    margin-bottom: 14px;
    font-variant-numeric: tabular-nums;
    background: linear-gradient(135deg, #4f6ef7, #7c3aed);
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
}
.bento-list {
    list-style: none; padding: 17px 0 0; margin: 20px 0 0;
    border-top: 1px solid var(--line-soft);
    display: flex; flex-direction: column; gap: 10px;
}
.bento-list li { display: flex; align-items: center; gap: 10px; font-size: .825rem; color: #475569; }
.bento-list i { color: rgb(var(--accent-rgb)); font-size: .92rem; flex: none; }

/* The headline tile gets a soft tinted wash instead of a flat white face. */
.bento-tile.is-accent {
    background:
        radial-gradient(120% 110% at 8% 0%, rgba(124,58,237,.10), transparent 58%),
        linear-gradient(155deg, #f7f5ff 0%, #eff3ff 100%);
    border-color: rgba(124,58,237,.2);
}
.bento-tile.is-accent .bento-list { border-top-color: rgba(124,58,237,.16); }

.bento-tile > *:not(.bento-ripple) { position: relative; z-index: 1; }

/* Click ripple, kept faint on a light surface. */
.bento-ripple {
    position: absolute; z-index: 0; pointer-events: none;
    border-radius: 50%;
    left: var(--x); top: var(--y);
    width: var(--r); height: var(--r);
    margin: calc(var(--r) / -2) 0 0 calc(var(--r) / -2);
    background: radial-gradient(circle, rgba(var(--accent-rgb), .22) 0%, transparent 68%);
    transform: scale(0); opacity: 1;
    animation: bentoRipple .8s var(--ease-out) forwards;
}
@keyframes bentoRipple { to { transform: scale(1); opacity: 0; } }

@media (max-width: 900px) { .bento { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .bento { grid-template-columns: 1fr; } }

/* ══ FAQ ════════════════════════════════════════════════════════════════ */
.faq { max-width: 780px; margin: 0 auto; display: flex; flex-direction: column; gap: 12px; }
.faq-item {
    background: #fff; border: 1px solid var(--line); border-radius: 14px;
    box-shadow: var(--shadow-sm);
    transition: border-color .25s var(--ease), box-shadow .25s var(--ease);
}
.faq-item.is-open { border-color: rgba(79,110,247,.35); box-shadow: var(--shadow-md); }
.faq-q {
    width: 100%; text-align: left; cursor: pointer;
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
    padding: 18px 22px; border: none; background: none;
    font-family: inherit; font-size: .95rem; font-weight: 700; color: var(--ink-2);
}
.faq-q i { flex: none; color: var(--brand); font-size: 1rem; transition: transform .3s var(--ease-out); }
.faq-item.is-open .faq-q i { transform: rotate(45deg); }
/* 0fr → 1fr animates cleanly without measuring heights. */
.faq-a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .35s var(--ease-out); }
.faq-item.is-open .faq-a { grid-template-rows: 1fr; }
.faq-a > div { overflow: hidden; }
.faq-a p { padding: 0 22px 20px; font-size: .875rem; color: var(--muted); line-height: 1.75; }
html:not(.js) .faq-a { grid-template-rows: 1fr; }

/* ══ RESPONSIVE ═════════════════════════════════════════════════════════ */
@media (max-width: 900px) { .nav-links { display: none; } }
@media (max-width: 760px) {
    /* Flat, and without the floating chips covering the screenshot. */
    .app-mock { transform: none; }
    .mock-float { display: none; }
    .mock-wrap { margin-top: 40px; }
}
@media (max-width: 640px) {
    nav { padding: 0 1rem; height: 64px; }
    nav.is-stuck { height: 58px; }
    .hero { padding: 72px 1rem 62px; }
    .section { padding: 72px 1.25rem; }
    .trial-banner { padding: 48px 26px; border-radius: 22px; }
    .trial-wrap { padding: 0 1.25rem 72px; }
    .hero-scroll { display: none; }
    .bento-tile { padding: 22px; }
    .bento-big { font-size: 2.5rem; }
    .faq-q { padding: 16px 18px; font-size: .9rem; }
}

/* ══ REDUCED MOTION ═════════════════════════════════════════════════════
   Everything still renders — it just arrives instead of animating. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
    [data-reveal], .split-word { opacity: 1 !important; transform: none !important; }
    .hero-aurora span { animation: none; }
    .steps-rail::before { transform: scaleX(1); }
    .steps-pulse { animation: none !important; opacity: 0; }
    .magnetic { transform: none !important; }

    /* New sections: show the finished state, hold everything still. */
    .marquee-track { animation: none; transform: none; }
    .mock-float { animation: none; }
    .banner-aurora { display: none; }
    .app-mock { transform: none; }
    .bento-tile { transform: none !important; }
    .nav-pill { display: none; }
    .hero-rotate > span { position: static; }
    .hero-rotate > span:not(.is-on) { display: none; }
    .scroll-progress { display: none; }
}
