/* ============================================================================
   Dhwani landing — monochrome / liquid glass

   Everything is drawn from theme tokens so the page can flip between dark and
   light with no per-rule overrides. The one rule to keep: never hard-code a
   colour below. Glass washes use `rgb(var(--tint-rgb) / a)` — the tint is a
   light bone on dark and near-black on light, so every translucent surface
   inverts correctly on its own.

   Which theme loads first is decided server-side by settings.LANDING_DEFAULT_DARK
   and stamped on <html data-theme> before first paint; the footer toggle lets a
   visitor override it.

   PERFORMANCE: this page scrolls, so the expensive primitives are rationed.
   `backdrop-filter` is allowed on exactly three surfaces (nav, island, call
   card) — it is the costliest thing here and a dozen of them made the page
   stutter. No blur() filters on large always-on layers, no mix-blend-mode on
   full-screen overlays, and the only per-frame JS is one rAF for the hero lift.
   Reveal-on-scroll blur runs both ways (in on arrival, out on departure) but only
   on the crossing, never per frame, and it always settles to blur(0)/none. Fonts
   load from <link> tags in the template, not @import, so this file never blocks on
   them.
   ========================================================================== */

:root,
:root[data-theme="dark"] {
    color-scheme: dark;
    --bg: #060606;
    --bg-rgb: 6 6 6;
    --tint-rgb: 244 242 238;
    --shadow-rgb: 0 0 0;
    --fg: #f4f2ee;
    --fg-dim: rgb(var(--tint-rgb) / 0.76);
    --fg-faint: rgb(var(--tint-rgb) / 0.52);
    --line: rgb(var(--tint-rgb) / 0.16);
    --line-strong: rgb(var(--tint-rgb) / 0.3);
    --glass: rgb(var(--tint-rgb) / 0.06);
    --glass-2: rgb(var(--tint-rgb) / 0.1);
    /* The code surface has to read recessed while --glass reads raised, and the
       two themes need different amounts of it: on #060606 there is no room to go
       darker, so dark lifts slightly and sells the well with an inset shadow. */
    --code-bg: rgb(var(--tint-rgb) / 0.05);
    --btn-bg: #f4f2ee;
    --btn-fg: #08080a;
    --nav-bg: rgb(10 10 11 / 0.62);
    --nav-bg-scrolled: rgb(8 8 9 / 0.82);
    --pop-bg: rgb(14 14 15 / 0.97);
    --grain-opacity: 0.16;
    --vignette-strength: 0.3;
    --sheen: rgb(255 255 255 / 0.7);
    --ember: #d0663c;
}

:root[data-theme="light"] {
    color-scheme: light;
    --bg: #f5f4f2;
    --bg-rgb: 245 244 242;
    --tint-rgb: 18 18 20;
    --shadow-rgb: 38 37 35;
    --fg: #121213;
    --fg-dim: rgb(var(--tint-rgb) / 0.78);
    --fg-faint: rgb(var(--tint-rgb) / 0.56);
    --line: rgb(var(--tint-rgb) / 0.18);
    --line-strong: rgb(var(--tint-rgb) / 0.32);
    --glass: rgb(var(--tint-rgb) / 0.045);
    --glass-2: rgb(var(--tint-rgb) / 0.08);
    --code-bg: rgb(var(--tint-rgb) / 0.04);
    --btn-bg: #16161a;
    --btn-fg: #f6f4f0;
    --nav-bg: rgb(255 255 255 / 0.7);
    --nav-bg-scrolled: rgb(255 255 255 / 0.88);
    --pop-bg: rgb(252 251 249 / 0.97);
    --grain-opacity: 0.07;
    --vignette-strength: 0.07;
    --sheen: rgb(255 255 255 / 0.35);
    --ember: #b0512e;
}

:root {
    --radius: 26px;
    --radius-sm: 18px;
    --section-gap: clamp(90px, 12vw, 165px);
    --hero-progress: 0;
    --ease: cubic-bezier(0.22, 1, 0.36, 1);
    --ease-soft: cubic-bezier(0.4, 0.01, 0.2, 1);
    /* Instrument Sans and Instrument Serif are one superfamily, drawn together, so
       the italic accents read as the same voice rather than a borrowed face. Geist
       carries body copy because it holds up better at the small sizes the platform
       and FAQ sections run at. */
    --font-display: 'Instrument Sans', system-ui, sans-serif;
    --font-body: 'Geist', system-ui, sans-serif;
    --font-serif: 'Instrument Serif', Georgia, serif;
    /* System mono only. The developer section shows a request body, and it is not
       worth a fifth webfont request to set it. */
    --font-mono:
        ui-monospace, 'SF Mono', SFMono-Regular, Menlo, 'Cascadia Mono',
        Consolas, 'Liberation Mono', 'DejaVu Sans Mono', monospace;
    /* The brand mark ध्वनि only. Kept separate from --font-scripts so the mark and
       the language marquee can carry different Devanagari faces: Sahitya is subset
       to the five glyphs of the mark, and falls back to the marquee's Tiro. */
    --font-brand: 'Sahitya', 'Tiro Devanagari Hindi', serif;
    /* Script fonts are subset in the template; Devanagari leads because the
       marquee lists Hindi, Marathi and Nepali in their own script. */
    --font-scripts:
        'Tiro Devanagari Hindi', 'Noto Sans Bengali', 'Noto Sans Tamil',
        'Noto Sans Telugu', 'Noto Sans Kannada', 'Noto Sans Malayalam',
        'Noto Sans Gujarati', 'Noto Sans Gurmukhi', 'Noto Sans Oriya',
        'Noto Sans Arabic', 'Noto Sans Sinhala', 'Noto Sans Thai',
        'Noto Sans SC', 'Noto Sans JP', 'Noto Sans KR', serif;
}

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

html {
    width: 100%;
    overflow-x: hidden;
    scroll-behavior: smooth;
    background: var(--bg);
    /* No visible scrollbar; the page still scrolls normally. */
    scrollbar-width: none;
    -ms-overflow-style: none;
}
html::-webkit-scrollbar,
body::-webkit-scrollbar { width: 0; height: 0; display: none; }

body {
    position: relative;
    background: var(--bg);
    color: var(--fg);
    font-family: var(--font-body);
    font-weight: 400;
    line-height: 1.6;
    width: 100%;
    overflow-x: hidden;
    -webkit-font-smoothing: antialiased;
    letter-spacing: -0.005em;
}

/* Ambient light: two soft pools painted as gradients on one fixed layer.
   Gradients cost nothing to composite; the blurred divs this replaced were the
   main source of scroll jank. */
body::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background:
        radial-gradient(46vw 46vw at 8% -6%, rgb(var(--tint-rgb) / 0.10), transparent 70%),
        radial-gradient(52vw 52vw at 96% 104%, rgb(var(--tint-rgb) / 0.08), transparent 70%);
}

.container { width: min(1180px, 90%); margin: 0 auto; }

::selection { background: var(--fg); color: var(--bg); }

h1, h2, h3, .hero-tagline, .demo-title { text-wrap: balance; }
/* Headings break between sentences, never inside one (see the sentence_lines
   template filter). */
.ln { display: inline-block; }

/* Devanagari / multi-script display type */
.dev { font-family: var(--font-brand); font-style: normal; letter-spacing: 0; }

/* --- Ambient film -------------------------------------------------------- */
.grain {
    position: fixed;
    inset: 0;
    z-index: 900;
    pointer-events: none;
    opacity: var(--grain-opacity);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='160' height='160' filter='url(%23n)' opacity='0.55'/></svg>");
}
.vignette {
    position: fixed;
    inset: 0;
    z-index: 899;
    pointer-events: none;
    background: radial-gradient(135% 95% at 50% 30%, transparent 62%, rgb(var(--shadow-rgb) / var(--vignette-strength)) 100%);
}
/* Kept in the markup for compatibility; the light pools now live on
   body::before, so these draw nothing. */
.aura { display: none; }

/* --- Motion / reveal primitives ------------------------------------------

   These use animations, not transitions, on purpose. A transition here loses to
   any component that declares its own `transition` shorthand later in the file
   (.bento-card animates border-color/box-shadow on hover, .usecase-search
   animates width) — the shorthand replaces the property list wholesale, the
   reveal ends up with no transition at all, and the block pops in with no
   animation. Animations occupy a separate channel, so a component keeps its own
   transition and still blurs in and out.                                       */
.reveal {
    opacity: 0;
    transform: translateY(34px);
    filter: blur(9px);
}
.reveal.in { animation: revealIn 0.85s var(--ease) both; }
.reveal.out-up { animation: revealOutUp 0.55s var(--ease) both; }
.reveal.out-down { animation: revealOutDown 0.55s var(--ease) both; }

@keyframes revealIn {
    from { opacity: 0; transform: translateY(34px); filter: blur(9px); }
    to   { opacity: 1; transform: none; filter: blur(0); }
}
@keyframes revealOutUp {
    from { opacity: 1; transform: none; filter: blur(0); }
    to   { opacity: 0; transform: translateY(-26px); filter: blur(9px); }
}
@keyframes revealOutDown {
    from { opacity: 1; transform: none; filter: blur(0); }
    to   { opacity: 0; transform: translateY(34px); filter: blur(9px); }
}

/* Lighter blur for blocks too wide to blur at full radius cheaply (the player
   shell, the footer grid, the marquee strip). Same move, smaller cost. */
.reveal-lite { filter: blur(6px); }
.reveal-lite.in { animation-name: revealInLite; }
.reveal-lite.out-up { animation-name: revealOutUpLite; }
.reveal-lite.out-down { animation-name: revealOutDownLite; }
@keyframes revealInLite {
    from { opacity: 0; transform: translateY(34px); filter: blur(6px); }
    to   { opacity: 1; transform: none; filter: blur(0); }
}
@keyframes revealOutUpLite {
    from { opacity: 1; transform: none; filter: blur(0); }
    to   { opacity: 0; transform: translateY(-26px); filter: blur(6px); }
}
@keyframes revealOutDownLite {
    from { opacity: 1; transform: none; filter: blur(0); }
    to   { opacity: 0; transform: translateY(34px); filter: blur(6px); }
}

.reveal[data-delay="1"] { animation-delay: 0.08s; }
.reveal[data-delay="2"] { animation-delay: 0.16s; }
.reveal[data-delay="3"] { animation-delay: 0.24s; }
.reveal[data-delay="4"] { animation-delay: 0.32s; }
.reveal[data-delay="5"] { animation-delay: 0.4s; }

/* Doodles draw themselves in when revealed */
.doodle { pointer-events: none; overflow: visible; }
.doodle path,
.doodle circle,
.doodle line,
.doodle polyline {
    fill: none;
    stroke: var(--fg);
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-dasharray: 1200;
    stroke-dashoffset: 1200;
    opacity: 0.4;
}
.doodle.drawn path,
.doodle.drawn circle,
.doodle.drawn line,
.doodle.drawn polyline {
    animation: drawIn 1.8s var(--ease) forwards;
}
@keyframes drawIn { to { stroke-dashoffset: 0; } }

/* ============================================================================
   Navigation
   ========================================================================== */
.nav-bar {
    position: fixed;
    top: 18px;
    left: 50%;
    transform: translateX(-50%);
    width: min(1180px, 94%);
    padding: 10px 12px 10px 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    border-radius: 100px;
    border: 1px solid var(--line);
    background: var(--nav-bg);
    backdrop-filter: blur(14px) saturate(1.25);
    -webkit-backdrop-filter: blur(14px) saturate(1.25);
    box-shadow:
        inset 0 1px 0 rgb(var(--tint-rgb) / 0.10),
        0 18px 44px rgb(var(--shadow-rgb) / 0.22);
    z-index: 1000;
    transition: background 0.4s var(--ease), top 0.4s var(--ease);
}
.nav-bar.scrolled {
    top: 10px;
    background: var(--nav-bg-scrolled);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

.brand {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-family: var(--font-display);
    font-weight: 500;
    font-size: 1.14rem;
    color: var(--fg);
    text-decoration: none;
}
/* Devanagari reads optically smaller than Latin at the same point size, because
   the glyph body hangs below a headline rather than filling a cap height, so the
   mark is set larger and heavier than the Latin wordmark it replaced.
   700 is deliberate, not 600: Sahitya is loaded at 400 and 700 only, so any weight
   in between silently renders as the regular and the mark looks unchanged. */
.brand .dev { font-size: 1.66rem; font-weight: 700; line-height: 1; }
.brand img { width: 26px; height: 26px; }
:root[data-theme="dark"] .brand img { filter: grayscale(1) brightness(1.9) contrast(1.1); }
:root[data-theme="light"] .brand img { filter: grayscale(1) contrast(1.05); }
.brand:link, .brand:visited { color: var(--fg); }

.nav-links { display: flex; align-items: center; gap: 4px; }
.nav-links a {
    color: var(--fg-dim);
    text-decoration: none;
    font-size: 0.86rem;
    font-weight: 500;
    padding: 8px 14px;
    border-radius: 100px;
    transition: color 0.3s var(--ease), background 0.3s var(--ease);
}
.nav-links a:hover { color: var(--fg); background: var(--glass); }

.nav-actions { display: flex; align-items: center; gap: 10px; }

.nav-toggle {
    display: none;
    flex-direction: column;
    gap: 4px;
    padding: 10px;
    border-radius: 12px;
    border: 1px solid var(--line);
    background: var(--glass);
    cursor: pointer;
}
.nav-toggle span { display: block; width: 18px; height: 1.5px; background: var(--fg); border-radius: 2px; }

/* ============================================================================
   Buttons

   One filled button per view carries the action. Everything secondary is a text
   action with a rule under it — a second pill competing with the first is what
   made the old pair look wrong.
   ========================================================================== */
.btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    padding: 14px 26px;
    border: 1px solid transparent;
    border-radius: 100px;
    font-family: var(--font-body);
    font-size: 0.9rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    text-decoration: none;
    cursor: pointer;
    overflow: hidden;
    transition: transform 0.4s var(--ease), box-shadow 0.4s var(--ease),
                background 0.35s var(--ease), color 0.35s var(--ease), border-color 0.35s var(--ease);
}
.btn svg { width: 16px; height: 16px; }
.btn-primary {
    background: var(--btn-bg);
    color: var(--btn-fg);
    box-shadow: 0 10px 26px -12px rgb(var(--tint-rgb) / 0.4);
}
.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 18px 38px -14px rgb(var(--tint-rgb) / 0.5); }
.btn-primary::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(105deg, transparent 30%, var(--sheen) 50%, transparent 70%);
    transform: translateX(-120%);
    transition: transform 0.85s var(--ease);
}
.btn-primary:hover::after { transform: translateX(120%); }

/* Secondary: an outlined pill. Same silhouette as the filled button so a pair
   reads as one control group, with no fill competing for attention. */
.btn-ghost {
    background: transparent;
    color: var(--fg);
    border-color: var(--line-strong);
}
.btn-ghost:hover {
    background: var(--glass-2);
    border-color: var(--fg-faint);
    transform: translateY(-2px);
}
/* Tertiary: plain text, used for the nav's log in link */
.btn-quiet { background: transparent; border-color: transparent; color: var(--fg-dim); }
.btn-quiet:hover { color: var(--fg); background: var(--glass); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none !important; }

.nav-actions .nav-cta { padding: 11px 20px; font-size: 0.85rem; }

/* ============================================================================
   Hero
   ========================================================================== */
.hero {
    position: relative;
    min-height: 100svh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 150px 0 90px;
    overflow: hidden;
}
.hero-content { position: relative; z-index: 3; }

.eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 7px 16px 7px 12px;
    border-radius: 100px;
    border: 1px solid var(--line);
    background: var(--glass);
    color: var(--fg-dim);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
}
.eyebrow .pip {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--fg);
    animation: pip 2.8s ease-out infinite;
}
@keyframes pip {
    0%   { box-shadow: 0 0 0 0 rgb(var(--tint-rgb) / 0.4); }
    70%  { box-shadow: 0 0 0 9px rgb(var(--tint-rgb) / 0); }
    100% { box-shadow: 0 0 0 0 rgb(var(--tint-rgb) / 0); }
}

/* The brand mark carries the hero; the tagline sits under it */
.hero-mark {
    /* Same token as .dev. Declared again because this rule sits later in the file
       at equal specificity, so it would otherwise win and undo the brand face. */
    font-family: var(--font-brand);
    font-weight: 400;
    font-size: clamp(4.6rem, 17vw, 13rem);
    line-height: 0.94;
    letter-spacing: -0.01em;
    margin: 20px 0 4px;
    opacity: 0;
    animation: markIn 1.5s var(--ease) 0.1s forwards;
}
@keyframes markIn {
    from { opacity: 0; transform: translateY(0.1em) scale(0.97); filter: blur(24px); }
    to   { opacity: 1; transform: none; filter: blur(0); }
}
.hero-tagline {
    font-family: var(--font-display);
    font-weight: 400;
    font-size: clamp(1.5rem, 3.6vw, 2.7rem);
    line-height: 1.08;
    letter-spacing: -0.035em;
    max-width: 24ch;
    margin: 0 auto 20px;
}
.hero-tagline em {
    font-family: var(--font-serif);
    font-style: italic;
    letter-spacing: -0.015em;
}
/* Per-word motion-blur reveal */
.word {
    display: inline-block;
    opacity: 0;
    filter: blur(14px);
    transform: translateY(0.36em);
    animation: wordIn 1s var(--ease) forwards;
}
@keyframes wordIn { to { opacity: 1; filter: blur(0); transform: none; } }

.hero .subhead {
    color: var(--fg-dim);
    font-size: clamp(0.98rem, 1.5vw, 1.1rem);
    max-width: 46ch;
    margin: 0 auto 34px;
    opacity: 0;
    animation: wordIn 1.1s var(--ease) 0.8s forwards;
}
/* Layout only, so the class is reusable further down the page. The staggered
   entrance belongs to the hero alone — left on the bare class it fired on load
   for a button group the visitor would not reach for another ten screens. */
.cta-group {
    display: flex;
    gap: 12px;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
}
.hero .cta-group {
    opacity: 0;
    animation: wordIn 1.1s var(--ease) 0.95s forwards;
}

/* Hero doodles float behind the type (transform only) */
.hero-doodle { position: absolute; z-index: 1; opacity: 0.5; }
.hero-doodle svg { width: 100%; height: 100%; }
.hero-doodle path, .hero-doodle circle, .hero-doodle polyline {
    fill: none; stroke: var(--fg); stroke-width: 1.4;
    stroke-linecap: round; stroke-dasharray: 900; stroke-dashoffset: 900;
    animation: drawIn 2.4s var(--ease) 0.4s forwards;
    opacity: 0.28;
}
.hd-1 { top: 15%; left: 5%; width: 180px; height: 124px; animation: floatY 10s ease-in-out infinite alternate; }
.hd-2 { top: 22%; right: 6%; width: 144px; height: 144px; animation: floatY 12s ease-in-out infinite alternate-reverse; }
.hd-3 { bottom: 19%; left: 11%; width: 126px; height: 88px; animation: floatY 14s ease-in-out infinite alternate; }
.hd-4 { bottom: 23%; right: 10%; width: 200px; height: 96px; animation: floatY 11s ease-in-out infinite alternate-reverse; }
@keyframes floatY {
    from { transform: translate3d(0, 0, 0); }
    to   { transform: translate3d(0, -20px, 0); }
}

/* Sound bloom: gradient only, no blur filter */
.hero-bloom {
    position: absolute;
    top: 46%;
    left: 50%;
    width: clamp(340px, 52vw, 760px);
    height: clamp(340px, 52vw, 760px);
    transform: translate(-50%, -50%);
    border-radius: 50%;
    z-index: 0;
    pointer-events: none;
    background:
        radial-gradient(circle at 38% 32%, rgb(var(--tint-rgb) / 0.13), transparent 58%),
        radial-gradient(circle at 62% 70%, rgb(var(--tint-rgb) / 0.07), transparent 62%);
    animation: bloomBreathe 11s ease-in-out infinite alternate;
}
@keyframes bloomBreathe {
    from { transform: translate(-50%, -50%) scale(1); opacity: 0.9; }
    to   { transform: translate(-50%, -52%) scale(1.08); opacity: 1; }
}
.hero-rings { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.hero-rings span {
    position: absolute;
    top: 50%;
    left: 50%;
    width: clamp(300px, 38vw, 520px);
    height: clamp(300px, 38vw, 520px);
    margin: calc(clamp(300px, 38vw, 520px) / -2) 0 0 calc(clamp(300px, 38vw, 520px) / -2);
    border: 1px solid rgb(var(--tint-rgb) / 0.13);
    border-radius: 50%;
    animation: ringOut 7s ease-out infinite;
}
.hero-rings span:nth-child(2) { animation-delay: 2.4s; }
.hero-rings span:nth-child(3) { animation-delay: 4.8s; }
@keyframes ringOut {
    0%   { transform: scale(0.72); opacity: 0; }
    24%  { opacity: 0.85; }
    100% { transform: scale(1.6); opacity: 0; }
}

/* ============================================================================
   Sections & marquee
   ========================================================================== */
/* scroll-margin-top clears the fixed nav. Every anchored block needs it, not
   just the first one: without it a nav link lands its section's heading
   underneath the bar. */
.section { position: relative; padding: var(--section-gap) 0; z-index: 2; scroll-margin-top: 110px; }
.section-first {
    scroll-margin-top: 130px;
    transform: translateY(calc(100px * (1 - var(--hero-progress, 0))));
}
.hero::after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 180px;
    background: linear-gradient(to bottom, rgb(var(--bg-rgb) / 0) 0%, rgb(var(--bg-rgb) / 0.85) 55%, var(--bg) 100%);
    pointer-events: none;
    z-index: 2;
}

.section-heading { max-width: 900px; margin: 0 auto clamp(46px, 6vw, 76px); text-align: center; }
.section-heading h2 {
    font-family: var(--font-display);
    font-weight: 400;
    font-size: clamp(2rem, 4.4vw, 3.3rem);
    line-height: 1.06;
    letter-spacing: -0.035em;
    margin-top: 18px;
}
.section-heading h2 em { font-family: var(--font-serif); font-style: italic; }
.section-heading p { color: var(--fg-dim); margin-top: 16px; font-size: 1rem; }

.marquee {
    position: relative;
    padding: 24px 0;
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    overflow: hidden;
}
.marquee-track {
    display: flex;
    gap: 42px;
    width: max-content;
    animation: marquee 90s linear infinite;
}
.marquee:hover .marquee-track { animation-play-state: paused; }
/* Set by marqueeIdle() while the strip is off screen. The page is long enough now
   that a 90s infinite animation would otherwise composite the whole time somebody
   is reading the FAQ. */
.marquee.idle .marquee-track { animation-play-state: paused; }
.marquee-track span {
    display: inline-flex;
    align-items: center;
    gap: 42px;
    font-family: var(--font-scripts);
    font-size: clamp(1rem, 1.7vw, 1.35rem);
    line-height: 1.9;
    color: var(--fg-faint);
    white-space: nowrap;
}
.marquee-track span::after { content: "◦"; opacity: 0.55; }
@keyframes marquee { to { transform: translate3d(-50%, 0, 0); } }
.marquee::before, .marquee::after {
    content: "";
    position: absolute;
    top: 0; bottom: 0;
    width: 18%;
    z-index: 2;
    pointer-events: none;
}
.marquee::before { left: 0; background: linear-gradient(to right, var(--bg), rgb(var(--bg-rgb) / 0)); }
.marquee::after { right: 0; background: linear-gradient(to left, var(--bg), rgb(var(--bg-rgb) / 0)); }

/* ============================================================================
   Bento — glass cards with 3D tilt
   ========================================================================== */
.bento-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 16px;
}
.bento-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-height: 240px;
    padding: 30px;
    border-radius: var(--radius);
    border: 1px solid var(--line);
    background: linear-gradient(155deg, rgb(var(--tint-rgb) / 0.075), rgb(var(--tint-rgb) / 0.025) 55%);
    box-shadow: inset 0 1px 0 rgb(var(--tint-rgb) / 0.09), 0 24px 54px -30px rgb(var(--shadow-rgb) / 0.55);
    overflow: hidden;
    transform-style: preserve-3d;
    transition: border-color 0.45s var(--ease), box-shadow 0.45s var(--ease);
}
.bento-card:hover {
    border-color: var(--line-strong);
    box-shadow: inset 0 1px 0 rgb(var(--tint-rgb) / 0.16), 0 36px 72px -34px rgb(var(--shadow-rgb) / 0.65);
}
/* Pointer-tracked specular highlight — the "liquid" in liquid glass */
.bento-card::before {
    content: "";
    position: absolute;
    inset: -1px;
    border-radius: inherit;
    background: radial-gradient(240px circle at var(--mx, 50%) var(--my, 0%), rgb(var(--tint-rgb) / 0.15), transparent 65%);
    opacity: 0;
    transition: opacity 0.45s var(--ease);
    pointer-events: none;
}
.bento-card:hover::before { opacity: 1; }
.bento-card > * { transform: translateZ(26px); }
.bento-card h3 {
    font-family: var(--font-display);
    font-weight: 400;
    font-size: 1.42rem;
    letter-spacing: -0.028em;
    line-height: 1.14;
}
.bento-card p { color: var(--fg-dim); font-size: 0.92rem; line-height: 1.55; }
.bento-card .card-doodle {
    position: absolute;
    right: 18px;
    bottom: 14px;
    width: 120px;
    height: 90px;
    transform: translateZ(8px);
    opacity: 0.5;
}
.bento-card .card-num {
    font-family: var(--font-serif);
    font-size: 1.1rem;
    font-style: italic;
    color: var(--fg-faint);
}
.span-2 { grid-column: span 2; }
.featured-card {
    background:
        radial-gradient(120% 100% at 0% 0%, rgb(var(--tint-rgb) / 0.12), transparent 60%),
        linear-gradient(160deg, rgb(var(--tint-rgb) / 0.07), rgb(var(--tint-rgb) / 0.02));
    border-color: rgb(var(--tint-rgb) / 0.2);
}

/* ============================================================================
   Call widget — "let ध्वनि call you"
   ========================================================================== */
.callme {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: clamp(22px, 4vw, 54px);
    align-items: center;
    padding: clamp(28px, 4vw, 54px);
    border-radius: 38px;
    border: 1px solid var(--line);
    background: linear-gradient(150deg, rgb(var(--tint-rgb) / 0.09), rgb(var(--tint-rgb) / 0.025) 60%);
    box-shadow: inset 0 1px 0 rgb(var(--tint-rgb) / 0.12), 0 44px 96px -50px rgb(var(--shadow-rgb) / 0.7);
    overflow: hidden;
}
.callme::after {
    content: "";
    position: absolute;
    width: 62%;
    height: 170%;
    top: -35%;
    right: -20%;
    background: radial-gradient(circle, rgb(var(--tint-rgb) / 0.1), transparent 62%);
    pointer-events: none;
}
.callme-copy { position: relative; z-index: 2; }
.callme-copy h2 {
    font-family: var(--font-display);
    font-weight: 400;
    font-size: clamp(1.9rem, 3.6vw, 2.9rem);
    line-height: 1.04;
    letter-spacing: -0.038em;
    margin: 16px 0 14px;
}
.callme-copy h2 em { font-family: var(--font-serif); font-style: italic; }
.callme-copy h2 .dev { font-size: 0.96em; }
.callme-copy p { color: var(--fg-dim); font-size: 0.97rem; max-width: 40ch; }
.callme-meta { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 22px; }
.callme-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 7px 14px;
    border-radius: 100px;
    border: 1px solid var(--line);
    background: var(--glass);
    color: var(--fg-dim);
    font-size: 0.76rem;
    font-weight: 600;
}
.callme-chip svg { width: 13px; height: 13px; stroke: currentColor; fill: none; stroke-width: 1.6; flex: none; }

.callme-form { position: relative; z-index: 2; display: grid; gap: 14px; }
.field-label {
    display: block;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--fg-faint);
    margin-bottom: 9px;
}
.agent-picker { display: flex; flex-wrap: wrap; gap: 8px; }
.agent-option {
    display: inline-flex;
    flex-direction: column;
    gap: 2px;
    padding: 11px 17px;
    border-radius: 16px;
    border: 1px solid var(--line);
    background: var(--glass);
    color: var(--fg-dim);
    font-family: inherit;
    font-size: 0.86rem;
    font-weight: 600;
    text-align: left;
    cursor: pointer;
    transition: background 0.3s var(--ease), color 0.3s var(--ease), border-color 0.3s var(--ease), transform 0.3s var(--ease);
}
.agent-option small { font-size: 0.7rem; font-weight: 500; opacity: 0.64; }
.agent-option:hover { background: var(--glass-2); color: var(--fg); transform: translateY(-1px); }
.agent-option.selected {
    background: var(--btn-bg);
    color: var(--btn-fg);
    border-color: var(--btn-bg);
}
.agent-option.selected small { opacity: 0.72; }

.phone-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr); gap: 10px; }
.input-shell {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 18px;
    min-height: 58px;
    border-radius: 18px;
    border: 1px solid var(--line);
    background: rgb(var(--tint-rgb) / 0.05);
    transition: border-color 0.3s var(--ease), background 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.input-shell:focus-within {
    border-color: var(--line-strong);
    background: rgb(var(--tint-rgb) / 0.085);
    box-shadow: 0 0 0 4px rgb(var(--tint-rgb) / 0.06);
}
.input-shell.invalid { border-color: var(--ember); box-shadow: 0 0 0 4px rgb(208 102 60 / 0.14); }
.input-prefix { color: var(--fg-faint); font-size: 0.95rem; font-weight: 600; }
.input-shell input {
    flex: 1;
    min-width: 0;
    background: transparent;
    border: none;
    outline: none;
    color: var(--fg);
    font-family: inherit;
    font-size: 1rem;
    font-weight: 500;
    letter-spacing: 0.04em;
}
.input-shell input::placeholder { color: var(--fg-faint); letter-spacing: 0.02em; }

.call-btn {
    position: relative;
    min-height: 60px;
    padding: 0 28px;
    border-radius: 100px;
    border: none;
    background: var(--btn-bg);
    color: var(--btn-fg);
    font-family: inherit;
    font-size: 0.98rem;
    font-weight: 700;
    cursor: pointer;
    overflow: hidden;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    box-shadow: 0 16px 38px -18px rgb(var(--tint-rgb) / 0.5);
    transition: transform 0.4s var(--ease), box-shadow 0.4s var(--ease), opacity 0.3s ease;
}
.call-btn:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 24px 52px -20px rgb(var(--tint-rgb) / 0.6); }
.call-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.call-btn svg { width: 17px; height: 17px; stroke: currentColor; fill: none; stroke-width: 2; }
.call-btn .ripple {
    position: absolute;
    border-radius: 50%;
    background: rgb(var(--shadow-rgb) / 0.22);
    transform: scale(0);
    animation: rippleOut 0.7s var(--ease) forwards;
    pointer-events: none;
}
@keyframes rippleOut { to { transform: scale(2.6); opacity: 0; } }
.call-btn.is-busy { pointer-events: none; }
.call-btn.is-busy::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(100deg, transparent 20%, rgb(var(--shadow-rgb) / 0.16) 50%, transparent 80%);
    animation: busySweep 1.15s linear infinite;
}
@keyframes busySweep { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

.callme-fineprint { color: var(--fg-faint); font-size: 0.76rem; line-height: 1.5; }
.callme-fineprint a { color: var(--fg-dim); text-decoration: none; border-bottom: 1px solid var(--line-strong); }
.callme-fineprint a:hover { color: var(--fg); }

/* Live call state — replaces the form while a call is running */
.call-live {
    display: none;
    grid-template-columns: auto minmax(0, 1fr);
    gap: 18px;
    align-items: center;
    padding: 20px 22px;
    border-radius: 22px;
    border: 1px solid var(--line-strong);
    background: rgb(var(--tint-rgb) / 0.07);
}
.call-live.show { display: grid; animation: wordIn 0.6s var(--ease) forwards; }
.call-live-orb {
    position: relative;
    width: 54px;
    height: 54px;
    border-radius: 50%;
    background: radial-gradient(circle at 34% 30%, rgb(var(--tint-rgb) / 0.85), rgb(var(--tint-rgb) / 0.2) 62%, transparent 74%);
}
.call-live-orb::before {
    content: "";
    position: absolute;
    inset: -10px;
    border: 1px solid rgb(var(--tint-rgb) / 0.32);
    border-radius: 50%;
    animation: ringOut 2.8s ease-out infinite;
}
.call-live.ember .call-live-orb { background: radial-gradient(circle at 34% 30%, rgb(208 102 60 / 0.95), rgb(208 102 60 / 0.24) 62%, transparent 74%); }
.call-live.ember .call-live-orb::before { border-color: rgb(208 102 60 / 0.5); }
.call-live.done .call-live-orb::before { animation: none; opacity: 0.3; }
.call-live-title { font-family: var(--font-display); font-size: 1.06rem; letter-spacing: -0.02em; }
.call-live-sub { color: var(--fg-dim); font-size: 0.84rem; margin-top: 3px; }
.call-live-again { grid-column: 1 / -1; justify-self: start; margin-top: 2px; font-size: 0.84rem; }

/* ============================================================================
   Showcase player (behaviour preserved from the original, restyled)
   ========================================================================== */
.demo-panel { padding: 0; background: transparent; border: none; max-width: 100%; }
.demo-panel .section-heading { margin-bottom: clamp(30px, 4vw, 48px); }

.usecase-search {
    width: min(520px, 100%);
    margin: 0 0 38px auto;
    position: relative;
    z-index: 6;
    transition: width 0.4s var(--ease), margin-bottom 0.3s var(--ease);
}
.usecase-search-label {
    display: block;
    max-height: 36px;
    overflow: hidden;
    margin-bottom: 11px;
    color: var(--fg-faint);
    font-size: 0.68rem;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    font-weight: 700;
    transition: opacity 0.3s ease, max-height 0.3s ease, margin-bottom 0.3s ease;
}
.usecase-search-box { position: relative; display: flex; align-items: center; min-height: 56px; }
.usecase-search-toggle {
    position: absolute;
    right: 7px;
    top: 50%;
    width: 42px;
    height: 42px;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--line);
    border-radius: 50%;
    background: var(--glass);
    color: var(--fg-dim);
    cursor: pointer;
    transition: background 0.3s var(--ease), color 0.25s ease;
}
.usecase-search-toggle:hover { background: var(--glass-2); color: var(--fg); }
.usecase-search-icon { font-size: 1rem; }
.usecase-search-input {
    width: 100%;
    min-height: 56px;
    padding: 0 58px 0 20px;
    border-radius: 100px;
    border: 1px solid var(--line);
    background: rgb(var(--tint-rgb) / 0.05);
    color: var(--fg);
    font-family: inherit;
    font-size: 0.96rem;
    outline: none;
    transition: border-color 0.3s ease, background 0.3s ease, box-shadow 0.3s ease, opacity 0.3s ease;
}
.usecase-search-input::placeholder { color: var(--fg-faint); }
.usecase-search-input:focus {
    border-color: var(--line-strong);
    background: rgb(var(--tint-rgb) / 0.08);
    box-shadow: 0 0 0 4px rgb(var(--tint-rgb) / 0.05);
}
.usecase-search.is-collapsed { width: 56px; margin: 0 0 26px auto; }
.usecase-search.is-collapsed .usecase-search-label { opacity: 0; pointer-events: none; max-height: 0; margin-bottom: 0; }
.usecase-search.is-collapsed .usecase-search-toggle { border-color: var(--line-strong); background: var(--glass-2); color: var(--fg); }
.usecase-search.is-collapsed .usecase-search-input { opacity: 0; pointer-events: none; }
.usecase-search-results {
    position: absolute;
    top: calc(100% + 12px);
    left: 0; right: 0;
    display: none;
    gap: 8px;
    padding: 12px;
    border-radius: 24px;
    border: 1px solid var(--line);
    background: var(--pop-bg);
    box-shadow: 0 30px 64px -30px rgb(var(--shadow-rgb) / 0.7);
}
.usecase-search-results:not([hidden]) { display: grid; }
.usecase-search-result {
    width: 100%;
    border: 1px solid var(--line);
    background: var(--glass);
    color: var(--fg);
    border-radius: 16px;
    padding: 13px 16px;
    text-align: left;
    font-family: inherit;
    cursor: pointer;
    transition: background 0.25s ease, border-color 0.25s ease, transform 0.25s ease;
}
.usecase-search-result:hover { background: var(--glass-2); border-color: var(--line-strong); transform: translateY(-1px); }
.usecase-search-result-label, .usecase-search-result-meta { display: block; }
.usecase-search-result-label { font-weight: 700; margin-bottom: 3px; font-size: 0.9rem; }
.usecase-search-result-meta { color: var(--fg-faint); font-size: 0.8rem; }

.showcase-shell {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(420px, 620px);
    gap: 22px;
    align-items: center;
    max-width: 100%;
}
.showcase-copy { position: relative; min-height: 400px; display: flex; align-items: center; }
.demo-content { display: none; max-width: 540px; }
.demo-content.active { display: block; }
/* Directional swap between conversations — motion-blurred slide */
@keyframes slideFromRight {
    from { opacity: 0; transform: translateX(56px); filter: blur(10px); }
    to   { opacity: 1; transform: translateX(0); filter: blur(0); }
}
@keyframes slideFromLeft {
    from { opacity: 0; transform: translateX(-56px); filter: blur(10px); }
    to   { opacity: 1; transform: translateX(0); filter: blur(0); }
}
.anim-from-right { animation: slideFromRight 0.6s var(--ease) forwards; }
.anim-from-left  { animation: slideFromLeft 0.6s var(--ease) forwards; }
.demo-kicker {
    color: var(--fg-faint);
    text-transform: uppercase;
    letter-spacing: 0.22em;
    font-size: 0.7rem;
    font-weight: 700;
    margin-bottom: 16px;
}
.demo-title {
    font-family: var(--font-display);
    font-weight: 400;
    font-size: clamp(1.9rem, 3.8vw, 2.8rem);
    line-height: 1.05;
    letter-spacing: -0.035em;
    margin-bottom: 16px;
}
.demo-copy { color: var(--fg-dim); font-size: 1rem; margin-bottom: 20px; max-width: 50ch; }
.demo-stat {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 26px;
    padding: 9px 16px;
    border-radius: 100px;
    color: var(--fg-dim);
    background: var(--glass);
    border: 1px solid var(--line);
    font-size: 0.86rem;
}
.demo-actions { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }

.showcase-stage { display: flex; justify-content: flex-end; min-width: 0; max-width: 100%; }
.voice-orb-box { position: relative; width: min(100%, 620px); min-height: 620px; max-width: 100%; }
.semi-orb-stage { position: absolute; inset: 0; display: flex; align-items: center; justify-content: flex-end; }
.semi-orb-stage::after {
    content: "";
    position: absolute;
    right: 0;
    top: 50%;
    width: clamp(260px, 34vw, 390px);
    height: clamp(420px, 46vw, 560px);
    transform: translateY(-50%);
    border: 1px solid var(--line);
    border-right: none;
    border-radius: 520px 0 0 520px;
    pointer-events: none;
    z-index: 1;
}
/* No hard rim: the disc fades out into the page through a mask, which is what
   "blurry border" means here without paying for a blur filter. */
.voice-orb {
    width: clamp(340px, 36vw, 460px);
    height: clamp(340px, 36vw, 460px);
    border-radius: 50%;
    position: relative;
    z-index: 3;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 22px;
    padding: 34px;
    text-align: center;
    background:
        radial-gradient(circle at 34% 26%, rgb(var(--tint-rgb) / 0.2), transparent 46%),
        radial-gradient(circle at 50% 55%, rgb(var(--tint-rgb) / 0.12), rgb(var(--tint-rgb) / 0.04) 62%, transparent 78%);
    -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 52%, transparent 78%);
    mask-image: radial-gradient(circle at 50% 50%, #000 52%, transparent 78%);
    opacity: 0;
    transform: translateX(70px);
    transition: transform 0.9s var(--ease), opacity 0.9s var(--ease);
}
.voice-orb.orb-in-view { opacity: 1; transform: translateX(0); }
.orb-status { display: flex; flex-direction: column; gap: 8px; width: min(100%, 260px); }
.orb-status-label {
    font-family: var(--font-display);
    font-size: clamp(1.55rem, 2.9vw, 2.1rem);
    font-weight: 500;
    line-height: 1.05;
    letter-spacing: -0.03em;
    color: var(--fg);
}
.orb-status-line { color: var(--fg-dim); font-size: 0.9rem; font-weight: 500; line-height: 1.45; }
.orb-status.orb-out { animation: orbOut 0.2s ease forwards; }
.orb-status.orb-in { animation: orbIn 0.42s var(--ease) forwards; }
@keyframes orbOut {
    from { opacity: 1; transform: translateY(0); filter: blur(0); }
    to   { opacity: 0; transform: translateY(-10px); filter: blur(4px); }
}
@keyframes orbIn {
    from { opacity: 0; transform: translateY(12px); filter: blur(6px); }
    to   { opacity: 1; transform: translateY(0); filter: blur(0); }
}
.voice-orb.orb-pulse { animation: orbPulse 0.7s ease-out forwards; }
@keyframes orbPulse {
    0%   { transform: scale(1); }
    38%  { transform: scale(1.035); }
    100% { transform: scale(1); }
}
.player-controls { display: flex; align-items: center; justify-content: center; gap: 12px; }
.player-btn {
    width: 58px;
    height: 58px;
    border-radius: 50%;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--btn-bg);
    border: none;
    color: var(--btn-fg);
    cursor: pointer;
    transition: transform 0.3s var(--ease), opacity 0.25s ease, box-shadow 0.3s ease;
    box-shadow: 0 12px 28px -14px rgb(var(--shadow-rgb) / 0.6);
}
.player-btn:hover { transform: scale(1.07); }
.player-btn:disabled { opacity: 0.3; cursor: not-allowed; transform: none; }
.player-btn-icon { font-size: 1.1rem; line-height: 1; }
.replay-btn {
    width: 48px;
    height: 48px;
    background: var(--glass-2);
    border: 1px solid var(--line-strong);
    color: var(--fg);
}
.replay-btn .player-btn-icon { font-size: 1rem; }
.replay-btn[hidden] { display: none; }

.tab-arc { position: absolute; inset: 0; z-index: 2; }
.tab-arc-item {
    position: absolute;
    border: 1px solid var(--line-strong);
    background: var(--pop-bg);
    color: var(--fg);
    border-radius: 100px;
    padding: 13px 22px;
    min-width: 152px;
    font-family: inherit;
    font-weight: 600;
    font-size: 0.92rem;
    white-space: nowrap;
    cursor: pointer;
    box-shadow: 0 18px 40px -26px rgb(var(--shadow-rgb) / 0.7);
    transition:
        transform 0.45s var(--ease),
        opacity 0.3s ease,
        filter 0.3s ease,
        background 0.3s ease,
        color 0.3s ease,
        border-color 0.3s ease;
}
.tab-arc-item:hover { border-color: var(--fg-faint); }
/* The selected conversation is announced by the orb itself, so its pill steps
   aside instead of sitting on top of the disc. Inline opacity comes from the arc
   positioning code, hence the !important. */
.tab-arc-item.active {
    background: var(--btn-bg);
    color: var(--btn-fg);
    border-color: var(--btn-bg);
    opacity: 0 !important;
    pointer-events: none;
}
.trigger-rail {
    position: absolute;
    top: 50%;
    right: 0;
    transform: translateY(-50%);
    z-index: 4;
    display: flex;
    justify-content: center;
}
.selector-rail-track {
    position: relative;
    width: 30px;
    height: 250px;
    border-radius: 100px;
    border: 1px solid var(--line);
    background: rgb(var(--tint-rgb) / 0.06);
}
.selector-thumb {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 44px;
    height: 86px;
    border-radius: 100px;
    border: 1px solid var(--line-strong);
    background: var(--pop-bg);
    color: var(--fg);
    cursor: grab;
    box-shadow: 0 14px 30px -18px rgb(var(--shadow-rgb) / 0.7);
    touch-action: none;
    transition: box-shadow 0.25s ease, border-color 0.25s ease;
}
.selector-thumb:hover { border-color: var(--fg-faint); }
.selector-thumb:active { cursor: grabbing; }
.selector-thumb-core {
    position: absolute;
    inset: 50% auto auto 50%;
    width: 12px;
    height: 40px;
    transform: translate(-50%, -50%);
    border-radius: 100px;
    background: var(--fg);
    opacity: 0.7;
}
.selector-thumb-core::before, .selector-thumb-core::after {
    content: "";
    position: absolute;
    left: 50%;
    width: 16px;
    height: 1.5px;
    border-radius: 100px;
    background: var(--bg);
    opacity: 0.55;
    transform: translateX(-50%);
}
.selector-thumb-core::before { top: 10px; }
.selector-thumb-core::after { bottom: 10px; }
.rail-hint {
    margin: 6px auto 0;
    max-width: 40ch;
    color: var(--fg-faint);
    font-size: 0.76rem;
    line-height: 1.5;
    text-align: center;
}

/* ============================================================================
   How it works — a connected spine, not four cards

   Each step draws the hairline to the NEXT dot, so the spine assembles as the
   steps reveal in and leaves with them, and the same rule becomes a vertical
   timeline when the band stacks. The dot is filled with --bg so the line passes
   behind it.

   One thing to know before adding hover states anywhere below: `.reveal.in` runs
   its animation with `both`, so the final keyframe's `transform: none` stays
   applied and outranks any normal author rule. A `transform` in `:hover` on a
   .reveal element is silently dead. Colour, background, border and box-shadow are
   fine; motion has to go on a child.
   ========================================================================== */
.steps-rail {
    --dot: 11px;
    --rail-gap: clamp(18px, 2.4vw, 34px);
    --rail-gap-v: 30px;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    /* index, title, copy. The steps map onto these shared rows with subgrid, so a
       title that wraps at one width cannot push its own copy out of line with its
       neighbours'. The previous fix was a two line floor on .step-title, which
       aligned the row but spent an empty line on every step that did not wrap. */
    grid-template-rows: auto auto auto;
    gap: 0 var(--rail-gap);
}
.step {
    position: relative;
    display: grid;
    grid-template-rows: subgrid;
    grid-row: span 3;
    padding-top: calc(var(--dot) + 18px);
    min-width: 0;
}
/* connector: this dot's centre to the next dot's centre */
.step::before {
    content: "";
    position: absolute;
    top: calc((var(--dot) - 1px) / 2);
    left: calc(var(--dot) / 2);
    right: calc(-1 * (var(--rail-gap) + var(--dot) / 2));
    height: 1px;
    background: var(--line);
}
.step:last-child::before { display: none; }

.step-dot {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    width: var(--dot);
    height: var(--dot);
    border-radius: 50%;
    border: 1px solid var(--line-strong);
    background: var(--bg);
    transition: border-color 0.35s var(--ease);
}
.step-dot::after {
    content: "";
    position: absolute;
    inset: 50% auto auto 50%;
    width: 3px;
    height: 3px;
    border-radius: 50%;
    background: var(--fg);
    opacity: 0.55;
    transform: translate(-50%, -50%);
    transition: width 0.35s var(--ease), height 0.35s var(--ease), opacity 0.35s var(--ease);
}
.step:hover .step-dot { border-color: var(--fg-faint); }
.step:hover .step-dot::after { width: 5px; height: 5px; opacity: 0.85; }

/* The step numbers are Devanagari digits (०१ ०२ ०३ ०४), so this cannot use
   --font-serif: Instrument Serif has no Devanagari and every number would render
   as tofu. --font-scripts leads with Tiro Devanagari Hindi, which the template
   loads unsubset, so the digits are covered. Upright rather than italic, because
   a slanted Devanagari numeral reads as a mistake. */
.step-index {
    display: block;
    font-family: var(--font-scripts);
    font-style: normal;
    font-size: 1.18rem;
    line-height: 1;
    color: var(--fg-faint);
    margin-bottom: 9px;
}
.step-title {
    font-family: var(--font-display);
    font-weight: 400;
    font-size: clamp(1.12rem, 1.7vw, 1.34rem);
    letter-spacing: -0.028em;
    line-height: 1.16;
    margin-bottom: 8px;
    align-self: start;
}
.step-copy { color: var(--fg-dim); font-size: 0.9rem; line-height: 1.55; max-width: 30ch; }

/* ============================================================================
   Platform deck — the same stacked, draggable cards as the Tools page

   Ported from dashboard/templates/dashboard/tools.html, with two differences:
   there are no previous/next buttons (the cards are dragged), and every colour
   comes from a landing token instead of the console palette, so this inverts with
   the theme on its own rather than needing a [data-theme="dark"] override block
   like the original does.

   Depth is a data attribute, so the resting stack is pure CSS and does not wait
   on any script: if deck() never runs the cards still look right, they just do
   not move. The card background is --pop-bg rather than --glass because stacked
   cards have to hide the ones behind them; a translucent wash would let four
   layers of text show through.
   ========================================================================== */
/* Every card sits in the same grid cell rather than being absolutely positioned,
   so the deck is exactly as tall as its longest card at whatever width it is
   rendered. The Tools page hard-codes a height, which works there because its
   cards are one short paragraph each; here the copy varies from three lines to
   seven, and a fixed height would mean either a clipped card or a hollow one at
   every breakpoint. This also means no height needs maintaining when copy
   changes, and no JS measures anything. */
.deck {
    position: relative;
    display: grid;
    width: 100%;
    max-width: 760px;
    /* Bottom margin clears the rotated cards behind, which extend past the front
       card's box. */
    margin: 0 auto 2.4rem;
    padding: 0 6px;
    touch-action: pan-y;
    user-select: none;
}
.deck-card {
    grid-area: 1 / 1;
    position: relative;
    display: flex;
    gap: 16px;
    align-items: flex-start;
    border-radius: var(--radius-sm);
    padding: 24px 26px;
    /* A fully opaque base, not --glass or --pop-bg. The cards overlap, so anything
       translucent lets the card behind read through the front one: at --pop-bg's
       0.97 the next card's heading was legible through this card's own heading.
       The tint wash on top keeps it looking like the rest of the page's surfaces. */
    background:
        linear-gradient(155deg, rgb(var(--tint-rgb) / 0.05), rgb(var(--tint-rgb) / 0.015)),
        var(--bg);
    color: var(--fg);
    border: 1px solid var(--line);
    box-shadow: 0 22px 48px -26px rgb(var(--shadow-rgb) / 0.55);
    transform-origin: 50% 50%;
    transition: transform 0.4s cubic-bezier(.22, .68, .36, 1), opacity 0.4s ease;
    cursor: grab;
    overflow: hidden;
}
.deck-card.is-dragging { transition: none; cursor: grabbing; }
.deck-card[data-depth="0"]   { transform: none; opacity: 1; z-index: 5; }
.deck-card[data-depth="1"]   { transform: translateY(7px)  scale(.977) rotate(1.4deg);  opacity: .9;  z-index: 4; }
.deck-card[data-depth="2"]   { transform: translateY(14px) scale(.955) rotate(-1.8deg); opacity: .72; z-index: 3; }
.deck-card[data-depth="3"]   { transform: translateY(20px) scale(.934) rotate(2.2deg);  opacity: .52; z-index: 2; }
.deck-card[data-depth="4"]   { transform: translateY(26px) scale(.915) rotate(-2.6deg); opacity: .32; z-index: 1; }
.deck-card[data-depth="out"] { transform: translateX(-125%) rotate(-6deg); opacity: 0; z-index: 0; }

/* The icon sits where the Tools deck puts its number. Same geometry, but it says
   which capability the card is about rather than counting to eight. */
.deck-icon {
    flex: 0 0 34px;
    height: 34px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    border: 1px solid var(--line-strong);
    color: var(--fg-dim);
}
.deck-icon svg {
    width: 17px;
    height: 17px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.deck-body { min-width: 0; }
.deck-title {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: 1.04rem;
    letter-spacing: -0.022em;
    line-height: 1.25;
    margin-bottom: 8px;
}
.deck-copy { color: var(--fg-dim); font-size: 0.88rem; line-height: 1.6; }

/* Dots only: a position readout for eight cards, not a second way to page. */
.deck-controls {
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto;
    max-width: 760px;
    position: relative;
    z-index: 10;    /* above the offset cards behind the front one */
}
.deck-dots { display: flex; gap: 7px; }
.deck-dot {
    width: 7px;
    height: 7px;
    padding: 0;
    border: 0;
    border-radius: 100px;
    background: var(--line-strong);
    cursor: pointer;
    transition: background 0.2s var(--ease), transform 0.2s var(--ease);
}
.deck-dot.is-active { background: var(--fg); transform: scale(1.35); }
.deck-dot:focus-visible { outline: 2px solid var(--fg-faint); outline-offset: 3px; }
.deck:focus-visible { outline: 2px solid var(--fg-faint); outline-offset: 6px; border-radius: var(--radius-sm); }

/* ============================================================================
   Built for developers — prose beside a recessed monospace surface
   ========================================================================== */
.dev-split {
    display: grid;
    grid-template-columns: minmax(0, 0.88fr) minmax(0, 1.12fr);
    gap: clamp(26px, 4vw, 60px);
    align-items: start;
}
.dev-prose { min-width: 0; }
.dev-auth {
    color: var(--fg-faint);
    font-size: 0.82rem;
    line-height: 1.6;
}
.dev-auth code {
    font-family: var(--font-mono);
    font-size: 0.78rem;
    color: var(--fg-dim);
    overflow-wrap: anywhere;
}
.dev-note {
    margin: clamp(28px, 3.4vw, 42px) auto 0;
    max-width: 62ch;
    text-align: center;
    color: var(--fg-faint);
    font-size: 0.84rem;
    line-height: 1.6;
}

.endpoint-list { list-style: none; margin-top: 22px; }
.endpoint-row {
    display: grid;
    /* Wide enough for "GET POST" on one line: the webhook settings route answers
       both, and wrapping the label made it read as two separate endpoints. */
    grid-template-columns: 64px minmax(0, 1fr);
    gap: 0 13px;
    align-items: baseline;
    padding: 11px 0;
    border-top: 1px solid var(--line);
}
.endpoint-method {
    font-family: var(--font-mono);
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: var(--fg-faint);
}
.endpoint-row code {
    font-family: var(--font-mono);
    font-size: 0.8rem;
    color: var(--fg);
    /* a long path wraps instead of forcing the column to overflow at 420 */
    overflow-wrap: anywhere;
}
.endpoint-row span:not(.endpoint-method) {
    grid-column: 2;
    color: var(--fg-faint);
    font-size: 0.8rem;
    margin-top: 3px;
}

/* --- the mono surface ---------------------------------------------------- */
.code-card {
    /* Without this the grid item's automatic minimum size is min-content, which
       for a 70 character JSON line is 70 characters wide: the column grows, the
       container overflows, and html { overflow-x: hidden } swallows it while the
       layout is quietly broken. It pairs with minmax(0, …) in .dev-split. */
    min-width: 0;
    border: 1px solid var(--line);
    border-radius: var(--radius-sm);
    background: var(--code-bg);
    box-shadow: inset 0 1px 0 rgb(var(--shadow-rgb) / 0.22);
    overflow: hidden;
}
.code-head {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--line);
    background: var(--glass-2);
}
.code-verb {
    flex: none;
    padding: 4px 9px;
    border-radius: 7px;
    background: var(--btn-bg);
    color: var(--btn-fg);
    font-family: var(--font-mono);
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.07em;
}
.code-path {
    flex: 1;
    min-width: 0;
    font-family: var(--font-mono);
    font-size: 0.78rem;
    color: var(--fg-dim);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.code-copy {
    flex: none;
    padding: 5px 11px;
    border-radius: 100px;
    border: 1px solid var(--line);
    background: transparent;
    color: var(--fg-faint);
    font-family: inherit;
    font-size: 0.72rem;
    font-weight: 600;
    cursor: pointer;
    transition: color 0.25s var(--ease), border-color 0.25s var(--ease), background 0.25s var(--ease);
}
.code-copy:hover { color: var(--fg); border-color: var(--line-strong); background: var(--glass); }
.code-copy:focus-visible { outline: 2px solid var(--fg-faint); outline-offset: 2px; }

.code-body {
    margin: 0;
    padding: 18px 20px 20px;
    font-family: var(--font-mono);
    font-size: 0.795rem;
    line-height: 1.72;
    tab-size: 2;
    white-space: pre;
    font-variant-ligatures: none;
    /* the snippet scrolls, never the page body */
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    /* html and body hide their scrollbars globally, but that selector does not
       reach here. Keeping this one visible is deliberate: it is the only thing
       telling the reader the block scrolls. */
    scrollbar-width: thin;
    scrollbar-color: rgb(var(--tint-rgb) / 0.26) transparent;
}
.code-body::-webkit-scrollbar { height: 8px; }
.code-body::-webkit-scrollbar-track { background: transparent; }
.code-body::-webkit-scrollbar-thumb { background: rgb(var(--tint-rgb) / 0.22); border-radius: 100px; }
.code-body:focus-visible { outline: 2px solid var(--fg-faint); outline-offset: -2px; }
.code-body code { font: inherit; color: var(--fg-dim); }

/* Three tint derived tiers instead of syntax colours, so the block inverts with
   the theme for free and needs no per-theme override. --ember is deliberately not
   used: it is reserved for live and error states, and spending it on a verb
   dilutes the one signal colour this page has. */
.tok-punc { color: var(--fg-faint); }
.tok-key  { color: var(--fg-dim); }
.tok-str  { color: var(--fg); }
.tok-num  { color: var(--fg); font-weight: 600; }
.tok-cmt  { color: var(--fg-faint); font-style: italic; }

/* ============================================================================
   Data and security — four retention windows on one scale
   ========================================================================== */
.retention-band {
    position: relative;
    padding: clamp(26px, 3.6vw, 46px);
    border-radius: 34px;
    border: 1px solid var(--line);
    background: linear-gradient(150deg, rgb(var(--tint-rgb) / 0.08), rgb(var(--tint-rgb) / 0.022) 62%);
    box-shadow:
        inset 0 1px 0 rgb(var(--tint-rgb) / 0.1),
        0 40px 88px -48px rgb(var(--shadow-rgb) / 0.6);
    overflow: hidden;
}
/* gradient bloom, no blur filter and no fourth backdrop-filter */
.retention-band::after {
    content: "";
    position: absolute;
    inset: -30% -12% auto auto;
    width: 55%;
    height: 150%;
    background: radial-gradient(circle, rgb(var(--tint-rgb) / 0.08), transparent 62%);
    pointer-events: none;
}
.ret-grid {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0 clamp(14px, 2vw, 30px);
}
.ret-stop { position: relative; min-width: 0; padding-bottom: 26px; }
/* shared baseline, same connector trick as the step rail, so it survives any
   column count with no nth-child maths */
.ret-stop::before {
    content: "";
    position: absolute;
    left: 0;
    right: calc(-1 * clamp(14px, 2vw, 30px));
    bottom: 0;
    height: 1px;
    background: var(--line);
}
.ret-stop:last-child::before { right: 0; }
/* the tick grows left to right, so four numbers read as one increasing scale
   rather than four equal cards */
.ret-tick {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 1px;
    background: var(--line-strong);
}
.ret-stop:nth-child(1) .ret-tick { height: 5px; }
.ret-stop:nth-child(2) .ret-tick { height: 9px; }
.ret-stop:nth-child(3) .ret-tick { height: 14px; }
.ret-stop:nth-child(4) .ret-tick { height: 20px; }

.ret-value {
    display: block;
    font-family: var(--font-display);
    font-weight: 400;
    font-size: clamp(1.55rem, 3vw, 2.3rem);
    line-height: 1;
    letter-spacing: -0.04em;
}
.ret-unit {
    display: block;
    margin-top: 7px;
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--fg-faint);
}
.ret-copy { color: var(--fg-dim); font-size: 0.85rem; line-height: 1.5; margin-top: 10px; max-width: 26ch; }
.ret-note {
    position: relative;
    z-index: 1;
    margin-top: 18px;
    color: var(--fg-faint);
    font-size: 0.82rem;
}

/* ============================================================================
   FAQ accordion

   The open and close motion is a transition on grid-template-rows (0fr to 1fr)
   on .faq-panel, a CHILD of the .reveal element. Nothing here declares a
   transition on .faq-item itself, so the reveal keeps its animation channel by
   construction rather than by luck. Do not move .reveal onto .faq-panel.

   The button's aria-expanded is the single source of truth: CSS reads it with a
   sibling selector, so the JS flips one attribute and never keeps a class in sync.
   ========================================================================== */
.faq-block { width: min(760px, 100%); margin: 0 auto; scroll-margin-top: 110px; }
.faq-item { border-top: 1px solid var(--line); }
.faq-item:last-child { border-bottom: 1px solid var(--line); }

.faq-q {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 20px;
    width: 100%;
    padding: 22px 2px;
    border: none;
    background: transparent;
    color: var(--fg-dim);
    font-family: var(--font-display);
    font-weight: 400;
    font-size: clamp(1.02rem, 1.7vw, 1.2rem);
    line-height: 1.32;
    letter-spacing: -0.022em;
    text-align: left;
    cursor: pointer;
    transition: color 0.3s var(--ease);
}
.faq-q:hover,
.faq-q[aria-expanded="true"] { color: var(--fg); }
.faq-q:focus-visible { outline: 2px solid var(--fg-faint); outline-offset: 3px; border-radius: 10px; }

/* plus to minus, transform only */
.faq-sign { position: relative; flex: none; width: 15px; height: 15px; margin-top: 5px; }
.faq-sign::before,
.faq-sign::after {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    width: 15px;
    height: 1.5px;
    border-radius: 2px;
    background: currentColor;
    transition: transform 0.4s var(--ease), opacity 0.3s var(--ease);
}
.faq-sign::after { transform: rotate(90deg); }
.faq-q[aria-expanded="true"] .faq-sign::after { transform: rotate(0deg); opacity: 0; }

.faq-panel {
    display: grid;
    grid-template-rows: 0fr;
    overflow: hidden;
    /* keeps the reflow scope small while a panel opens */
    contain: layout paint;
    transition: grid-template-rows 0.45s var(--ease);
}
.faq-q[aria-expanded="true"] + .faq-panel { grid-template-rows: 1fr; }

/* The grid item carries NO padding and NO border of its own, and that is the
   whole trick. A 0fr track sizes the item's content box to zero, but padding is
   added on top of it, so padding here left 24px of dead space under every
   collapsed question and pushed each hairline away from its text. The padding
   goes on the inner element instead, where it is content that overflows the zero
   track and gets clipped by .faq-panel.
   min-height: 0 is still required: a grid item's min-height is auto, so without
   it 0fr does not clip at all and the panel never closes. */
.faq-a { min-height: 0; }
.faq-a p {
    /* Unconditional on purpose: applying it only in the open state makes the row
       height jump at frame 0 of the collapse. */
    padding: 0 40px 24px 2px;
    color: var(--fg-dim);
    font-size: 0.94rem;
    line-height: 1.62;
    opacity: 0;
    transition: opacity 0.3s var(--ease);
}
.faq-q[aria-expanded="true"] + .faq-panel .faq-a p { opacity: 1; }

/* Pre-init and no-JS fallback: answers stay visible until faq() marks the list
   ready, so a failed script leaves a readable FAQ rather than eight dead rows. */
.faq-list:not([data-faq-ready]) .faq-panel { grid-template-rows: 1fr; }
.faq-list:not([data-faq-ready]) .faq-a p { opacity: 1; }

/* ============================================================================
   Closing CTA — full bleed, sitting directly on the footer

   Not a .section: it carries its own padding. Only a top hairline, because
   .footer already draws border-top and two rules 1px apart look like a mistake.
   ========================================================================== */
.cta-band {
    position: relative;
    z-index: 2;
    overflow: hidden;
    padding: clamp(66px, 9vw, 122px) 0;
    scroll-margin-top: 110px;
    border-top: 1px solid var(--line);
    background:
        radial-gradient(58% 120% at 50% 0%, rgb(var(--tint-rgb) / 0.09), transparent 70%),
        linear-gradient(180deg, rgb(var(--tint-rgb) / 0.05), rgb(var(--tint-rgb) / 0.014));
}
.cta-band-inner { position: relative; z-index: 2; text-align: center; }
.cta-band-inner h2 {
    font-family: var(--font-display);
    font-weight: 400;
    font-size: clamp(2.1rem, 4.8vw, 3.5rem);
    line-height: 1.04;
    letter-spacing: -0.04em;
    margin: 18px auto 16px;
    max-width: 26ch;
}
.cta-band-inner h2 em { font-family: var(--font-serif); font-style: italic; }
.cta-band-inner > p { color: var(--fg-dim); font-size: 1rem; max-width: 46ch; margin: 0 auto 30px; }
/* Reuses the .doodle system, so the strokes draw in when the band reveals and
   latch with .drawn. No new keyframes. */
.cta-band .cta-doodle {
    position: absolute;
    left: 50%;
    bottom: 6%;
    width: min(560px, 76%);
    height: 90px;
    transform: translateX(-50%);
    opacity: 0.32;
    z-index: 1;
}
.cta-fineprint {
    margin: 26px auto 0;
    max-width: 46ch;
    color: var(--fg-faint);
    font-size: 0.82rem;
    line-height: 1.6;
}
.cta-fineprint a { color: var(--fg-dim); text-decoration: underline; text-underline-offset: 3px; }
.cta-fineprint a:hover { color: var(--fg); }

/* ============================================================================
   Landing island (single notification surface for this page)
   ========================================================================== */
.lp-island {
    position: fixed;
    top: 88px;
    left: 50%;
    z-index: 1200;
    display: flex;
    align-items: center;
    gap: 12px;
    max-width: min(560px, 92vw);
    padding: 0;
    height: 0;
    opacity: 0;
    transform: translate(-50%, -20px) scale(0.92);
    border-radius: 100px;
    border: 1px solid transparent;
    background: var(--pop-bg);
    backdrop-filter: blur(22px) saturate(1.3);
    -webkit-backdrop-filter: blur(22px) saturate(1.3);
    box-shadow: 0 22px 54px -22px rgb(var(--shadow-rgb) / 0.7);
    overflow: hidden;
    pointer-events: none;
    transition:
        opacity 0.35s var(--ease),
        transform 0.5s var(--ease),
        height 0.4s var(--ease),
        padding 0.4s var(--ease),
        border-color 0.35s var(--ease);
}
.lp-island.show {
    height: auto;
    min-height: 52px;
    padding: 11px 18px;
    opacity: 1;
    transform: translate(-50%, 0) scale(1);
    border-color: var(--line-strong);
    pointer-events: auto;
}
.lp-island .li-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--fg);
    flex: none;
    animation: pip 2.4s ease-out infinite;
}
.lp-island.urgent .li-dot { background: var(--ember); }
.lp-island .li-msg { font-size: 0.88rem; color: var(--fg); line-height: 1.4; }
.lp-island .li-btn {
    flex: none;
    padding: 7px 15px;
    border-radius: 100px;
    border: none;
    background: var(--btn-bg);
    color: var(--btn-fg);
    font-family: inherit;
    font-size: 0.8rem;
    font-weight: 700;
    cursor: pointer;
}
.lp-island .li-btn.ghost { background: var(--glass-2); color: var(--fg); }

/* ============================================================================
   Theme toggle — deliberately low on the page
   ========================================================================== */
.theme-switch {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px;
    border-radius: 100px;
    border: 1px solid var(--line);
    background: var(--glass);
}
.theme-switch button {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 14px;
    border: none;
    border-radius: 100px;
    background: transparent;
    color: var(--fg-dim);
    font-family: inherit;
    font-size: 0.76rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.35s var(--ease), color 0.35s var(--ease);
}
.theme-switch button svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 1.7; }
.theme-switch button:hover { color: var(--fg); }
.theme-switch button[aria-pressed="true"] { background: var(--btn-bg); color: var(--btn-fg); }

/* ============================================================================
   Footer
   ========================================================================== */
.footer {
    position: relative;
    z-index: 2;
    padding: 70px 0 30px;
    border-top: 1px solid var(--line);
}
.footer-grid-new {
    display: grid;
    grid-template-columns: 1.6fr 1fr 0.8fr 1.2fr;
    gap: 40px;
    padding-bottom: 36px;
    border-bottom: 1px solid var(--line);
}
.footer-col h4 {
    font-family: var(--font-display);
    font-weight: 500;
    font-size: 0.92rem;
    margin-bottom: 18px;
    color: var(--fg);
}
.company-name { font-weight: 600; font-size: 0.86rem; margin-bottom: 6px; }
.address { color: var(--fg-faint); font-size: 0.78rem; line-height: 1.5; max-width: 250px; }
.contact-list, .footer-links-list { list-style: none; }
.contact-list li, .footer-links-list li {
    color: var(--fg-dim);
    font-size: 0.82rem;
    margin-bottom: 10px;
    display: flex;
    align-items: center;
    gap: 10px;
}
.contact-list svg, .footer-links-list svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 1.6; opacity: 0.7; }
.contact-list a, .footer-links-list a { color: inherit; text-decoration: none; transition: color 0.25s ease; }
.contact-list a:hover, .footer-links-list a:hover { color: var(--fg); }
.footer-btn-group { display: flex; flex-direction: column; gap: 10px; margin-bottom: 18px; }
.footer-btn-group .btn { width: 100%; }
.social-links { display: flex; gap: 9px; }
.social-icon {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: 1px solid var(--line);
    background: var(--glass);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--fg-dim);
    text-decoration: none;
    transition: color 0.3s var(--ease), border-color 0.3s var(--ease), transform 0.3s var(--ease);
}
.social-icon svg { width: 17px; height: 17px; fill: currentColor; }
.social-icon:hover { color: var(--fg); border-color: var(--line-strong); transform: translateY(-2px); }
.footer-bottom {
    padding-top: 26px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    font-size: 0.72rem;
    color: var(--fg-faint);
}
.footer-bottom .legal { max-width: 62ch; text-align: left; }
.disclaimer { margin-top: 8px; opacity: 0.75; }

/* ============================================================================
   Responsive
   ========================================================================== */
@media (min-width: 1800px) {
    .container { width: 1240px; }
    .nav-bar { width: 1240px; }
}

@media (max-width: 1024px) {
    /* Seven links plus the brand and two buttons stop fitting the pill on one row
       somewhere under 1000px. Tighten them rather than let them wrap: a wrapped
       pill bar grows taller, and the fixed nav then covers the heading of whatever
       section it just scrolled you to. */
    .nav-bar { padding-left: 16px; gap: 10px; }
    .nav-links { gap: 0; }
    .nav-links a { padding: 8px 9px; font-size: 0.8rem; }
    .nav-actions { gap: 8px; }
    .nav-actions .nav-cta { padding: 10px 15px; font-size: 0.8rem; }

    .bento-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .callme { grid-template-columns: 1fr; }
    .showcase-shell { grid-template-columns: minmax(0, 1fr) minmax(360px, 520px); gap: 18px; }
    .showcase-copy { min-height: 360px; }
    .voice-orb-box { min-height: 600px; overflow: hidden; }
    .semi-orb-stage::after { width: clamp(230px, 36vw, 330px); height: clamp(360px, 48vw, 500px); }
    .footer-grid-new { grid-template-columns: 1fr 1fr; }
    .steps-rail { --rail-gap: 16px; }
    .step-copy { font-size: 0.86rem; }
    .dev-split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 26px; }
}

@media (max-width: 860px) {
    .nav-links {
        display: none;
        position: absolute;
        top: 66px;
        left: 10px;
        right: 10px;
        flex-direction: column;
        align-items: stretch;
        gap: 4px;
        padding: 12px;
        border-radius: 24px;
        border: 1px solid var(--line);
        background: var(--pop-bg);
        box-shadow: 0 26px 54px -24px rgb(var(--shadow-rgb) / 0.75);
        /* The drawer holds every section link, so on a short viewport it has to
           scroll rather than run off the bottom of the screen. */
        max-height: min(68vh, 520px);
        overflow-y: auto;
        overscroll-behavior: contain;
    }
    .nav-links.open { display: flex; }
    .nav-toggle { display: inline-flex; order: 3; }
    .nav-actions { order: 2; }
    .nav-actions .btn-quiet { display: none; }

    /* The spine rotates to vertical here rather than at 768: the container is
       already down to about 774px, and four columns of title plus rule is cramped
       well before that. The `bottom` value below reaches exactly the next dot's
       centre, so the vertical line is continuous and stops at the last step. */
    /* Stacked, each step owns its own rows again: sharing three tracks down a single
       column would stretch every step to the tallest title and tallest copy. */
    .steps-rail { grid-template-columns: 1fr; grid-template-rows: none; gap: var(--rail-gap-v) 0; }
    .step { display: block; grid-row: auto; padding: 0 0 0 calc(var(--dot) + 20px); }
    .step-dot { top: 3px; }
    .step::before {
        top: calc(3px + var(--dot) / 2);
        bottom: calc(-1 * (var(--rail-gap-v) + 3px + var(--dot) / 2));
        left: calc((var(--dot) - 1px) / 2);
        right: auto;
        width: 1px;
        height: auto;
    }
    .step-copy { max-width: 46ch; }

    .dev-split { grid-template-columns: 1fr; }

    .ret-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 26px; }
    .ret-stop:nth-child(2)::before { right: 0; }   /* end of row 1 */
    .ret-copy { max-width: none; }
}

@media (max-width: 768px) {
    .bento-grid { grid-template-columns: 1fr; }
    .span-2 { grid-column: span 1; }
    .hero { padding: 130px 0 80px; }
    .hero-doodle { display: none; }
    .phone-row { grid-template-columns: 1fr; }
    .showcase-shell { grid-template-columns: 1fr; gap: 8px; }
    .showcase-copy { min-height: 0; justify-content: center; }
    .demo-content.active { text-align: center; max-width: none; }
    .demo-copy { margin-left: auto; margin-right: auto; }
    .demo-actions { justify-content: center; }
    .showcase-stage { justify-content: center; }
    .voice-orb-box { width: 100%; min-height: 560px; overflow: hidden; }
    .semi-orb-stage { justify-content: center; }
    .semi-orb-stage::after { right: auto; left: 50%; transform: translate(12%, -50%); }
    .trigger-rail { top: auto; bottom: 20px; left: 50%; right: auto; transform: translateX(-50%); }
    .selector-rail-track { width: 220px; height: 28px; }
    .selector-thumb { width: 86px; height: 44px; }
    .selector-thumb-core { width: 40px; height: 12px; }
    .selector-thumb-core::before,
    .selector-thumb-core::after { top: 50%; bottom: auto; left: auto; width: 1.5px; height: 16px; transform: translateY(-50%); }
    .selector-thumb-core::before { left: 10px; }
    .selector-thumb-core::after { right: 10px; }
    .voice-orb { width: min(76vw, 330px); height: min(76vw, 330px); padding: 26px; transform: translateX(0); }
    .footer-grid-new { grid-template-columns: 1fr; }
    .footer-bottom { flex-direction: column-reverse; align-items: flex-start; }
    .tab-arc-item { min-width: 120px; padding: 10px 14px; font-size: 0.8rem; }
    .cta-band .cta-doodle { display: none; }
}

@media (max-width: 420px) {
    .callme { padding: 22px 18px; border-radius: 28px; }
    .hero-mark { font-size: clamp(3.6rem, 24vw, 5.4rem); }
    .hero-tagline { font-size: clamp(1.3rem, 7vw, 1.7rem); }
    .steps-rail { --rail-gap-v: 24px; }
    .deck-card { padding: 20px 18px; gap: 12px; }
    .deck-icon { flex-basis: 30px; height: 30px; }
    .code-body { font-size: 0.74rem; padding: 15px 16px 17px; }
    .endpoint-row { grid-template-columns: 56px minmax(0, 1fr); gap: 0 10px; }
    .endpoint-method { font-size: 0.62rem; letter-spacing: 0.05em; }
    .retention-band { padding: 22px 18px; border-radius: 26px; }
    .ret-grid { grid-template-columns: 1fr; row-gap: 22px; }
    .ret-stop::before { right: 0; }
    .ret-tick { display: none; }        /* a scale of one column is not a scale */
    .faq-q { padding: 19px 2px; gap: 14px; }
    .faq-a p { padding-right: 18px; }
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.001s !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001s !important;
    }
    .reveal { opacity: 1; transform: none; filter: none; }
    .word, .hero-mark, .subhead, .hero .cta-group { opacity: 1; filter: none; transform: none; }
    /* Defensive: the answer's fade lives on a child, so make sure a snapped
       transition can never leave an open panel invisible. */
    .faq-q[aria-expanded="true"] + .faq-panel .faq-a p { opacity: 1; }
    /* A stack that cannot animate is unreadable, so the deck becomes a plain list.
       Zeroing the durations alone would leave seven cards hidden behind the front
       one with no way to bring them forward. */
    .deck { display: block; }
    .deck-card {
        grid-area: auto;
        opacity: 1 !important;
        transform: none !important;
        margin-bottom: 12px;
    }
    .deck-controls { display: none; }
    .grain { display: none; }
    html { scroll-behavior: auto; }
}
