# Marketing sections

> Building blocks for a product page. How it works steps, a feature grid, a closing call to action banner, credit packs, aurora and grid backgrounds, a hero with an app mockup and a scripted AI session that plays back. They sit beside the existing feature story, plan cards and testimonials.

Source: https://docs.nasaqui.com/components/marketing-sections

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/marketing-sections.json
```

Pieces for building a landing page in the product's own brand. They are presentational: pass copy, icons and buttons, and they lay them out.

| Piece | What it is |
| --- | --- |
| `AppMockupHero` | Headline, buttons and a framed picture of the app over an aurora or grid backdrop. |
| `HowItWorks` | Three or four numbered steps joined by a line. |
| `FeatureGrid` | Short feature tiles: icon, title, one or two lines, optionally a link. |
| `PricingPacks` | One-off bundles of credits with a bonus, a unit price and a buy button. |
| `CtaBanner` | The closing ask: one title, one main button, an optional second. |
| `SessionPlayback` | A scripted AI conversation that types out like a recording, with play, pause and a scrubber. |
| `AuroraBackground` / `GridBackground` | Decorative backdrops you can put behind any section. |

Already in Nasaq and not repeated here: [`FeatureStory`](https://docs.nasaqui.com/components/feature-story) (one feature with a picture), [`PlanGrid` and `PlanCard`](https://docs.nasaqui.com/components/plan-card) (recurring
plans), [`TestimonialWall`](https://docs.nasaqui.com/components/testimonials) and [`SubscriptionLanding`](https://docs.nasaqui.com/components/subscription-landing).

## When to use

- A public product page, a launch page or an app-store style landing page.
- The empty or first-run screen of a product that must explain itself.

## When not to use

- Inside the working part of an app: use its own layout components.
- Recurring subscription plans: use `PlanGrid`.
- A live chat: use `Chat` or `CopilotChat`. `SessionPlayback` only replays a script.

## Import

```tsx
import { AppMockupHero, HowItWorks, FeatureGrid, PricingPacks, CtaBanner, SessionPlayback, AuroraBackground } from "@fadymondy/nasaq/web";
```

## Quick start

```tsx
import { AppMockupHero, Button, CtaBanner, FeatureGrid, HowItWorks } from "@fadymondy/nasaq/web";
import { Zap } from "lucide-react";

export function Page() {
  return (
    <main className="flex flex-col gap-20">
      <AppMockupHero
        title="Book seats in seconds"
        description="Plans, seat maps and payments in one place."
        actions={<Button variant="primary" size="lg">Start free</Button>}
        mockup={<img src="/app.png" alt="" />}
        mockupLabel="The seat map"
        frameTitle="app.example.com"
      />
      <HowItWorks title="How it works" steps={[{ title: "Create" }, { title: "Share" }, { title: "Sell" }]} />
      <FeatureGrid title="Everything you need" features={[{ icon: <Zap />, title: "Fast", description: "Pages load at once." }]} />
      <CtaBanner title="Ready to start?" action={<Button variant="primary">Create account</Button>} />
    </main>
  );
}
```

## Anatomy

```
AppMockupHero      data-slot="app-mockup-hero"    backdrop > eyebrow, h1, text, actions, proof, ScreenshotFrame (fades out at the bottom)
HowItWorks         data-slot="how-it-works"       intro + ol: number badge, line, title, text, optional media
FeatureGrid        data-slot="feature-grid"       intro + ul of tiles
PricingPacks       data-slot="pricing-packs"      intro + ul of article cards: name, credits, bonus, price, unit price, Buy
CtaBanner          data-slot="cta-banner"         panel (aurora when brand) with title, text, buttons, note
SessionPlayback    data-slot="session-playback"   header, role="log" transcript, play / scrubber / clock
AuroraBackground   data-slot="aurora-background"  drifting colour blobs behind children
GridBackground     data-slot="grid-background"    line or dot grid behind children
```

## API

### AppMockupHero

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `title` | `ReactNode` | none | Headline (renders the page's `h1`). |
| `eyebrow` / `description` / `actions` / `proof` | `ReactNode` | none | Small label, text, buttons and a line of proof. |
| `mockup` | `ReactNode` | none | The picture or live markup, inside a `ScreenshotFrame`. |
| `frame` | `"browser" \| "window" \| "phone"` | `"browser"` | Frame style. |
| `frameTitle` | `ReactNode` | none | Address or window title. |
| `mockupLabel` | `string` | none | Describes the mockup for screen readers; its content is then hidden and inert. |
| `background` | `"aurora" \| "grid" \| "none"` | `"aurora"` | Backdrop. |

### HowItWorks

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `steps` | `{ title, description?, icon?, media? }[]` | none | The steps. |
| `eyebrow` / `title` / `description` | `ReactNode` | none | Intro. |
| `layout` | `"row" \| "column"` | `"row"` | Side by side from a wide container, or always vertical. |
| `titleAs` | `"h2" \| "h3"` | `"h2"` | Heading level. |

### FeatureGrid

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `features` | `{ icon?, title, description?, href?, wide? }[]` | none | The tiles. `href` makes the tile a link; `wide` spans two columns. |
| `columns` | `2 \| 3 \| 4` | `3` | Columns at the widest. Sized by the container, not the screen. |
| `variant` | `"cards" \| "plain"` | `"cards"` | Bordered tiles or bare. |
| `align` | `"start" \| "center"` | `"start"` | Intro alignment. |
| `eyebrow` / `title` / `description` / `titleAs` | | | As `HowItWorks`. |

### CtaBanner

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `title` | `ReactNode` | none | The ask. |
| `description` / `note` | `ReactNode` | none | Supporting text and a line of reassurance. |
| `action` / `secondaryAction` | `ReactNode` | none | Buttons. Only one primary. |
| `tone` | `"brand" \| "neutral"` | `"brand"` | Brand panel with an aurora, or a quiet surface. |
| `layout` | `"center" \| "split"` | `"center"` | Buttons under the text, or at the inline end from a wide container. |

### PricingPacks

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `packs` | `PricingPack[]` | none | `{ id, name, credits, bonus?, price, currency?, highlighted?, badge?, description? }`. |
| `onPurchase` | `(pack) => void \| Promise<void>` | none | A pack was picked; the button shows loading until it settles. |
| `showUnitPrice` | `boolean` | `true` | Price per credit. |
| `labels` | `PricingPacksLabels` | en / ar | `buy`, `bonus`, `unit`, `perUnit`. |
| `eyebrow` / `title` / `description` / `titleAs` | | | Intro. |

### SessionPlayback

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `events` | `SessionEvent[]` | none | `{ role: "user" \| "assistant" \| "tool" \| "status", text, title?, delay? }`. |
| `title` | `ReactNode` | "AI session" | Header text. |
| `autoPlay` | `boolean` | `true` | Start when scrolled into view. Under reduced motion the whole session shows at once. |
| `loop` | `boolean` | `false` | Start again after the end. |
| `timing` | `{ wordMs?, gapMs?, holdMs? }` | 90 / 500 / 900 | Speed. |
| `names` | `{ user?, assistant? }` | You / Assistant | Names above messages. |
| `height` | `string` | `"22rem"` | Height of the transcript. |
| `onEnd` | `() => void` | none | The script finished. |
| `labels` / `lang` | | en / ar | Text overrides; language for word splitting. |

### AuroraBackground and GridBackground

`AuroraBackground`: `tone` (`"brand" \| "multi"`), `animate` (default true), `fade` (default true). `GridBackground`: `cell` (40), `pattern` (`"lines" \| "dots"`), `fade` (true). Both take `children`, which render above the backdrop.

### Helpers (pure, no React)

`sessionTimeline`, `sessionStateAt`, `sessionTimeFromRatio` and `formatSessionClock` are the timeline maths of `SessionPlayback`.

## Examples

```tsx
import { Button, PricingPacks } from "@fadymondy/nasaq/web";

export const Credits = () => (
  <PricingPacks
    title="Top up"
    packs={[
      { id: "s", name: "Starter", credits: 500, price: 9 },
      { id: "p", name: "Pro", credits: 2500, bonus: 250, price: 39, highlighted: true, badge: "Best value" },
    ]}
    onPurchase={async (pack) => { await fetch(`/buy/${pack.id}`, { method: "POST" }); }}
  />
);
```

## Accessibility

- One `h1` (the hero); sections use `h2` and their steps and tiles `h3`. Pass `titleAs="h3"` inside another section.
- The backdrops are `aria-hidden` and ignore the pointer. Motion in the aurora stops under reduced motion.
- `SessionPlayback` is a `role="log"` with live updates off, so it does not read itself out while typing. It has a labelled play / pause button and a labelled scrubber. Under reduced motion it shows the whole session and does not autoplay.
- A `mockupLabel` on the hero makes the framed picture one image with a description.

## RTL & i18n

- Everything uses logical placement (`start`, `end`), so steps, tiles and buttons mirror in Arabic; the connector line and play arrow mirror too.
- Step numbers, credit amounts and the playback clock use Latin digits in both languages.
- `SessionPlayback` reveals Arabic word by word, never letter by letter.

## Styling & tokens

Backdrops use `--nq-brand`, the tag colours and `--nq-line`. Panels use `bg-nq-selected`, `bg-card` and `border-border`. Layout follows the container width (`@container`), so a section works in a narrow column as well as a full page.

## Do / Don't

- Do give each page one hero and one final banner with one main button.
- Do describe steps with verbs ("Create", "Share", "Sell").
- Don't stack more than one aurora on a screen; it is a glow, not a pattern.
- Don't use `SessionPlayback` to promise features the product does not have.

## Related

- [`FeatureStory`](https://docs.nasaqui.com/components/feature-story)
- [`PlanCard`](https://docs.nasaqui.com/components/plan-card)
- [`TestimonialWall`](https://docs.nasaqui.com/components/testimonials)
- [`ScreenshotFrame`](https://docs.nasaqui.com/components/screenshot-frame)
- [`text-effects`](https://docs.nasaqui.com/components/text-effects)

## Lab

https://docs.nasaqui.com/?path=/docs/components-website-marketing-sections--docs

## Code

### React

```tsx
import { AppMockupHero, Button, CtaBanner, FeatureGrid, HowItWorks } from "@fadymondy/nasaq/web";
import { Zap } from "lucide-react";

export function Page() {
  return (
    <main className="flex flex-col gap-20">
      <AppMockupHero
        title="Book seats in seconds"
        description="Plans, seat maps and payments in one place."
        actions={<Button variant="primary" size="lg">Start free</Button>}
        mockup={<img src="/app.png" alt="" />}
        mockupLabel="The seat map"
        frameTitle="app.example.com"
      />
      <HowItWorks title="How it works" steps={[{ title: "Create" }, { title: "Share" }, { title: "Sell" }]} />
      <FeatureGrid title="Everything you need" features={[{ icon: <Zap />, title: "Fast", description: "Pages load at once." }]} />
      <CtaBanner title="Ready to start?" action={<Button variant="primary">Create account</Button>} />
    </main>
  );
}
```

### shadcn

```tsx
import { AppMockupHero, CtaBanner, FeatureGrid, HowItWorks } from "@/components/ui/marketing-sections";
import { Button } from "@/components/ui/button";
import { Zap } from "lucide-react";

export function Page() {
  return (
    <main className="flex flex-col gap-20">
      <AppMockupHero
        title="Book seats in seconds"
        description="Plans, seat maps and payments in one place."
        actions={<Button variant="primary" size="lg">Start free</Button>}
        mockup={<img src="/app.png" alt="" />}
        mockupLabel="The seat map"
        frameTitle="app.example.com"
      />
      <HowItWorks title="How it works" steps={[{ title: "Create" }, { title: "Share" }, { title: "Sell" }]} />
      <FeatureGrid title="Everything you need" features={[{ icon: <Zap />, title: "Fast", description: "Pages load at once." }]} />
      <CtaBanner title="Ready to start?" action={<Button variant="primary">Create account</Button>} />
    </main>
  );
}
```

### Vue

```vue
<script setup lang="ts">
import { NqAppMockupHero, NqButton, NqCtaBanner, NqFeatureGrid, NqHowItWorks, NqPricingPacks, NqSessionPlayback } from "@fadymondy/nasaq/vue";
import { Zap } from "lucide-vue-next";

const steps = [{ title: "Create" }, { title: "Share" }, { title: "Sell" }];
const features = [{ icon: Zap, title: "Fast", description: "Pages load at once." }];
const packs = [
  { id: "s", name: "Starter", credits: 500, price: 9 },
  { id: "p", name: "Pro", credits: 2500, bonus: 250, price: 39, highlighted: true, badge: "Best value" },
];
const events = [
  { role: "user", text: "Summarise yesterday's bookings." },
  { role: "tool", title: "Read bookings", text: "42 rows" },
  { role: "assistant", text: "You had 42 bookings, 6 more than the day before." },
] as const;
</script>

<template>
  <main class="flex flex-col gap-20">
    <NqAppMockupHero title="Book seats in seconds" description="Plans, seat maps and payments in one place." mockup-label="The seat map" frame-title="app.example.com">
      <template #actions><NqButton variant="primary" size="lg">Start free</NqButton></template>
      <template #mockup><div class="h-40 bg-nq-surface-soft" /></template>
    </NqAppMockupHero>
    <NqHowItWorks title="How it works" :steps="steps" />
    <NqFeatureGrid title="Everything you need" :features="features" />
    <NqPricingPacks title="Top up" :packs="packs" />
    <NqSessionPlayback title="AI session" :events="[...events]" :auto-play="false" height="14rem" />
    <NqCtaBanner title="Ready to start?">
      <template #action><NqButton variant="primary">Create account</NqButton></template>
    </NqCtaBanner>
  </main>
</template>
```

### Blade

```blade
<main class="flex flex-col gap-20">
    <x-nq::marketing-sections.app-mockup-hero id="mk-hero" title="Book seats in seconds" description="Plans, seat maps and payments in one place." mockup-label="The seat map" frame-title="app.example.com">
        <x-slot:actions><x-nq::button variant="primary" size="lg">Start free</x-nq::button></x-slot:actions>
        <div class="h-40 bg-nq-surface-soft"></div>
    </x-nq::marketing-sections.app-mockup-hero>
    <x-nq::marketing-sections.how-it-works id="mk-how" title="How it works" :steps="[['title' => 'Create'], ['title' => 'Share'], ['title' => 'Sell']]" />
    <x-nq::marketing-sections.feature-grid id="mk-features" title="Everything you need" :features="[['icon' => 'zap', 'title' => 'Fast', 'description' => 'Pages load at once.'], ['title' => 'Docs', 'href' => '/docs']]" />
    <x-nq::marketing-sections.pricing-packs id="mk-packs" title="Top up" :packs="[['id' => 's', 'name' => 'Starter', 'credits' => 500, 'price' => 9], ['id' => 'p', 'name' => 'Pro', 'credits' => 2500, 'bonus' => 250, 'price' => 39, 'highlighted' => true, 'badge' => 'Best value']]" />
    <x-nq::marketing-sections.session-playback id="mk-session" title="Booking assistant" :auto-play="false" height="14rem"
        :events="[['role' => 'user', 'text' => 'Summarise yesterday bookings.'], ['role' => 'tool', 'title' => 'Read bookings', 'text' => '42 rows'], ['role' => 'assistant', 'text' => 'You had 42 bookings, 6 more than the day before.']]" />
    <x-nq::marketing-sections.cta-banner id="mk-cta" title="Ready to start?" note="No card needed">
        <x-slot:action><x-nq::button variant="primary">Create account</x-nq::button></x-slot:action>
    </x-nq::marketing-sections.cta-banner>
    <x-nq::marketing-sections.grid-background id="mk-grid" pattern="dots" class="p-10"><p class="text-center">A quiet dot grid</p></x-nq::marketing-sections.grid-background>
</main>
```

### HTML + Alpine

```html
<main class="flex flex-col gap-20">
    <section data-slot="app-mockup-hero" id="mk-hero" class="w-full min-w-0">
            <div data-slot="aurora-background" x-data="nqAuroraBackground(JSON.parse('{\u0022animate\u0022:true}'))"
    class="relative isolate overflow-hidden">
    <div aria-hidden="true" class="pointer-events-none absolute inset-0 -z-10 overflow-hidden"  style="mask-image: linear-gradient(to bottom, black 55%, transparent); -webkit-mask-image: linear-gradient(to bottom, black 55%, transparent)" >
                    <span data-blob class="absolute aspect-square rounded-full opacity-25 blur-3xl"
                style="top: -30%; inset-inline-start: -10%;   width: 55%; background: var(--nq-brand)"></span>
                    <span data-blob class="absolute aspect-square rounded-full opacity-25 blur-3xl"
                style="top: -20%;  inset-inline-end: -8%;  width: 50%; background: var(--nq-tag-blue, var(--nq-brand))"></span>
                    <span data-blob class="absolute aspect-square rounded-full opacity-25 blur-3xl"
                style="top: 5%; inset-inline-start: 30%;   width: 40%; background: var(--nq-tag-violet, var(--nq-brand))"></span>
            </div>
    <div class="@container mx-auto flex w-full max-w-5xl min-w-0 flex-col items-center gap-10 px-4 pt-14 pb-0 text-center @2xl:pt-20">
    <div class="flex min-w-0 max-w-2xl flex-col items-center gap-4">
                <h1 class="font-semibold text-display text-foreground text-balance">Book seats in seconds</h1>
        <p class="text-body text-nq-fg-body text-pretty">Plans, seat maps and payments in one place.</p>        <div class="flex flex-wrap justify-center gap-2 pt-2"><button data-slot="button"
     type="button"                         class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] h-[calc(var(--nq-control)+8px)] px-5 text-body">
        Start free</button></div>            </div>
    <div class="w-full min-w-0 max-w-4xl" style="mask-image: linear-gradient(to bottom, black 70%, transparent); -webkit-mask-image: linear-gradient(to bottom, black 70%, transparent)">
        <figure data-slot="screenshot-frame" data-variant="browser" class="flex min-w-0 flex-col gap-3 shadow-floating">
            <div class="w-full overflow-hidden rounded-card bg-nq-surface-raised shadow-lg ring-1 ring-border">
            <div data-slot="screenshot-frame-bar" class="flex h-9 items-center gap-3 px-3">
                <span aria-hidden="true" class="flex gap-1.5">
                    <span class="size-2.5 rounded-full bg-nq-line-strong"></span>
                    <span class="size-2.5 rounded-full bg-nq-line-strong"></span>
                    <span class="size-2.5 rounded-full bg-nq-line-strong"></span>
                </span>
                                                            <span dir="ltr" class="mx-auto flex h-6 w-full max-w-xs items-center justify-center truncate rounded-control bg-secondary px-3 text-caption text-muted-foreground">app.example.com</span>
                                                    <span aria-hidden="true" class="w-[42px]"></span>
            </div>
            <div data-slot="screenshot-frame-screen"  role="img" aria-label="The seat map"  class="relative overflow-hidden bg-background rounded-b-[calc(var(--radius-card)-1px)]">
                <div  aria-hidden="true" inert  class="size-full"><div class="h-40 bg-nq-surface-soft"></div></div>
            </div>
        </div>
        </figure>
    </div>
</div>
</div>
    </section>
    <section data-slot="how-it-works"  aria-labelledby="nq-how-23d85f61"     id="mk-how" class="@container flex min-w-0 flex-col gap-8">
    <div class="flex max-w-2xl flex-col gap-2">
                <h2 id="nq-how-23d85f61" class="font-semibold text-foreground text-h2 text-balance">How it works</h2>            </div>
    <ol class="grid gap-6 @3xl:grid-cols-[repeat(var(--steps),minmax(0,1fr))] @3xl:gap-8" style="--steps: 3">
                    <li class="relative flex min-w-0 gap-4 @3xl:flex-col">
                                    <span aria-hidden="true" class="absolute bg-border start-5 top-11 bottom-[-1.5rem] w-px @3xl:start-12 @3xl:top-5 @3xl:bottom-auto @3xl:h-px @3xl:w-[calc(100%-2rem)]"></span>
                                <span dir="ltr" class="relative z-1 grid size-10 shrink-0 place-items-center rounded-full border border-border bg-nq-surface font-semibold text-body-sm text-nq-brand tabular-nums [&_svg]:size-4">
                    1                </span>
                <div class="flex min-w-0 flex-1 flex-col gap-1.5 pb-2">
                    <h3 class="font-semibold text-foreground text-h3">Create</h3>
                                                        </div>
            </li>
                    <li class="relative flex min-w-0 gap-4 @3xl:flex-col">
                                    <span aria-hidden="true" class="absolute bg-border start-5 top-11 bottom-[-1.5rem] w-px @3xl:start-12 @3xl:top-5 @3xl:bottom-auto @3xl:h-px @3xl:w-[calc(100%-2rem)]"></span>
                                <span dir="ltr" class="relative z-1 grid size-10 shrink-0 place-items-center rounded-full border border-border bg-nq-surface font-semibold text-body-sm text-nq-brand tabular-nums [&_svg]:size-4">
                    2                </span>
                <div class="flex min-w-0 flex-1 flex-col gap-1.5 pb-2">
                    <h3 class="font-semibold text-foreground text-h3">Share</h3>
                                                        </div>
            </li>
                    <li class="relative flex min-w-0 gap-4 @3xl:flex-col">
                                <span dir="ltr" class="relative z-1 grid size-10 shrink-0 place-items-center rounded-full border border-border bg-nq-surface font-semibold text-body-sm text-nq-brand tabular-nums [&_svg]:size-4">
                    3                </span>
                <div class="flex min-w-0 flex-1 flex-col gap-1.5 pb-2">
                    <h3 class="font-semibold text-foreground text-h3">Sell</h3>
                                                        </div>
            </li>
            </ol>
</section>
    <section data-slot="feature-grid"  aria-labelledby="nq-features-60eae2ca"     id="mk-features" class="@container flex min-w-0 flex-col gap-8">
    <div class="flex max-w-2xl flex-col gap-2">
                <h2 id="nq-features-60eae2ca" class="font-semibold text-foreground text-h2 text-balance">Everything you need</h2>            </div>
    <ul class="grid grid-cols-1 gap-4 @2xl:grid-cols-2 @4xl:grid-cols-3">
                                <li class="min-w-0">
                <div  class="group flex h-full min-w-0 flex-col items-start gap-3 p-4 text-start rounded-card border border-border bg-card">
                                            <span class="grid size-9 shrink-0 place-items-center rounded-control bg-nq-selected text-nq-brand [&_svg]:size-5"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M15.914 4a1.5 1.5 0 00-2.474-1.561l-9 9A1.5 1.5 0 005.5 14h4.002a.5.5 0 01.471.666L8.086 20a1.5 1.5 0 002.475 1.56l9-9A1.5 1.5 0 0018.5 10h-3.997a.5.5 0 01-.472-.667z"/>
</svg></span>
                                        <span class="flex min-w-0 flex-col gap-1">
                        <span class="flex items-center gap-1 font-semibold text-foreground text-label">
                            Fast
                                                    </span>
                        <span class="text-body-sm text-nq-fg-body">Pages load at once.</span>                    </span>
                </div>
            </li>
                                <li class="min-w-0">
                <a  href="/docs"  class="group flex h-full min-w-0 flex-col items-start gap-3 p-4 text-start rounded-card border border-border bg-card outline-none transition-colors hover:border-nq-line-strong focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus">
                                        <span class="flex min-w-0 flex-col gap-1">
                        <span class="flex items-center gap-1 font-semibold text-foreground text-label">
                            Docs
                            <svg aria-hidden="true" class="size-3.5 text-muted-foreground transition-transform group-hover:translate-x-0.5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
  <path d="m12 5 7 7-7 7"/>
</svg>                        </span>
                                            </span>
                </a>
            </li>
            </ul>
</section>
    <section data-slot="pricing-packs"  aria-labelledby="nq-packs-0f2b039d"  x-data="nqPricingPacks(JSON.parse('{\u0022packs\u0022:[{\u0022id\u0022:\u0022s\u0022,\u0022name\u0022:\u0022Starter\u0022,\u0022credits\u0022:500,\u0022price\u0022:9},{\u0022id\u0022:\u0022p\u0022,\u0022name\u0022:\u0022Pro\u0022,\u0022credits\u0022:2500,\u0022bonus\u0022:250,\u0022price\u0022:39}]}'))"
    id="mk-packs" class="@container flex min-w-0 flex-col gap-8">
    <div class="flex max-w-2xl flex-col gap-2">
                <h2 id="nq-packs-0f2b039d" class="font-semibold text-foreground text-h2 text-balance">Top up</h2>            </div>
    <ul class="grid grid-cols-1 gap-4 @2xl:grid-cols-[repeat(var(--packs),minmax(0,1fr))]" style="--packs: 2">
                                <li class="min-w-0">
                <article class="flex h-full min-w-0 flex-col gap-4 rounded-card p-5 border border-border bg-card">
                    <div class="flex items-center justify-between gap-2">
                        <h3 class="font-semibold text-foreground text-h3">Starter</h3>
                                            </div>
                    <div class="flex flex-col gap-1">
                        <div class="flex items-baseline gap-1.5">
                            <bdi class="font-semibold text-display text-foreground tabular-nums">500</bdi>
                            <span class="text-body-sm text-muted-foreground">credits</span>
                        </div>
                                                                    </div>
                    <div class="mt-auto flex flex-col gap-3">
                        <div class="flex flex-col gap-0.5">
                            <span data-slot="price" class="inline-flex flex-wrap items-baseline gap-x-1.5 text-foreground text-body-sm">
        <span>
            <bdi class="tabular-nums text-h2 font-semibold tracking-tight">$9</bdi>
                    </span>
            </span>
                                                            <span class="text-caption text-muted-foreground"><bdi dir="ltr">$0.018</bdi> per credit</span>
                                                    </div>
                        <button data-slot="button"
     type="button"                         data-pack="s" x-on:click="buy(`s`)" x-bind:aria-busy="busyAttr(`s`)" x-bind:disabled="blocked(`s`)" x-bind:data-disabled="disabledAttr(`s`)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)] w-full">
        <template x-if="isBusy(`s`)"><svg data-slot="spinner" aria-hidden="true" class="size-4 animate-spin motion-reduce:animate-none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21 12a9 9 0 1 1-6.219-8.56"/>
</svg></template>
                            Buy</button>
                    </div>
                </article>
            </li>
                                <li class="min-w-0">
                <article class="flex h-full min-w-0 flex-col gap-4 rounded-card p-5 border border-nq-brand/40 bg-nq-selected">
                    <div class="flex items-center justify-between gap-2">
                        <h3 class="font-semibold text-foreground text-h3">Pro</h3>
                        <span data-slot="badge"     class="inline-flex h-5 shrink-0 items-center gap-1 whitespace-nowrap rounded-[4px] border px-1.5 text-caption font-medium [&_svg]:size-3 border-nq-brand/40 bg-[color-mix(in_oklab,var(--nq-brand)_14%,transparent)] text-foreground">Best value</span>
                    </div>
                    <div class="flex flex-col gap-1">
                        <div class="flex items-baseline gap-1.5">
                            <bdi class="font-semibold text-display text-foreground tabular-nums">2,500</bdi>
                            <span class="text-body-sm text-muted-foreground">credits</span>
                        </div>
                                                    <div class="text-caption text-nq-success-text"><bdi>+250</bdi> bonus</div>
                                                                    </div>
                    <div class="mt-auto flex flex-col gap-3">
                        <div class="flex flex-col gap-0.5">
                            <span data-slot="price" class="inline-flex flex-wrap items-baseline gap-x-1.5 text-foreground text-body-sm">
        <span>
            <bdi class="tabular-nums text-h2 font-semibold tracking-tight">$39</bdi>
                    </span>
            </span>
                                                            <span class="text-caption text-muted-foreground"><bdi dir="ltr">$0.014</bdi> per credit</span>
                                                    </div>
                        <button data-slot="button"
     type="button"                         data-pack="p" x-on:click="buy(`p`)" x-bind:aria-busy="busyAttr(`p`)" x-bind:disabled="blocked(`p`)" x-bind:data-disabled="disabledAttr(`p`)" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] h-control px-[var(--nq-control-pad)] w-full">
        <template x-if="isBusy(`p`)"><svg data-slot="spinner" aria-hidden="true" class="size-4 animate-spin motion-reduce:animate-none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21 12a9 9 0 1 1-6.219-8.56"/>
</svg></template>
                            Buy</button>
                    </div>
                </article>
            </li>
            </ul>
</section>
    <figure data-slot="session-playback" x-data="nqSessionPlayback(JSON.parse('{\u0022events\u0022:[{\u0022role\u0022:\u0022user\u0022,\u0022text\u0022:\u0022Summarise yesterday bookings.\u0022,\u0022title\u0022:null,\u0022delay\u0022:0},{\u0022role\u0022:\u0022tool\u0022,\u0022text\u0022:\u002242 rows\u0022,\u0022title\u0022:\u0022Read bookings\u0022,\u0022delay\u0022:0},{\u0022role\u0022:\u0022assistant\u0022,\u0022text\u0022:\u0022You had 42 bookings, 6 more than the day before.\u0022,\u0022title\u0022:null,\u0022delay\u0022:0}],\u0022autoPlay\u0022:false,\u0022loop\u0022:false,\u0022timing\u0022:{},\u0022lang\u0022:\u0022en\u0022,\u0022labels\u0022:{\u0022play\u0022:\u0022Play\u0022,\u0022pause\u0022:\u0022Pause\u0022,\u0022restart\u0022:\u0022Replay\u0022}}'))"
    id="mk-session" class="flex min-w-0 flex-col overflow-hidden rounded-card border border-border bg-card">
    <figcaption class="flex items-center gap-2 border-border border-b bg-nq-surface-soft px-3 py-2 text-caption text-muted-foreground">
        <svg aria-hidden="true" class="size-3.5 text-nq-brand" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z"/>
  <path d="M20 2v4"/>
  <path d="M22 4h-4"/>
  <circle cx="4" cy="20" r="2"/>
</svg>        <span class="min-w-0 flex-1 truncate">Booking assistant</span>
    </figcaption>
    <div data-log x-ref="log" role="log" aria-label="AI session" class="flex flex-col gap-3 overflow-y-auto p-4" style="height: 14rem">
                                                                <div data-event="0" class="flex min-w-0 flex-col gap-1 items-end">
                    <span class="text-caption text-muted-foreground">You</span>
                    <p dir="auto" class="max-w-[85%] rounded-card px-3 py-2 text-body-sm text-start bg-nq-selected text-foreground"><span data-text>Summarise yesterday bookings.</span><span data-cursor hidden aria-hidden="true" class="ms-0.5 inline-block h-3.5 w-px translate-y-0.5 animate-pulse bg-foreground"></span></p>
                </div>
                                                            <div data-event="1" class="flex min-w-0 items-center gap-2 rounded-control border border-border bg-nq-surface-soft px-2.5 py-1.5 text-caption text-muted-foreground">
                    <svg aria-hidden="true" class="size-3.5 shrink-0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z"/>
</svg>                    <span class="font-medium text-foreground">Read bookings</span>                    <span dir="auto" class="min-w-0 truncate">42 rows</span>
                </div>
                                                                            <div data-event="2" class="flex min-w-0 flex-col gap-1 items-start">
                    <span class="text-caption text-muted-foreground">Assistant</span>
                    <p dir="auto" class="max-w-[85%] rounded-card px-3 py-2 text-body-sm text-start bg-secondary text-nq-fg-body"><span data-text>You had 42 bookings, 6 more than the day before.</span><span data-cursor hidden aria-hidden="true" class="ms-0.5 inline-block h-3.5 w-px translate-y-0.5 animate-pulse bg-foreground"></span></p>
                </div>
                        </div>
    <div class="flex items-center gap-3 border-border border-t px-3 py-2">
        <button data-slot="button"
     type="button"                         x-on:click="toggle()" x-bind:aria-label="playLabel()" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg aria-hidden="true" x-show="mode() === `restart`" class="rtl:-scale-x-100" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/>
  <path d="M3 3v5h5"/>
</svg>            <svg aria-hidden="true" style="display: none" x-show="mode() === `pause`" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <rect x="14" y="3" width="5" height="18" rx="1"/>
  <rect x="5" y="3" width="5" height="18" rx="1"/>
</svg>            <svg aria-hidden="true" style="display: none" x-show="mode() === `play`" class="rtl:-scale-x-100" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z"/>
</svg></button>
        <div data-slot="slider" x-data="nqSlider(JSON.parse('{\u0022value\u0022:100,\u0022min\u0022:0,\u0022max\u0022:100,\u0022step\u0022:1,\u0022disabled\u0022:false,\u0022minStepsBetweenThumbs\u0022:0}'))" x-modelable="model"     aria-label="Playback position" x-model="pct" class="flex w-full flex-col gap-2 data-disabled:opacity-50 min-w-0 flex-1">
        <div data-slot="slider-control"  x-on:pointerdown="down($event)" class="flex h-5 w-full touch-none select-none items-center">
        <div data-slot="slider-track" x-ref="track" class="relative h-1.5 w-full rounded-full bg-nq-surface-soft">
            <div data-slot="slider-range" :style="rangeStyle()" style="position: absolute; top: 0; bottom: 0; inset-inline-start: 0px; inset-inline-end: calc(100% - calc(100% + -8.00px))" class="rounded-full bg-primary"></div>
                            <div data-slot="slider-thumb" role="slider" tabindex="0"
                                        aria-valuemin="0" aria-valuemax="100" aria-orientation="horizontal"
                    :aria-valuenow="values[0]" :aria-valuetext="fmt(values[0])" :data-dragging="dragging && active === 0 ? '' : undefined"
                                        x-on:keydown="key($event, 0)" :style="thumbStyle(0)"
                    style="inset-inline-start: calc(100% + -8.00px); top: 50%; translate: -50% -50%; position: absolute"
                    class="size-4 rounded-full border border-primary bg-card shadow-xs outline-none transition-[box-shadow] duration-150 ease-nq motion-reduce:transition-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-dragging:shadow-md data-disabled:pointer-events-none"></div>
                                    </div>
    </div>
    </div>
        <span dir="ltr" class="w-20 shrink-0 text-end text-caption text-muted-foreground tabular-nums" x-text="clock()">0:03 / 0:03</span>
    </div>
</figure>
    <section data-slot="cta-banner" aria-labelledby="nq-cta-706a2215"
    id="mk-cta" class="@container w-full overflow-hidden rounded-card border border-nq-brand/30 bg-nq-selected">
            <div data-slot="aurora-background" x-data="nqAuroraBackground(JSON.parse('{\u0022animate\u0022:true}'))"
    class="relative isolate overflow-hidden">
    <div aria-hidden="true" class="pointer-events-none absolute inset-0 -z-10 overflow-hidden" >
                    <span data-blob class="absolute aspect-square rounded-full opacity-25 blur-3xl"
                style="top: -30%; inset-inline-start: -10%;   width: 55%; background: var(--nq-brand)"></span>
                    <span data-blob class="absolute aspect-square rounded-full opacity-25 blur-3xl"
                style="top: -20%;  inset-inline-end: -8%;  width: 50%; background: var(--nq-tag-blue, var(--nq-brand))"></span>
                    <span data-blob class="absolute aspect-square rounded-full opacity-25 blur-3xl"
                style="top: 5%; inset-inline-start: 30%;   width: 40%; background: var(--nq-tag-violet, var(--nq-brand))"></span>
            </div>
    <div class="relative flex min-w-0 flex-col gap-6 p-6 @2xl:p-10 items-center text-center">
    <div class="flex min-w-0 max-w-xl flex-col gap-2 items-center">
        <h2 id="nq-cta-706a2215" class="font-semibold text-foreground text-h2 text-balance">Ready to start?</h2>
            </div>
    <div class="flex min-w-0 flex-col gap-2 items-center">
        <div class="flex flex-wrap gap-2 justify-center">
            <button data-slot="button"
     type="button"                         class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] h-control px-[var(--nq-control-pad)]">
        Create account</button>
        </div>
        <p class="text-caption text-muted-foreground">No card needed</p>    </div>
</div>
</div>
    </section>
    <div data-slot="grid-background" id="mk-grid" class="relative isolate overflow-hidden p-10">
    <div aria-hidden="true" class="pointer-events-none absolute inset-0 -z-10" style="background-image: radial-gradient(circle, var(--nq-line-strong, var(--nq-line)) 1px, transparent 1.5px); background-size: 40px 40px; mask-image: radial-gradient(ellipse 70% 60% at 50% 40%, black 30%, transparent 100%); -webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 40%, black 30%, transparent 100%)"></div>
    <p class="text-center">A quiet dot grid</p>
</div>
</main>
```
