/* Scan the sources, not the generated index.html: a stale build would
   otherwise keep classes alive that nothing references any more. */

/* ============================================================================
   FONTS — Gabarito, one variable file doing every weight.

   It replaced Polymath (OH no Type Company), which was in here as a demo cut:
   67 glyphs, Latin only, and licensed for testing rather than for a site. Chosen
   against seven other free faces by putting each one on the real landing rather
   than on a specimen — it was the closest to Polymath's warm geometry and the
   only one whose set width matched to within a percent, so nothing reflowed.

   SIL Open Font License, commercial use included.

   Two files, not thirteen: a variable font carries the whole 400–900 range in
   one, and the second file is only the Latin Extended block, requested by the
   browser exclusively when a page actually uses one of its characters.

   Display and body point at the same family. Polymath shipped a separate
   display cut with a taller x-height; Gabarito has one optical size, and giving
   headings a second family that is the same drawing would only be another file
   to load.
   ========================================================================== */

@font-face {
  font-family: "Gabarito";
  src: url("/v2/fonts/Gabarito-latin.woff2") format("woff2");
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Gabarito";
  src: url("/v2/fonts/Gabarito-ext.woff2") format("woff2");
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ============================================================================
   TOKENS
   ========================================================================== */


/* ============================================================================
   SEMANTIC COLOUR
   ----------------------------------------------------------------------------
   The values live here, outside @theme, because the theme toggle swaps them at
   runtime — @theme only maps them onto utility names.

   Text was written as raw alpha before this: eight shades of dimmed white
   between 40% and 85%, each used once or twice, plus 71 flat `text-white`.
   Nobody can see 45 against 50, and none of it could be themed — "white at 55%"
   has no light-theme counterpart, whereas "secondary text" does.
   ========================================================================== */

html[data-design="v2"] {
  /* Text on the page surface */
  --fg:        #ffffff;
  --fg-muted:  rgba(255, 255, 255, 0.8);
  --fg-subtle: rgba(255, 255, 255, 0.6);
  --fg-faint:  rgba(255, 255, 255, 0.4);
  --fg-ghost:  rgba(255, 255, 255, 0.25);

  /* Page and panel surfaces. Literal hex before this, so nothing below the
     text layer could follow the theme at all. */
  --bg-page:    #0a0a0a;
  --bg-section: transparent;
  --bg-raised:  #131313;
  --panel-fill: linear-gradient(180deg, #131313 0%, #000000 100%);

  /* Hairlines. They were static inside @theme, which meant a light theme would
     have kept drawing white edges on a white page. */
  --hairline:        rgba(255, 255, 255, 0.2);
  --hairline-dim:    rgba(255, 255, 255, 0.08);
  --hairline-strong: rgba(255, 255, 255, 0.4);

  /* Section edges — a triplet rather than a colour, so --section-rule stays an
     alpha knob a section can turn down. Same shape as --accent. */
  --edge-ink: 255, 255, 255;
  --edge-glow: 0.1;

  /* The agent diagram's wiring: resting line, travelling pulse, and the rim
     spark that hands off to it. Brand, so it does not follow the theme — ink
     went grey-on-grey and read as dirt on the light panel. One source for all
     three so the diagram cannot drift apart. */
  --wire-ink: var(--color-flame);


  /* ── Component fills ─────────────────────────────────────────────────────
     Surfaces inside the section machinery. They were literal hex, and three of
     them were the same gradient typed out three times.

     These carry lighting, not just colour. --fill-sculpted is lit from the
     middle so a pill reads as raised; --fill-well is dark at the top and light
     at the bottom so a socket reads as recessed. Inverting the numbers for the
     light theme would flip the light source and turn a raised pill into a
     dented one, so the light values keep the direction and re-key the range. */
  --fill-tile:     #18181b;
  --fill-sculpted: linear-gradient(180deg, #282828 15%, #171717 50%, #282828 85%);
  --fill-well:     linear-gradient(180deg, #1f1e1e 0%, #343434 49.5%, #484848 100%);
  --fill-stage:    linear-gradient(180deg, #131110 0%, #0f0e0d 100%);
  --fill-avatar:   #2a2a2a;
  /* Niche marker. Its three stops are read straight by the inline SVG. */
  --mark-1: var(--v2-sand);
  --mark-2: var(--v2-flame);
  --mark-3: var(--v2-flame-deep);
  --fill-footer:   linear-gradient(180deg, #0a0a0a 0%, #070707 100%);
  /* A background image cannot take currentColor, so each theme gets its file. */
  --cta-stars:     url("/v2/img/cta/particles.svg");

  /* Raised fills on the page surface */
  --surface-1: rgba(255, 255, 255, 0.04);
  --surface-2: rgba(255, 255, 255, 0.08);
  --surface-3: rgba(255, 255, 255, 0.16);

  /* Content sitting on the brand surface. Deliberately outside the theme
     blocks: the accent does not change between themes, so anything on top of it
     must not either. Without this, --fg followed the page and put dark ink on
     an orange button in the light theme. */
  /* Over an image, not over the page: a label needs the picture darkened behind
     it whichever theme is on. */
  --scrim: rgba(0, 0, 0, 0.4);

  --fg-on-accent:       #ffffff;
  --hairline-on-accent: rgba(255, 255, 255, 0.4);

  /* The hero glow is artwork, not a surface. Its dark ellipse subtracts light
     from the warm one; pointed at --color-ink it followed the page and turned
     pale in the light theme, so instead of cutting the glow back it washed it
     out. Pinned dark in both themes. */
  --glow-ink: #0a0a0a;

  /* Text on the light glass panels — the language menu and the cookie modal are
     light in the dark theme too, so this pair does not follow --fg. */
  --fg-on-light:       #16181d;
  --fg-on-light-muted: rgba(0, 0, 0, 0.6);

  /* Paint for controls sitting on that same glass. Keyed to the surface, not
     the theme: the panel is light either way, so anything pointed at --fg or
     --fg-subtle inverts under it and the control goes dark on a light card. */
  --fill-on-light:     rgba(255, 255, 255, 0.6);
  --knob-on-light:     #ffffff;
  --hairline-on-light: rgba(255, 255, 255, 0.2);
}

/* Provisional. Written so the toggle already does something visible; the real
   values come from the Figma light scheme. Light is not the mirror of dark —
   the same alpha reads differently against white, which is why these are not
   the dark values inverted arithmetically. */
html[data-design="v2"][data-theme="light"] {
  --surface-1: rgba(0, 0, 0, 0.04);
  --surface-2: rgba(0, 0, 0, 0.07);
  --surface-3: rgba(0, 0, 0, 0.12);

  /* Ink measured off the Figma light frame; every step below it is the same
     alpha ladder the dark theme uses. The frame draws its secondary text in the
     full ink and separates it by weight, but a step that exists in one theme and
     not the other is not a step — the markup cannot swap font weight per theme,
     so the hierarchy would simply flatten here. Same ladder, different ink. */
  --fg:        #040c13;
  --fg-muted:  rgba(4, 12, 19, 0.8);
  --fg-subtle: rgba(4, 12, 19, 0.6);
  --fg-faint:  rgba(4, 12, 19, 0.4);
  --fg-ghost:  rgba(4, 12, 19, 0.25);

  /* The page is the lightest thing on it and every surface sits into it, not on
     it — the reverse of the dark theme, where a panel is raised by being lighter
     than its page. Three steps: page, section band, panel. */
  --bg-page:    #ffffff;
  --bg-section: #f7f7f7;
  --bg-raised:  #f2f2f2;
  /* Flat in this theme — the panel gradient is a dark-theme device. */
  --panel-fill: linear-gradient(180deg, #f2f2f2 0%, #f2f2f2 100%);

  /* A tile inside a panel stays white: it is a field on a card, so it reads as
     raised against the panel rather than sinking further. */
  --fill-tile:     #ffffff;
  --fill-sculpted: linear-gradient(180deg, #ffffff 15%, #eeeeee 50%, #ffffff 85%);
  --fill-well:     linear-gradient(180deg, #dcdcdc 0%, #efefef 49.5%, #ffffff 100%);
  --fill-stage:    linear-gradient(180deg, #f2f2f2 0%, #ededed 100%);
  --fill-avatar:   #dcdcdc;
  /* Backed off the deep red: on a 33px shape against white it reads as dirt
     rather than depth. */
  --mark-1: var(--v2-flare-soft);
  --mark-2: var(--v2-flare-a);
  --mark-3: var(--v2-flame-mid);
  /* The page, deepening a touch toward the bottom — the same relationship the
     dark theme has (#0a0a0a to #070707). It was #ececec to #e4e4e4, a fourth
     step below the panel, which read as a different material. */
  --fill-footer:   linear-gradient(180deg, #ffffff 0%, #f4f4f4 100%);
  --cta-stars:     url("/v2/img/cta/particles-light.svg");

  /* Solid greys rather than ink at an alpha. Matching the dark theme's ladder
     step for step put the edge at rgba(4,12,19,.2), which over white computes to
     about #ced0d2 — considerably harder than the reference draws it. Dark on
     light carries further than light on dark, and on a hairline that shows.
     In this theme an edge only ever meets a light surface, so it does not need
     the alpha to adapt. */
  --hairline:        #e4e4e4;
  --hairline-dim:    #efefef;
  --hairline-strong: #cfcfcf;

  /* On dark the dome is light rising off the edge; on light the only way to keep
     an edge visible is to take light away, so the same dome reads as shade.
     Pitched lower than 0.1 — ink on a near-white page carries much further than
     white on near-black. */
  --edge-ink: 4, 12, 19;
  --edge-glow: 0.055;

  /* The headline gradient opens on sand (#ddc5a9), which is all but invisible
     on a white page — the last word of every gradient heading faded out. Same
     three-stop warm ramp, with the pale end replaced by a light orange that
     still reads as ink. The dark theme keeps the original; .on-artwork restates
     it, because artwork is dark in both themes. */
  --gradient-title: linear-gradient(
    225deg,
    var(--v2-flame-soft) 0%,
    var(--v2-flame) 55%,
    var(--v2-flame-deep) 100%
  );
}

/* Registered so it interpolates as a number instead of flipping between two
   tokens — that is what lets the mixer readout count up in pure CSS. It
   inherits on purpose: one animation on the row then drives both the printed
   percentage and the bar's width, which cannot drift apart. */
@property --v2-pos {
  syntax: "<percentage>";
  initial-value: 38%;
  inherits: true;
}

@property --v2-mix {
  syntax: "<integer>";
  initial-value: 0;
  inherits: true;
}

html[data-design="v2"] {
  /* Brand gradient. In Figma this is a Diamond fill with three stops.
     Inside a single quadrant a diamond gradient is t = x*u + y*v, i.e. strictly
     linear, and its centre sits at the element's top-right corner, so the whole
     visible area falls in one quadrant. Hence 225deg. */
  --gradient-flame: linear-gradient(
    225deg,
    var(--v2-sand) 0%,
    var(--v2-flame) 70%,
    var(--v2-flame-deep) 100%
  );

  /* Linear fill, white 100% -> 0%, layer opacity 20%. Every glass surface uses
     it — three separate copies at 99deg/15%, 102deg/10% and 102.4deg/20% used
     to exist, and nobody could tell them apart. */
  --gradient-glass: linear-gradient(
    102.4deg,
    rgba(255, 255, 255, 0.2) 0%,
    rgba(255, 255, 255, 0) 100%
  );

  /* Same fill, backed off — for a glass surface that is present but not active. */
  --gradient-glass-dim: linear-gradient(
    102.4deg,
    rgba(255, 255, 255, 0.02) 0%,
    rgba(255, 255, 255, 0) 100%
  );

  /* Heading gradient. Diamond fill in Figma with the same three stops as the
     brand gradient, so the values match today — kept as its own token so titles
     can be retuned without dragging buttons along. The heading's own geometry
     (717x120) reduces to 217deg; 225 is used to stay in one visual language,
     the 8 degrees are not distinguishable at this size. */
  --gradient-title: linear-gradient(
    225deg,
    var(--v2-sand) 0%,
    var(--v2-flame) 70%,
    var(--v2-flame-deep) 100%
  );

  --gradient-panel: var(--panel-fill);
  /* Arrow pointing north-east, used as a mask so it inherits its colour */
  --icon-arrow-ne: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.4 8.6 8.6 3.4'/%3E%3Cpath d='M4.6 3.4h4v4'/%3E%3C/svg%3E");


  /* Figma's blur sigma differs from the CSS one by roughly 4x. */
  --render-label-blur: 2px;

  /* One marquee step: (317.244 card + 5 gap) x 5 unique cards */
  --marquee-shift: 1611.22px;
}

/* ============================================================================
   BASE
   ========================================================================== */

html[data-design="v2"] {
    scroll-behavior: smooth;
  }

html[data-design="v2"] body {
    background-color: var(--color-ink);
    color: var(--fg);
    font-family: var(--font-body);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: hidden;
  }

html[data-design="v2"] ::selection {
    background: var(--color-flame);
    color: var(--fg);
  }

html[data-design="v2"] ::-webkit-scrollbar       { width: 8px; }

html[data-design="v2"] ::-webkit-scrollbar-track { background: var(--color-ink); }

html[data-design="v2"] ::-webkit-scrollbar-thumb { background: #2e2e2e; border-radius: 4px; }

html[data-design="v2"] ::-webkit-scrollbar-thumb:hover { background: #3d3d3d; }

/* ============================================================================
   UTILITIES
   ========================================================================== */

html[data-design="v2"] .bg-flame { background-image: var(--gradient-flame);
}
html[data-design="v2"] .bg-glass { background-image: var(--gradient-glass);
}
html[data-design="v2"] .bg-panel { background-image: var(--gradient-panel);
}
html[data-design="v2"] .bg-sculpted { background-image: var(--fill-sculpted);
}

html[data-design="v2"] .text-flame {
  background-image: var(--gradient-flame);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

html[data-design="v2"] .shell {
  width: 100%;
  max-width: var(--container-shell);
  margin-inline: auto;
  padding-inline: 24px;
}

/* ============================================================================
   COMPONENTS
   ========================================================================== */

/* ── Shared panel edge ───────────────────────────────────────────────────
     Six panels across five sections, all on the same radius and the same
     hairline. They used to declare it separately and had drifted to four
     different border alphas — the order the sections were built in, nothing
     more. What still differs between them is the fill, and only the fill. */

html[data-design="v2"] .stat-card,
  html[data-design="v2"] .quote-card,
  html[data-design="v2"] .faq-item,
  html[data-design="v2"] .demo-panel,
  html[data-design="v2"] .prompt-widget__field,
  html[data-design="v2"] .render-card {
    border-radius: 20px;
    border: 1px solid var(--color-hairline);
  }

html[data-design="v2"] .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 16px 30px;
    border-radius: 10px;
    border: 1px solid transparent;
    font-size: 20px;
    line-height: 19.2px;
    white-space: nowrap;
    overflow: hidden;
    position: relative;
    isolation: isolate;
    transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1),
                box-shadow 0.25s cubic-bezier(0.22, 1, 0.36, 1),
                border-color 0.25s ease;
  }

html[data-design="v2"] .btn:hover  { transform: translateY(-2px); }

html[data-design="v2"] .btn:active { transform: translateY(0); }

html[data-design="v2"] .btn--flame {
    background-image: var(--gradient-flame);
    border-color: var(--hairline-on-accent);
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--fg-on-accent);
    text-shadow: 0 0 4px rgba(0, 0, 0, 0.15);
  }

html[data-design="v2"] .btn--flame:hover {
    box-shadow: 0 10px 34px -8px rgba(var(--v2-accent-rgb), 0.65);
  }

/* Lifted from groilot.webflow.io, where every button carries it: a tight
     contact shadow, a wide faint one for distance, and a white line inside the
     top edge. Light theme only — on a dark page a black shadow does nothing,
     and there the button is already separated by being brighter than its page.

     Their third layer, an inset white line along the top edge, is not taken. It
     is a material property of a white button: on white it barely registers and
     just suggests a curve, on our orange gradient the same 90% white reads as a
     stripe across the face. .btn--flame already carries a white 40% border doing
     that job.

     --btn-lift is kept as its own variable so the flame button's hover glow can
     add to it instead of replacing it; a plain box-shadow on :hover would drop
     the contact shadow at exactly the moment the button is being pressed. */

html[data-design="v2"][data-theme="light"] .btn {
    --btn-lift:
      0 21px 8px rgba(0, 0, 0, 0.03),
      0 1px 3px rgba(0, 0, 0, 0.18);
    box-shadow: var(--btn-lift);
  }

html[data-design="v2"][data-theme="light"] .btn--flame:hover {
    box-shadow: var(--btn-lift), 0 10px 34px -8px rgba(var(--v2-accent-rgb), 0.65);
  }

/* Except where the button is not on the light page at all. The hero stays dark
     artwork in both themes, so a button on it must look the same in both — the
     lift is keyed to the surface, not to the theme, and keying it to the theme
     put a white top edge and a black contact shadow on a dark picture.
     Set outright rather than by blanking --btn-lift: `none` cannot sit inside a
     shadow list, so the hover rule above would stop parsing. */

html[data-design="v2"][data-theme="light"] .on-artwork .btn { box-shadow: none; }

/* The mark is a raster of pale neon, and a bitmap cannot follow the theme, so
     it is filtered instead. The brightening was an arbitrary utility in the
     markup, which no rule here could have overridden — utilities outrank the
     components layer — so it lives here now and the light case can differ.

     INTERIM on the light side: at its shipped luminance of 196 the mark sits at
     about 1.65:1 against a white page once the bar leaves the hero. Darkening a
     neon drawing is not the same as drawing it for a light page; this holds
     until a proper export exists. */

html[data-design="v2"] .site-nav__mark { filter: grayscale(1) brightness(1.3); }

/* The :not(.on-artwork) guard was here because the artwork stayed dark in the
     light theme, so the mark passing over the hero still needed the pale
     version. The artwork follows the theme now, so in this theme the mark is
     dark wherever the bar happens to be. */
html[data-design="v2"][data-theme="light"] .site-nav .site-nav__mark {
    filter: grayscale(1) brightness(0.32);
  }

html[data-design="v2"][data-theme="light"] .on-artwork .btn--flame:hover {
    box-shadow: 0 10px 34px -8px rgba(var(--v2-accent-rgb), 0.65);
  }

/* Smaller than the Figma button: the language / theme / Sign In cluster to
     its right is not in the design, and nothing else fits the 1200 grid. */

/* Figma specifies #404040 here, but that stroke was drawn against the dark
     hero. On the glass pill it reads as a black ring, so the button follows the
     hero CTA and keeps the white 40% stroke from .btn--flame. */

html[data-design="v2"] .btn--nav {
    text-shadow: 0 1px 0 rgba(0, 0, 0, 0.15);
    padding: 10px 20px;
    font-size: var(--text-small);
    line-height: 1.2;
  }

/* ── Section 3: Why Creators Switch ─────────────────────────────────────── */

/* Gradient headline text */

html[data-design="v2"] .title-gradient {
    background-image: var(--gradient-title);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }

/* Pill tag above a section heading */

html[data-design="v2"] .section-tag {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 40px;
    padding: 0 35px;
    border-radius: 20px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-glass);
    font-size: 20px;
    line-height: 19.2px;
    color: var(--fg);
    white-space: nowrap;
  }

/* Role chip in the pipeline diagram */

html[data-design="v2"] .role-chip {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    padding: 10px;
    border-radius: 30px;
    border: 1px solid var(--color-hairline);
    background-image: var(--fill-sculpted);
    font-family: var(--font-display);
    font-size: 14px;
    line-height: 20px;
    color: var(--fg);
    white-space: nowrap;
  }

/* Rim spark. The chip's own edge lights just before its wire fires, so the
     pulse reads as leaving the chip instead of appearing out of nowhere. Both
     layers run the wire's clock and delay, set per chip by the wiring script,
     and lean toward the rim the wire actually leaves from (--spark-angle). */

html[data-design="v2"] .role-chip::before,
  html[data-design="v2"] .role-chip::after {
    content: "";
    position: absolute;
    border-radius: inherit;
    opacity: 0;
    pointer-events: none;
    -webkit-mask-image: linear-gradient(var(--spark-angle, 90deg), transparent 15%, #fff 100%);
    mask-image: linear-gradient(var(--spark-angle, 90deg), transparent 15%, #fff 100%);
    animation: v2-chip-spark var(--wire-cycle, 3.6s) ease-out infinite;
    animation-delay: var(--wire-delay, 0ms);
    animation-play-state: paused;
  }

/* the lit edge itself, sitting exactly on the chip's own border. It carries
     the wire's colour because it is the same signal one moment earlier — a
     white rim fired against a white chip, and an ink one just looked smudged. */

html[data-design="v2"] .role-chip::after {
    inset: 0;
    border: 1px solid var(--wire-ink);
  }

/* the bloom around it — the same rim, widened and blurred */

html[data-design="v2"] .role-chip::before {
    inset: -2px;
    border: 2px solid color-mix(in srgb, var(--wire-ink) 55%, transparent);
    filter: blur(4px);
  }

html[data-design="v2"] .reveal.is-revealed .role-chip::before,
  html[data-design="v2"] .reveal.is-revealed .role-chip::after {
    animation-play-state: running;
  }

/* Lucide draws on 24 units at stroke 2, and these sit in wells of two sizes —
     32px in the diagram, 24px in the hub — so the stroke would land at 1.5px in
     one and 1.17px in the other. non-scaling-stroke takes the scale out of it. */

html[data-design="v2"] .agent-glyph [stroke], html[data-design="v2"] .agent-glyph[stroke] {
    vector-effect: non-scaling-stroke;
    stroke-width: 1.5px;
  }

/* Comparison table. "Yes" is a brand tile with a tick in it, "no" a bare
     cross — the design leans on that difference to tell the two columns apart,
     and it was lost when both became plain glyphs. The tick stays white in
     either theme: it sits on the accent. */

html[data-design="v2"] .diff-yes {
    display: inline-grid;
    place-items: center;
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border-radius: 10px;
    background-image: var(--gradient-flame);
    color: var(--fg-on-accent);
  }

html[data-design="v2"] .diff-no { color: var(--fg-faint); }

/* Bullet badge in the switch cards. Was two SVG files, avatar-check and
     avatar-alt, byte-identical in content: the same check path over the same
     circle — and that circle was a sixth copy of --fill-sculpted. */

html[data-design="v2"] .check-badge {
    display: inline-grid;
    place-items: center;
    width: 40px;
    height: 40px;
    flex-shrink: 0;
    border-radius: 50%;
    border: 1px solid var(--color-hairline);
    background-image: var(--fill-sculpted);
    color: var(--fg);
  }

/* Recessed icon well inside a role chip */

html[data-design="v2"] .role-chip__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border-radius: 50%;
    background-image: var(--fill-well);
  }

/* Phone: the two chip columns plus the hub between them ran 75px past the
     viewport, so the right-hand column was cut in half. Chips come down to
     their text plus a 24px well; the hub is halved in the markup. */

@media (width < 64rem) {
    html[data-design="v2"] .role-chip {
      gap: 4px;
      padding: 6px;
      border-radius: 22px;
      font-size: 12px;
      line-height: 16px;
    }

    html[data-design="v2"] .role-chip__icon {
      width: 24px;
      height: 24px;
    }

    html[data-design="v2"] .role-chip .agent-glyph {
      width: 14px;
      height: 14px;
    }
  }

/* Bar chart behind the 90% figure.
     Five bars, 60 wide, 10 apart, 23px tall rising in 30px steps; opacity
     climbs with height. They grow from the baseline shortest-first once the
     card is revealed, so the reveal observer drives them — no extra JS. */

html[data-design="v2"] .bar-chart {
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    z-index: 0;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: 10px;
    pointer-events: none;
  }

html[data-design="v2"] .bar-chart__bar {
    width: 60px;
    flex-shrink: 0;
    border-radius: 10px 10px 0 0;
    background: var(--v2-bar);
    /* Each bar keeps its own opacity from the design; the keyframes fade to it
       rather than to 1, and it doubles as the state when animations are off. */
    opacity: var(--bar-opacity, 1);
    transform-origin: bottom;
    transform: scaleY(1);
    animation: v2-bar-cycle var(--bar-cycle, 4.2s) linear infinite;
    animation-delay: var(--bar-delay, 0ms);
    animation-play-state: paused;
  }

/* The loop only runs while the card is on screen */

html[data-design="v2"] .reveal.is-revealed .bar-chart__bar { animation-play-state: running; }

/* Chart on the 8+hrs card.
     The Figma asset is a raster with the line and the fill baked together, so
     they could not be driven separately. The curve here is traced out of that
     PNG (top-most saturated pixel per column, smoothed into beziers) and its
     colours sampled from the same file — so the shape is the asset's, not an
     invention. That buys two independent reveals: the fill wipes top to bottom
     via a clip rect, the line draws left to right via stroke-dashoffset. */

html[data-design="v2"] .hours-chart {
    /* The traced curve runs right up to the top of the viewBox on the right,
       and an svg clips to its viewport by default — that shaved the top pixel
       off the stroke. The card's own overflow still contains it. */
    overflow: visible;
    animation: v2-chart-fade var(--chart-cycle, 7s) linear infinite;
    animation-play-state: paused;
  }

/* Feathered wipe rather than a hard clip edge. It runs left to right, the
     same way the line draws, so the two read as one curtain crossing the card
     instead of two separate reveals. */

html[data-design="v2"] .hours-chart__fill {
    -webkit-mask-image: linear-gradient(90deg, #000 0 38%, transparent 62% 100%);
    mask-image: linear-gradient(90deg, #000 0 38%, transparent 62% 100%);
    -webkit-mask-size: 200% 100%;
    mask-size: 200% 100%;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    animation: v2-chart-curtain var(--chart-cycle, 7s) linear infinite;
    animation-play-state: paused;
  }

/* pathLength="1" normalises the curve, so the dash values need no measuring */

html[data-design="v2"] .hours-chart__line {
    stroke-dasharray: 1;
    stroke-dashoffset: 0;
    animation: v2-chart-line var(--chart-cycle, 7s) linear infinite;
    animation-play-state: paused;
  }

html[data-design="v2"] .reveal.is-revealed .hours-chart,
  html[data-design="v2"] .reveal.is-revealed .hours-chart__fill,
  html[data-design="v2"] .reveal.is-revealed .hours-chart__line {
    animation-play-state: running;
  }

/* Agent wiring.
     A repeating dash across one shared path read as a marching LED strip:
     identical blobs, evenly spaced, all wires firing together. Instead each
     wire carries a single comet — a bright core with a dimmer, wider tail
     sharing its leading edge — and the wires are staggered so the diagram
     looks like hand-offs rather than a machine.

     pathLength="1" normalises every wire, so one dash period equals one wire
     no matter how long it actually is. */

html[data-design="v2"] .wire {
    fill: none;
    /* Brand, not ink. A white comet is invisible on a light page and an ink one
       reads as grime on the grey panel; the accent carries on both. */
    stroke: var(--wire-ink);
    /* Butt caps and one flat width: the lit stretch is the same thin line as
       the wire under it, just brighter. */
    stroke-linecap: butt;
    stroke-width: 1.5;
    opacity: 0;
    animation:
      v2-wire-run var(--wire-cycle, 3.6s) cubic-bezier(0.4, 0, 0.5, 1) infinite,
      v2-wire-glow var(--wire-cycle, 3.6s) ease-in-out infinite;
    animation-delay: var(--wire-delay, 0ms);
    animation-play-state: paused;
  }

html[data-design="v2"] .reveal.is-revealed .wire { animation-play-state: running; }

/* Hover lift — the same gesture as the hero buttons, a touch taller because
     a 300px card needs more travel than a button to read as the same nudge.
     It rides `translate`, not `transform`: the reveal already owns `transform`
     on these very elements, and the two properties compose instead of one
     winning on specificity. */

html[data-design="v2"] .card-lift {
    transition: translate 0.25s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .card-lift:hover {
    translate: 0 var(--card-lift, -4px);
  }

/* Stat card shared shell */

html[data-design="v2"] .stat-card {
    display: flex;
    flex-direction: column;
    height: 200px;
    padding: 20px;
    background-image: var(--gradient-panel);
    overflow: hidden;
    position: relative;
  }

/* ── Section 4: How It Works ────────────────────────────────────────────
     Three demo panels differing only by accent, so the colour is a variable. */

/* ── Section 4 demo panels ──────────────────────────────────────────────
     Four scenes rebuilt from the Remotion compositions on vidnext.ai. There
     the frames are driven by React springs; here each scene is one CSS loop
     on --demo-cycle, gated by .is-active so only the panel you are looking at
     is animating — and so it restarts from frame zero when you land on it. */

/* Phone: the panel is 840x520 of absolutely positioned scene, so it cannot be
     reflowed — it is scaled. zoom, not transform: the carousel measures
     offsetWidth to work out its scroll step, and a transform leaves layout at
     840 while the panel paints at 294, which would scroll it a panel and a half
     per press. 0.35 lands on the 294px the vidnext.ai mobile panel uses. */

@media (width < 64rem) {
    html[data-design="v2"] .demo-panel {
      zoom: 0.35;
    }
  }

/* Between the phone and the desktop the panel kept the phone's 294px and sat
     in the middle of a 768px screen looking like a postage stamp. It grows with
     the room instead: 462 at 640, 655 from 768 up to the 840 the desktop uses. */

@media (width >= 40rem) and (width < 48rem) {
    html[data-design="v2"] .demo-panel { zoom: 0.55; }
  }

@media (width >= 48rem) and (width < 64rem) {
    html[data-design="v2"] .demo-panel { zoom: 0.78; }
  }

html[data-design="v2"] .demo-panel {
    --accent: var(--v2-accent-rgb);
    --demo-cycle: 8s;
    position: relative;
    height: 520px;
    width: 840px;
    flex-shrink: 0;
    overflow: hidden;
    background-image: var(--fill-stage);
    scroll-snap-align: center;
    transition: opacity 0.5s ease, scale 0.5s cubic-bezier(0.22, 1, 0.36, 1);
    opacity: 0.35;
    scale: 0.94;
  }

html[data-design="v2"] .demo-panel.is-active {
    opacity: 1;
    scale: 1;
  }

/* 1px dots on a 22px pitch — the faint graph paper under every scene */

html[data-design="v2"] .demo-panel__grid {
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0.5;
    background-image: radial-gradient(circle, var(--color-hairline) 1px, transparent 1px);
    background-size: 22px 22px;
  }

html[data-design="v2"] .demo-panel__glow {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image: radial-gradient(60% 45% at 50% 42%, rgba(var(--accent), 0.1) 0%, transparent 100%);
  }

html[data-design="v2"] .demo-panel__caption {
    position: absolute;
    left: 20px;
    right: 20px;
    bottom: 18px;
    z-index: 3;
    display: flex;
    align-items: center;
    gap: 10px;
  }

html[data-design="v2"] .demo-panel__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    flex-shrink: 0;
    border-radius: 8px;
    border: 1px solid rgba(var(--accent), 0.3);
    background: rgba(var(--accent), 0.12);
  }

html[data-design="v2"] .demo-panel__num {
    margin-right: 6px;
    color: rgb(var(--accent));
  }

/* Every scene fills the panel above the caption */

html[data-design="v2"] .demo-stage {
    position: absolute;
    inset: 0 0 76px 0;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }

html[data-design="v2"] .demo-label {
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--fg-faint);
  }

html[data-design="v2"] .demo-title {
    font-family: var(--font-display);
    font-size: 32px;
    font-weight: 700;
    line-height: 38px;
    color: var(--fg);
  }

html[data-design="v2"] .demo-title--sm { font-size: 18px; }

/* ── Scene 1: write a prompt ───────────────────────────────────────────
     The widget is the hero's, rebuilt: flame panel underneath, dark field on
     top, and the bottom 40px strip left uncovered so the gradient shows as
     the action bar. Beats off the original: the box springs in at 0.6s,
     typing runs 1.2s to 4.0s, "Create a video" is clicked at 4.3s and the
     status pill arrives at 5.8s. On a 7s clock: 8.6 / 17-57 / 61 / 83 %. */

html[data-design="v2"] .demo-stage--prompt { gap: 26px; }

html[data-design="v2"] .demo-stage--prompt .demo-label {
    font-family: var(--font-mono);
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 4px;
    color: var(--fg-subtle);
    animation: v2-s1-label var(--demo-cycle) ease-out infinite;
  }

html[data-design="v2"] .prompt-widget {
    position: relative;
    width: 620px;
    height: 120px;
    border-radius: 20px;
    overflow: hidden;
    background-image: var(--gradient-flame);
    animation: v2-s1-box var(--demo-cycle) cubic-bezier(0.34, 1.56, 0.64, 1) infinite;
  }

/* Overlay, not a border: overflow:hidden clips to the padding box, so the
     dark field could never cover a border on its parent and two lines would
     show along the top. Same reasoning as the hero widget. */

html[data-design="v2"] .prompt-widget__rim {
    position: absolute;
    inset: 0;
    z-index: 2;
    border-radius: 20px;
    border: 1px solid var(--color-hairline-strong);
    pointer-events: none;
  }

html[data-design="v2"] .prompt-widget__field {
    position: absolute;
    inset: 0 0 auto 0;
    display: flex;
    align-items: center;
    height: 80px;
    padding-inline: 26px;
    background-image: var(--gradient-panel);
    overflow: hidden;
  }

/* Typed by revealing width in whole characters, so the monospace font is
     what makes 44ch land exactly on the last glyph. */

html[data-design="v2"] .prompt-line__text {
    --chars: 44;
    display: inline-block;
    overflow: hidden;
    white-space: nowrap;
    width: calc(var(--chars) * 1ch);
    font-family: var(--font-mono);
    font-size: 18px;
    font-weight: 500;
    line-height: 26px;
    color: var(--fg);
    border-right: 2px solid var(--color-flame-hot);
    animation:
      v2-s1-type var(--demo-cycle) steps(var(--chars)) infinite,
      v2-demo-caret 1s steps(2) infinite;
  }

html[data-design="v2"] .prompt-widget__bar {
    position: absolute;
    inset: auto 0 0 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 40px;
    padding-inline: 16px 26px;
  }

html[data-design="v2"] .prompt-widget__stage {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-family: var(--font-display);
    font-size: 13px;
    font-weight: 400;
    color: var(--fg);
    white-space: nowrap;
  }

/* The two stage lines share the slot and cross-fade on the click */

html[data-design="v2"] .prompt-widget__stage--idle { animation: v2-s1-stage-idle var(--demo-cycle) ease-out infinite; }

html[data-design="v2"] .prompt-widget__stage--run {
    position: absolute;
    left: 16px;
    opacity: 0;
    animation: v2-s1-stage-run var(--demo-cycle) ease-out infinite;
  }

html[data-design="v2"] .prompt-widget__cta {
    position: relative;
    font-family: var(--font-display);
    font-size: 17px;
    color: var(--fg);
    white-space: nowrap;
    animation: v2-s1-press var(--demo-cycle) ease-out infinite;
  }

/* Reads as a tap: the label dips, a ring opens out of it and fades */

html[data-design="v2"] .prompt-widget__ripple {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 26px;
    height: 26px;
    translate: -50% -50%;
    border-radius: 50%;
    border: 2px solid var(--hairline-strong);
    opacity: 0;
    pointer-events: none;
    animation: v2-s1-ripple var(--demo-cycle) cubic-bezier(0.22, 1, 0.36, 1) infinite;
  }

html[data-design="v2"] .demo-status {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 11px 26px;
    border-radius: 30px;
    border: 1px solid rgba(var(--accent), 0.26);
    background: var(--surface-1);
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 500;
    color: var(--fg-muted);
    animation: v2-s1-status var(--demo-cycle) cubic-bezier(0.22, 1, 0.36, 1) infinite;
  }

/* Three dots 120 degrees apart on a 5px circle. They hold different
     opacities, so spinning the box alone reads as a comet trail. */

html[data-design="v2"] .demo-spinner {
    position: relative;
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    animation: v2-s1-spin 1.1s linear infinite;
  }

html[data-design="v2"] .demo-spinner i {
    position: absolute;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: rgb(var(--accent));
  }

html[data-design="v2"] .demo-spinner i:nth-child(1) { left: 6px;     top: 1px;   opacity: 0.85; }

html[data-design="v2"] .demo-spinner i:nth-child(2) { left: 10.33px; top: 8.5px; opacity: 0.6; }

html[data-design="v2"] .demo-spinner i:nth-child(3) { left: 1.67px;  top: 8.5px; opacity: 0.35; }

html[data-design="v2"] .prompt-widget__stage .demo-spinner i { background: var(--fg); }

/* ── Scene 2: configure quality and sources ────────────────────────────
     Not one scene but five, timed off the original composition:
     format 0-1.7s, duration 1.7-3.4s, voice 3.4-5.2s, mixer 5.2-9.6s,
     visual style from 9.6s. On a 13s clock that is 13.1 / 26.2 / 40 / 73.8
     per cent, which is where the five cfg-* keyframe sets put their turns.
     Chips along the top accumulate as each choice is made and never leave,
     so they only ever need an entrance plus animation-delay. */

html[data-design="v2"] .demo-stage--config { justify-content: flex-start; }

html[data-design="v2"] .cfg-chips {
    position: absolute;
    top: 16px;
    left: 0;
    right: 0;
    display: flex;
    justify-content: center;
    gap: 6px;
    z-index: 2;
  }

html[data-design="v2"] .cfg-chip {
    padding: 3px 12px;
    border-radius: 20px;
    border: 1px solid rgba(var(--accent), 0.21);
    background: rgba(var(--accent), 0.07);
    font-family: var(--font-display);
    font-size: 13px;
    font-weight: 600;
    color: var(--fg);
    white-space: nowrap;
    animation: v2-cfg-chip 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) var(--chip-in) both;
  }

html[data-design="v2"] .cfg-scene {
    position: absolute;
    inset: 52px 40px 0 40px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    opacity: 0;
  }

html[data-design="v2"] .cfg-scene--format   { animation: v2-cfg-s1 var(--demo-cycle) linear infinite; }

html[data-design="v2"] .cfg-scene--duration {
    animation:
      v2-cfg-s2 var(--demo-cycle) linear infinite,
      v2-cfg-dial 1.6s cubic-bezier(0.22, 1, 0.36, 1) 1.9s both;
  }

html[data-design="v2"] .cfg-scene--voice    { animation: v2-cfg-s3 var(--demo-cycle) linear infinite; }

/* gap 0: this scene is the tallest of the five and its own margins already
     space it — the shared gap would push it past the stage. */

html[data-design="v2"] .cfg-scene--mixer {
    gap: 0;
    animation: v2-cfg-s4 var(--demo-cycle) linear infinite;
  }

html[data-design="v2"] .cfg-scene--style    { animation: v2-cfg-s5 var(--demo-cycle) linear infinite; }

/* Scene 1 — aspect ratio */

html[data-design="v2"] .fmt {
    display: flex;
    gap: 18px;
    margin-top: 26px;
  }

html[data-design="v2"] .fmt__card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
    width: 156px;
    height: 118px;
    border-radius: 20px;
    border: 2px solid var(--color-hairline-dim);
    background: var(--fill-tile);
    font-family: var(--font-display);
    font-size: 17px;
    font-weight: 600;
    color: var(--fg-subtle);
  }

html[data-design="v2"] .fmt__card.is-on {
    border-color: rgba(var(--accent), 0.5);
    color: var(--fg);
    box-shadow: 0 0 44px rgba(var(--accent), 0.18);
  }

html[data-design="v2"] .fmt__box {
    border: 2.5px solid var(--color-hairline);
    border-radius: 8px;
  }

html[data-design="v2"] .fmt__card.is-on .fmt__box { border-color: rgb(var(--accent)); }

html[data-design="v2"] .fmt__box--wide { width: 34px; height: 20px; }

html[data-design="v2"] .fmt__box--tall { width: 16px; height: 27px; }

/* Scene 2 — duration */

html[data-design="v2"] .cfg-time {
    font-family: var(--font-display);
    font-size: 92px;
    font-weight: 700;
    line-height: 96px;
    color: var(--fg);
    counter-reset: n var(--v2-mix);
  }

html[data-design="v2"] .cfg-time::after { content: counter(n) ":00"; }

/* --pos is animated once on the track and inherited: the fill's width and
     the knob's and badge's offsets are then the same number by construction. */

html[data-design="v2"] .cfg-slider {
    position: relative;
    width: 390px;
    height: 8px;
    margin-top: 44px;
    border-radius: 8px;
    background: var(--surface-2);
    animation: v2-cfg-slide 1.6s cubic-bezier(0.22, 1, 0.36, 1) 1.9s both;
  }

html[data-design="v2"] .cfg-slider__fill,
  html[data-design="v2"] .cfg-slider__knob,
  html[data-design="v2"] .cfg-slider__badge {
    position: absolute;
  }

html[data-design="v2"] .cfg-slider__fill {
    left: 0;
    top: 0;
    bottom: 0;
    width: var(--v2-pos);
    border-radius: 8px;
    background-image: linear-gradient(90deg, rgba(var(--accent), 0.35), rgb(var(--accent)));
  }

html[data-design="v2"] .cfg-slider__knob {
    left: var(--v2-pos);
    top: -7px;
    width: 21px;
    height: 21px;
    margin-left: -10px;
    border-radius: 50%;
    border: 4px solid rgb(var(--accent));
    background: var(--fg);
  }

html[data-design="v2"] .cfg-slider__badge {
    left: var(--v2-pos);
    top: -40px;
    margin-left: -22px;
    padding: 3px 9px;
    border-radius: 8px;
    background: rgb(var(--accent));
    font-family: var(--font-display);
    font-size: 13px;
    font-weight: 700;
    color: var(--fg);
    counter-reset: n var(--v2-mix);
  }

html[data-design="v2"] .cfg-slider__badge::after { content: counter(n) ":00"; }

html[data-design="v2"] .cfg-slider__ends {
    display: flex;
    justify-content: space-between;
    width: 390px;
    margin-top: 8px;
    font-family: var(--font-display);
    font-size: 13px;
    color: var(--fg-ghost);
  }

/* Scene 3 — voice */

html[data-design="v2"] .voices {
    display: flex;
    flex-direction: column;
    gap: 4px;
    width: 320px;
    margin-top: 22px;
  }

html[data-design="v2"] .voice {
    display: flex;
    align-items: center;
    gap: 12px;
    height: 38px;
    padding: 0 12px;
    border-radius: 10px;
    border: 1px solid var(--color-hairline);
    background: rgba(24, 24, 27, 0.5);
    font-family: var(--font-display);
    font-size: 17px;
    color: var(--fg-subtle);
  }

html[data-design="v2"] .voice__ava {
    width: 23px;
    height: 23px;
    flex-shrink: 0;
    border-radius: 50%;
    border: 2px solid rgba(var(--accent), 0.25);
    background-image: linear-gradient(135deg, rgba(var(--accent), 0.3), rgba(var(--accent), 0.05));
  }

html[data-design="v2"] .voice.is-on {
    color: var(--fg);
    font-weight: 600;
    border-color: rgba(var(--accent), 0.5);
    background: rgba(var(--accent), 0.08);
    animation: v2-cfg-pick 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) 4.2s both;
  }

/* Same trick as the audio clip in scene 4: every bar is one height, so a
     repeating gradient stands in for eight elements. */

html[data-design="v2"] .voice__wave {
    width: 38px;
    height: 16px;
    margin-left: auto;
    background-image: repeating-linear-gradient(
      90deg,
      rgb(var(--accent)) 0 2px,
      transparent 2px 6px
    );
  }

/* Scene 4 — content mixer */

html[data-design="v2"] .mixer {
    width: 460px;
    margin-top: 14px;
    display: flex;
    flex-direction: column;
    gap: 10px;
  }

html[data-design="v2"] .mixer__row {
    display: grid;
    grid-template-columns: 8px 1fr auto;
    align-items: center;
    gap: 0 10px;
    /* --mix is registered and inheriting, so one animation here drives both
       the readout below and the bar's width. */
    --v2-mix: var(--pct);
    animation: v2-cfg-mix 1.5s cubic-bezier(0.22, 1, 0.36, 1) var(--v2-mix-in) both;
  }

html[data-design="v2"] .mixer__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--tint);
  }

html[data-design="v2"] .mixer__name {
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 500;
    color: var(--fg-muted);
  }

html[data-design="v2"] .mixer__pct {
    font-family: var(--font-display);
    font-size: 19px;
    font-weight: 700;
    color: var(--tint);
    counter-reset: n var(--v2-mix);
  }

html[data-design="v2"] .mixer__pct::after { content: counter(n) "%"; }

html[data-design="v2"] .mixer__track {
    grid-column: 1 / -1;
    margin-top: 4px;
    height: 8px;
    border-radius: 8px;
    background: var(--surface-2);
    overflow: hidden;
  }

html[data-design="v2"] .mixer__fill {
    display: block;
    height: 100%;
    width: calc(var(--v2-mix) * 1%);
    border-radius: 8px;
    background: linear-gradient(90deg, color-mix(in srgb, var(--tint) 55%, #000), var(--tint));
  }

html[data-design="v2"] .mixer__stack {
    display: flex;
    gap: 3px;
    width: 460px;
    margin-top: 16px;
  }

html[data-design="v2"] .mixer__seg {
    --v2-mix: var(--pct);
    height: 8px;
    width: calc(var(--v2-mix) * 1%);
    border-radius: 4px;
    background: var(--tint);
    animation: v2-cfg-mix 1.5s cubic-bezier(0.22, 1, 0.36, 1) var(--v2-mix-in) both;
  }

html[data-design="v2"] .mixer__total {
    margin-top: 8px;
    font-family: var(--font-display);
    font-size: 12px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--fg-faint);
  }

/* Scene 5 — visual style */

html[data-design="v2"] .cfg-scene--style { justify-content: flex-start; gap: 10px; padding-top: 4px; }

html[data-design="v2"] .style-tabs {
    display: flex;
    gap: 5px;
  }

html[data-design="v2"] .style-tabs span {
    padding: 3px 11px;
    border-radius: 8px;
    border: 1.5px solid var(--color-hairline-dim);
    font-family: var(--font-display);
    font-size: 13px;
    font-weight: 500;
    color: var(--fg-ghost);
  }

html[data-design="v2"] .style-tabs .is-on {
    border-color: rgba(var(--accent), 0.31);
    background: rgba(var(--accent), 0.12);
    color: rgb(var(--accent));
  }

html[data-design="v2"] .style-body {
    display: flex;
    gap: 14px;
    width: 100%;
    margin-top: 4px;
  }

html[data-design="v2"] .style-list__label {
    margin-bottom: 6px;
    font-family: var(--font-display);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--fg-ghost);
  }

html[data-design="v2"] .style-list__grid {
    display: grid;
    grid-template-columns: repeat(2, 78px);
    gap: 5px;
  }

html[data-design="v2"] .style-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    height: 50px;
    border-radius: 10px;
    border: 1px solid var(--color-hairline);
    background-image: linear-gradient(135deg, var(--surface-1), transparent);
    font-family: var(--font-display);
    font-size: 10px;
    font-weight: 600;
    color: var(--fg-faint);
  }

html[data-design="v2"] .style-card b { font-size: 20px; font-weight: 800; color: var(--fg-faint); }

html[data-design="v2"] .style-card.is-on {
    border-color: rgba(var(--accent), 0.31);
    background-image: linear-gradient(135deg, rgba(var(--accent), 0.16), rgba(var(--accent), 0.02));
    color: var(--fg);
  }

html[data-design="v2"] .style-card.is-on b { color: rgb(var(--accent)); }

html[data-design="v2"] .style-preview {
    position: relative;
    flex: 1;
    border-radius: 10px;
    border: 1px solid rgba(var(--accent), 0.13);
    background-image:
      radial-gradient(60% 50% at 50% 40%, rgba(var(--accent), 0.12), transparent 100%),
      var(--fill-stage);
  }

html[data-design="v2"] .style-preview__tag {
    position: absolute;
    left: 9px;
    top: 8px;
    padding: 2px 7px;
    border-radius: 4px;
    border: 1px solid var(--color-hairline);
    background: var(--scrim);
    font-family: var(--font-display);
    font-size: 10px;
    font-weight: 600;
    color: var(--fg-faint);
  }

html[data-design="v2"] .style-preview__tag--on {
    left: auto;
    right: 9px;
    border-color: rgba(var(--accent), 0.19);
    background: rgba(var(--accent), 0.08);
    color: rgb(var(--accent));
  }

html[data-design="v2"] .style-preview__play {
    position: absolute;
    left: 50%;
    top: 50%;
    translate: -50% -50%;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    border: 1px solid var(--color-hairline);
    background: var(--surface-1);
  }

html[data-design="v2"] .style-preview__play::after {
    content: "";
    position: absolute;
    left: 11px;
    top: 9px;
    border-style: solid;
    border-width: 6px 0 6px 9px;
    border-color: transparent transparent transparent var(--fg-muted);
  }

html[data-design="v2"] .style-preview__caption {
    position: absolute;
    left: 14px;
    right: 14px;
    bottom: 12px;
    height: 30px;
    border-radius: 10px;
    border: 1px solid var(--color-hairline);
    background-image: linear-gradient(135deg, var(--surface-2), transparent);
  }

html[data-design="v2"] .style-swatches {
    display: flex;
    gap: 5px;
  }

html[data-design="v2"] .style-swatches span {
    padding: 2px 9px;
    border-radius: 8px;
    border: 1px solid var(--color-hairline);
    background: var(--surface-1);
    font-family: var(--font-display);
    font-size: 11px;
    color: var(--fg-ghost);
  }

html[data-design="v2"] .style-swatches .is-on {
    border-color: rgba(var(--accent), 0.31);
    background: rgba(var(--accent), 0.09);
    color: rgb(var(--accent));
  }

/* ── Scene 3: grab a cup of coffee ─────────────────────────────────────
     Five beats, not three — the first pass missed two of them. Off the
     original: stock footage 0-2.3s, images 2.3-4.4s, motion design 4.4-6.5s,
     the hub 6.5-9.6s, ready from 9.6s. On a 12s clock that is 19.2 / 36.7 /
     54.2 / 80 per cent, where the five bld-s* keyframe sets turn.

     Each search leaves its results behind: they shrink to the edges and, in
     the hub beat, spiral into the core. */

html[data-design="v2"] .demo-stage--build { justify-content: flex-start; padding-top: 22px; }

html[data-design="v2"] .build-head {
    position: absolute;
    top: 22px;
    z-index: 3;
    font-family: var(--font-display);
    font-size: 16px;
    font-weight: 700;
    color: var(--fg);
  }

html[data-design="v2"] .build-head--find   { animation: v2-bld-h1 var(--demo-cycle) linear infinite; }

html[data-design="v2"] .build-head--shots  { animation: v2-bld-h2 var(--demo-cycle) linear infinite; }

html[data-design="v2"] .build-head--design { animation: v2-bld-h3 var(--demo-cycle) linear infinite; }

html[data-design="v2"] .build-head--asm    { animation: v2-bld-h4 var(--demo-cycle) linear infinite; }

html[data-design="v2"] .bld-scene {
    position: absolute;
    inset: 58px 40px 0 40px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    opacity: 0;
  }

html[data-design="v2"] .bld-scene--finds   { animation: v2-bld-s1 var(--demo-cycle) cubic-bezier(0.4, 0, 1, 1) infinite; }

html[data-design="v2"] .bld-scene--shots   { animation: v2-bld-s2 var(--demo-cycle) cubic-bezier(0.4, 0, 1, 1) infinite; }

html[data-design="v2"] .bld-scene--designs { animation: v2-bld-s3 var(--demo-cycle) cubic-bezier(0.4, 0, 1, 1) infinite; }

html[data-design="v2"] .bld-scene--hub     { animation: v2-bld-s4 var(--demo-cycle) linear infinite; }

html[data-design="v2"] .bld-scene--ready   { animation: v2-bld-s5 var(--demo-cycle) cubic-bezier(0.22, 1, 0.36, 1) infinite; }

/* Beat 1 — stock footage results */

html[data-design="v2"] .finds {
    display: flex;
    flex-direction: column;
    gap: 5px;
    width: 420px;
  }

html[data-design="v2"] .find,
  html[data-design="v2"] .shot {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 6px 10px;
    border-radius: 10px;
    border: 1px solid var(--color-hairline);
    background: var(--surface-1);
  }

html[data-design="v2"] .find { animation: v2-bld-card-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) var(--find-in) both; }

html[data-design="v2"] .find.is-on,
  html[data-design="v2"] .shot.is-on {
    border-color: rgba(var(--accent), 0.27);
    background: rgba(var(--accent), 0.07);
  }

/* The duration sits in the corner of the thumbnail, as on any video card */

html[data-design="v2"] .find__thumb {
    display: flex;
    align-items: flex-end;
    justify-content: flex-end;
    width: 54px;
    height: 36px;
    flex-shrink: 0;
    padding: 3px 4px;
    border-radius: 8px;
    border: 1px solid var(--color-hairline);
    font-family: var(--font-display);
    font-size: 9px;
    color: var(--fg-faint);
  }

html[data-design="v2"] .find.is-on .find__thumb {
    background-image: linear-gradient(135deg, var(--fill-tile), rgba(var(--accent), 0.25));
  }

html[data-design="v2"] .find__meta,
  html[data-design="v2"] .shot__meta {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
  }

html[data-design="v2"] .find__meta b,
  html[data-design="v2"] .shot__meta b {
    font-family: var(--font-display);
    font-size: 13px;
    font-weight: 600;
    color: var(--fg-subtle);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

html[data-design="v2"] .find.is-on .find__meta b,
  html[data-design="v2"] .shot.is-on .shot__meta b { color: var(--fg); }

html[data-design="v2"] .find__meta i,
  html[data-design="v2"] .shot__meta i {
    font-family: var(--font-display);
    font-size: 10px;
    font-style: normal;
    color: var(--fg-ghost);
  }

html[data-design="v2"] .find__check {
    width: 15px;
    height: 15px;
    flex-shrink: 0;
    margin-left: auto;
    border-radius: 50%;
    background: rgb(var(--accent));
  }

html[data-design="v2"] .find__check::after {
    content: "";
    display: block;
    width: 4px;
    height: 7px;
    margin: 3px 0 0 5px;
    border: solid var(--fg);
    border-width: 0 1.5px 1.5px 0;
    rotate: 45deg;
  }

/* Beat 2 — image references. They land staggered sideways, so the column
     reads as a scatter of finds rather than a tidy list. */

html[data-design="v2"] .shots {
    display: flex;
    flex-direction: column;
    gap: 4px;
    width: 320px;
  }

html[data-design="v2"] .shot {
    width: 100%;
    animation: v2-bld-shot-in 0.55s cubic-bezier(0.34, 1.4, 0.64, 1) var(--shot-in) both;
  }

html[data-design="v2"] .shot__thumb {
    width: 34px;
    height: 26px;
    flex-shrink: 0;
    border-radius: 8px;
    border: 1px solid rgba(var(--accent), 0.14);
    background-image: linear-gradient(145deg, var(--fill-tile), rgba(var(--accent), 0.18));
  }

html[data-design="v2"] .shots__count {
    margin-top: 16px;
    padding: 4px 14px;
    border-radius: 20px;
    border: 1px solid var(--color-hairline);
    background: var(--surface-1);
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 500;
    color: var(--fg-muted);
    counter-reset: n var(--v2-mix);
    animation: v2-bld-found 1.5s linear 2.6s both;
  }

html[data-design="v2"] .shots__count::after { content: "Found " counter(n) " images"; }

/* Beat 3 — motion design cards, scattered around the middle */

html[data-design="v2"] .bld-scene--designs { display: block; }

html[data-design="v2"] .design {
    position: absolute;
    left: 50%;
    top: 50%;
    translate: calc(-50% + var(--dx)) calc(-50% + var(--dy));
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    width: 128px;
    padding: 12px 10px 14px;
    border-radius: 10px;
    border: 2px solid color-mix(in srgb, var(--tint) 32%, transparent);
    background-image: linear-gradient(145deg, var(--fill-tile), color-mix(in srgb, var(--tint) 12%, var(--fill-tile)));
    animation: v2-bld-design-in 0.6s cubic-bezier(0.34, 1.5, 0.64, 1) var(--design-in) both;
  }

html[data-design="v2"] .design i {
    padding: 1px 6px;
    border-radius: 4px;
    background: color-mix(in srgb, var(--tint) 16%, transparent);
    font-family: var(--font-display);
    font-size: 8px;
    font-style: normal;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--tint);
  }

html[data-design="v2"] .design b {
    font-family: var(--font-display);
    font-size: 13px;
    font-weight: 700;
    color: var(--fg);
  }

html[data-design="v2"] .design em {
    font-family: var(--font-display);
    font-size: 10px;
    font-style: normal;
    color: var(--fg-faint);
  }

/* Beat 4 — the production hub. Same wiring language as the Why Creators
     Switch diagram: three chips a side, a long straight run out of each, a
     rounded 90 degree turn, then into the logo. The geometry is authored into
     the markup rather than measured in JS — this panel is a fixed 840px, so
     there is nothing to recompute. */

html[data-design="v2"] .bld-scene--hub { display: block; }

/* The wiring's resting hairline. It used to carry stroke="#fff" as a
     presentation attribute, which no theme can reach.
     Held at a higher alpha than the old neutral: the accent is a mid-tone, so
     0.2 of it disappears where 0.2 of white or black still registered. */

html[data-design="v2"] [data-wiring-base] {
    stroke: var(--wire-ink);
    stroke-opacity: 0.32;
  }

html[data-design="v2"] .hub-wires {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
  }

/* Authored logo -> chip, so the pulse (which travels from a path's end to
     its start) runs from the chip into the core, as it does in section 3. */

html[data-design="v2"] .hub-wire {
    fill: none;
    stroke: var(--wire-ink);
    stroke-linecap: butt;
    stroke-width: 1.5;
    opacity: 0;
    animation:
      v2-wire-run 1.7s cubic-bezier(0.4, 0, 0.5, 1) var(--wire-delay) infinite,
      v2-wire-glow 1.7s ease-in-out var(--wire-delay) infinite;
  }

html[data-design="v2"] .hub-core {
    position: absolute;
    left: 380px;
    top: 186px;
    z-index: 2;
    translate: -50% -50%;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 96px;
    height: 96px;
    border-radius: 30px;
    border: 1px solid var(--color-hairline);
    background-image: var(--fill-sculpted);
    animation: v2-bld-pop 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) 6.7s both;
  }

html[data-design="v2"] .hub-chip {
    position: absolute;
    z-index: 2;
    translate: 0 -50%;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 12px;
    border-radius: 20px;
    border: 1px solid var(--color-hairline);
    background-image: var(--fill-sculpted);
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 500;
    color: var(--fg);
    white-space: nowrap;
    animation: v2-bld-pop 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) var(--hub-delay) both;
  }

html[data-design="v2"] .hub-chip__icon {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
  }

/* Beat 5 — video ready */

html[data-design="v2"] .ready__pct {
    font-family: var(--font-display);
    font-size: 96px;
    font-weight: 900;
    line-height: 96px;
    color: var(--fg);
    counter-reset: n var(--v2-mix);
    animation: v2-bld-count 1.1s cubic-bezier(0.22, 1, 0.36, 1) 9.7s both;
  }

html[data-design="v2"] .ready__pct::after { content: counter(n) "%"; }

html[data-design="v2"] .ready__title {
    margin-top: 18px;
    font-family: var(--font-display);
    font-size: 22px;
    font-weight: 600;
    color: rgb(var(--accent));
  }

html[data-design="v2"] .ready__note {
    font-family: var(--font-display);
    font-size: 13px;
    color: var(--fg-faint);
  }

/* ── Scene 4: polish with the editor ───────────────────────────────────
     One scene, but not a still one. The playhead crosses the whole timeline
     once per 9s cycle, and twice along the way an edit is applied and
     announced: the overlay slides at 2.5-3.9s, the narration is extended at
     4.3-5.5s. That is 28-43% and 48-61% of the clock. */

html[data-design="v2"] .demo-stage--editor { padding: 0 50px; }

html[data-design="v2"] .editor {
    position: relative;
    width: 100%;
    padding: 14px 16px 16px;
    border-radius: 20px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-panel);
    animation: v2-ed-in 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
  }

html[data-design="v2"] .editor__ruler {
    display: flex;
    justify-content: space-between;
    padding: 0 4px 12px;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--fg-ghost);
  }

html[data-design="v2"] .editor__tracks {
    display: flex;
    flex-direction: column;
    gap: 6px;
  }

html[data-design="v2"] .editor__track {
    position: relative;
    height: 34px;
    border-radius: 10px;
    background: var(--surface-1);
  }

html[data-design="v2"] .demo-clip {
    position: absolute;
    left: var(--x);
    width: var(--w);
    top: 3px;
    bottom: 3px;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 0 8px;
    border-radius: 10px;
    /* One recipe for every clip: a tint at 16% with its own rim at 34%. The
       variants below set nothing but --tint, all of it from the warm ramp in
       @theme, so a new track is one line. */
    --tint: var(--color-flame);
    background-color: color-mix(in srgb, var(--tint) 16%, transparent);
    border: 1px solid color-mix(in srgb, var(--tint) 34%, transparent);
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 500;
    color: var(--fg);
    white-space: nowrap;
    overflow: hidden;
    animation: v2-ed-clip-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
  }

/* the little thumbnail square at the head of a video clip */

/* a 4px bar filled with the brand gradient */

html[data-design="v2"] .demo-clip i {
    width: 22px;
    height: 17px;
    flex-shrink: 0;
    border-radius: 4px;
    border: 1px solid var(--hairline-on-accent);
    background-image: var(--gradient-flame);
  }

html[data-design="v2"] .demo-clip--video { --tint: var(--color-flame); }

/* The clip being edited: white rim marks it as selected, and it is the one
     that slides when the first instruction lands. */

/* The selected clip. Marked with a flame rim, the same way the step tabs
     and the diagram chips mark themselves — a white one belonged to the
     original's palette, not ours. */

html[data-design="v2"] .demo-clip--marker {
    --tint: var(--color-sand);
    border-width: 2px;
    border-color: color-mix(in srgb, var(--color-flame) 75%, transparent);
    font-weight: 700;
    animation:
      v2-ed-clip-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) 0.12s both,
      v2-ed-move var(--demo-cycle) cubic-bezier(0.22, 1, 0.36, 1) infinite;
  }

html[data-design="v2"] .demo-clip--caption {
    --tint: var(--color-apricot);
    animation-delay: 0.2s;
  }

/* Four bars bouncing out of step, so the track reads as sound rather than a
     plain block. Centre-aligned, so a change in height opens the bar equally
     up and down instead of growing off a baseline. Resting height sits
     mid-bounce: inactive panels have their animations stripped, and a flat row
     would look broken. */

html[data-design="v2"] .clip-eq {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    height: 14px;
    flex-shrink: 0;
  }

html[data-design="v2"] .clip-eq b {
    width: 2px;
    height: 8px;
    border-radius: 4px;
    background: currentColor;
    animation: v2-ed-eq 0.9s ease-in-out infinite;
  }

html[data-design="v2"] .clip-eq b:nth-child(1) { animation-delay: 0ms; }

html[data-design="v2"] .clip-eq b:nth-child(2) { animation-delay: 150ms; }

html[data-design="v2"] .clip-eq b:nth-child(3) { animation-delay: 300ms; }

html[data-design="v2"] .clip-eq b:nth-child(4) { animation-delay: 80ms; }

/* Solid, with the waveform as a repeating gradient: on the original every
     bar is the same height, so no per-bar markup is needed. This is the clip
     the second instruction stretches. */

/* The only track that carries a waveform. Kept faint on purpose: it only has
     to hint that the clip is audio, and at any real strength it fights the
     label sitting on top of it. */

html[data-design="v2"] .demo-clip--audio {
    --tint: var(--color-ember);
    background-image: repeating-linear-gradient(
      90deg,
      color-mix(in srgb, var(--color-flame) 12%, transparent) 0 5px,
      transparent 5px 11px
    );
    font-weight: 600;
    animation:
      v2-ed-clip-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) 0.28s both,
      v2-ed-extend var(--demo-cycle) cubic-bezier(0.22, 1, 0.36, 1) infinite;
  }

html[data-design="v2"] .demo-clip--extra {
    --tint: var(--color-flame-deep);
    font-weight: 700;
    animation-delay: 0.36s;
  }

/* Line plus the head that rides on top of it, as in any NLE */

html[data-design="v2"] .editor__playhead {
    position: absolute;
    top: 34px;
    bottom: 14px;
    width: 1px;
    background: var(--fg-muted);
    box-shadow: 0 0 8px var(--fg-subtle);
    animation: v2-ed-playhead var(--demo-cycle) linear infinite;
  }

html[data-design="v2"] .editor__playhead::before {
    content: "";
    position: absolute;
    left: -3px;
    top: -4px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--fg);
  }

/* Neutral, not branded: on the original these read as system notices */

html[data-design="v2"] .editor__toast {
    position: absolute;
    right: 18px;
    top: 10px;
    padding: 3px 11px;
    border-radius: 8px;
    border: 1px solid var(--color-hairline);
    background: var(--surface-2);
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 500;
    color: var(--fg-subtle);
    opacity: 0;
  }

html[data-design="v2"] .editor__toast--move { animation: v2-ed-toast-move var(--demo-cycle) cubic-bezier(0.22, 1, 0.36, 1) infinite; }

html[data-design="v2"] .editor__toast--narr { animation: v2-ed-toast-narr var(--demo-cycle) cubic-bezier(0.22, 1, 0.36, 1) infinite; }

/* The carousel's step buttons, and the carousel's tabs at the same time.
     They used to be .step-chip with their own glass fill at 102deg/10% — a
     third hand-rolled copy of --gradient-glass. Now they are a size on
     .btn--glass, so the fill and the edge come from one place. */

html[data-design="v2"] .btn--chip {
    gap: 4px;
    padding: 8px 20px;
    border-radius: 30px;
    font-family: var(--font-display);
    font-size: 14px;
    line-height: 1.2;
    font-weight: 700;
    cursor: pointer;
    transition: color 0.3s ease, border-color 0.3s ease, background-image 0.3s ease;
  }

html[data-design="v2"] .btn--chip[aria-selected="false"] {
    border-color: var(--color-hairline-dim);
    background-image: var(--gradient-glass-dim);
    color: var(--fg-ghost);
  }

html[data-design="v2"] .btn--chip[aria-selected="false"] img { opacity: 0.3; }

/* Phone: icon only, as on vidnext.ai — four labelled chips will not sit on a
     375px row, and wrapped they cost more height than the panel they index.
     The label stays in the DOM so the tab still announces what it selects.

     The box itself grows to 44 rather than gaining a hit area underneath:
     .btn clips its children, so the pseudo-element the other small controls
     use would be cut back to the chip. Four at 48 plus three 8px gaps is
     216px — still a single row on the narrowest phone. */

@media (width < 64rem) {
    html[data-design="v2"] [role="tablist"] .btn--chip {
      width: 48px;
      height: 44px;
      padding: 0;
      gap: 0;
      justify-content: center;
    }

    html[data-design="v2"] [role="tablist"] .btn--chip .btn__label {
      position: absolute;
      width: 1px;
      height: 1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
    }
  }

html[data-design="v2"] .btn--chip[aria-selected="false"]:hover {
    border-color: var(--color-hairline-strong);
    color: var(--fg-muted);
  }

/* ── Section 5: Testimonials ────────────────────────────────────────────
     Three columns drift vertically; the middle one runs the other way. */

html[data-design="v2"] .quote-card {
    display: flex;
    flex-direction: column;
    gap: 20px;
    padding: 20px;
    background-image: var(--gradient-panel);
    position: relative;
    transition: border-color 0.35s ease;
  }

/* Hover fill. Figma: a radial centred on the top-left corner reaching the
     opposite one, stops at 16% / 77% / 99% with alphas 0 / 50 / 80 per cent.
     The mockup's stops are green and blue — a leftover palette — so the same
     gradient is rebuilt in the brand colours. It rides its own layer rather
     than the card's background, because background-image cannot be
     transitioned and the fill has to fade in. */

html[data-design="v2"] .quote-card::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.35s ease;
    /* Opaque from the first stop. It used to start transparent at the top-left
       corner, which is exactly where the quote sits — white type over the card's
       own white panel, invisible. Moving the origin only moves the pale patch
       onto the name, which is white too; the fix is for there to be no pale
       patch. Direction and character are unchanged: lighter flame at the corner
       the light comes from, deepening to the far one. */
    background-image: radial-gradient(
      farthest-corner at 0% 0%,
      var(--v2-flare-a) 0%,
      var(--v2-flare-b) 55%,
      var(--v2-flame-deep) 100%
    );
  }

/* keeps the quote above the fill, which is a positioned layer */

html[data-design="v2"] .quote-card > * { position: relative; }

html[data-design="v2"] .quote-card:hover { border-color: var(--hairline-on-accent); }

/* The initials sit on the brand surface once hovered, so the disc is white at
     the surface alpha the rest of the page uses rather than its resting grey. */

html[data-design="v2"] .quote-card:hover .quote-card__avatar {
    background: var(--surface-3);
    border-color: var(--hairline-on-accent);
  }

html[data-design="v2"] .quote-card:hover::before { opacity: 1; }

html[data-design="v2"] .quote-card__text {
    font-size: 16px;
    line-height: 24px;
    color: var(--fg-muted);
  }

html[data-design="v2"] .quote-card__rule {
    height: 1px;
    background: var(--surface-2);
  }

html[data-design="v2"] .quote-card__avatar {
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    flex-shrink: 0;
    border-radius: 50%;
    border: 1px solid var(--color-hairline);
    background: var(--fill-avatar);
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 700;
    color: var(--fg);
  }

html[data-design="v2"] .quote-card__metric {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 6px 12px;
    border-radius: 20px;
    border: 1px solid rgba(var(--v2-accent-rgb), 0.25);
    background: rgba(var(--v2-accent-rgb), 0.1);
    font-size: 13px;
    white-space: nowrap;
    color: var(--color-flame);
    transition: color 0.35s ease, border-color 0.35s ease, background-color 0.35s ease;
  }

/* Drawn as a mask over currentColor rather than a coloured image, so the
     arrow follows the pill's text through the hover swap on its own. */

html[data-design="v2"] .quote-card__arrow {
    width: 12px;
    height: 12px;
    flex-shrink: 0;
    background: currentColor;
    -webkit-mask: var(--icon-arrow-ne) center / contain no-repeat;
    mask: var(--icon-arrow-ne) center / contain no-repeat;
  }

/* On the lit card the pill drops the brand tint and goes white at the very
     same alphas — only the hue changes. */

/* On hover the card fills with the brand gradient, so this pill is sitting on
     the accent even though its own fill is a translucent white. Its ink, edge
     and fill are all pinned light — --fg and --surface-* follow the page, and in
     the light theme that put black text on an orange card. */

html[data-design="v2"] .quote-card:hover .quote-card__metric {
    color: var(--fg-on-accent);
    border-color: var(--hairline-on-accent);
    background: rgba(255, 255, 255, 0.1);
  }

/* ── Section 6: Use Cases ───────────────────────────────────────────────
     Only the first niche carries copy in the design, so the list switches the
     active state and the preview stays put until per-niche content exists. */

/* Sphere of brand light behind the preview. Figma: 550px circle, fill
     VidNext_Title, layer blur 400, opacity 50 — and Figma's blur sigma runs
     about 4x the CSS one, so 400 lands on blur(100px). It replaces a baked PNG
     export: same shape, no asset, sharp at any density. */

html[data-design="v2"] .case-glow {
    position: absolute;
    right: -180px;
    bottom: -180px;
    width: 550px;
    height: 550px;
    rotate: -90deg;
    border-radius: 50%;
    background-image: var(--gradient-flame);
    filter: blur(100px);
    opacity: 0.5;
    pointer-events: none;
  }

html[data-design="v2"] .niche {
    position: relative;
    display: flex;
    align-items: center;
    gap: 24px;
    width: 100%;
    text-align: left;
    color: var(--fg-ghost);
    transition: color 0.3s ease;
  }

html[data-design="v2"] .niche__num {
    font-family: var(--font-display);
    font-size: 36px;
    line-height: 36px;
    font-weight: 700;
    flex-shrink: 0;
  }

html[data-design="v2"] .niche__label {
    font-family: var(--font-display);
    font-size: 20px;
    line-height: 20px;
  }

html[data-design="v2"] .niche:hover { color: var(--fg-subtle); }

html[data-design="v2"] .niche[aria-current="true"] { color: var(--fg); }

/* Marker for the niche you are on. Drawn in SVG — a 33x23 tag with a rounded
     left end and a point on the right, filled with the brand radial — because
     it straddles the card's left edge, and the card clips its own content: as
     a child it would be sliced in half. It is
     positioned by initNiches() against the live row and card rects.

     Figma reports 23 x 32.64 with a 90 degree rotation, and those figures are
     the unrotated ones — on screen the pill lies down at 33 x 23. The viewBox
     is padded 30 all round so the blurred copy underneath has room — the blur
     carries about 3 sigma, and sigma is 6 — and the filter region and mask are
     wider still. The rect stays centred in it, so centring the box centres the
     pill. */

html[data-design="v2"] .niche-mark {
    position: absolute;
    left: 0;
    top: 0;
    z-index: 2;
    width: 93px;
    height: 83px;
    translate: -50% -50%;
    opacity: 0;
    pointer-events: none;
    transition: top 0.35s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.3s ease;
  }

html[data-design="v2"] .niche-mark.is-placed { opacity: 1; }

/* The blurred copy under the shape is a glow. On a near-white page there is no
     light to add, so it spreads as a brown smear instead — dropped, and the
     shape gets a coloured shadow to sit on rather than a halo to sit in. */

html[data-design="v2"][data-theme="light"] .niche-mark g[mask] { display: none; }

html[data-design="v2"][data-theme="light"] .niche-mark svg {
    filter: drop-shadow(0 3px 8px rgba(var(--v2-accent-rgb), 0.4));
  }

html[data-design="v2"] .niche-mark svg {
    width: 100%;
    height: 100%;
    display: block;
    /* svg clips to its viewport by default, which would slice the halo */
    overflow: visible;
  }

/* Floating chip over the preview still */

/* Floats over the preview image, so it stays light glass in either theme —
     --gradient-glass is deliberately not themed for exactly this. */

html[data-design="v2"] .preview-chip {
    position: absolute;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 15px 20px;
    border-radius: 20px;
    border: 1px solid var(--hairline-on-accent);
    background-image: var(--gradient-glass);
    backdrop-filter: blur(6px);
    font-size: 20px;
    line-height: 19.2px;
    color: var(--fg-on-accent);
    white-space: nowrap;
  }

/* The chip that is actually a button. Its resting colours live here rather
     than as background and border utilities in the markup: utilities outrank
     the components layer, and the hover and copied states could never
     override them. */

html[data-design="v2"] .preview-chip--action {
    cursor: pointer;
    border-color: var(--hairline-on-accent);
    /* The same white glass as the prompt line beside it, not an orange fill —
       all three chips sit on the photograph and read as one family. */
    background-color: rgba(255, 255, 255, 0.14);
    transition: background-color 0.25s ease, border-color 0.25s ease, scale 0.25s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .preview-chip--action:hover {
    scale: 1.04;
    border-color: var(--hairline-on-accent);
    background-color: rgba(255, 255, 255, 0.26);
  }

html[data-design="v2"] .preview-chip--action:active { scale: 0.98; }

/* Phone: the still is about 300px wide, and three chips laid across it at
     desktop metrics covered the picture they sit on.
       - the prompt line goes: it is the longest of the three and the copy
         button carries the same text to the clipboard anyway
       - watch keeps its glyph and drops its label
       - copy halves and moves into the corner on a fixed inset, because a
         percentage offset drifts as the still changes aspect */

@media (width < 64rem) {
    /* the whole chip, not just its text — hiding the label alone left the
       glyph sitting on the still with nothing beside it */
    html[data-design="v2"] .preview-chip--prompt { display: none; }

    html[data-design="v2"] [data-watch] .chip-label { display: none; }

    html[data-design="v2"] [data-watch].preview-chip {
      gap: 0;
      padding: 12px;
      border-radius: 999px;
    }

    html[data-design="v2"] [data-watch] .copy-face svg {
      width: 22px;
      height: 22px;
    }

    html[data-design="v2"] .chip-corner.preview-chip {
      gap: 5px;
      padding: 7px 10px;
      border-radius: 10px;
      font-size: 11px;
      line-height: 1.2;
    }

    html[data-design="v2"] .chip-corner .copy-face svg {
      width: 13px;
      height: 13px;
    }

    /* The niche list is the card's whole left column on a phone */
    html[data-design="v2"] .niche { gap: 12px; }
    html[data-design="v2"] .niche__num { font-size: 22px; line-height: 22px; }
    html[data-design="v2"] .niche__label { font-size: 14px; line-height: 17px; }
  }

/* Each state is a whole face — its own icon and label — and both live in one
     grid cell. The wider face sets the button's width, so it never resizes,
     and each face centres itself rather than the label drifting inside a slot
     sized for the other one. */

html[data-design="v2"] .preview-chip--action {
    display: grid;
    place-items: center;
  }

html[data-design="v2"] .copy-face {
    grid-area: 1 / 1;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    white-space: nowrap;
    transition: opacity 0.2s ease;
  }

html[data-design="v2"] .copy-face[data-copy-done] { opacity: 0; }

html[data-design="v2"] .is-copied .copy-face:not([data-copy-done]) { opacity: 0; }

html[data-design="v2"] .is-copied .copy-face[data-copy-done] { opacity: 1; }

/* Confirmation lives inside the button, so nothing shifts around it */

html[data-design="v2"] .preview-chip--action.is-copied {
    border-color: var(--hairline-on-accent);
    background-color: rgba(255, 255, 255, 0.26);
  }

/* ── Section 8: FAQ ─────────────────────────────────────────────────────
     The answer opens on grid-template-rows 0fr -> 1fr rather than a measured
     max-height: the row resolves to the content's own height, so nothing has
     to be measured and long answers cannot be clipped. */

/* Closed: nothing but a hairline, exactly as in the macket — white at 20%,
     inside, 1px. Open: a dark panel ringed by the brand gradient. The ring is
     two background layers rather than an extra element — the panel is clipped
     to the padding box, the gradient to the border box, so the 1px the border
     leaves transparent shows the gradient through. */

html[data-design="v2"] .faq-item {
    transition: border-color 0.3s ease, box-shadow 0.3s ease;
  }

html[data-design="v2"] .faq-item.is-open {
    border-color: transparent;
    background-image: var(--gradient-panel), var(--gradient-flame);
    background-origin: border-box;
    background-clip: padding-box, border-box;
    box-shadow: 0 0 40px rgba(var(--v2-accent-rgb), 0.12);
  }

html[data-design="v2"] .faq-item__q {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    width: 100%;
    padding: 18px 22px;
    text-align: left;
    cursor: pointer;
    font-family: var(--font-display);
    font-size: 16px;
    font-weight: 700;
    color: var(--fg);
  }

/* Chevron drawn from two borders, so it needs no asset and turns with the
     item rather than swapping between two icons. */

/* Was two borders on an empty span, turned 45 degrees to make a corner —
     drawn in white, so the light theme had nothing to show. A real glyph now,
     which also means it takes the theme's ink like every other icon. */

html[data-design="v2"] .faq-item__chevron {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    color: var(--fg-muted);
    transition: rotate 0.3s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .faq-item.is-open .faq-item__chevron { rotate: 180deg; }

html[data-design="v2"] .faq-item__a {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.35s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .faq-item.is-open .faq-item__a { grid-template-rows: 1fr; }

html[data-design="v2"] .faq-item__a > p {
    overflow: hidden;
    padding-inline: 22px;
    font-family: var(--font-display);
    font-size: 15px;
    line-height: 22px;
    font-weight: 400;
    color: var(--fg-muted);
  }

/* The padding has to collapse with the row, or a closed item keeps its gap */

html[data-design="v2"] .faq-item.is-open .faq-item__a > p { padding-bottom: 20px; }

/* ── Section 10: blog ─────────────────────────────────────────────────── */

html[data-design="v2"] .post {
    display: flex;
    flex-direction: column;
    gap: 16px;
  }

html[data-design="v2"] .post__art {
    position: relative;
    display: block;
    aspect-ratio: 310 / 240;
    overflow: hidden;
    border-radius: 20px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-panel);
  }

/* The thumbnails are 760x600 while the card is a touch wider than that
     ratio, so they are cropped rather than squashed. */

html[data-design="v2"] .post__art img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: scale 0.5s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .post__art:hover img { scale: 1.04; }

html[data-design="v2"] .post__date {
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: var(--font-display);
    font-size: 14px;
    color: var(--fg-subtle);
  }

html[data-design="v2"] .post__title {
    font-family: var(--font-display);
    font-size: var(--text-h6);
    font-weight: 500;
    line-height: 24px;
    color: var(--fg);
  }

html[data-design="v2"] .post__title a { transition: color 0.25s ease; }

html[data-design="v2"] .post__title a:hover { color: rgb(var(--accent, var(--v2-accent-rgb))); }

html[data-design="v2"] .post__more {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding-top: 16px;
    border-top: 1px solid var(--color-hairline);
    font-family: var(--font-display);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--fg);
  }

html[data-design="v2"] .post__more span { transition: translate 0.25s cubic-bezier(0.22, 1, 0.36, 1); }

html[data-design="v2"] .post__more:hover span { translate: 4px 0; }

/* ── Section 9: bottom CTA ──────────────────────────────────────────────
     Built after the CTA on setrex-saas-template.webflow.io/home-02: a drifting
     star field, the copy centred over it, and the product frame cropped by the
     bottom edge. */

html[data-design="v2"] .cta-band {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    overflow: hidden;
    padding-top: 118px;
  }

/* The reference runs this as a Lottie holding two copies of one 2880x1220
     bitmap, halved to 1440x610, stacked a tile apart and scrolled up by exactly
     one tile per 8.017s — a wrap, nothing more. A repeating background is the
     same picture with no player and no JSON. The tile is generated seamlessly
     on both axes, so the wrap has no seam to hide.
     Faded out at the bottom: the frame below needs a clean field to sit on. */

html[data-design="v2"] .cta-band__stars {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image: var(--cta-stars);
    background-repeat: repeat;
    background-size: 1440px 610px;
    animation: v2-cta-stars 8.02s linear infinite;
    --cta-stars-mask: linear-gradient(
      to bottom,
      rgba(0, 0, 0, 1) 0%,
      rgba(0, 0, 0, 1) 55%,
      rgba(0, 0, 0, 0) 92%
    );
    mask-image: var(--cta-stars-mask);
    -webkit-mask-image: var(--cta-stars-mask);
  }

@keyframes v2-cta-stars {
    from { background-position: 0 0; }
    to   { background-position: 0 -610px; }
  }

html[data-design="v2"] .cta-band__points {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 12px 34px;
    margin-top: 46px;
    font-family: var(--font-display);
    font-size: 15px;
    color: var(--fg-muted);
  }

html[data-design="v2"] .cta-band__points li {
    display: flex;
    align-items: center;
    gap: 10px;
  }

/* Phone: the three points wrapped 2+1 and the odd one sat alone under the
     pair. Tightened until they hold one row at 375. */

@media (width < 64rem) {
    html[data-design="v2"] .cta-band__points {
      gap: 8px 14px;
      margin-top: 32px;
      font-size: 12px;
      white-space: nowrap;
    }

    html[data-design="v2"] .cta-band__points li { gap: 6px; }
  }

html[data-design="v2"] .cta-band__dot {
    width: 8px;
    height: 8px;
    flex-shrink: 0;
    border-radius: 50%;
    background-image: var(--gradient-flame);
  }

/* Crops rather than scales, so the frame runs off the bottom of the section
     instead of shrinking to fit it. The bottom is masked away rather than
     covered by a matching gradient: an opaque band would also hide the section's
     own glow, and it would need repainting every time the background changes. */

html[data-design="v2"] .cta-band__frame {
    position: relative;
    z-index: 3;
    width: 100%;
    max-width: 1148px;
    /* Deep enough to keep the empty state's icon and button in frame — the crop
       has to stop below them, not through them. The reference runs 480. */
    height: 470px;
    margin-top: 72px;
    padding: 0 24px;
    overflow: hidden;
    --cta-frame-mask: linear-gradient(
      to bottom,
      rgba(0, 0, 0, 1) 0%,
      rgba(0, 0, 0, 1) 48%,
      rgba(0, 0, 0, 0) 100%
    );
    mask-image: var(--cta-frame-mask);
    -webkit-mask-image: var(--cta-frame-mask);
  }

html[data-design="v2"] .cta-band__frame img,
  html[data-design="v2"] .cta-band__frame .cta-band__frame-art {
    display: block;
    width: 100%;
    height: auto;
  }

/* Declared after .cta-band__frame, not in the media block further up: same
     specificity, so the later rule is the one that counts.

     The frame crops to a fixed 470px so the artwork bleeds off the section's
     bottom edge. On a phone that art is only 185px tall, leaving 285px of
     nothing and a crop that never reached the edge it is meant to run into. */

@media (width < 64rem) {
    html[data-design="v2"] .cta-band__frame {
      height: auto;
      margin-top: 40px;
    }
  }

/* Inlined rather than linked so its shapes can read currentColor: the frame is
     drawn in one ink at a dozen alphas, and a file behind <img> can never see
     the page's colour. The brand gradient inside it stays as it is. */

html[data-design="v2"] .cta-band__frame-art { color: var(--fg); }

/* ── Section 11: footer ─────────────────────────────────────────────────
     The wordmark is bled off the bottom edge and clipped by the footer, so it
     reads as the page running out rather than as a cropped graphic. */

html[data-design="v2"] .site-footer {
    position: relative;
    overflow: hidden;
    background-image: var(--fill-footer);
  }

/* At 21vw the wordmark is 79px on a phone — too small to read as the giant
     bleed it is on desktop, and it collided with the copyright row. Dropped
     there, along with the padding that was reserved for it. */

@media (width < 64rem) {
    html[data-design="v2"] .footer-word { display: none; }
  }

html[data-design="v2"] .footer-word {
    position: absolute;
    left: 50%;
    bottom: -0.22em;
    translate: -50% 0;
    z-index: 0;
    font-family: var(--font-display);
    font-size: clamp(120px, 21vw, 268px);
    font-weight: 700;
    line-height: 1;
    white-space: nowrap;
    pointer-events: none;
    background-image: var(--gradient-flame);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    opacity: 0.45;
  }

html[data-design="v2"] .footer-col {
    display: flex;
    flex-direction: column;
    gap: 14px;
    font-family: var(--font-display);
    font-size: 15px;
  }

html[data-design="v2"] .footer-col__title {
    margin-bottom: 4px;
    font-size: 18px;
    font-weight: 700;
    color: var(--fg);
  }

html[data-design="v2"] .footer-col a {
    color: var(--fg-subtle);
    transition: color 0.25s ease;
    width: fit-content;
  }

html[data-design="v2"] .footer-col a:hover { color: var(--fg); }

html[data-design="v2"] .footer-social {
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    border: 1px solid var(--color-hairline);
    color: var(--fg-subtle);
    transition: color 0.25s ease, border-color 0.25s ease, background-color 0.25s ease;
  }

html[data-design="v2"] .footer-social svg { width: 17px; height: 17px; }

html[data-design="v2"] .footer-social:hover {
    color: var(--fg);
    border-color: rgba(var(--v2-accent-rgb), 0.5);
    background: rgba(var(--v2-accent-rgb), 0.12);
  }

/* Field and button are two separate rounded blocks with a gap, not one shell
     with the button tucked inside. */

/* One pill holding the field and a chevron, at the donor's geometry: 278x44
     outside, 8px of padding, a 100px radius, a 24px glyph. The field carries no
     box of its own — the pill is the control. */

html[data-design="v2"] .subscribe {
    position: relative;
    display: flex;
    align-items: center;
    width: 100%;
    max-width: 278px;
    height: 44px;
    margin-top: 14px;
    /* No padding above or below: the field is the only thing a thumb aims at
       here, and at 26px it left 9px of dead border on each side of itself. */
    padding: 0 8px;
    border: 1px solid var(--color-hairline);
    border-radius: 20px;
    transition: border-color 0.25s ease;
  }

/* The fill: a white diagonal wash with a dark radial pressed into the middle,
     the pair dropped to 16%. Left as two gradients on one layer rather than
     folded into flat colours — the opacity is what makes it read as a film. */

html[data-design="v2"] .subscribe::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    opacity: 0.16;
    background-color: rgba(0, 0, 0, 0.99);
    background-image:
      radial-gradient(65.6% 65.6% at 50% 50%, rgba(0, 0, 0, 0.32) 0%, rgba(0, 0, 0, 0) 100%),
      linear-gradient(350deg, rgb(255, 255, 255) 0%, rgba(255, 255, 255, 0.32) 100%);
  }

html[data-design="v2"] .subscribe:focus-within { border-color: var(--color-hairline-strong); }

html[data-design="v2"] .subscribe input {
    position: relative;
    flex: 1;
    min-width: 0;
    height: 100%;
    padding: 0 12px;
    border: 0;
    background: transparent;
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 500;
    letter-spacing: -0.15px;
    color: var(--fg);
    outline: none;
  }

html[data-design="v2"] .subscribe input::placeholder { color: var(--fg-subtle); }

html[data-design="v2"] .subscribe__go {
    position: relative;
    flex-shrink: 0;
    display: grid;
    place-items: center;
    width: 30px;
    height: 24px;
    color: var(--color-flame);
    cursor: pointer;
    transition: translate 0.25s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .subscribe__go svg { width: 24px; height: 24px; }

html[data-design="v2"] .subscribe__go:hover { translate: 2px 0; }

/* ── Cookie preferences ─────────────────────────────────────────────────
     The language menu's glass, used as a modal: light panel, dark text. Its
     own displacement filter — a map is stretched to the element it filters,
     and this panel is nothing like the dropdown's shape. */

html[data-design="v2"] .cookie-modal {
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.28s ease, visibility 0.28s;
  }

html[data-design="v2"] .cookie-modal.is-open {
    opacity: 1;
    visibility: visible;
  }

/* Compound on purpose: .glass-panel is declared further down the sheet and
     would otherwise win position, radius and the filter on equal specificity. */

html[data-design="v2"] .cookie-panel.glass-panel {
    position: relative;
    width: 100%;
    max-width: 470px;
    max-height: 100%;
    overflow-y: auto;
    padding: 22px;
    border-radius: 20px;
    /* The navbar's numbers. A heavier blur would read as "more glass" but the
       gaussian runs after the channels are displaced, so it averages the
       colour split straight back into grey. */
    backdrop-filter: url("#cookie-liquid-glass") blur(7px) saturate(140%);
    -webkit-backdrop-filter: blur(7px) saturate(140%);
    transform: scale(0.97);
    transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .cookie-modal.is-open .cookie-panel { transform: none; }

/* Its own veil, compounded so it beats .nav-backdrop no matter which is
     declared first. The shared one is tuned to hide the page behind a dropdown;
     this panel is built to refract what is behind it, and a near-uniform dark
     wash gives the displacement nothing to bend. */

html[data-design="v2"] [data-cookie-backdrop].nav-backdrop { background: rgba(10, 10, 10, 0.42); }

html[data-design="v2"] [data-cookie-backdrop].nav-backdrop.is-open {
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }

/* The search palette frosts harder than the cookie modal: that one is a
     decision about the page you were reading, this one replaces it — the page
     behind should stop competing for attention entirely. */

html[data-design="v2"] [data-docs-dialog-backdrop].nav-backdrop { background: rgba(10, 10, 10, 0.55); }

html[data-design="v2"] [data-docs-dialog-backdrop].nav-backdrop.is-open {
    backdrop-filter: blur(14px) saturate(120%);
    -webkit-backdrop-filter: blur(14px) saturate(120%);
  }

html[data-design="v2"] .cookie-panel__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
  }

html[data-design="v2"] .cookie-x {
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    font-size: 22px;
    line-height: 1;
    color: var(--fg-on-light-muted);
    cursor: pointer;
    transition: background-color 0.2s ease, color 0.2s ease;
  }

html[data-design="v2"] .cookie-x:hover {
    background: rgba(0, 0, 0, 0.06);
    color: var(--fg-on-light);
  }

html[data-design="v2"] .cookie-panel__title {
    font-family: var(--font-display);
    font-size: 22px;
    font-weight: 700;
    color: var(--fg-on-light);
  }

html[data-design="v2"] .cookie-panel__lede {
    margin: 8px 0 18px;
    font-family: var(--font-display);
    font-size: 14px;
    line-height: 21px;
    color: var(--fg-on-light-muted);
  }

html[data-design="v2"] .cookie-group {
    margin-bottom: 10px;
    padding: 14px 16px;
    border-radius: 10px;
    border: 1px solid rgba(0, 0, 0, 0.07);
    background: rgba(255, 255, 255, 0.45);
  }

html[data-design="v2"] .cookie-group__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
  }

html[data-design="v2"] .cookie-group__name {
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 700;
    color: var(--fg-on-light);
  }

html[data-design="v2"] .cookie-group__name span { font-weight: 400; color: var(--fg-on-light-muted); }

html[data-design="v2"] .cookie-group__text {
    margin-top: 6px;
    font-family: var(--font-display);
    font-size: 13px;
    line-height: 19px;
    color: var(--fg-on-light-muted);
  }

html[data-design="v2"] .cookie-always {
    flex-shrink: 0;
    padding: 4px 12px;
    border-radius: 20px;
    background: rgba(var(--v2-accent-rgb), 0.14);
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 600;
    color: var(--color-flame-deep);
  }

html[data-design="v2"] .cookie-receipt b {
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--color-flame-deep);
  }

/* Switch built off the checkbox itself, so it stays keyboard-reachable and
     carries its own state without a script. */

html[data-design="v2"] .cookie-switch {
    position: relative;
    flex-shrink: 0;
    width: 44px;
    height: 25px;
    cursor: pointer;
  }

html[data-design="v2"] .cookie-switch input {
    position: absolute;
    inset: 0;
    opacity: 0;
    margin: 0;
    cursor: pointer;
  }

html[data-design="v2"] .cookie-switch > span[aria-hidden] {
    position: absolute;
    inset: 0;
    border-radius: 20px;
    background: rgba(0, 0, 0, 0.22);
    transition: background-color 0.25s ease;
    pointer-events: none;
  }

html[data-design="v2"] .cookie-switch > span[aria-hidden]::after {
    content: "";
    position: absolute;
    left: 3px;
    top: 3px;
    width: 19px;
    height: 19px;
    border-radius: 50%;
    background: var(--knob-on-light);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
    transition: translate 0.25s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .cookie-switch input:checked + span[aria-hidden] { background-image: var(--gradient-flame); }

html[data-design="v2"] .cookie-switch input:checked + span[aria-hidden]::after { translate: 19px 0; }

html[data-design="v2"] .cookie-switch input:focus-visible + span[aria-hidden] { outline: 2px solid var(--color-flame); outline-offset: 2px; }

html[data-design="v2"] .cookie-panel__note {
    margin: 14px 0 18px;
    font-family: var(--font-display);
    font-size: 12px;
    line-height: 18px;
    color: var(--fg-on-light-muted);
  }

/* Near-black rather than the brand colour: the panel is light glass, and the
     deep red sat too close to the body text in weight without reading as a
     link. White would disappear here entirely. */

html[data-design="v2"] .cookie-panel__note a {
    color: var(--fg-on-light);
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
  }

html[data-design="v2"] .cookie-panel__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    justify-content: center;
  }

/* A slab that sits above the panel rather than being cut into it. The shadow
     is a ladder: a hairline ring draws the edge, then four shadows of growing
     radius and falling opacity carry the distance. One big soft shadow cannot
     do both jobs — it either smudges the edge or stops short of the drop.

     The four inset layers are the same recipe re-keyed for a light surface.
     The donor models a black slab, where white at 0.12 already reads; here the
     highlights have to climb near opaque to register, and the bottom glow flips
     to shade — white cannot model white. Radius is left to .btn. */

html[data-design="v2"] .cookie-btn {
    flex: 1;
    min-width: 128px;
    padding: 12px 16px;
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 700;
    color: var(--fg-on-light);
    background-color: var(--fill-on-light);
    border-color: var(--hairline-on-light);
    box-shadow:
      0 0 0 0.75px rgba(0, 0, 0, 0.56),
      0 3px 6px rgba(0, 0, 0, 0.19),
      0 10px 10px rgba(0, 0, 0, 0.12),
      0 23px 14px rgba(0, 0, 0, 0.08),
      0 40px 24px rgba(0, 0, 0, 0.06),
      inset 0 0.5px 0.5px rgba(255, 255, 255, 0.95),
      inset 0 1.5px 0.5px rgba(255, 255, 255, 0.55),
      inset 0 6px 18px rgba(255, 255, 255, 0.6),
      inset 0 -12px 16px rgba(0, 0, 0, 0.05);
    transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1),
                box-shadow 0.25s cubic-bezier(0.22, 1, 0.36, 1),
                background-color 0.25s ease;
  }

html[data-design="v2"] .cookie-btn:hover {
    background-color: rgba(255, 255, 255, 0.72);
    box-shadow:
      0 0 0 0.75px rgba(0, 0, 0, 0.56),
      0 4px 8px rgba(0, 0, 0, 0.21),
      0 12px 12px rgba(0, 0, 0, 0.14),
      0 27px 16px rgba(0, 0, 0, 0.09),
      0 46px 28px rgba(0, 0, 0, 0.07),
      inset 0 0.5px 0.5px rgba(255, 255, 255, 1),
      inset 0 1.5px 0.5px rgba(255, 255, 255, 0.7),
      inset 0 6px 18px rgba(255, 255, 255, 0.75),
      inset 0 -12px 16px rgba(0, 0, 0, 0.06);
  }

/* Video lightbox. Nothing here fights the backdrop — that is .nav-backdrop,
     shared with the navbar's dropdowns, so the page frosts identically. */

html[data-design="v2"] .video-player {
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.28s ease, visibility 0.28s;
  }

html[data-design="v2"] .video-player.is-open {
    opacity: 1;
    visibility: visible;
  }

html[data-design="v2"] .video-player__stage {
    transform: scale(0.97);
    transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .video-player.is-open .video-player__stage { transform: none; }

html[data-design="v2"] .video-player__close {
    position: absolute;
    right: -6px;
    top: -46px;
    display: grid;
    place-items: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: 1px solid var(--color-hairline);
    background: var(--surface-2);
    font-family: var(--font-display);
    font-size: 22px;
    line-height: 1;
    color: var(--fg);
    cursor: pointer;
    transition: background-color 0.25s ease, border-color 0.25s ease;
  }

html[data-design="v2"] .video-player__close:hover {
    border-color: var(--color-hairline-strong);
    background: var(--surface-3);
  }

/* ── Section 7: comparison table ─────────────────────────────────────────
     The "no" marker is a recessed grey disc in the design, not a plain icon. */

html[data-design="v2"] .mark-no {
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    flex-shrink: 0;
    border-radius: 10px;
    background-image: radial-gradient(
      120% 120% at 100% 100%,
      rgba(75, 75, 74, 0.6) 16%,
      rgba(96, 96, 96, 0.6) 67%
    );
  }

/* ── Section 2: Build-For-Creators ──────────────────────────────────────
     Both the fill and the bottom rule are gradients in the design:
       fill    white 100% -> 0% top to bottom, layer opacity 30%
       stroke  1px inside, bottom only, transparent -> white -> transparent
               left to right, layer opacity 75%
     A gradient rule cannot be a border, so it is drawn by ::after. */

/* Shared section footing: a dome of light rising off the bottom edge, closed
     by a hairline that fades out to both sides.
     Figma: Radial fill at 10%, Inside stroke 1px with white 0/100/0 stops.
     The fill sits behind --section-fill so a section can swap it and still
     keep the rule. */

html[data-design="v2"] .section-edge {
    position: relative;
    background-image: var(
      --section-fill,
      radial-gradient(
        50% 50% at 50% 100%,
        rgba(var(--edge-ink), var(--edge-glow)) 0%,
        rgba(var(--edge-ink), 0) 100%
      )
    );
  }

/* A section framed on both sides carries the rule top and bottom, and the
     dome is mirrored to match. --section-fill takes both radials at once. */

html[data-design="v2"] .section-edge--both {
    --section-fill:
      radial-gradient(
        50% 50% at 50% 0%,
        rgba(var(--edge-ink), var(--edge-glow)) 0%,
        rgba(var(--edge-ink), 0) 100%
      ),
      radial-gradient(
        50% 50% at 50% 100%,
        rgba(var(--edge-ink), var(--edge-glow)) 0%,
        rgba(var(--edge-ink), 0) 100%
      );
  }

html[data-design="v2"] .section-edge--both::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 1px;
    pointer-events: none;
    background-image: linear-gradient(
      90deg,
      rgba(var(--edge-ink), 0) 0%,
      rgba(var(--edge-ink), var(--section-rule, 1)) 50%,
      rgba(var(--edge-ink), 0) 100%
    );
  }

html[data-design="v2"] .section-edge::after {
    content: "";
    position: absolute;
    inset: auto 0 0 0;
    height: 1px;
    pointer-events: none;
    background-image: linear-gradient(
      90deg,
      rgba(var(--edge-ink), 0) 0%,
      rgba(var(--edge-ink), var(--section-rule, 1)) 50%,
      rgba(var(--edge-ink), 0) 100%
    );
  }

/* Section 2 keeps its own footing: the fill is linear from the bottom rather
     than a dome, and the rule is turned down. Both ride --edge-ink now, so the
     section follows the theme with the rest of them. */

/* On light the edge is drawn the way groilot draws its buttons: a plain band
     of shade hugging the boundary, not a dome. Two reasons the dome does not
     translate. It is radial, so it gathers into a smudge in the middle of a
     1440px section, where a shadow is even across the width. And it is a glow
     inverted — on a white page there is no light to add, so the same shape has
     to become shade, and shade reads as a shadow or as nothing.

     The falloff follows their two-layer recipe: dense against the edge, then a
     long faint tail. The hairline above it plays the part of their contact
     shadow. */

html[data-design="v2"][data-theme="light"] .section-edge {
    background-image: linear-gradient(
      to top,
      rgba(4, 12, 19, 0.05) 0,
      rgba(4, 12, 19, 0.018) 14px,
      rgba(4, 12, 19, 0) 56px
    );
  }

html[data-design="v2"][data-theme="light"] .section-edge--both {
    background-image:
      linear-gradient(
        to bottom,
        rgba(4, 12, 19, 0.05) 0,
        rgba(4, 12, 19, 0.018) 14px,
        rgba(4, 12, 19, 0) 56px
      ),
      linear-gradient(
        to top,
        rgba(4, 12, 19, 0.05) 0,
        rgba(4, 12, 19, 0.018) 14px,
        rgba(4, 12, 19, 0) 56px
      );
  }

html[data-design="v2"] .creators-band {
    position: relative;
    background-image: linear-gradient(
      0deg,
      rgba(var(--edge-ink), calc(var(--edge-glow) * 3)) 0%,
      rgba(var(--edge-ink), 0) 40%
    );
  }

/* Ink mask over the whole band, not just the strip: it is what darkens the
     left and right edges of the band itself, and it clears in the middle so
     the heading and the logos read. */

html[data-design="v2"] .creators-band__mask {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image: linear-gradient(
      90deg,
      var(--color-ink) 20%,
      transparent 48%,
      transparent 52%,
      var(--color-ink) 80%
    );
  }

html[data-design="v2"] .creators-band::after {
    content: "";
    position: absolute;
    inset: auto 0 0 0;
    height: 1px;
    pointer-events: none;
    background-image: linear-gradient(
      90deg,
      rgba(var(--edge-ink), 0) 0%,
      rgba(var(--edge-ink), 0.75) 50%,
      rgba(var(--edge-ink), 0) 100%
    );
  }

/* Those stops are a share of the band's width, so the same gradient that
     vignettes a 1200px band leaves only 4% of a 375px one clear — the heading
     and the logos were being eaten from both ends. Pushed out to a 64% window,
     and the bottom glow eased off with it. */

@media (width < 64rem) {
    html[data-design="v2"] .creators-band__mask {
      background-image: linear-gradient(
        90deg,
        var(--color-ink) 0%,
        transparent 18%,
        transparent 82%,
        var(--color-ink) 100%
      );
    }

    html[data-design="v2"] .creators-band {
      background-image: linear-gradient(
        0deg,
        rgba(var(--edge-ink), calc(var(--edge-glow) * 1.8)) 0%,
        rgba(var(--edge-ink), 0) 40%
      );
    }
  }

/* ── Sticky navbar ───────────────────────────────────────────────────────
     Transparent and full width at the top of the page; once scrolled it pulls
     in to a glass pill. The refraction comes from an SVG displacement filter
     fed into backdrop-filter — a plain blur only frosts, it does not bend what
     is behind. Chromium honours the url() reference; Safari and Firefox ignore
     it and fall back to blur + saturate, which still reads as glass. */

/* The bar is chrome, and on a phone chrome competes with the page for a
     screen that is 812px tall, not 900+. At 26px block padding and a 70px mark
     it stood 124px tall — with the promo strip above it, 28% of the viewport
     was gone before the headline started.

     The phone metrics are open-design.ai's, measured: 16px block padding
     around a 38px row, 14px side padding, a 34px mark. */

html[data-design="v2"] .site-nav {
    position: fixed;
    left: 0;
    right: 0;
    top: var(--nav-rest-top, 0px);
    z-index: 50;
    padding-block: 16px;
    transition: top 0.42s cubic-bezier(0.22, 0.61, 0.36, 1),
                padding 0.42s cubic-bezier(0.22, 0.61, 0.36, 1);
  }

/* A 38px control is under the 44px a fingertip wants. Rather than inflate
     the box and lose the reference's proportions, the target grows beneath
     it: 38 + 4 on every side = 46, invisible and inside the button so every
     hit still lands on the control itself. */

html[data-design="v2"] .tap-target {
    position: relative;
  }

/* Sized rather than inset by -4: an absolutely positioned child resolves
     against the padding box, so on the two bordered controls a symmetric inset
     landed at 44 while the borderless one reached 46. A centred minimum is the
     same on all three, and width/height at 100% keep it from ever being
     narrower than the control it belongs to. */

/* The same target, granted to controls the design draws small: a niche row is
     22px of text, a carousel arrow 32px, the subscribe arrow 30x24. They carry
     it from here rather than from a class in the markup because each is one of
     a set — seven rows, two arrows — and the reason is the control, not the
     page it sits on. Every one of them is already positioned and none clips its
     children, so the pseudo-element can overhang. */

html[data-design="v2"] .tap-target::before,
  html[data-design="v2"] .niche::before,
  html[data-design="v2"] .works-arrow::before,
  html[data-design="v2"] .subscribe__go::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    translate: -50% -50%;
    width: 100%;
    height: 100%;
    min-width: 46px;
    min-height: 46px;
  }

@media (width >= 64rem) {
    html[data-design="v2"] .tap-target::before,
    html[data-design="v2"] .niche::before,
    html[data-design="v2"] .works-arrow::before,
    html[data-design="v2"] .subscribe__go::before { content: none; }
  }

@media (width >= 64rem) {
    html[data-design="v2"] .site-nav { padding-block: 26px; }
  }

/* 24 = the button's 10px radius plus the bar's 14px padding, so the outer and
     inner curves stay concentric instead of fighting each other. Change the
     padding and this has to move with it. */

html[data-design="v2"] .site-nav > nav {
    border: 1px solid transparent;
    border-radius: 20px;
    transition: max-width 0.42s cubic-bezier(0.22, 0.61, 0.36, 1),
                padding 0.42s cubic-bezier(0.22, 0.61, 0.36, 1),
                background-color 0.42s ease,
                border-color 0.42s ease,
                box-shadow 0.42s ease;
  }

/* The bar's width comes from the max-w-[var(--container-shell)] utility, and
     a utility cannot be overridden from the components layer — so the variable
     itself is narrowed here instead. It only inherits inside the navbar. */

html[data-design="v2"] .site-nav.is-stuck {
    --container-shell: 1180px;
    top: 12px;
    padding-block: 0;
  }

/* Phone form, measured off open-design.ai's stuck bar: a capsule inset 16px
     from both edges, 58px tall (9 + the 38px row + 9 + the 1px border), with
     the content pushed 28px in from the pill's own edge. Ours ran full-bleed
     at a 20px radius, which is what still read as a slab.

     The height half of this lives below the base .is-stuck rule, not here:
     same specificity, so source order decides and a media query does nothing
     to that. */

@media (width < 64rem) {
    html[data-design="v2"] .site-nav > nav {
      border-radius: 999px;
    }

    html[data-design="v2"] .site-nav.is-stuck {
      padding-inline: 16px;
    }
  }

html[data-design="v2"] .site-nav.is-stuck > nav {
    padding-block: 14px;
    background-color: var(--surface-2);
    border-color: var(--color-hairline);
    /* Do not build this sheet with --minify. Lightning CSS treats
       -webkit-backdrop-filter and backdrop-filter as one property and forces
       them to a single value, which either deletes the url() reference or
       copies it into the -webkit- line where Safari cannot resolve it. Either
       way the liquid glass is gone. Minifying saved 1.3KB gzipped. */
    backdrop-filter: url("#nav-liquid-glass") blur(7px) saturate(1.4);
    -webkit-backdrop-filter: blur(7px) saturate(1.4);
    box-shadow:
      inset 0 0 2px 1px rgba(255, 255, 255, 0.35),
      inset 0 0 10px 4px rgba(255, 255, 255, 0.1),
      0 6px 24px rgba(0, 0, 0, 0.1),
      0 12px 40px rgba(0, 0, 0, 0.08);
  }

/* Declared after the rule above, not inside the media block further up: the
     two have the same specificity, so whichever comes last wins. */

@media (width < 64rem) {
    html[data-design="v2"] .site-nav.is-stuck > nav {
      padding-block: 9px;
    }
  }

html[data-design="v2"] .site-nav img[alt="VidNext"] {
    transition: height 0.42s cubic-bezier(0.22, 0.61, 0.36, 1),
                width 0.42s cubic-bezier(0.22, 0.61, 0.36, 1),
                /* The mark darkens with the links when the bar crosses onto
                   the document card — see .site-nav.on-light. */
                filter 0.28s ease;
  }

/* Backdrop behind open nav dropdowns: a neutral dark wash. Tinting it with
     the brand orange muddied the blur, so the wash stays colourless. */

html[data-design="v2"] .nav-backdrop {
    background: rgba(10, 10, 10, 0.5);
    opacity: 0;
    visibility: hidden;
    backdrop-filter: blur(0px);
    -webkit-backdrop-filter: blur(0px);
    transition: opacity 0.28s ease, visibility 0.28s,
                backdrop-filter 0.28s ease, -webkit-backdrop-filter 0.28s ease;
  }

html[data-design="v2"] .nav-backdrop.is-open {
    opacity: 1;
    visibility: visible;
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
  }

/* Dropdowns fade and settle instead of snapping. They cannot use the hidden
     attribute for this — display:none never transitions. */

html[data-design="v2"] .dropdown {
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px) scale(0.985);
    transform-origin: top right;
    transition: opacity 0.22s ease, visibility 0.22s,
                transform 0.24s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .dropdown.is-open {
    opacity: 1;
    visibility: visible;
    transform: none;
  }

/* Frosted panel for nav dropdowns — values taken from Figma.
       fill          linear, #FFFFFF 70% -> #FFFFFF 20%, corner to corner
       stroke        linear, 1px inside, layer opacity 60%,
                     #FFFFFF 100% at 34% -> #FFFFFF 0% at 100%
       inner shadow  x0 y0 blur 24, #FFFFFF
       radius        12
     The stroke is a gradient, which `border` cannot do, so it is drawn by the
     ::after ring below. */

html[data-design="v2"] .glass-panel {
    position: absolute;
    border-radius: 10px;
    background-image: linear-gradient(
      to bottom right,
      rgba(255, 255, 255, 0.7) 0%,
      rgba(255, 255, 255, 0.2) 100%
    );
    backdrop-filter: url("#panel-liquid-glass") blur(14px) saturate(140%);
    -webkit-backdrop-filter: blur(14px) saturate(140%);
    box-shadow:
      inset 0 0 2px 1px rgba(255, 255, 255, 0.55),
      inset 0 0 24px rgba(255, 255, 255, 0.9),
      0 6px 24px rgba(0, 0, 0, 0.1),
      0 12px 40px rgba(0, 0, 0, 0.08);
    color: var(--fg-on-light);
  }

/* The burger panel is that same glass, but it sits in the document flow
     rather than hanging off a trigger. Compounded so it beats .glass-panel's
     own `absolute` on equal specificity regardless of source order. */

html[data-design="v2"] .menu-panel.glass-panel {
    position: relative;
  }

/* Links on light glass cannot follow --fg — in the dark theme that is white,
     and the panel stays light in both. */

html[data-design="v2"] .menu-panel .nav-link {
    color: var(--fg-on-light);
  }

/* 1px gradient stroke, drawn inside the radius */

html[data-design="v2"] .glass-panel::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    border-radius: inherit;
    padding: 1px;
    pointer-events: none;
    background: linear-gradient(
      to bottom right,
      rgba(255, 255, 255, 0.6) 0%,
      rgba(255, 255, 255, 0.6) 34%,
      rgba(255, 255, 255, 0) 100%
    );
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask-composite: exclude;
  }

/* Language picker row */

html[data-design="v2"] .lang-option {
    display: flex;
    width: 100%;
    align-items: baseline;
    gap: 12px;
    padding: 9px 12px;
    white-space: nowrap;
    border-radius: 10px;
    font-size: 15px;
    color: var(--fg-on-light);
    text-align: left;
    transition: background-color 0.2s ease, color 0.2s ease;
  }

html[data-design="v2"] .lang-option__code {
    width: 38px;
    flex-shrink: 0;
    font-size: 11px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--fg-on-light-muted);
  }

html[data-design="v2"] .lang-option:hover {
    background-color: rgba(0, 0, 0, 0.06);
    color: #000;
  }

html[data-design="v2"] .lang-option[aria-selected="true"] {
    background-color: rgba(var(--v2-accent-rgb), 0.14);
    color: var(--color-flame-mid);
  }

html[data-design="v2"] .lang-option[aria-selected="true"] .lang-option__code {
    color: color-mix(in srgb, var(--color-flame-mid) 70%, transparent);
  }

/* Theme picker row */

html[data-design="v2"] .theme-option {
    display: flex;
    width: 100%;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: 8px;
    font-size: 14px;
    color: var(--fg-on-light);
    transition: background-color 0.2s ease, color 0.2s ease;
  }

html[data-design="v2"] .theme-option:hover {
    background-color: rgba(0, 0, 0, 0.06);
    color: #000;
  }

html[data-design="v2"] .theme-option[aria-selected="true"] {
    background-color: rgba(var(--v2-accent-rgb), 0.14);
    color: var(--color-flame-mid);
  }

html[data-design="v2"] .btn--glass {
    background-image: var(--gradient-glass);
    border-color: var(--color-hairline);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    color: var(--fg);
  }

html[data-design="v2"] .btn--glass:hover {
    border-color: var(--color-hairline-strong);
    box-shadow: 0 10px 30px -12px rgba(255, 255, 255, 0.25);
  }

/* Nav links turn bold on hover. Bold is wider, so the width is reserved up
     front by a hidden ::before carrying the same text — otherwise neighbouring
     items would shift on every hover.
     Figma specifies 22px; reduced to 17px to fit the added right-hand cluster. */

html[data-design="v2"] .nav-link {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    font-size: 17px;
    color: var(--fg);
    opacity: 0.5;
    /* Colour is in here because the bar swaps its ink mid-scroll on the
       document pages — see .on-light. Without it the links snap from white to
       black a frame before the glass under them changes. */
    transition: opacity 0.25s ease, color 0.28s ease;
  }

/* The bar dims its links to 0.5 and lifts them on hover. In the burger panel
     there is no hover to lift them with, and the panel is light glass over a
     blurred page — at half strength the items read as disabled. Full strength
     here; the current page is still the only bold one. */

html[data-design="v2"] #mobile-menu .nav-link {
    font-size: 20px;
    opacity: 1;
  }

html[data-design="v2"] .nav-link::before {
    content: attr(data-text);
    height: 0;
    overflow: hidden;
    visibility: hidden;
    pointer-events: none;
    font-family: var(--font-display);
    font-weight: 700;
  }

/* The width-reserving ::before is the first item of a column inline-flex, so
     the link's baseline moves to its top edge: the <li> line box grows and the
     text is pushed down (8.5px lower than the rest of the navbar).
     Making <li> a flex container removes the line box entirely. */

html[data-design="v2"] li:has(> .nav-link) {
    display: flex;
  }

html[data-design="v2"] .nav-link:hover,
  html[data-design="v2"] .nav-link--active {
    opacity: 1;
    font-family: var(--font-display);
    font-weight: 700;
  }

/* Timeline ruler.
     Figma exports this as a fixed 1402px image, which ran out on wide screens.
     The tick grid is strictly regular (every 35px, every fourth full height,
     period 140px), so a repeating gradient reproduces it at any width.
     Opacities taken from the SVG: long ticks 0.1, short ticks 0.2. */

html[data-design="v2"] .ruler {
    position: absolute;
    left: 0;
    right: 0;
    height: 115px;
    pointer-events: none;
  }

html[data-design="v2"] .ruler::before,
  html[data-design="v2"] .ruler::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    /* Tick phase from the design: the first long tick sits at x = 21 */
    background-position-x: 21px;
  }

/* Long ticks: full height, every 140px */

html[data-design="v2"] .ruler::before {
    top: 0;
    bottom: 0;
    background-image: repeating-linear-gradient(
      to right,
      rgba(255, 255, 255, 0.1) 0 2px,
      transparent 2px 140px
    );
    -webkit-mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.4), #000);
    mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.4), #000);
  }

/* Short ticks: bottom half, in between the long ones */

html[data-design="v2"] .ruler::after {
    bottom: 0;
    height: 57.5px;
    background-image: repeating-linear-gradient(
      to right,
      transparent 0 35px,
      rgba(255, 255, 255, 0.2) 35px 37px,
      transparent 37px 70px,
      rgba(255, 255, 255, 0.2) 70px 72px,
      transparent 72px 105px,
      rgba(255, 255, 255, 0.2) 105px 107px,
      transparent 107px 140px
    );
    -webkit-mask-image: linear-gradient(to bottom, transparent 20.19%, #000);
    mask-image: linear-gradient(to bottom, transparent 20.19%, #000);
  }

/* ── Render card ─────────────────────────────────────────────────────── */

html[data-design="v2"] .render-card {
    position: relative;
    display: block;
    flex: 0 0 auto;
    width: 317.244px;
    height: 134.896px;
    overflow: hidden;
    background: #000;
    isolation: isolate;
    transition: border-color 0.4s ease, transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
  }

/* The frame overflows the card by 18px: blurring fades the edges to
     transparent, and without that margin the seam shows inside the card. */

html[data-design="v2"] .render-card__img {
    position: absolute;
    inset: -18px;
    object-fit: cover;
    transition: filter 0.45s ease, transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .render-card__scrim {
    position: absolute;
    inset: 0;
    background: #000;
    transition: opacity 0.45s ease;
  }

html[data-design="v2"] .render-card__scrim--40 { opacity: 0.4; }

html[data-design="v2"] .render-card__scrim--70 { opacity: 0.7; }

html[data-design="v2"] .render-card__scrim--80 { opacity: 0.8; }

/* Warm overlay — Geography card */

html[data-design="v2"] .render-card--ember::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    background: linear-gradient(
      142.85deg,
      rgba(0, 0, 0, 0) 23.34%,
      rgba(255, 60, 0, 0.3) 96.36%
    );
  }

/* Card label. Figma applies a progressive layer blur (0 -> 20, rightwards);
     that was built from masked layers but read worse in the browser than in the
     mockup, so it is a flat blur across the whole word instead. */

html[data-design="v2"] .render-card__label {
    position: absolute;
    left: 50%;
    top: 50%;
    z-index: 2;
    translate: -50% -50%;
    white-space: nowrap;
    font-family: var(--font-display);
    font-size: 36px;
    font-weight: 700;
    background-image: var(--gradient-flame);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    filter: blur(var(--render-label-blur));
    transition: filter 0.45s ease;
  }

/* Rides .btn.btn--glass. Only what is peculiar to this one lives here: it is
     parked on the card's bottom edge, so it loses its bottom border and its
     bottom corners, and it waits below the edge until the card is hovered. */

html[data-design="v2"] .render-card__cta {
    position: absolute;
    bottom: 0;
    left: 50%;
    z-index: 3;
    translate: -50% 0;
    gap: 6px;
    padding: 10px 20px;
    /* width only — the shorthand would reset the colour to currentColor */
    border-bottom-width: 0;
    border-radius: 10px 10px 0 0;
    font-size: 14px;
    line-height: 19.2px;
    transform: translateY(110%);
    transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
  }

/* Hover state — exactly what the Psychology card shows in the design */

html[data-design="v2"] .render-card:hover {
    border-color: var(--color-hairline-strong);
  }

html[data-design="v2"] .render-card:hover .render-card__img {
    filter: blur(3px);
    transform: scale(1.04);
  }

html[data-design="v2"] .render-card:hover .render-card__scrim { opacity: 0.25; }

/* On hover the label turns white and fully sharp */

html[data-design="v2"] .render-card:hover .render-card__label {
    background-image: none;
    color: var(--fg);
    filter: none;
  }

html[data-design="v2"] .render-card:hover .render-card__cta { transform: translateY(0); }

/* Phone: the whole strip at 0.8 — cards, the tick grid under them, and the
     type inside. Declared after the rules above because they share its
     specificity, so source order is what decides.

     The 2px tick width does not scale with the rest: it is a hairline, and
     0.8 of one lands on a fraction of a pixel and greys out. */

@media (width < 64rem) {
    html[data-design="v2"] .render-card {
      width: 253.8px;
      height: 107.9px;
      border-radius: 16px;
    }

    html[data-design="v2"] .render-card__label { font-size: 28.8px; }

    html[data-design="v2"] .render-card__cta {
      gap: 5px;
      padding: 8px 16px;
      border-radius: 8px 8px 0 0;
      font-size: 11px;
      line-height: 15.4px;
    }

    html[data-design="v2"] .ruler { height: 92px; }

    html[data-design="v2"] .ruler::before,
    html[data-design="v2"] .ruler::after { background-position-x: 16.8px; }

    html[data-design="v2"] .ruler::before {
      background-image: repeating-linear-gradient(
        to right,
        rgba(255, 255, 255, 0.1) 0 2px,
        transparent 2px 112px
      );
    }

    html[data-design="v2"] .ruler::after {
      height: 46px;
      background-image: repeating-linear-gradient(
        to right,
        transparent 0 28px,
        rgba(255, 255, 255, 0.2) 28px 30px,
        transparent 30px 56px,
        rgba(255, 255, 255, 0.2) 56px 58px,
        transparent 58px 84px,
        rgba(255, 255, 255, 0.2) 84px 86px,
        transparent 86px 112px
      );
    }
  }

/* ══════════════════════════════════════════════════════════════════════════
     INNER PAGES
     Everything below serves the pages the landing links out to: the legal set,
     about, careers, contacts, the blog, the two auth screens, and pricing.
     Arrangement follows groilot.webflow.io/information-pages/privacy-policy;
     the surfaces, type and colour are the landing's own.
     ═══════════════════════════════════════════════════════════════════════ */

/* ── Page header ─────────────────────────────────────────────────────────
     The donor hangs a photograph behind each inner-page header. Ours reuses the
     hero artwork instead, at a header's height. */

html[data-design="v2"] .page-hero {
    position: relative;
    overflow: hidden;
    padding-block: 150px 90px;
  }

@media (width >= 64rem) {
    html[data-design="v2"] .page-hero { padding-block: 210px 120px; }
  }

/* The artwork runs to the section's own edge and stops there, the way the
     landing hero does. It was dissolved into the page here for a while — the
     glow is still lit at the bottom of a header-height box, where on the
     landing it has long gone dark — but the fade read as a smear across the
     gradient, and an untouched gradient with a clean edge is the call. */

/* .page-art, which overrides .hero-glow, cannot live in here: .hero-glow is
     unlayered, and an unlayered rule beats every layer. It is next to it
     instead, at the bottom of the file. */

html[data-design="v2"] .page-hero__inner {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 20px;
    text-align: center;
  }

html[data-design="v2"] .page-hero__title {
    max-width: 900px;
    font-family: var(--font-display);
    font-size: var(--text-h2);
    font-weight: 700;
    line-height: 1.08;
    color: var(--fg);
  }

html[data-design="v2"] .page-hero__lede {
    max-width: 680px;
    font-size: var(--text-lead);
    line-height: 1.6;
    color: var(--fg-muted);
  }

html[data-design="v2"] .page-hero__meta {
    font-family: var(--font-display);
    font-size: var(--text-small);
    color: var(--fg-subtle);
  }

/* ── Technical pages ─────────────────────────────────────────────────────
     The legal set is laid out like the docs article, and for the same reason:
     it is a document someone reads end to end, not a page they scan. No
     gradient behind it, the theme switch working, one centred column.

     688 is the docs article's own width — 1200 of grid minus the two rails and
     their gaps. Written out rather than shared through a variable because the
     two arrive at it from different directions: there it is what is left over,
     here it is the measure itself. */

html[data-design="v2"] .doc-page {
    width: 100%;
    max-width: 688px;
    margin-inline: auto;
  }

/* The rule under the date already separates the header from the body, so the
     first heading does not need the full 50 the others carry. */

html[data-design="v2"] .doc-page__meta + h2 { margin-top: 30px; }

html[data-design="v2"] .doc-page__meta {
    margin-top: 10px;
    padding-bottom: 24px;
    border-bottom: 1px solid var(--color-hairline-dim);
    font-family: var(--font-display);
    font-size: var(--text-small);
    color: var(--fg-subtle);
  }

/* ── Document card ───────────────────────────────────────────────────────
     The donor's privacy-policy-details: one white card over the backdrop,
     holding the whole document. No sidebar and no table of contents.

     It stays white in both themes, like the language menu and the cookie
     modal — the surface under it is artwork, not the page, so it has nothing
     to follow. Its ink comes from `.on-light` down in the STATE section, which
     the navbar borrows when it scrolls over this card. */

html[data-design="v2"] .doc-card {
    border-radius: 24px;
    background-color: #ffffff;
    padding: 40px 24px;
    /* No border: on artwork a hairline reads as a seam. The card is separated
       by a long shadow instead, the way a sheet of paper is. */
    box-shadow: 0 40px 100px -50px rgba(0, 0, 0, 0.85);
  }

@media (width >= 48rem) {
    html[data-design="v2"] .doc-card { padding: 60px; }
  }

@media (width >= 64rem) {
    html[data-design="v2"] .doc-card { padding: 80px; }
  }

/* ── Document prose ──────────────────────────────────────────────────────
     Shared by the legal pages and the blog article. The rules are element
     selectors under one class because the copy is pasted from vidnext.ai as
     plain HTML — putting a class on every paragraph of the Terms of Service
     would make the source unmaintainable and the next paste would drop them. */

html[data-design="v2"] .doc h2 {
    margin-top: 50px;
    margin-bottom: 16px;
    font-family: var(--font-display);
    font-size: var(--text-h4);
    font-weight: 700;
    line-height: 1.2;
    color: var(--fg);
  }

html[data-design="v2"] .doc > h2:first-child { margin-top: 0; }

html[data-design="v2"] .doc h3 {
    margin-top: 30px;
    margin-bottom: 10px;
    font-family: var(--font-display);
    font-size: var(--text-h5);
    font-weight: 600;
    line-height: 1.35;
    color: var(--fg);
  }

html[data-design="v2"] .doc h4 {
    margin-top: 24px;
    margin-bottom: 8px;
    font-family: var(--font-display);
    font-size: var(--text-h6);
    font-weight: 600;
    color: var(--fg);
  }

html[data-design="v2"] .doc p {
    margin-bottom: 16px;
    font-size: var(--text-body);
    line-height: 28px;
    color: var(--fg-muted);
  }

/* The card runs the full 1200 grid, which is a fine width for a panel and a
     terrible one for a line of text — about 130 characters. Capping the measure
     on the running copy alone keeps headings, tables and the card itself where
     the donor puts them. */

html[data-design="v2"] .doc p,
  html[data-design="v2"] .doc li {
    max-width: 78ch;
  }

html[data-design="v2"] .doc p:last-child { margin-bottom: 0; }

html[data-design="v2"] .doc ul,
  html[data-design="v2"] .doc ol {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin: 0 0 20px;
    counter-reset: doc-item;
  }

html[data-design="v2"] .doc li {
    position: relative;
    padding-left: 26px;
    font-size: var(--text-body);
    line-height: 26px;
    color: var(--fg-muted);
  }

html[data-design="v2"] .doc ul > li::before {
    content: "";
    position: absolute;
    left: 8px;
    top: 11px;
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background-color: var(--color-flame);
  }

html[data-design="v2"] .doc ol > li::before {
    counter-increment: doc-item;
    content: counter(doc-item) ".";
    position: absolute;
    left: 0;
    top: 0;
    font-variant-numeric: tabular-nums;
    color: var(--color-flame);
  }

html[data-design="v2"] .doc strong {
    font-weight: 600;
    color: var(--fg);
  }

html[data-design="v2"] .doc a {
    color: var(--color-flame);
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-thickness: 1px;
    transition: opacity 0.2s ease;
  }

html[data-design="v2"] .doc a:hover { opacity: 0.75; }

html[data-design="v2"] .doc code {
    font-family: var(--font-mono);
    font-size: 13px;
    padding: 2px 7px;
    border-radius: 6px;
    border: 1px solid var(--color-hairline-dim);
    background-color: var(--surface-2);
    color: var(--fg);
    white-space: nowrap;
  }

/* Cookie tables are four columns of short strings; below about 640px they
     scroll sideways rather than reflow, because a cookie name that wraps mid
     token stops being quotable. */

html[data-design="v2"] .doc-table {
    margin-bottom: 20px;
    overflow-x: auto;
    border-radius: 14px;
    border: 1px solid var(--color-hairline-dim);
  }

html[data-design="v2"] .doc table {
    width: 100%;
    min-width: 520px;
    border-collapse: collapse;
    font-size: var(--text-small);
  }

html[data-design="v2"] .doc th,
  html[data-design="v2"] .doc td {
    padding: 12px 16px;
    text-align: left;
    vertical-align: top;
    border-bottom: 1px solid var(--color-hairline-dim);
  }

html[data-design="v2"] .doc th {
    font-family: var(--font-display);
    font-weight: 600;
    color: var(--fg);
    background-color: var(--surface-1);
    white-space: nowrap;
  }

html[data-design="v2"] .doc td { color: var(--fg-muted); }

html[data-design="v2"] .doc tbody tr:last-child td { border-bottom: 0; }

/* A group of cookies from one provider: heading line, then its table. */

html[data-design="v2"] .doc-group {
    margin-bottom: 24px;
    padding-top: 4px;
  }

html[data-design="v2"] .doc-note {
    margin-top: 30px;
    padding: 20px 24px;
    border-radius: 16px;
    border: 1px solid rgba(var(--v2-accent-rgb), 0.3);
    background-color: rgba(var(--v2-accent-rgb), 0.08);
  }

html[data-design="v2"] .doc-note p { color: var(--fg); }

/* ── Blog list ───────────────────────────────────────────────────────────
     The donor's card: image on top, then the title, then a meta row with the
     category at one end and the date at the other. The surface is ours. */

/* A whole-card anchor gave the link an accessible name of "title, category,
     date" and handed a crawler that string as its anchor text. The title is the
     link now and stretches over the card, so the card is still clickable and
     the link says what it points at. */

/* The grid's own ink field. The hero keeps the warm page artwork; from the
     first row of cards down it fades to the artwork's ink so the covers -- which
     are themselves warm and dark -- read as lit objects instead of sitting in
     the glow. Fades to --glow-ink, not --bg-page: .page-art is pinned dark in
     both themes, so the field has to be too or the light theme tears. */

html[data-design="v2"] .blog-grid {
    position: relative;
  }

html[data-design="v2"] .blog-grid::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    /* Absolute stops, not percentages: the section is as tall as the grid,
       so a percentage fade would stretch across five rows on a full index and
       finish immediately on a short one. 220px lands the transition inside
       the section's own top padding, so every row of cards sits on flat ink. */
    background: linear-gradient(
      to bottom,
      transparent 0,
      color-mix(in srgb, var(--glow-ink) 82%, transparent) 110px,
      var(--glow-ink) 220px
    );
  }

html[data-design="v2"] .blog-grid > .shell,
html[data-design="v2"] .blog-grid > .shell > * {
    position: relative;
    z-index: 1;
  }

/* Card. No inner frame: the cover runs to the card edge and the card's own
     radius clips it, so the artwork gets the full width and the chrome stops
     competing with it. */

html[data-design="v2"] .blog-card {
    position: relative;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-radius: 20px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-panel);
    transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1),
                border-color 0.25s ease;
  }

html[data-design="v2"] .blog-card:hover {
    transform: translateY(-4px);
    border-color: var(--color-hairline-strong);
  }

/* Keyboard parity with the pointer hover, since the whole card is one link. */

html[data-design="v2"] .blog-card:focus-within {
    border-color: var(--color-hairline-strong);
  }

/* flex:1 with space-between so the meta row is pinned to the bottom of the
     card whatever the title's length — otherwise a one-line title in a row of
     three-line ones leaves its date floating in the middle. */

html[data-design="v2"] .blog-card__body {
    display: flex;
    flex: 1;
    flex-direction: column;
    justify-content: space-between;
    gap: 18px;
    padding: 20px;
  }

html[data-design="v2"] .blog-card__text {
    display: flex;
    flex-direction: column;
    gap: 10px;
  }

html[data-design="v2"] .stretched-link::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    border-radius: inherit;
  }

/* Titles clamp so a five-word headline and a fifteen-word one occupy the same
     block, which is what keeps the meta rows aligned across a row of cards. */

html[data-design="v2"] .blog-card__title {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    overflow: hidden;
    font-family: var(--font-display);
    font-size: var(--text-h5);
    font-weight: 600;
    line-height: 1.28;
    letter-spacing: -0.01em;
    color: var(--fg);
    transition: color 0.25s ease;
  }

/* The lede, two lines of it. The covers carry the hook; this carries the
     answer to "is this the guide I need". */

html[data-design="v2"] .blog-card__dek {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    font-size: var(--text-small);
    line-height: 1.5;
    color: var(--fg-muted);
  }

html[data-design="v2"] .blog-card:hover .blog-card__title a { color: var(--color-flame); }

/* Category at one end, date at the other, as the donor sets it. */

html[data-design="v2"] .blog-card__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding-top: 16px;
    border-top: 1px solid var(--color-hairline);
    font-family: var(--font-display);
    font-size: var(--text-small);
    color: var(--fg-subtle);
  }

html[data-design="v2"] .blog-card__art {
    display: block;
    overflow: hidden;
    /* No radius of its own: the cover runs full-bleed and the card's overflow
       clips its top corners, so a second rounded rectangle inside the first
       would only read as a frame. */
    /* Covers are authored 1280x720. Anything taller than 16/9 makes
       object-fit:cover crop the sides, which ate the title text and the
       logo on every card. Match the source and nothing is lost. */
    aspect-ratio: 16 / 9;
    border-bottom: 1px solid var(--color-hairline);
    background-image: var(--gradient-panel);
  }

html[data-design="v2"] .blog-card__art img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: scale 0.5s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .blog-card:hover .blog-card__art img { scale: 1.05; }

/* Category chip. Same pill as .section-tag but at a label's size. */

html[data-design="v2"] .chip {
    display: inline-flex;
    align-items: center;
    height: 28px;
    padding: 0 14px;
    border-radius: 14px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-glass);
    font-family: var(--font-display);
    font-size: var(--text-caption);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
    color: var(--fg);
  }

/* ── Article ─────────────────────────────────────────────────────────────
     The cover sits behind the sheet rather than above it. It opens showing its
     top half, and the sheet climbs over it as the page scrolls until it is gone
     — so the cover reads as something the article is laid on top of, not as a
     band the article has to be narrow enough to sit under.

     That is what lets the sheet run the full grid width, the same as the legal
     pages, instead of being cut down to whatever the cover could carry. */

html[data-design="v2"] .article-stage {
    position: relative;
  }

/* Pinned, not parked: the sheet has to move over a cover that stays put, or
     the two travel together and nothing is ever hidden. 100px clears the navbar
     in both its states.

     Nothing above this may set `overflow: hidden` — that turns the ancestor
     into a scroll container and leaves the sticky element with nothing to stick
     to. The section around it deliberately has no overflow at all. */

html[data-design="v2"] .article-cover {
    position: sticky;
    top: 100px;
    z-index: 0;
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    border-radius: 24px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-panel);
  }

/* A percentage margin resolves against the container's width, never its
     height — so half of a 16:9 box is 9/16/2 of the width. Written as the
     arithmetic rather than as 28.125% so it stays legible if the ratio moves;
     a fixed pixel offset would only be half the cover at one window size. */

html[data-design="v2"] .article-sheet {
    position: relative;
    z-index: 1;
    margin-top: calc(-9 / 16 / 2 * 100%);
  }

html[data-design="v2"] .back-link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-family: var(--font-display);
    font-size: var(--text-small);
    font-weight: 600;
    color: var(--fg-subtle);
    transition: color 0.25s ease;
  }

html[data-design="v2"] .back-link:hover { color: var(--fg); }

html[data-design="v2"] .back-link span { transition: translate 0.25s cubic-bezier(0.22, 1, 0.36, 1); }

html[data-design="v2"] .back-link:hover span { translate: -4px 0; }

/* The dot between the date and the read time */

html[data-design="v2"] .article-dot {
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background-color: var(--fg-faint);
  }

html[data-design="v2"] .article-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    margin-top: 50px;
    padding-top: 30px;
    border-top: 1px solid var(--color-hairline);
  }

html[data-design="v2"] .article-foot__label {
    font-family: var(--font-display);
    font-size: var(--text-caption);
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--fg-faint);
  }

/* The donor sticks this in a right-hand rail. Under the post it can be a
     single row instead, which is what lets the article keep one width from the
     cover down. It stacks below 768, where a row would squeeze the field. */

html[data-design="v2"] .article-subscribe {
    display: flex;
    flex-direction: column;
    gap: 20px;
    padding: 30px;
    border-radius: 24px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-panel);
  }

@media (width >= 48rem) {
    html[data-design="v2"] .article-subscribe {
      flex-direction: row;
      align-items: center;
      justify-content: space-between;
      gap: 40px;
      padding: 30px 40px;
    }
  }

/* The control carries a top margin for its place in the footer, where it sits
     under a paragraph. In a row it has nothing above it to clear. */

html[data-design="v2"] .article-subscribe .subscribe {
    flex: none;
    margin-top: 0;
  }

/* ── Form field ──────────────────────────────────────────────────────────
     Used by the auth screens and the careers/contact blocks. The footer's
     subscribe control keeps its own styling — it is a single joined pill, a
     different component. */

html[data-design="v2"] .field {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

html[data-design="v2"] .field__label {
    font-family: var(--font-display);
    font-size: var(--text-small);
    font-weight: 500;
    color: var(--fg-muted);
  }

html[data-design="v2"] .field__control { position: relative; }

html[data-design="v2"] .field__input {
    width: 100%;
    height: 52px;
    padding: 0 16px;
    border-radius: 12px;
    border: 1px solid var(--color-hairline);
    background-color: var(--surface-1);
    font-size: var(--text-body);
    color: var(--fg);
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
  }

html[data-design="v2"] .field__input::placeholder { color: var(--fg-faint); }

html[data-design="v2"] .field__input:focus {
    outline: none;
    border-color: var(--color-flame);
    box-shadow: 0 0 0 3px rgba(var(--v2-accent-rgb), 0.18);
  }

/* Room for the reveal button, so a long password does not run under it */

html[data-design="v2"] .field__input--pw { padding-right: 52px; }

html[data-design="v2"] .field__reveal {
    position: absolute;
    right: 6px;
    top: 50%;
    translate: 0 -50%;
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border-radius: 10px;
    color: var(--fg-subtle);
    transition: color 0.2s ease, background-color 0.2s ease;
  }

html[data-design="v2"] .field__reveal:hover {
    color: var(--fg);
    background-color: var(--surface-1);
  }

/* ── Auth screens ────────────────────────────────────────────────────────
     Sign-in and sign-up are one layout with a different form in it.

     These two do not take the navbar and footer: they live on
     accounts.vidnext.ai, a different origin with no marketing shell, and a
     sticky bar over a centred 100vh card fights it for the top of the screen.
     What they keep is the artwork, so the jump from the landing lands
     somewhere recognisable. */

html[data-design="v2"] .auth-page {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 30px;
    min-height: 100vh;
    overflow: hidden;
    padding: 60px 24px;
  }

html[data-design="v2"] .auth-card {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 420px;
    display: flex;
    flex-direction: column;
    gap: 24px;
    padding: 40px 30px;
    border-radius: 24px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-panel);
  }

@media (width >= 30rem) {
    html[data-design="v2"] .auth-card { padding: 40px; }
  }

html[data-design="v2"] .auth-card__title {
    font-family: var(--font-display);
    font-size: var(--text-h4);
    font-weight: 700;
    line-height: 1.15;
    color: var(--fg);
  }

html[data-design="v2"] .auth-card__lede {
    margin-top: 8px;
    font-size: var(--text-small);
    line-height: 22px;
    color: var(--fg-subtle);
  }

/* A provider button is a control, not a call to action: same geometry as the
     field above it so the column reads as one stack. */

html[data-design="v2"] .btn--provider {
    width: 100%;
    height: 52px;
    padding: 0 20px;
    gap: 12px;
    border-radius: 12px;
    border: 1px solid var(--color-hairline);
    background-color: var(--surface-1);
    font-family: var(--font-display);
    font-size: var(--text-body);
    font-weight: 500;
    color: var(--fg);
  }

html[data-design="v2"] .btn--provider:hover { background-color: var(--surface-2); }

/* The submit button matches those heights too, so .btn's 20px/16px padding
     is overridden rather than inherited. */

html[data-design="v2"] .btn--block {
    width: 100%;
    height: 52px;
    padding: 0 20px;
    border-radius: 12px;
    font-size: var(--text-body);
  }

html[data-design="v2"] .auth-divider {
    display: flex;
    align-items: center;
    gap: 16px;
    font-size: var(--text-caption);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--fg-faint);
  }

html[data-design="v2"] .auth-divider::before,
  html[data-design="v2"] .auth-divider::after {
    content: "";
    flex: 1;
    height: 1px;
    background-color: var(--color-hairline);
  }

html[data-design="v2"] .auth-legal {
    font-size: var(--text-caption);
    line-height: 18px;
    color: var(--fg-faint);
  }

html[data-design="v2"] .auth-legal a {
    color: var(--fg-subtle);
    text-decoration: underline;
    text-underline-offset: 2px;
  }

/* The track is drawn on the wrapper rather than on the input: a range input
     cannot paint a filled portion cross-browser, so the fill is a separate
     element sized from --price-pos and the input itself sits transparent on
     top, keeping the keyboard and pointer behaviour the browser gives it. */

html[data-design="v2"] .price-slider {
    position: relative;
    height: 24px;
    display: flex;
    align-items: center;
  }

html[data-design="v2"] .price-slider__track,
  html[data-design="v2"] .price-slider__fill {
    position: absolute;
    left: 0;
    height: 6px;
    border-radius: 3px;
    pointer-events: none;
  }

html[data-design="v2"] .price-slider__track {
    right: 0;
    background-color: var(--surface-2);
  }

html[data-design="v2"] .price-slider__fill {
    width: var(--price-pos, 0%);
    background-image: var(--gradient-flame);
  }

html[data-design="v2"] .price-slider input[type="range"] {
    position: relative;
    z-index: 1;
    width: 100%;
    height: 24px;
    margin: 0;
    background: transparent;
    appearance: none;
    -webkit-appearance: none;
    cursor: pointer;
  }

html[data-design="v2"] .price-slider input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 2px solid var(--fg-on-accent);
    background-image: var(--gradient-flame);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
  }

html[data-design="v2"] .price-slider input[type="range"]::-moz-range-thumb {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 2px solid var(--fg-on-accent);
    background-image: var(--gradient-flame);
  }

html[data-design="v2"] .price-includes {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    font-size: var(--text-body);
    line-height: 24px;
    color: var(--fg-muted);
  }

/* ── Planner ─────────────────────────────────────────────────────────────
     Arrangement from higgsfield.ai/pricing: pick what you make, say how much of
     it, read the answer off a card on the right.

     What it recommends is one of our twelve top-ups, not a subscription — we do
     not sell those. So the donor's Monthly/Annual switch is replaced by how many
     months the top-up should cover, which is the same question our pricing
     actually answers: buy more at once and the minute costs less. */

/* The whole configurator sits in one raised panel, as the donor's does — the
     three steps and the answer are one instrument, not four blocks that happen
     to be next to each other. */

html[data-design="v2"] .planner-shell {
    width: 100%;
    padding: 20px;
    border-radius: 24px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-panel);
  }

@media (width >= 48rem) {
    html[data-design="v2"] .planner-shell { padding: 24px; }
  }

html[data-design="v2"] .planner {
    display: grid;
    gap: 24px;
    align-items: start;
  }

@media (width >= 64rem) {
    html[data-design="v2"] .planner { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 30px; }
  }

html[data-design="v2"] .planner__steps {
    display: flex;
    flex-direction: column;
    gap: 36px;
  }

html[data-design="v2"] .step {
    display: grid;
    grid-template-columns: 26px minmax(0, 1fr);
    gap: 8px 14px;
  }

html[data-design="v2"] .step__num {
    grid-row: span 3;
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    margin-top: 2px;
    border-radius: 50%;
    background-color: var(--surface-2);
    font-family: var(--font-display);
    font-size: var(--text-caption);
    font-weight: 700;
    color: var(--fg-muted);
  }

html[data-design="v2"] .step__title {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    font-family: var(--font-display);
    font-size: var(--text-h6);
    font-weight: 700;
    color: var(--fg);
  }

html[data-design="v2"] .step__hint {
    font-size: var(--text-small);
    line-height: 20px;
    color: var(--fg-subtle);
  }

html[data-design="v2"] .step__body { margin-top: 8px; }

/* ── Step 1: what are you making ─────────────────────────────────────── */

html[data-design="v2"] .opt-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
  }

@media (width >= 26rem) {
    html[data-design="v2"] .opt-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  }

/* Stacked rather than a row of icon, label and checkbox. Three across leaves
     each tile about 150px in the planner's left column, and a row spends 96 of
     those on the two glyphs and the padding — the words get what is left. */

html[data-design="v2"] .opt {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 12px 14px 14px;
    border-radius: 12px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-panel);
    color: var(--fg-muted);
    cursor: pointer;
    transition: border-color 0.2s ease, color 0.2s ease;
  }

html[data-design="v2"] .opt__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
  }

html[data-design="v2"] .opt__label {
    font-size: var(--text-small);
    line-height: 18px;
  }

html[data-design="v2"] .opt:hover { border-color: var(--color-hairline-strong); }

html[data-design="v2"] .opt input { position: absolute; opacity: 0; pointer-events: none; }

html[data-design="v2"] .opt__icon {
    flex: none;
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    border-radius: 8px;
    background-color: var(--surface-2);
    color: var(--fg-subtle);
  }

html[data-design="v2"] .opt__box {
    flex: none;
    display: grid;
    place-items: center;
    width: 22px;
    height: 22px;
    border-radius: 6px;
    border: 1px solid var(--color-hairline-strong);
    color: transparent;
    transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
  }

html[data-design="v2"] .opt:has(input:checked) {
    border-color: var(--color-flame);
    color: var(--fg);
  }

html[data-design="v2"] .opt:has(input:checked) .opt__icon {
    background-color: rgba(var(--v2-accent-rgb), 0.14);
    color: var(--color-flame);
  }

html[data-design="v2"] .opt:has(input:checked) .opt__box {
    border-color: transparent;
    background-image: var(--gradient-flame);
    color: var(--fg-on-accent);
  }

html[data-design="v2"] .opt:has(input:focus-visible) {
    outline: 2px solid var(--color-flame);
    outline-offset: 2px;
  }

/* ── Step 2: how much of it ──────────────────────────────────────────── */

html[data-design="v2"] .range-set {
    display: flex;
    flex-direction: column;
    gap: 22px;
    padding: 20px;
    border-radius: 16px;
    border: 1px solid var(--color-hairline);
    background-color: var(--surface-1);
  }

html[data-design="v2"] .range-row[hidden] { display: none; }

html[data-design="v2"] .range-row {
    display: flex;
    flex-direction: column;
    gap: 10px;
  }

/* The donor draws a comb of marks above the track and colours the ones the
     handle has passed. Two copies of the same gradient, the lit one clipped to
     the handle's position — one element per state, no per-tick markup. */

html[data-design="v2"] .range__comb {
    position: relative;
    height: 14px;
    overflow: hidden;
    --comb: repeating-linear-gradient(to right,
              currentColor 0 2px, transparent 2px 14px);
  }

html[data-design="v2"] .range__comb::before,
  html[data-design="v2"] .range__comb::after {
    content: "";
    position: absolute;
    inset: 0;
    background-image: var(--comb);
  }

html[data-design="v2"] .range__comb::before { color: var(--fg-ghost); }

html[data-design="v2"] .range__comb::after {
    width: var(--range-pos, 0%);
    color: var(--color-flame);
  }

html[data-design="v2"] .range__foot {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    font-family: var(--font-display);
    font-size: var(--text-small);
    color: var(--fg);
  }

html[data-design="v2"] .range__cost {
    font-weight: 400;
    color: var(--fg-subtle);
  }

html[data-design="v2"] .range__cap {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border-radius: 999px;
    background-color: var(--surface-2);
    font-size: var(--text-caption);
    font-weight: 600;
    color: var(--fg-subtle);
    font-variant-numeric: tabular-nums;
  }

/* Shown when nothing is selected in step 1 — the sliders have nothing to ask
     about until there is something being made. */

html[data-design="v2"] .range-empty {
    font-size: var(--text-small);
    color: var(--fg-subtle);
  }

/* ── The recommendation ──────────────────────────────────────────────── */

html[data-design="v2"] .planner__panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 24px;
    padding: 24px 20px;
    border-radius: 20px;
    background-color: var(--surface-1);
  }

@media (width >= 48rem) {
    html[data-design="v2"] .planner__panel { padding: 30px; }
  }

html[data-design="v2"] .planner__lede {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    text-align: center;
  }

html[data-design="v2"] .planner__lede p {
    font-family: var(--font-display);
    font-size: var(--text-small);
    color: var(--fg-subtle);
  }

/* "See why" — the donor's tooltip, written as a disclosure so the reasoning
     is reachable by keyboard and readable with no JS at all. */

html[data-design="v2"] .why > summary {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 14px;
    border-radius: 999px;
    border: 1px solid rgba(var(--v2-accent-rgb), 0.4);
    background-color: rgba(var(--v2-accent-rgb), 0.1);
    font-family: var(--font-display);
    font-size: var(--text-caption);
    font-weight: 600;
    color: var(--color-flame);
    cursor: pointer;
    list-style: none;
  }

html[data-design="v2"] .why > summary::-webkit-details-marker { display: none; }

html[data-design="v2"] .why > p {
    max-width: 380px;
    margin-top: 12px;
    font-size: var(--text-small);
    line-height: 21px;
    color: var(--fg-subtle);
  }

html[data-design="v2"] .plan-card {
    width: 100%;
    max-width: 380px;
    display: flex;
    flex-direction: column;
    gap: 20px;
    padding: 24px;
    border-radius: 18px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-panel);
  }

html[data-design="v2"] .plan-card__name {
    font-family: var(--font-display);
    font-size: var(--text-h5);
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--fg);
  }

html[data-design="v2"] .plan-card__for {
    margin-top: 2px;
    font-size: var(--text-small);
    color: var(--fg-subtle);
  }

html[data-design="v2"] .plan-credits {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 14px;
    border-radius: 12px;
    background-color: var(--surface-1);
    font-family: var(--font-display);
    font-size: var(--text-small);
    font-weight: 600;
    color: var(--fg);
  }

html[data-design="v2"] .plan-credits__sub {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    border-radius: 10px;
    background-color: var(--surface-2);
    font-weight: 500;
    color: var(--fg-subtle);
  }

html[data-design="v2"] .plan-usage {
    display: flex;
    flex-direction: column;
    gap: 8px;
    font-family: var(--font-display);
    font-size: var(--text-caption);
    color: var(--fg-subtle);
  }

html[data-design="v2"] .plan-usage__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
  }

html[data-design="v2"] .plan-usage__value {
    font-weight: 700;
    color: var(--color-flame);
    font-variant-numeric: tabular-nums;
  }

html[data-design="v2"] .plan-usage__bar {
    height: 4px;
    border-radius: 2px;
    background-color: var(--surface-2);
    overflow: hidden;
  }

html[data-design="v2"] .plan-usage__bar span {
    display: block;
    width: var(--usage, 0%);
    height: 100%;
    border-radius: inherit;
    background-image: var(--gradient-flame);
    transition: width 0.3s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .plan-points {
    display: flex;
    flex-direction: column;
    gap: 12px;
    font-size: var(--text-small);
    line-height: 21px;
    color: var(--fg-muted);
  }

html[data-design="v2"] .plan-points li {
    display: flex;
    align-items: flex-start;
    gap: 10px;
  }

html[data-design="v2"] .plan-points svg {
    flex: none;
    margin-top: 4px;
    color: var(--color-flame);
  }

html[data-design="v2"] .plan-price {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 8px;
    font-family: var(--font-display);
    color: var(--fg);
  }

html[data-design="v2"] .plan-price b {
    font-size: 34px;
    font-weight: 700;
    line-height: 1;
    font-variant-numeric: tabular-nums;
  }

html[data-design="v2"] .plan-price span {
    font-size: var(--text-small);
    font-weight: 400;
    color: var(--fg-subtle);
  }

/* ── Tier cards ──────────────────────────────────────────────────────────
     Arrangement from vidrush.ai/pricing: three cards, the middle one marked,
     a switch above them that lowers the per-minute rate.

     Theirs switches monthly against yearly; ours switches how many months the
     top-up covers, which is the same lever with our mechanics — the saving is
     not a discount we grant, it is the ladder's own rate falling as the package
     grows. Every figure is read off the table further down. */

html[data-design="v2"] .tier-grid {
    display: grid;
    gap: 16px;
    width: 100%;
  }

@media (width >= 60rem) {
    html[data-design="v2"] .tier-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  }

html[data-design="v2"] .tier {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 20px;
    padding: 28px;
    border-radius: 24px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-panel);
    transition: border-color 0.25s ease, transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .tier:hover { border-color: var(--color-hairline-strong); }

/* The marked one. A border alone reads as hover, so it takes the accent edge
     and a little lift — on a three-card row that is what makes it the default
     rather than merely the middle. */

html[data-design="v2"] .tier--featured {
    border-color: transparent;
    background-image: var(--gradient-panel), var(--gradient-flame);
    background-origin: border-box;
    background-clip: padding-box, border-box;
    box-shadow: 0 0 50px rgba(var(--v2-accent-rgb), 0.14);
  }

@media (width >= 60rem) {
    html[data-design="v2"] .tier--featured { transform: translateY(-12px); }
    html[data-design="v2"] .tier--featured:hover { transform: translateY(-16px); }
  }

html[data-design="v2"] .tier__flag {
    position: absolute;
    top: -11px;
    left: 28px;
    padding: 3px 12px;
    border-radius: 999px;
    background-image: var(--gradient-flame);
    font-family: var(--font-display);
    font-size: var(--text-caption);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--fg-on-accent);
  }

html[data-design="v2"] .tier__name {
    font-family: var(--font-display);
    font-size: var(--text-h5);
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--fg);
  }

html[data-design="v2"] .tier__for {
    margin-top: 4px;
    font-size: var(--text-small);
    color: var(--fg-subtle);
  }

/* The rate is the headline here, not the total: it is the number that moves
     when the switch does, and the one that compares between cards. */

html[data-design="v2"] .tier__rate {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 8px;
    font-family: var(--font-display);
    color: var(--fg);
  }

html[data-design="v2"] .tier__rate b {
    font-size: 34px;
    font-weight: 700;
    line-height: 1;
    font-variant-numeric: tabular-nums;
  }

html[data-design="v2"] .tier__was {
    font-size: var(--text-small);
    color: var(--fg-faint);
    text-decoration: line-through;
    font-variant-numeric: tabular-nums;
  }

html[data-design="v2"] .tier__rate span:not(.tier__was) {
    font-size: var(--text-small);
    font-weight: 400;
    color: var(--fg-subtle);
  }

html[data-design="v2"] .tier__total {
    padding: 12px 14px;
    border-radius: 12px;
    background-color: var(--surface-1);
    font-family: var(--font-display);
    font-size: var(--text-small);
    color: var(--fg-muted);
  }

html[data-design="v2"] .tier__total b {
    font-size: var(--text-h6);
    font-weight: 700;
    color: var(--fg);
    font-variant-numeric: tabular-nums;
  }

html[data-design="v2"] .tier__specs {
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-size: var(--text-small);
    color: var(--fg-muted);
  }

html[data-design="v2"] .tier__specs li {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 9px 0;
    border-bottom: 1px solid var(--color-hairline-dim);
  }

html[data-design="v2"] .tier__specs li:last-child { border-bottom: 0; }

html[data-design="v2"] .tier__specs b {
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--fg);
    font-variant-numeric: tabular-nums;
  }

/* Pushes the button to the bottom edge whatever the card above it holds, so
     three cards of different lengths still line their calls to action up. */

html[data-design="v2"] .tier__cta { margin-top: auto; }

html[data-design="v2"] .tier-save {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border-radius: 999px;
    background-color: rgba(var(--v2-accent-rgb), 0.14);
    font-family: var(--font-display);
    font-size: var(--text-caption);
    font-weight: 700;
    color: var(--color-flame);
    white-space: nowrap;
  }

html[data-design="v2"] .tier-save[hidden] { display: none; }

/* ── Promo modal ─────────────────────────────────────────────────────────
     Arrangement from Open Design's desktop promo. White card over the frosted
     page, the accent doing the work in four small places: the eyebrow, the
     stop at the end of the headline, the ticks, and the disc in the button.

     Same open/close mechanics as the cookie modal, so the two behave alike. */

html[data-design="v2"] .promo-modal {
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s ease, visibility 0.3s;
  }

html[data-design="v2"] .promo-modal.is-open {
    opacity: 1;
    visibility: visible;
  }

html[data-design="v2"] .promo-panel {
    position: relative;
    overflow: hidden;
    width: 100%;
    max-width: 560px;
    max-height: 100%;
    overflow-y: auto;
    /* Its own stacking context, so the wash can sit at -1 and every child paints
       over it without each one needing a position of its own. Setting
       `position: relative` on the children instead took the close button with
       it and dropped it out of its corner. */
    isolation: isolate;
    padding: 32px 26px;
    border-radius: 28px;
    background-color: #ffffff;
    box-shadow: 0 40px 120px -40px rgba(0, 0, 0, 0.7);
    transform: scale(0.97) translateY(8px);
    transition: transform 0.32s cubic-bezier(0.22, 1, 0.36, 1);
  }

@media (width >= 30rem) {
    html[data-design="v2"] .promo-panel { padding: 40px; }
  }

html[data-design="v2"] .promo-modal.is-open .promo-panel { transform: none; }

/* The donor washes the top-right corner in its accent. Ours is the brand
     gradient at a tenth of itself — any more and the white card turns orange. */

html[data-design="v2"] .promo-panel__wash {
    position: absolute;
    z-index: -1;
    top: -140px;
    right: -140px;
    width: 380px;
    height: 380px;
    border-radius: 50%;
    background-image: radial-gradient(circle, rgba(var(--v2-accent-rgb), 0.16) 0%, rgba(var(--v2-accent-rgb), 0) 68%);
    pointer-events: none;
  }

html[data-design="v2"] .promo-panel__x {
    position: absolute;
    top: 20px;
    right: 20px;
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    border: 1px solid var(--color-hairline);
    background-color: #ffffff;
    color: var(--fg-muted);
    transition: border-color 0.2s ease, color 0.2s ease;
  }

html[data-design="v2"] .promo-panel__x:hover {
    border-color: var(--color-flame);
    color: var(--fg);
  }

/* The donor's app tile: a dark rounded square holding the mark, which is the
     one thing on this card that does not follow the light surface. */

html[data-design="v2"] .promo-mark {
    display: grid;
    place-items: center;
    width: 58px;
    height: 58px;
    border-radius: 16px;
    background-image: linear-gradient(180deg, #1c1c1c 0%, #0a0a0a 100%);
  }

html[data-design="v2"] .promo-eyebrow {
    margin-top: 26px;
    font-family: var(--font-display);
    font-size: var(--text-caption);
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--color-flame);
  }

/* Bigger than any step on the scale: the card is a poster, and at the h4 step
     the headline stopped carrying it. */

html[data-design="v2"] .promo-title {
    margin-top: 12px;
    font-family: var(--font-display);
    font-size: clamp(28px, 3.4vw, 40px);
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -0.01em;
    color: var(--fg);
  }

html[data-design="v2"] .promo-lede {
    margin-top: 16px;
    font-size: var(--text-small);
    line-height: 23px;
    color: var(--fg-muted);
  }

html[data-design="v2"] .promo-list {
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin-top: 24px;
    padding: 20px;
    border-radius: 16px;
    border: 1px solid var(--color-hairline);
  }

html[data-design="v2"] .promo-list li {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    font-size: var(--text-small);
    line-height: 20px;
    color: var(--fg-muted);
  }

html[data-design="v2"] .promo-list svg {
    flex: none;
    margin-top: 3px;
    color: var(--color-flame);
  }

html[data-design="v2"] .promo-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 22px;
    margin-top: 26px;
  }

/* Dark pill with a lit disc inside it — the donor's shape. The glow sits
     under the pill rather than around it, which is what stops it reading as a
     focus ring. */

html[data-design="v2"] .promo-cta {
    display: inline-flex;
    align-items: center;
    gap: 14px;
    padding: 8px 26px 8px 8px;
    border-radius: 999px;
    background-image: linear-gradient(180deg, #1c1c1c 0%, #0a0a0a 100%);
    font-family: var(--font-display);
    font-size: var(--text-h6);
    font-weight: 700;
    color: #ffffff;
    box-shadow: 0 8px 22px -6px rgba(var(--v2-accent-rgb), 0.55);
    transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.25s ease;
  }

html[data-design="v2"] .promo-cta:hover {
    transform: translateY(-2px);
    box-shadow: 0 12px 30px -6px rgba(var(--v2-accent-rgb), 0.7);
  }

html[data-design="v2"] .promo-cta__disc {
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    background-image: var(--gradient-flame);
    color: var(--fg-on-accent);
  }

html[data-design="v2"] .promo-cta:hover .promo-cta__disc svg { translate: 2px 0; }

html[data-design="v2"] .promo-cta__disc svg { transition: translate 0.25s cubic-bezier(0.22, 1, 0.36, 1); }

html[data-design="v2"] .promo-keep {
    font-family: var(--font-display);
    font-size: var(--text-small);
    font-weight: 500;
    color: var(--fg-subtle);
    transition: color 0.2s ease;
  }

html[data-design="v2"] .promo-keep:hover { color: var(--fg); }

html[data-design="v2"] .promo-note {
    margin-top: 18px;
    font-size: var(--text-caption);
    color: var(--fg-faint);
  }

/* ── Tier cards, glass cut ───────────────────────────────────────────────
     The same three profiles as .tier, drawn to a different reference: icon
     plate and the rate in the header, the name below, the checklist sunk into
     its own panel, the middle card raised on a flame rim.

     The glass is structural, not decorative. These cards sit straight on the
     artwork, so the side ones are dark glass — the gradient moves behind them
     when the page scrolls. The featured card is the exception: it goes solid,
     because it carries the flame rim, and a rim around a see-through panel
     reads as an empty frame. Being the one opaque object among glass is what
     makes it the default. */

html[data-design="v2"] .gtier-grid {
    display: grid;
    gap: 16px;
    width: 100%;
    align-items: start;
  }

@media (width >= 60rem) {
    html[data-design="v2"] .gtier-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
  }

html[data-design="v2"] .gtier {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 18px;
    padding: 26px;
    border-radius: 24px;
    border: 1px solid var(--color-hairline);
    background-image: linear-gradient(180deg, rgba(19, 19, 19, 0.62) 0%, rgba(0, 0, 0, 0.7) 100%);
    /* Do not build this sheet with --minify — Lightning CSS merges the pair
       and Safari loses the effect. Same story as the navbar. */
    backdrop-filter: blur(16px) saturate(1.25);
    -webkit-backdrop-filter: blur(16px) saturate(1.25);
    transition: border-color 0.25s ease, transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .gtier:hover { border-color: var(--color-hairline-strong); }

html[data-design="v2"] .gtier--featured {
    gap: 20px;
    border-color: transparent;
    background-image: var(--gradient-panel), var(--gradient-flame);
    background-origin: border-box;
    background-clip: padding-box, border-box;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    /* The reference pools its light under the card, not around it. */
    box-shadow: 0 34px 70px -34px rgba(var(--v2-accent-rgb), 0.55);
  }

@media (width >= 60rem) {
    html[data-design="v2"] .gtier--featured { transform: translateY(-14px); }
    html[data-design="v2"] .gtier--featured:hover { transform: translateY(-18px); }
  }

html[data-design="v2"] .gtier__flag {
    position: absolute;
    top: -12px;
    right: 24px;
    padding: 4px 12px;
    border-radius: 999px;
    background-image: var(--gradient-flame);
    font-family: var(--font-display);
    font-size: var(--text-caption);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--fg-on-accent);
    box-shadow: 0 6px 18px -4px rgba(var(--v2-accent-rgb), 0.6);
  }

/* Icon plate left, price block right — the reference's header row. */

html[data-design="v2"] .gtier__head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
  }

html[data-design="v2"] .gtier__icon {
    display: grid;
    place-items: center;
    width: 52px;
    height: 52px;
    border-radius: 14px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-glass);
    color: var(--fg);
  }

html[data-design="v2"] .gtier__price {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 2px;
    text-align: right;
    font-family: var(--font-display);
  }

html[data-design="v2"] .gtier__price b {
    font-size: 30px;
    font-weight: 700;
    line-height: 1;
    color: var(--fg);
    font-variant-numeric: tabular-nums;
  }

html[data-design="v2"] .gtier__price small {
    font-size: var(--text-caption);
    font-weight: 400;
    color: var(--fg-subtle);
  }

html[data-design="v2"] .gtier__saveline {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: var(--text-caption);
    color: var(--fg-faint);
  }

html[data-design="v2"] .gtier__saveline s { font-variant-numeric: tabular-nums; }

html[data-design="v2"] .gtier__name {
    font-family: var(--font-display);
    font-size: var(--text-h5);
    font-weight: 700;
    color: var(--fg);
  }

html[data-design="v2"] .gtier__for {
    margin-top: 6px;
    font-size: var(--text-small);
    line-height: 21px;
    color: var(--fg-muted);
  }

/* The sunken checklist. On the featured card it takes the accent's edge —
     the reference draws its middle list in a red frame. */

html[data-design="v2"] .gtier__list {
    display: flex;
    flex-direction: column;
    gap: 13px;
    padding: 18px;
    border-radius: 16px;
    border: 1px solid var(--color-hairline-dim);
    background-color: rgba(0, 0, 0, 0.25);
  }

html[data-design="v2"] .gtier--featured .gtier__list {
    border-color: rgba(var(--v2-accent-rgb), 0.45);
    background-color: rgba(var(--v2-accent-rgb), 0.05);
  }

html[data-design="v2"] .gtier__list li {
    display: flex;
    align-items: center;
    gap: 11px;
    font-size: var(--text-small);
    color: var(--fg-muted);
  }

html[data-design="v2"] .gtier__list b {
    margin-left: auto;
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--fg);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }

/* The reference's square tick. */

html[data-design="v2"] .gtier__check {
    flex: none;
    display: grid;
    place-items: center;
    width: 19px;
    height: 19px;
    border-radius: 6px;
    border: 1px solid var(--color-hairline-strong);
    background-color: var(--surface-1);
    color: var(--color-flame);
  }

html[data-design="v2"] .gtier--featured .gtier__check {
    border-color: transparent;
    background-image: var(--gradient-flame);
    color: var(--fg-on-accent);
  }

/* The reference's featured button is white — paper on a dark card. */

html[data-design="v2"] .btn--paper {
    background-color: #ffffff;
    border-color: transparent;
    font-family: var(--font-display);
    font-weight: 700;
    color: #0a0a0a;
  }

html[data-design="v2"] .btn--paper:hover { box-shadow: 0 10px 30px -8px rgba(255, 255, 255, 0.35); }

/* Glass cut of the coverage switch — the reference's dark pill with the lit
     active half, on our glass instead of flat dark. */

html[data-design="v2"] .seg--glass {
    background-image: var(--gradient-glass);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }

/* ══ DOCS ════════════════════════════════════════════════════════════════
     A copy of docs.vidnext.ai in the site's own parts. Three columns on a wide
     screen: the tree, the article, and what is on this page.

     The article gets a panel of its own while the two rails sit bare on the
     artwork. That split is deliberate — the rails are short labels a glow can
     sit behind, the article is several screens of technical prose and needs a
     surface. Same reasoning as the blog post, one shade darker: docs are a
     working surface, not a sheet of paper. */

html[data-design="v2"] .docs-layout {
    display: grid;
    gap: 30px;
    align-items: start;
  }

@media (width >= 64rem) {
    html[data-design="v2"] .docs-layout { grid-template-columns: 232px minmax(0, 1fr); gap: 40px; }
  }

@media (width >= 90rem) {
    html[data-design="v2"] .docs-layout { grid-template-columns: 232px minmax(0, 1fr) 200px; }
  }

/* The table of contents follows the page down. Three or four short labels,
     so the cap below is a formality — but it is the reason the cap exists at
     all, and the tree rail is explicitly exempt from it. */

@media (width >= 64rem) {
    /* Both classes, so this outranks the .docs-rail reset below whatever the
       source order — the table of contents carries both. */
    html[data-design="v2"] .docs-rail.docs-toc {
      position: sticky;
      top: 116px;
      /* 164, not 140: the rail's resting top is the section's 140px of
         padding, so a 140 subtrahend put its bottom edge exactly on the fold
         before the page is scrolled. */
      max-height: calc(100vh - 164px);
      overflow-y: auto;
      overscroll-behavior: contain;
    }
  }

/* The tree rail is shown whole and scrolls with the page — no cap, no
     scrollbar of its own.

     It used to be sticky and capped at the viewport, on the assumption that
     the tree would always be shorter than the article. Eleven demo links
     were; twenty-one real ones are not, and everything that assumption paid
     for then came due at once — the panel's bottom border sliced off at the
     fold, a permanent grey bar down its edge, the search button squashed
     from 44px to 24 because a flex item shrinks by default. A sidebar that
     scrolls inside a page that scrolls is two scrollbars for one list. It
     leaves the screen with the rest of the page instead. */

html[data-design="v2"] .docs-rail {
    position: static;
    max-height: none;
    overflow: visible;
  }

/* The button has one job and a fixed height; nothing above it should be
     able to squeeze it. Kept from when the rail was a flex container under a
     height cap — cheap, and it stops that failure returning. */

html[data-design="v2"] .docs-search { flex: none; }

/* The tree collapses below the docs layout's own breakpoint — see docs-nav. */

html[data-design="v2"] .docs-tree__summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 12px;
    border-radius: 12px;
    border: 1px solid var(--color-hairline);
    /* Same softened sheen as .docs-search, and for the same reason — this is
       the other full-width control in the rail. */
    background-image: linear-gradient(
      102.4deg,
      rgba(255, 255, 255, 0.08) 0%,
      rgba(255, 255, 255, 0) 100%
    );
    font-family: var(--font-display);
    font-size: var(--text-small);
    font-weight: 600;
    color: var(--fg);
    cursor: pointer;
    list-style: none;
  }

html[data-design="v2"] .docs-tree__summary::-webkit-details-marker { display: none; }

html[data-design="v2"] .docs-tree[open] .docs-tree__summary svg { rotate: 180deg; }

@media (width >= 64rem) {
    html[data-design="v2"] .docs-tree__summary { display: none; }
  }

/* ── Light theme ─────────────────────────────────────────────────────────
     The docs are the one place on the site that follows the theme instead of
     pinning itself to the artwork, so a handful of surfaces that only ever met
     a dark page need a light counterpart.

     --gradient-glass is white at 20% and vanishes on a white page. It is fixed
     here rather than at the root because everywhere else it meets `on-artwork`,
     which is dark in both themes — swapping the token globally would put a dark
     wash on the hero pills that sit on the artwork. */

html[data-design="v2"][data-theme="light"] .docs-search,
  html[data-design="v2"][data-theme="light"] .docs-card__icon,
  html[data-design="v2"][data-theme="light"] .docs-tree__summary {
    background-image: linear-gradient(102.4deg, rgba(4, 12, 19, 0.05) 0%, rgba(4, 12, 19, 0) 100%);
  }

/* The panels are near-white on a white page, so the hairline is doing all the
     separating; it gets a shadow to help. Dark keeps none — there a panel is
     raised by being lighter than its page, which the fill already does. */

html[data-design="v2"][data-theme="light"] .docs-panel,
  html[data-design="v2"][data-theme="light"] .docs-article,
  html[data-design="v2"][data-theme="light"] .docs-card,
  html[data-design="v2"][data-theme="light"] .cmdk__panel {
    box-shadow: 0 1px 2px rgba(4, 12, 19, 0.04), 0 12px 32px -20px rgba(4, 12, 19, 0.3);
  }

/* The tree sits on a panel of its own rather than bare on the artwork: the
     gradient runs bright behind the left rail exactly where the labels are, and
     at this size they were fighting it. */

html[data-design="v2"] .docs-panel {
    padding: 16px;
    border-radius: 20px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-panel);
  }

html[data-design="v2"] .docs-nav {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 10px;
  }

@media (width >= 64rem) {
    html[data-design="v2"] .docs-nav { margin-top: 0; }
  }

html[data-design="v2"] .docs-nav__group {
    margin-top: 18px;
    padding: 0 10px 6px;
    font-family: var(--font-display);
    font-size: var(--text-caption);
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--fg-faint);
  }

html[data-design="v2"] .docs-nav__group:first-child { margin-top: 0; }

html[data-design="v2"] .docs-nav a {
    display: block;
    padding: 7px 10px;
    border-radius: 8px;
    font-size: var(--text-small);
    line-height: 20px;
    color: var(--fg-subtle);
    transition: background-color 0.2s ease, color 0.2s ease;
  }

html[data-design="v2"] .docs-nav a:hover {
    background-color: var(--surface-1);
    color: var(--fg);
  }

/* The page you are on. A left rule rather than a fill: the tree is indented
     already, and a filled pill at this size reads as a button. */

html[data-design="v2"] .docs-nav a[aria-current="page"] {
    border-left: 2px solid var(--color-flame);
    border-radius: 0 8px 8px 0;
    background-color: rgba(var(--v2-accent-rgb), 0.08);
    font-weight: 600;
    color: var(--fg);
  }

html[data-design="v2"] .docs-nav__sub {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-left: 10px;
    padding-left: 10px;
    border-left: 1px solid var(--color-hairline-dim);
  }

/* Hidden by the search filter rather than removed, so the tree keeps its
     shape when the box is cleared. */

html[data-design="v2"] .docs-nav [hidden] { display: none; }

html[data-design="v2"] .docs-search {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    height: 44px;
    padding: 0 12px;
    border-radius: 12px;
    border: 1px solid var(--color-hairline);
    /* Not --gradient-glass. That fill peaks at rgba(255,255,255,0.2) in its
       top-left corner — the same value as the hairline border. Where the two
       meet, along this button's left edge, the border and the fill beneath it
       land one greyscale step apart (59 against 58) and the border stops
       existing; it reads as a missing pixel. Everywhere else the fill sits on
       something small enough that the bright corner is never a long straight
       run. Here it is 232px of edge, so the sheen is taken down to 0.08:
       still glass, but the border clears it by thirty steps and hover has
       room above that. */
    background-image: linear-gradient(
      102.4deg,
      rgba(255, 255, 255, 0.08) 0%,
      rgba(255, 255, 255, 0) 100%
    );
    color: var(--fg-subtle);
    transition: border-color 0.2s ease;
  }

html[data-design="v2"] .docs-search:focus-within { border-color: var(--color-flame); }

html[data-design="v2"] .docs-search__label {
    flex: 1;
    text-align: left;
    font-size: var(--text-small);
    color: var(--fg-faint);
  }

html[data-design="v2"] .docs-search:hover { border-color: var(--color-hairline-strong); }

html[data-design="v2"] .docs-kbd {
    flex: none;
    padding: 2px 7px;
    border-radius: 6px;
    border: 1px solid var(--color-hairline);
    background-color: var(--surface-1);
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--fg-faint);
  }

/* ── Search dialog ───────────────────────────────────────────────────────
     The donor's ⌘K palette. The index is the tree itself plus, on an article,
     its own headings — a static build has nothing else to search, and those are
     what the box is opened for anyway. */

html[data-design="v2"] .cmdk {
    position: fixed;
    inset: 0;
    z-index: 80;
    display: flex;
    justify-content: center;
    /* Without this the panel stretches to the full window height — a flex
       container aligns its items to stretch by default, and the panel has no
       height of its own to resist it. */
    align-items: flex-start;
    padding: 12vh 20px 20px;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.22s ease, visibility 0.22s;
  }

html[data-design="v2"] .cmdk.is-open {
    opacity: 1;
    visibility: visible;
  }

html[data-design="v2"] .cmdk__panel {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 560px;
    max-height: 100%;
    overflow: hidden;
    border-radius: 18px;
    border: 1px solid var(--color-hairline-strong);
    background-image: var(--gradient-panel);
    box-shadow: 0 40px 90px -30px rgba(0, 0, 0, 0.85);
    transform: scale(0.98) translateY(-6px);
    transition: transform 0.24s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .cmdk.is-open .cmdk__panel { transform: none; }

html[data-design="v2"] .cmdk__field {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px 18px;
    border-bottom: 1px solid var(--color-hairline-dim);
    color: var(--fg-subtle);
  }

html[data-design="v2"] .cmdk__field input {
    flex: 1;
    min-width: 0;
    background: transparent;
    border: 0;
    outline: none;
    font-size: var(--text-h6);
    color: var(--fg);
  }

html[data-design="v2"] .cmdk__field input::placeholder { color: var(--fg-faint); }

/* Sized to its content up to the panel's limit — flex:1 stretched a
     four-result list down the whole window. */

html[data-design="v2"] .cmdk__list {
    flex: 0 1 auto;
    min-height: 0;
    max-height: 46vh;
    overflow-y: auto;
    padding: 8px;
  }

html[data-design="v2"] .cmdk__group {
    padding: 12px 10px 6px;
    font-family: var(--font-display);
    font-size: var(--text-caption);
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--fg-faint);
  }

html[data-design="v2"] .cmdk__item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border-radius: 10px;
    font-size: var(--text-small);
    color: var(--fg-muted);
  }

html[data-design="v2"] .cmdk__item svg {
    flex: none;
    color: var(--fg-faint);
  }

/* One highlight, driven by the arrow keys — hover does not move it, or the
     pointer resting anywhere would fight whatever the keyboard selected. */

html[data-design="v2"] .cmdk__item.is-active {
    background-color: rgba(var(--v2-accent-rgb), 0.12);
    color: var(--fg);
  }

html[data-design="v2"] .cmdk__item.is-active svg { color: var(--color-flame); }

html[data-design="v2"] .cmdk__item mark {
    background: transparent;
    color: var(--color-flame);
    font-weight: 600;
  }

html[data-design="v2"] .cmdk__empty {
    padding: 26px 12px;
    text-align: center;
    font-size: var(--text-small);
    color: var(--fg-faint);
  }

html[data-design="v2"] .cmdk__foot {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    padding: 10px 18px;
    border-top: 1px solid var(--color-hairline-dim);
    font-size: var(--text-caption);
    color: var(--fg-faint);
  }

html[data-design="v2"] .cmdk__foot span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
  }

html[data-design="v2"] .docs-article {
    padding: 30px 24px;
    border-radius: 24px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-panel);
  }

@media (width >= 48rem) {
    html[data-design="v2"] .docs-article { padding: 44px; }
  }

html[data-design="v2"] .docs-crumb {
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: var(--font-display);
    font-size: var(--text-caption);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--color-flame);
  }

html[data-design="v2"] .docs-title {
    margin-top: 12px;
    font-family: var(--font-display);
    font-size: var(--text-h3);
    font-weight: 700;
    line-height: 1.12;
    color: var(--fg);
  }

html[data-design="v2"] .docs-lede {
    margin-top: 12px;
    padding-bottom: 26px;
    border-bottom: 1px solid var(--color-hairline-dim);
    font-size: var(--text-lead);
    line-height: 1.55;
    color: var(--fg-muted);
  }

/* A figure in the prose. The live docs put screenshots between paragraphs;
     until there are exports, this is the frame they land in. */

html[data-design="v2"] .docs-figure {
    display: grid;
    place-items: center;
    margin: 26px 0;
    padding: 20px;
    aspect-ratio: 16 / 8;
    border-radius: 16px;
    border: 1px dashed var(--color-hairline);
    background-color: var(--surface-1);
    font-size: var(--text-small);
    text-align: center;
    color: var(--fg-faint);
  }

/* On this page */

html[data-design="v2"] .docs-toc {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

html[data-design="v2"] .docs-toc__title {
    font-family: var(--font-display);
    font-size: var(--text-caption);
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--fg-faint);
  }

html[data-design="v2"] .docs-toc a {
    padding: 4px 0 4px 12px;
    border-left: 1px solid var(--color-hairline-dim);
    font-size: var(--text-small);
    line-height: 19px;
    color: var(--fg-subtle);
    transition: color 0.2s ease, border-color 0.2s ease;
  }

html[data-design="v2"] .docs-toc a:hover,
  html[data-design="v2"] .docs-toc a.is-current {
    border-color: var(--color-flame);
    color: var(--fg);
  }

/* Previous / next, the pair of cards that closes every docs page. */

html[data-design="v2"] .docs-pager {
    display: grid;
    gap: 12px;
    margin-top: 40px;
  }

@media (width >= 48rem) {
    html[data-design="v2"] .docs-pager { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }

html[data-design="v2"] .docs-pager a {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 16px 18px;
    border-radius: 14px;
    border: 1px solid var(--color-hairline);
    transition: border-color 0.2s ease, background-color 0.2s ease;
  }

html[data-design="v2"] .docs-pager a:hover {
    border-color: var(--color-hairline-strong);
    background-color: var(--surface-1);
  }

html[data-design="v2"] .docs-pager a:last-child { text-align: right; }

html[data-design="v2"] .docs-pager small {
    font-family: var(--font-display);
    font-size: var(--text-caption);
    color: var(--fg-faint);
  }

html[data-design="v2"] .docs-pager b {
    font-family: var(--font-display);
    font-size: var(--text-small);
    font-weight: 600;
    color: var(--fg);
  }

/* Docs home: the six entry cards. */

html[data-design="v2"] .docs-card {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 24px;
    border-radius: 20px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-panel);
    transition: border-color 0.25s ease, transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
  }

html[data-design="v2"] .docs-card:hover {
    border-color: var(--color-hairline-strong);
    transform: translateY(-3px);
  }

html[data-design="v2"] .docs-card--row {
    flex-direction: row;
    align-items: center;
    gap: 16px;
    padding: 18px 20px;
  }

html[data-design="v2"] .docs-card__icon {
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border-radius: 11px;
    border: 1px solid var(--color-hairline);
    background-image: var(--gradient-glass);
    color: var(--color-flame);
  }

html[data-design="v2"] .docs-card__name {
    font-family: var(--font-display);
    font-size: var(--text-h6);
    font-weight: 600;
    color: var(--fg);
  }

html[data-design="v2"] .docs-card__desc {
    font-size: var(--text-small);
    line-height: 21px;
    color: var(--fg-subtle);
  }

/* ── Coverage switch ─────────────────────────────────────────────────── */

html[data-design="v2"] .seg {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px;
    border-radius: 999px;
    border: 1px solid var(--color-hairline);
    background-color: var(--surface-1);
  }

html[data-design="v2"] .seg button {
    padding: 7px 16px;
    border-radius: 999px;
    font-family: var(--font-display);
    font-size: var(--text-small);
    font-weight: 600;
    color: var(--fg-subtle);
    white-space: nowrap;
    transition: background-color 0.2s ease, color 0.2s ease;
  }

html[data-design="v2"] .seg button:hover { color: var(--fg); }

html[data-design="v2"] .seg button[aria-pressed="true"] {
    background-image: var(--gradient-flame);
    color: var(--fg-on-accent);
  }

/* The full ladder as a table — twelve packages is too many for cards, and the
     only question it answers is how the per-minute rate falls with size. */

html[data-design="v2"] .price-table td:not(:first-child),
  html[data-design="v2"] .price-table th:not(:first-child) {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }

/* The row the planner landed on. Read-only: the table reports the answer,
     it is not a second way to give one. */

html[data-design="v2"] .price-table tr[data-price-row] td { transition: background-color 0.2s ease; }

html[data-design="v2"] .price-table tr[data-price-row].is-current td {
    background-color: rgba(var(--v2-accent-rgb), 0.1);
    color: var(--fg);
  }

/* ============================================================================
   STATE
   ========================================================================== */

/* Both rules are unlayered on purpose: the nav carries px-6 and the logo carries
   h-[70px]/w-[69px] as utilities, and the utilities layer beats components no
   matter the specificity. */
/* Unlayered: the row carries px-[14px] as a utility, and a utility outranks
   anything in the components layer. */
html[data-design="v2"] .site-nav.is-stuck > nav {
  padding-inline: 34px;
}

@media (width < 64rem) {
  html[data-design="v2"] .site-nav.is-stuck > nav {
    padding-inline: 28px;
  }
}

html[data-design="v2"] .site-nav.is-stuck img[alt="VidNext"] {
  height: 34px;
  width: 34px;
}

/* Prompt field: the demo and the real input swap on focus.
   Deliberately outside @layer — the input carries the opacity-0 utility, and
   the utilities layer wins over components regardless of specificity. */
html[data-design="v2"] [data-prompt].is-editing [data-demo] { opacity: 0; }
html[data-design="v2"] [data-prompt].is-editing [data-idea] { opacity: 1; }

/* A surface whose own colour does not follow the theme, so its contents must not
   either. Two of them:

   - the hero, which is artwork: a warm ellipse with a black one subtracting it,
     and pinning only the black one would leave dark ink on a dark picture;
   - a testimonial card under the pointer, which fills with the brand gradient —
     the accent is the same in both themes, so everything on it stays light.

   Redeclaring the tokens is enough: everything inside reads them through the
   cascade, so no element needs to know which theme is on. */
html[data-design="v2"] .on-artwork,
html[data-design="v2"] .quote-card:hover {
  --fg:        #ffffff;
  --fg-muted:  rgba(255, 255, 255, 0.8);
  --fg-subtle: rgba(255, 255, 255, 0.6);
  --fg-faint:  rgba(255, 255, 255, 0.4);
  --fg-ghost:  rgba(255, 255, 255, 0.25);

  --hairline:        rgba(255, 255, 255, 0.2);
  --hairline-dim:    rgba(255, 255, 255, 0.08);
  --hairline-strong: rgba(255, 255, 255, 0.4);

  --surface-1: rgba(255, 255, 255, 0.04);
  --surface-2: rgba(255, 255, 255, 0.08);
  --surface-3: rgba(255, 255, 255, 0.16);

  /* The --color-* names have to be restated, not just the values behind them.
     Tailwind declares them on :root as `--color-fg: var(--fg)`, and that
     substitution happens on :root — descendants inherit the resolved colour, so
     redeclaring --fg further down the tree changes nothing on its own. */
  --color-fg:        #ffffff;
  --color-fg-muted:  rgba(255, 255, 255, 0.8);
  --color-fg-subtle: rgba(255, 255, 255, 0.6);
  --color-fg-faint:  rgba(255, 255, 255, 0.4);
  --color-fg-ghost:  rgba(255, 255, 255, 0.25);

  --color-hairline:        rgba(255, 255, 255, 0.2);
  --color-hairline-dim:    rgba(255, 255, 255, 0.08);
  --color-hairline-strong: rgba(255, 255, 255, 0.4);

  --color-surface-1: rgba(255, 255, 255, 0.04);
  --color-surface-2: rgba(255, 255, 255, 0.08);
  --color-surface-3: rgba(255, 255, 255, 0.16);

}

/* Surface fills, and only for the hero. A hovered card must not take these: it
   keeps its own light panel and lays the brand gradient over it — inheriting the
   hero's near-black panel is what turned the card muddy in the light theme.
   Declared here rather than at :root for the usual reason: Tailwind resolves
   --gradient-panel and --color-ink on :root, so redeclaring what they point at
   further down the tree changes nothing. */
html[data-design="v2"] .on-artwork {
  --gradient-panel:  linear-gradient(180deg, #131313 0%, #000000 100%);
  --color-ink:       #0a0a0a;
  --color-ink-soft:  #131313;
  --fill-tile:       #18181b;
  --fill-sculpted:   linear-gradient(180deg, #282828 15%, #171717 50%, #282828 85%);
  --fill-well:       linear-gradient(180deg, #1f1e1e 0%, #343434 49.5%, #484848 100%);
  /* Inert on the landing, where the hero is the only thing wearing this class.
     The document pages wrap the whole page in it, footer included — and a
     footer that followed the theme would end a dark artwork page with a white
     slab in the light one. */
  --fill-footer:     linear-gradient(180deg, #0a0a0a 0%, #070707 100%);
  /* Inert on the dark theme, which never changed it. In the light one the page
     took a darker ramp for contrast on white — but artwork is dark in both, so
     here it keeps the original. */
  --gradient-title:  linear-gradient(225deg, var(--v2-sand) 0%, var(--v2-flame) 70%, var(--v2-flame-deep) 100%);
}

/* The same idea pointed the other way: a surface that is light whatever the
   theme, so its contents have to be dark whatever the theme. Two wear it:

   - the document card, which is white paper laid over the artwork;
   - the navbar, while it is passing over that card. The bar is transparent and
     the glass pill is barely tinted, so over white paper its white links
     vanished — initStickyNav() swaps this in for `on-artwork` on the overlap
     and back out again.

   Both the --fg and the --color-fg names have to be set, for the reason spelled
   out above .on-artwork: Tailwind resolves `--color-fg: var(--fg)` on :root, so
   redeclaring only --fg further down the tree leaves every utility class
   pointing at the colour that was resolved up there. */
html[data-design="v2"] .on-light,
html[data-design="v2"] .doc-card,
html[data-design="v2"] .promo-panel {
  --fg:        var(--fg-on-light);
  --fg-muted:  var(--fg-on-light-muted);
  --fg-subtle: rgba(0, 0, 0, 0.55);
  --fg-faint:  rgba(0, 0, 0, 0.4);
  --fg-ghost:  rgba(0, 0, 0, 0.25);

  --hairline:        rgba(0, 0, 0, 0.12);
  --hairline-dim:    rgba(0, 0, 0, 0.07);
  --hairline-strong: rgba(0, 0, 0, 0.24);

  --surface-1: rgba(0, 0, 0, 0.03);
  --surface-2: rgba(0, 0, 0, 0.06);
  --surface-3: rgba(0, 0, 0, 0.12);

  --color-fg:        var(--fg-on-light);
  --color-fg-muted:  var(--fg-on-light-muted);
  --color-fg-subtle: rgba(0, 0, 0, 0.55);
  --color-fg-faint:  rgba(0, 0, 0, 0.4);
  --color-fg-ghost:  rgba(0, 0, 0, 0.25);

  --color-hairline:        rgba(0, 0, 0, 0.12);
  --color-hairline-dim:    rgba(0, 0, 0, 0.07);
  --color-hairline-strong: rgba(0, 0, 0, 0.24);

  --color-surface-1: rgba(0, 0, 0, 0.03);
  --color-surface-2: rgba(0, 0, 0, 0.06);
  --color-surface-3: rgba(0, 0, 0, 0.12);

  /* Panels nested inside the sheet. On paper a panel is raised by a hairline and
     the faintest wash, not by being lighter than its surroundings the way it is
     on the dark page. Without these a `bg-panel` child would keep painting
     near-black on white. */
  --gradient-panel: linear-gradient(180deg, #ffffff 0%, #f4f4f4 100%);
  --panel-fill:     linear-gradient(180deg, #ffffff 0%, #f4f4f4 100%);
  --color-ink:      #ffffff;
  --color-ink-soft: #f5f5f5;
  --fill-tile:      #ffffff;
}

/* The mark is a raster of pale neon and cannot follow a token, so it is filtered
   instead — the same darkening the light theme already applies to it once the
   bar leaves the hero, keyed here to the surface rather than to the theme. */
html[data-design="v2"] .site-nav.on-light .site-nav__mark {
  filter: grayscale(1) brightness(0.32);
}


/* ============================================================================
   ANIMATION
   ========================================================================== */

/* Scroll reveal. The initial hidden state is scoped to .js so the content
   stays visible if the script never runs. */
html[data-design="v2"] .js .reveal {
  opacity: 0;
  transform: translateY(26px);
  /* translate is listed here, not left to .card-lift, because this rule is
     unlayered and its shorthand would reset whatever .card-lift declared.
     Only the reveal's own two properties carry the stagger — the hover lift
     has to answer the pointer immediately. */
  transition: opacity 0.9s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.9s cubic-bezier(0.22, 1, 0.36, 1),
              translate 0.25s cubic-bezier(0.22, 1, 0.36, 1);
  transition-delay: var(--reveal-delay, 0ms), var(--reveal-delay, 0ms), 0ms;
}

html[data-design="v2"] .js .reveal.is-revealed {
  opacity: 1;
  transform: none;
}

/* Section rules enter the way the donor's do: growing out from the centre while
   they fade up, one second on an out-quart. Scoped to .js for the same reason
   as .reveal — with no script the rules must simply be there.

   The dome of light under them is left alone on purpose. On the donor it is a
   static blurred ellipse with no interaction attached; animating it too would
   read as the whole section flickering rather than an edge being drawn. */
html[data-design="v2"] .js .section-edge::after,
html[data-design="v2"] .js .section-edge--both::before {
  opacity: 0;
  scale: 0.75;
  transition: opacity 1s cubic-bezier(0.165, 0.84, 0.44, 1),
              scale 1s cubic-bezier(0.165, 0.84, 0.44, 1);
}

html[data-design="v2"] .js .section-edge.is-edge-bottom::after,
html[data-design="v2"] .js .section-edge--both.is-edge-top::before {
  opacity: 1;
  scale: 1;
}

/* One 7s loop shared by the chart's three parts: draw to 34%, hold to 62%,
   fade out by 76%, then rest until 100%. Both reveals reset during that rest,
   while the chart is already invisible. */
/* Travel finishes at 62%; the rest of the cycle is the gap before the next
   comet. The reset to 0 happens while opacity is already 0. */
@keyframes v2-wire-run {
  0%        { stroke-dashoffset: 0; }
  62%, 100% { stroke-dashoffset: 1; }
}

@keyframes v2-wire-glow {
  0%, 4%    { opacity: 0; }
  16%, 48%  { opacity: 0.85; }
  62%, 100% { opacity: 0; }
}

/* Only the panel you are looking at animates, and it starts from frame zero
   every time you arrive. Clearing animation-name is what does the rewind:
   pausing merely freezes the clock, so a panel revisited later would resume
   mid-scene. Unlayered, because the scene rules live in @layer components.

   Every scene element rests in its finished state, never its first frame, so
   dropping the animation leaves a complete picture — which is what the panels
   peeking at the edges show, and what anyone on prefers-reduced-motion gets. */
html[data-design="v2"] .demo-panel:not(.is-active) * {
  animation: none;
}

/* ── Section 4 demo scenes ───────────────────────────────────────────────
   One 8s loop per scene, matching the carousel's dwell time. Everything is
   done and held by ~70%, leaving the tail as the pause before the panel
   either advances or replays. */

/* Scene 3 — five beats on a 12s clock. Turns at 19.2 / 36.7 / 54.2 / 80 per
   cent, i.e. 2.3 / 4.4 / 6.5 / 9.6 seconds, the same as the original. */
@keyframes v2-bld-h1 {
  0%          { opacity: 0; transform: translateY(-6px); }
  2%, 19.2%   { opacity: 1; transform: none; }
  21.7%, 100% { opacity: 0; transform: translateY(-6px); }
}

@keyframes v2-bld-h2 {
  0%, 19.2%    { opacity: 0; transform: translateY(-6px); }
  21.7%, 36.7% { opacity: 1; transform: none; }
  39.2%, 100%  { opacity: 0; transform: translateY(-6px); }
}

@keyframes v2-bld-h3 {
  0%, 36.7%    { opacity: 0; transform: translateY(-6px); }
  39.2%, 54.2% { opacity: 1; transform: none; }
  56.7%, 100%  { opacity: 0; transform: translateY(-6px); }
}

@keyframes v2-bld-h4 {
  0%, 54.2%   { opacity: 0; transform: translateY(-6px); }
  56.7%, 80%  { opacity: 1; transform: none; }
  82.5%, 100% { opacity: 0; transform: translateY(-6px); }
}

/* Results do not simply fade — they shrink toward the hub they are feeding */
@keyframes v2-bld-s1 {
  0%, 19.2%   { opacity: 1; transform: none; }
  23%, 100%   { opacity: 0; transform: scale(0.6); }
}

@keyframes v2-bld-s2 {
  0%, 19.2%    { opacity: 0; transform: scale(0.85); }
  21.7%, 36.7% { opacity: 1; transform: none; }
  40.5%, 100%  { opacity: 0; transform: scale(0.6); }
}

@keyframes v2-bld-s3 {
  0%, 36.7%    { opacity: 0; transform: scale(0.85); }
  39.2%, 54.2% { opacity: 1; transform: none; }
  58%, 100%    { opacity: 0; transform: scale(0.6); }
}

@keyframes v2-bld-s4 {
  0%, 54.2%   { opacity: 0; }
  57%, 80%    { opacity: 1; }
  82.5%, 100% { opacity: 0; }
}

@keyframes v2-bld-s5 {
  0%, 80%     { opacity: 0; transform: scale(0.94); }
  83.5%, 100% { opacity: 1; transform: none; }
}

@keyframes v2-bld-card-in {
  from { opacity: 0; transform: translateX(26px); }
  to   { opacity: 1; transform: none; }
}

@keyframes v2-bld-shot-in {
  from { opacity: 0; transform: translateX(var(--shot-x)) scale(0.9); }
  to   { opacity: 1; transform: none; }
}

@keyframes v2-bld-design-in {
  0%   { opacity: 0; scale: 0.6; }
  70%  { opacity: 1; scale: 1.05; }
  100% { opacity: 1; scale: 1; }
}

@keyframes v2-bld-found {
  from { --v2-mix: 0; }
  to   { --v2-mix: 24; }
}

@keyframes v2-bld-pop {
  0%   { opacity: 0; transform: scale(0.5); }
  70%  { opacity: 1; transform: scale(1.06); }
  100% { opacity: 1; transform: scale(1); }
}

@keyframes v2-bld-count {
  from { --v2-mix: 0; }
  to   { --v2-mix: 100; }
}

/* Scene 4 — the playhead crosses once per cycle; the two edits land at
   2.5-3.9s and 4.3-5.5s, each announced a beat before it is applied. */
@keyframes v2-ed-in {
  from { opacity: 0; transform: translateY(16px) scale(0.99); }
  to   { opacity: 1; transform: none; }
}

@keyframes v2-ed-clip-in {
  from { opacity: 0; transform: translateX(-14px); }
  to   { opacity: 1; transform: none; }
}

@keyframes v2-ed-playhead {
  0%   { left: 22px; }
  100% { left: calc(100% - 22px); }
}

/* The overlay is dragged along its track, not teleported */
@keyframes v2-ed-move {
  0%, 30%    { transform: translateX(0); }
  43%, 100%  { transform: translateX(88px); }
}

@keyframes v2-ed-extend {
  0%, 50%    { width: var(--w); }
  61%, 100%  { width: calc(var(--w) + 5%); }
}

@keyframes v2-ed-eq {
  0%, 100% { height: 4px; }
  50%      { height: 13px; }
}

@keyframes v2-ed-toast-move {
  0%, 26%     { opacity: 0; transform: translateY(-6px); }
  29%, 42%    { opacity: 1; transform: none; }
  45%, 100%   { opacity: 0; transform: translateY(-6px); }
}

@keyframes v2-ed-toast-narr {
  0%, 46%     { opacity: 0; transform: translateY(-6px); }
  49%, 60%    { opacity: 1; transform: none; }
  63%, 100%   { opacity: 0; transform: translateY(-6px); }
}

/* Scene 3 — three beats on an 11s clock: footage search to 6.0s (54.5%),
   hub to 8.5s (77.3%), then the ready card holds to the end. */
/* The list does not just fade: it shrinks toward the hub it is feeding */
@keyframes v2-bld-pop {
  0%   { opacity: 0; transform: scale(0.5); }
  70%  { opacity: 1; transform: scale(1.06); }
  100% { opacity: 1; transform: scale(1); }
}

@keyframes v2-bld-count {
  from { --v2-mix: 0; }
  to   { --v2-mix: 100; }
}

/* Scene 2 — five sub-scenes on a 13s clock. The turns land at 13.1 / 26.2 /
   40 / 73.8 per cent, which is 1.7 / 3.4 / 5.2 / 9.6 seconds: the same beats
   the original composition uses. Each scene slides in from the right and
   leaves to the left, overlapping its neighbour by about a third of a second. */
@keyframes v2-cfg-s1 {
  0%          { opacity: 0; transform: translateX(46px); }
  3.5%, 13.1% { opacity: 1; transform: none; }
  16.5%, 100% { opacity: 0; transform: translateX(-46px); }
}

@keyframes v2-cfg-s2 {
  0%, 13.1%    { opacity: 0; transform: translateX(46px); }
  16.5%, 26.2% { opacity: 1; transform: none; }
  29.6%, 100%  { opacity: 0; transform: translateX(-46px); }
}

@keyframes v2-cfg-s3 {
  0%, 26.2%    { opacity: 0; transform: translateX(46px); }
  29.6%, 40%   { opacity: 1; transform: none; }
  43.4%, 100%  { opacity: 0; transform: translateX(-46px); }
}

@keyframes v2-cfg-s4 {
  0%, 40%      { opacity: 0; transform: translateX(46px); }
  43.4%, 73.8% { opacity: 1; transform: none; }
  77.2%, 100%  { opacity: 0; transform: translateX(-46px); }
}

@keyframes v2-cfg-s5 {
  0%, 73.8%   { opacity: 0; transform: translateX(46px); }
  77.2%, 100% { opacity: 1; transform: none; }
}

@keyframes v2-cfg-chip {
  from { opacity: 0; transform: translateY(-8px) scale(0.85); }
  to   { opacity: 1; transform: none; }
}

/* The dial runs past the answer and comes back, as the original does */
@keyframes v2-cfg-dial {
  0%   { --v2-mix: 1; }
  62%  { --v2-mix: 14; }
  100% { --v2-mix: 12; }
}

@keyframes v2-cfg-slide {
  0%   { --v2-pos: 3%; }
  62%  { --v2-pos: 46%; }
  100% { --v2-pos: 38%; }
}

@keyframes v2-cfg-pick {
  0%   { transform: scale(0.97); }
  55%  { transform: scale(1.03); }
  100% { transform: scale(1); }
}

/* Each source overshoots and settles: on the original the earlier bars are
   diluted as the next one is added, so nobody lands straight on their number. */
@keyframes v2-cfg-mix {
  0%   { --v2-mix: 0; }
  47%  { --v2-mix: var(--peak); }
  100% { --v2-mix: var(--pct); }
}

/* Scene 1 on a 7s clock — the same seconds the original uses: box in at 0.6s,
   typing 1.2s to 4.0s, button at 4.2s, status pill at 5.8s, then a beat of
   hold before the carousel moves on. */
@keyframes v2-s1-label {
  0%       { opacity: 0; transform: translateY(6px); }
  5%, 100% { opacity: 1; transform: none; }
}

@keyframes v2-s1-box {
  0%, 8.6%  { opacity: 0; transform: translateY(52px) scale(0.96); }
  15%, 100% { opacity: 1; transform: none; }
}

/* steps() on width is what makes this read as typing rather than a wipe */
@keyframes v2-s1-type {
  0%, 17.1%   { width: 0; }
  57.1%, 100% { width: calc(var(--chars) * 1ch); }
}

/* The click lands at 4.3s — 61.4% of the 7s clock */
@keyframes v2-s1-press {
  0%, 61.4%   { scale: 1; }
  63.5%       { scale: 0.93; }
  67%, 100%   { scale: 1; }
}

@keyframes v2-s1-ripple {
  0%, 61.4%   { opacity: 0; scale: 0.3; }
  63.5%       { opacity: 0.85; scale: 1; }
  72%, 100%   { opacity: 0; scale: 3.4; }
}

@keyframes v2-s1-stage-idle {
  0%, 61.4%   { opacity: 1; }
  65%, 100%   { opacity: 0; }
}

@keyframes v2-s1-stage-run {
  0%, 63.5%   { opacity: 0; }
  67%, 100%   { opacity: 1; }
}

@keyframes v2-s1-status {
  0%, 82.9%   { opacity: 0; transform: translateY(19px); }
  88.6%, 100% { opacity: 1; transform: none; }
}

@keyframes v2-s1-spin {
  to { transform: rotate(360deg); }
}

@keyframes v2-demo-caret {
  0%, 100% { border-color: rgb(var(--accent)); }
  50%      { border-color: transparent; }
}

/* The rim peaks at 6%, while the wire's own glow is still ramping in from
   4% to 16% — that overlap is the hand-off from chip to line. */
@keyframes v2-chip-spark {
  0%        { opacity: 0; }
  6%        { opacity: 1; }
  26%, 100% { opacity: 0; }
}

@keyframes v2-chart-fade {
  0%, 62%   { opacity: 1; animation-timing-function: ease-in-out; }
  76%, 100% { opacity: 0; }
}

/* The reveals rewind at 88%, well inside the invisible window that starts at
   76%. Holding them "drawn" until 100% raced the opacity jump at the loop
   wrap — opacity is composited, mask-position and dashoffset are not, so the
   finished chart flashed for a frame before resetting. */
@keyframes v2-chart-curtain {
  0% {
    -webkit-mask-position: 100% 0;
    mask-position: 100% 0;
    animation-timing-function: cubic-bezier(0.33, 0, 0.25, 1);
  }
  40%, 88% {
    -webkit-mask-position: 0 0;
    mask-position: 0 0;
  }
  89%, 100% {
    -webkit-mask-position: 100% 0;
    mask-position: 100% 0;
  }
}

@keyframes v2-chart-line {
  0%        { stroke-dashoffset: 1; animation-timing-function: cubic-bezier(0.33, 0, 0.25, 1); }
  40%, 88%  { stroke-dashoffset: 0; }
  89%, 100% { stroke-dashoffset: 1; }
}

/* Rises from the baseline, holds, then fades out at full height. The reset to
   scaleY(0) rides the 100% -> 0% wrap, where opacity is already 0, so the snap
   back is never visible. Timing is per keyframe: a spring for the rise, a flat
   ease for the fade — one shared curve makes the fade lurch. */
@keyframes v2-bar-cycle {
  0% {
    transform: scaleY(0);
    opacity: var(--bar-opacity, 1);
    animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
  }
  20%, 72% {
    transform: scaleY(1);
    opacity: var(--bar-opacity, 1);
    animation-timing-function: ease-in-out;
  }
  92%, 100% {
    transform: scaleY(1);
    opacity: 0;
  }
}

@keyframes v2-marquee-y {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(0, calc(var(--marquee-shift) * -1), 0); }
}

html[data-design="v2"] .marquee-column {
  animation: v2-marquee-y var(--marquee-duration, 60s) linear infinite;
  will-change: transform;
}

html[data-design="v2"] .marquee-column--reverse { animation-direction: reverse; }

html[data-design="v2"] .marquee-y:hover .marquee-column { animation-play-state: paused; }

@keyframes v2-marquee {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(calc(var(--marquee-shift) * -1), 0, 0); }
}

html[data-design="v2"] .marquee-track {
  animation: v2-marquee var(--marquee-duration, 32s) linear infinite;
  will-change: transform;
}



html[data-design="v2"] .marquee:hover .marquee-track {
  animation-play-state: paused;
}

@keyframes v2-caret-blink {
  0%, 45%   { opacity: 1; }
  55%, 100% { opacity: 0; }
}

html[data-design="v2"] .caret {
  animation: v2-caret-blink 1.05s steps(1) infinite;
}

@keyframes v2-spin-slow {
  to { transform: rotate(360deg); }
}

html[data-design="v2"] .spin-slow {
  animation: v2-spin-slow 2.4s linear infinite;
}

@keyframes v2-playhead-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(var(--v2-accent-rgb), 0.55); }
  70%      { box-shadow: 0 0 0 12px rgba(var(--v2-accent-rgb), 0); }
}

html[data-design="v2"] .playhead-dot {
  animation: v2-playhead-pulse 2.2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

/* Slow drift of the hero background particles */
@keyframes v2-drift {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(0, -18px, 0) scale(1.04); }
  100% { transform: translate3d(0, 0, 0) scale(1); }
}

html[data-design="v2"] .drift {
  animation: v2-drift var(--drift-duration, 18s) ease-in-out infinite;
  animation-delay: var(--drift-delay, 0s);
}

/* ── Hero background breathing ───────────────────────────────────────────
   In Figma this is the hero-orange component: two variants driven by Smart
   Animate. Neither ellipse moves — the variants share centres (light 719/384,
   shadow 1284/326) and only the size changes, in opposite directions.

       light   1854.08x1502.61 -> 1754.63x1422.02   = scale 0.9464
       shadow  1525.33x970.66  -> 2006.54x1276.89   = scale 1.3155

   Prototype timing: After delay 800ms -> Smart animate 3000ms, Ease out.
   Full round trip = 2 x (800 + 3000) = 7600ms, hence the percentages:
   800/7600 = 10.53%, 3800/7600 = 50%, 4600/7600 = 60.53%. */

@keyframes v2-glow-light-breathe {
  0%     { transform: scale(1); }
  10.53% { transform: scale(1);      animation-timing-function: cubic-bezier(0, 0, 0.58, 1); }
  50%    { transform: scale(0.9464); }
  60.53% { transform: scale(0.9464); animation-timing-function: cubic-bezier(0, 0, 0.58, 1); }
  100%   { transform: scale(1); }
}

@keyframes v2-glow-shadow-breathe {
  0%     { transform: rotate(43.53deg) scale(1); }
  10.53% { transform: rotate(43.53deg) scale(1);      animation-timing-function: cubic-bezier(0, 0, 0.58, 1); }
  50%    { transform: rotate(43.53deg) scale(1.3155); }
  60.53% { transform: rotate(43.53deg) scale(1.3155); animation-timing-function: cubic-bezier(0, 0, 0.58, 1); }
  100%   { transform: rotate(43.53deg) scale(1); }
}

html[data-design="v2"] .hero-glow {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background-color: var(--color-ink);
}

/* Page-wide artwork — the inner pages hang the gradient off the window instead
   of off a section.

   Fixed rather than absolute: the ellipses are drawn to the frame they sit in,
   so stretched down a 70-screen Terms of Service they would smear into bands.
   Pinned to the window they keep the landing's proportions at every scroll
   position.

   Its ink is pinned dark. .hero-glow paints --color-ink, which is the page
   colour and turns white in the light theme — and a white base bleaches the
   pale end of the gradient into the page, taking the white text on it with it.

   This sits beside .hero-glow rather than in the components layer, which is
   where it started: .hero-glow is unlayered, so a layered override of its
   position and fill lost to it and the artwork stayed absolute and white. */
html[data-design="v2"] .page-art {
  position: fixed;
  z-index: -1;
  background-color: var(--glow-ink);
}

/* Warm glow. The design uses a slightly skewed radial gradient; its axes are
   near-perpendicular and near-equal (1690 and 1724), so it is reduced to a
   circular one centred on the frame's top-right corner. */
html[data-design="v2"] .hero-glow__light {
  position: absolute;
  left: -14.444%;
  top: -28.231%;
  width: 128.756%;
  height: 115.585%;
  border-radius: 50%;
  background: radial-gradient(
    92.07% 113.6% at 88.483% 25.131%,
    var(--v2-flame-deep) 0%,
    var(--v2-flame-deep) 55.29%,
    var(--v2-glow-gold) 83.65%,
    var(--v2-sand) 100%
  );
  filter: blur(100px);
  will-change: transform;
  animation: v2-glow-light-breathe var(--glow-cycle, 7600ms) linear infinite;
}

/* Dark ellipse on top — kills the glow on the right */
html[data-design="v2"] .hero-glow__shadow {
  position: absolute;
  left: 36.217%;
  top: -12.244%;
  width: 105.926%;
  height: 74.666%;
  border-radius: 50%;
  background-color: var(--glow-ink);
  transform: rotate(43.53deg);
  filter: blur(200px);
  will-change: transform;
  animation: v2-glow-shadow-breathe var(--glow-cycle, 7600ms) linear infinite;
}

/* ── The artwork, and the pages on it, in the light theme ────────────────
   The blog and changelog wrap their whole tree in .on-artwork, which exists to
   say "this surface does not follow the theme, so its contents must not
   either". That was true while the artwork was pinned dark in both themes: the
   page went white underneath but the fixed .page-art covered it, so the light
   theme was inert on those pages while /docs switched properly.

   The artwork follows the theme instead. Its composition is unchanged — one
   warm ellipse, one ink ellipse subtracting from it — because both the page
   base and the shadow ellipse read a single token. Flipping --glow-ink to
   white turns the subtracting ellipse into a white one, and the warm ellipse
   becomes a dawn wash bleeding out of the top-left corner.

   The original reason for pinning it dark ("a white base bleaches the pale end
   of the gradient into the page, taking the white text on it with it") was
   about white text. In this theme the text is ink, so the concern inverts:
   what matters now is that the wash stays light enough to read ink on, which
   is what the opacity below is for. */

html[data-design="v2"][data-theme="light"] {
  --glow-ink: #ffffff;
}

/* The warm ellipse is authored at full strength for a near-black base. On
   white it would be a sunset, not a wash, and ink on it would fight. */
html[data-design="v2"][data-theme="light"] .hero-glow__light {
  opacity: 0.42;
}

/* Contents follow the theme again. Both the --x and --color-x names have to be
   restored, for the reason spelled out above .on-artwork: Tailwind resolves
   --color-fg: var(--fg) on :root, so redeclaring only --fg further down the
   tree leaves every utility class pointing at the value resolved up there. */
html[data-design="v2"][data-theme="light"] .on-artwork {
  --fg:        #040c13;
  --fg-muted:  rgba(4, 12, 19, 0.8);
  --fg-subtle: rgba(4, 12, 19, 0.6);
  --fg-faint:  rgba(4, 12, 19, 0.4);
  --fg-ghost:  rgba(4, 12, 19, 0.25);

  --hairline:        rgba(0, 0, 0, 0.12);
  --hairline-dim:    rgba(0, 0, 0, 0.07);
  --hairline-strong: rgba(0, 0, 0, 0.24);

  --surface-1: rgba(0, 0, 0, 0.04);
  --surface-2: rgba(0, 0, 0, 0.07);
  --surface-3: rgba(0, 0, 0, 0.12);

  --color-fg:        #040c13;
  --color-fg-muted:  rgba(4, 12, 19, 0.8);
  --color-fg-subtle: rgba(4, 12, 19, 0.6);
  --color-fg-faint:  rgba(4, 12, 19, 0.4);
  --color-fg-ghost:  rgba(4, 12, 19, 0.25);

  --color-hairline:        rgba(0, 0, 0, 0.12);
  --color-hairline-dim:    rgba(0, 0, 0, 0.07);
  --color-hairline-strong: rgba(0, 0, 0, 0.24);

  --color-surface-1: rgba(0, 0, 0, 0.04);
  --color-surface-2: rgba(0, 0, 0, 0.07);
  --color-surface-3: rgba(0, 0, 0, 0.12);

  /* Surface fills, back to the light ramp. */
  --gradient-panel:  var(--panel-fill);
  --color-ink:       #ffffff;
  --color-ink-soft:  #f7f7f7;
  --fill-tile:       #ffffff;
  --fill-sculpted:   linear-gradient(180deg, #ffffff 15%, #eeeeee 50%, #ffffff 85%);
  --fill-well:       linear-gradient(180deg, #dcdcdc 0%, #efefef 49.5%, #ffffff 100%);
  --fill-footer:     linear-gradient(180deg, #ffffff 0%, #f4f4f4 100%);
  --gradient-title:  linear-gradient(225deg, var(--v2-flame-soft) 0%, var(--v2-flame) 55%, var(--v2-flame-deep) 100%);
}

/* Honour the reduced-motion preference */
@media (prefers-reduced-motion: reduce) {
  html[data-design="v2"] *,
  html[data-design="v2"] *::before,
  html[data-design="v2"] *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  html[data-design="v2"] .js .reveal {
    opacity: 1;
    transform: none;
  }

  html[data-design="v2"] .bar-chart__bar {
    opacity: var(--bar-opacity, 1) !important;
    transform: scaleY(1) !important;
  }

  html[data-design="v2"] .hours-chart__fill { -webkit-mask-image: none !important; mask-image: none !important; }
  html[data-design="v2"] .hours-chart__line    { stroke-dashoffset: 0 !important; }
}

/* How It Works arrows on a phone: the donor floats 32px discs hard against the
   viewport edges, so they need a surface of their own — at 60px they were bare
   glyphs lying across the panel. Unlayered: the size and position come from
   utilities in the markup, and those outrank the components layer. */
@media (width < 64rem) {
  html[data-design="v2"] .works-arrow {
    display: grid;
    place-items: center;
    padding: 7px;
    border-radius: 999px;
    border: 1px solid var(--color-hairline);
    background-color: var(--surface-2);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
  }
}


/* == touch-effects-kill v3 == */
@media (hover: none) and (pointer: coarse) {
  *, *::before, *::after {
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
  }
  /* Hero glow: the blurred ellipses are replaced by one static two-stop
     radial wash on their container — same warm mood, zero per-frame cost.
     Every rule below carries BOTH scopes: .landing-v2 (frontend sheet) and
     html[data-design="v2"] (docs-site sheet, where the blog pins this glow
     as a FIXED full-viewport .page-art backdrop — the worst GPU case). The
     unmatched twin in each sheet is inert. */
  .landing-v2 .hero-glow__light, .landing-v2 .hero-glow__shadow,
  html[data-design="v2"] .hero-glow__light, html[data-design="v2"] .hero-glow__shadow { display: none !important; }
  .landing-v2 .hero-glow,
  html[data-design="v2"] .hero-glow {
    background:
      radial-gradient(95% 70% at 82% 8%, var(--glow-ink, #1c0f08) 0%, transparent 58%),
      radial-gradient(130% 100% at 28% 28%, var(--v2-flame-deep, #c2410c) 0%, var(--v2-glow-gold, #ee8c2c) 52%, transparent 84%) !important;
  }
  .landing-v2 .case-glow,
  html[data-design="v2"] .case-glow {
    filter: none !important;
    background-image: radial-gradient(closest-side, var(--v2-flare-a, #ff5f2e) 0%, transparent 72%) !important;
  }
  /* Focus-cycle blurs read as crisp text/images on phones instead. */
  .landing-v2 .niche, .landing-v2 .render-card__label,
  html[data-design="v2"] .niche, html[data-design="v2"] .render-card__label { filter: none !important; }
  .landing-v2 .render-card:hover .render-card__img,
  html[data-design="v2"] .render-card:hover .render-card__img { filter: none !important; }
  /* Chip rim blooms are blurred rim copies — invisible rather than doubled. */
  .landing-v2 .role-chip::before, .landing-v2 .role-chip::after,
  html[data-design="v2"] .role-chip::before, html[data-design="v2"] .role-chip::after { opacity: 0 !important; }
  /* Tailwind arbitrary blur utilities on marketing surfaces (V1 + V2). */
  .blur-\[0\.6px\], .blur-\[1\.2px\], .blur-\[2px\], .blur-\[3px\] { filter: none !important; }
  .blur-\[120px\] { display: none !important; }

  /* Glass panels (mobile menu, dropdowns, consent modal): the sheet's fill
     is a white translucency DESIGNED to be frosted; with backdrop-filter
     gone it read as a washed-out film over the page (owner: "i don't like
     that dropdown design"). Solid light panel instead — everything inside
     (--fg-on-light ink, the option rows, the 0.1-black dividers) was
     authored for a light surface in both themes. */
  .landing-v2 .glass-panel,
  html[data-design="v2"] .glass-panel {
    background: linear-gradient(160deg, #fbfbfc 0%, #ebebee 100%) !important;
    border-color: rgba(12, 12, 16, 0.1) !important;
    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.38) !important;
  }
}

/* Mobile burger-menu internals (V2Nav moves the theme + language pickers in
   here below lg — their pill-anchored dropdowns mis-placed on phones).
   Width-scoped, not pointer-scoped: the menu also exists in narrow desktop
   windows. */
@media (max-width: 1023.98px) {
  .landing-v2 .menu-group,
  html[data-design="v2"] .menu-group {
    display: flex;
    flex-direction: column;
    gap: 10px;
    border-top: 1px solid rgba(0, 0, 0, 0.1);
    padding-top: 16px;
  }
  .landing-v2 .menu-group__label,
  html[data-design="v2"] .menu-group__label {
    font-family: var(--font-display);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: rgba(24, 24, 28, 0.55);
  }
  .landing-v2 .menu-group__row,
  html[data-design="v2"] .menu-group__row {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: 6px;
  }
  .landing-v2 .menu-panel .theme-option,
  .landing-v2 .menu-panel .lang-option,
  html[data-design="v2"] .menu-panel .theme-option,
  html[data-design="v2"] .menu-panel .lang-option {
    min-width: 0;
    justify-content: center;
    gap: 7px;
    padding: 11px 6px;
    font-size: 13px;
    white-space: nowrap;
    border: 1px solid rgba(12, 12, 16, 0.12);
    border-radius: 12px;
    background: rgba(255, 255, 255, 0.6);
  }
  .landing-v2 .menu-panel .theme-option[aria-selected="true"],
  .landing-v2 .menu-panel .lang-option[aria-selected="true"],
  html[data-design="v2"] .menu-panel .theme-option[aria-selected="true"],
  html[data-design="v2"] .menu-panel .lang-option[aria-selected="true"] {
    border-color: rgba(12, 12, 16, 0.35);
    background: rgba(12, 12, 16, 0.08);
  }
}
