From 02a76bd05aadbb1b619bcdb5aad8fd087e9bcc35 Mon Sep 17 00:00:00 2001 From: Elliot Hopkins <160373706+elliothco@users.noreply.github.com> Date: Sun, 12 Apr 2026 12:14:56 -0700 Subject: [PATCH] Redesign landing: section components, hero proof, install journey --- public/images/hero-illustration.svg | 14 + src/components/SiteFooter.astro | 21 + src/components/SiteHeader.astro | 64 +- src/components/sections/EditorialValue.astro | 24 + src/components/sections/FAQCompact.astro | 27 + src/components/sections/HeroWithProof.astro | 90 +++ src/components/sections/InstallJourney.astro | 84 +++ src/components/sections/PrivacyBand.astro | 24 + src/components/sections/UsageMicro.astro | 29 + src/data/site.ts | 2 + src/layouts/BaseLayout.astro | 7 + src/pages/index.astro | 285 +-------- src/styles/global.css | 589 +++++++++++-------- 13 files changed, 729 insertions(+), 531 deletions(-) create mode 100644 public/images/hero-illustration.svg create mode 100644 src/components/SiteFooter.astro create mode 100644 src/components/sections/EditorialValue.astro create mode 100644 src/components/sections/FAQCompact.astro create mode 100644 src/components/sections/HeroWithProof.astro create mode 100644 src/components/sections/InstallJourney.astro create mode 100644 src/components/sections/PrivacyBand.astro create mode 100644 src/components/sections/UsageMicro.astro create mode 100644 src/data/site.ts diff --git a/public/images/hero-illustration.svg b/public/images/hero-illustration.svg new file mode 100644 index 0000000..b1250a4 --- /dev/null +++ b/public/images/hero-illustration.svg @@ -0,0 +1,14 @@ + diff --git a/src/components/SiteFooter.astro b/src/components/SiteFooter.astro new file mode 100644 index 0000000..da7d27d --- /dev/null +++ b/src/components/SiteFooter.astro @@ -0,0 +1,21 @@ +--- +interface Props { + tangled: string; +} + +const { tangled } = Astro.props; +--- + + diff --git a/src/components/SiteHeader.astro b/src/components/SiteHeader.astro index 3721766..423a5e1 100644 --- a/src/components/SiteHeader.astro +++ b/src/components/SiteHeader.astro @@ -1,44 +1,46 @@ --- -const tangled = "https://tangled.org/ellioth.co/summarizer-extension"; +interface Props { + tangled: string; +} + +const { tangled } = Astro.props; const links = [ { href: "#privacy", label: "Privacy" }, - { href: "#features", label: "Features" }, + { href: "#product", label: "Product" }, + { href: "#usage", label: "Usage" }, { href: "#faq", label: "FAQ" }, { href: tangled, label: "Repo", external: true }, ] as const; --- diff --git a/src/components/sections/EditorialValue.astro b/src/components/sections/EditorialValue.astro new file mode 100644 index 0000000..ab7f982 --- /dev/null +++ b/src/components/sections/EditorialValue.astro @@ -0,0 +1,24 @@ +--- +// Product story: editorial blocks, not a card grid. +--- + +
+
+

Product

+

Built for the tab in front of you

+
+
+
+

Verdict first

+

One action pulls the lede out of long articles, tickets, and threads so you can bail early or read with intent.

+
+
+

Questions stay grounded

+

Follow-ups reference the page and the summary you already generated—no free-floating chat pretending it read for you.

+
+
+

Your stack

+

Ollama native, OpenAI-compatible hosts, Groq, LM Studio—pick the model and base URL in settings instead of a locked vendor.

+
+
+
diff --git a/src/components/sections/FAQCompact.astro b/src/components/sections/FAQCompact.astro new file mode 100644 index 0000000..b9eb87b --- /dev/null +++ b/src/components/sections/FAQCompact.astro @@ -0,0 +1,27 @@ +
+
+

FAQ

+

When something blocks install

+
+
+
+ Cannot connect to localhost:11434 +
+

+ Run ollama serve, confirm models with ollama list, and keep + Native mode on http://localhost:11434 without /v1. +

+
+
+
+ HTTP 403 or 405 +
+

+ Wrong API mode for the URL: Native → no /v1. OpenAI-compatible → include + /v1 (for example http://localhost:11434/v1 for Ollama + compatibility mode). +

+
+
+
+
diff --git a/src/components/sections/HeroWithProof.astro b/src/components/sections/HeroWithProof.astro new file mode 100644 index 0000000..e54990d --- /dev/null +++ b/src/components/sections/HeroWithProof.astro @@ -0,0 +1,90 @@ +--- +/** + * Hero imagery: add optional optimized assets (recommended ~1600–2400px wide, 3:2 or 16:10). + * Drop files as `public/images/hero.avif` and `public/images/hero.webp` to replace the illustration + * for LCP; `` sources are wired below when those files exist. + */ +import { existsSync } from "node:fs"; +import path from "node:path"; + +interface Props { + tangled: string; +} + +const { tangled } = Astro.props; + +const imagesDir = path.join(process.cwd(), "public", "images"); +const hasAvif = existsSync(path.join(imagesDir, "hero.avif")); +const hasWebp = existsSync(path.join(imagesDir, "hero.webp")); + +const fallbackSrc = "/images/hero-illustration.svg"; +const alt = + "Lede extension popup over a browser page: summarize and ask questions grounded in the active tab."; +--- + +
+
+
+

Page summarizer and chat · Chrome and Firefox

+

Don't bury the lede

+

+ Summarize and ask about this tab before you spend twenty minutes on noise. +

+

+ Answers trace the page you have open—not a blank assistant waiting for a prompt. +

+ +

Keyboard

+

+ Ctrl + Shift + U + + ⌘ + Shift + U on macOS — + Summarize with Lede +

+
+
+
+ { + hasAvif || hasWebp ? ( + + {hasAvif ? : null} + {hasWebp ? : null} + {alt} + + ) : ( + {alt} + ) + } +
+
+ Beta + + Not in the Chrome Web Store or Firefox Add-ons yet—install from source, then wire Ollama or your API in + settings. + +
+
+
+
diff --git a/src/components/sections/InstallJourney.astro b/src/components/sections/InstallJourney.astro new file mode 100644 index 0000000..3525deb --- /dev/null +++ b/src/components/sections/InstallJourney.astro @@ -0,0 +1,84 @@ +--- +interface Props { + tangled: string; +} + +const { tangled } = Astro.props; +--- + +
+
+
+

Install

+

From repo to toolbar

+
+ +
+

+ Clone webai-summarizer on Tangled—not this marketing repo. You need a folder that contains + manifest.json. lede-website is only this page. +

+
+ +
+
+ +

Get the code

+

Download or clone the extension repo so the project lives on disk.

+ Open Tangled repo +
+
+ +

Choose a browser

+

Chrome uses unpacked load; Firefox uses a temporary add-on.

+
+
+ +

Load and configure

+

Point settings at Ollama native or an OpenAI-compatible endpoint, then try a tab.

+
+
+ +
+
+
+

Chrome

+
    +
  1. Open chrome://extensions/
  2. +
  3. Enable Developer mode
  4. +
  5. Click Load unpacked
  6. +
  7. Select the webai-summarizer folder that contains manifest.json
  8. +
  9. Optional: shortcuts at chrome://extensions/shortcuts
  10. +
+
+
+

Firefox

+
    +
  1. Open about:debugging#/runtime/this-firefox
  2. +
  3. Click Load Temporary Add-on
  4. +
  5. Select manifest.json inside webai-summarizer
  6. +
  7. Add-ons → gear → Manage Extension Shortcuts for the hotkey
  8. +
+

+ Temporary add-ons clear when you fully quit Firefox—reload during active dev sessions. +

+
+
+
+ +
+ Advanced: build scripts per browser +
+

+ If you already use split manifests, ./build.sh chrome or + ./build.sh firefox from the extension repo targets a specific build. +

+
+
+ +

+ Source: + {tangled} +

+
+
diff --git a/src/components/sections/PrivacyBand.astro b/src/components/sections/PrivacyBand.astro new file mode 100644 index 0000000..9164785 --- /dev/null +++ b/src/components/sections/PrivacyBand.astro @@ -0,0 +1,24 @@ +
+
+
+

Privacy and APIs

+

Where text goes

+
+
+
+

Ollama native

+

+ /api/generate on your machine. Base URL omits /v1. +

+
+
+

OpenAI-compatible

+

+ /v1/chat/completions to the endpoint you configure. Content leaves the browser only when + you summarize or chat—not via a script on every site. +

+
+
+

Extraction is on-demand when you ask.

+
+
diff --git a/src/components/sections/UsageMicro.astro b/src/components/sections/UsageMicro.astro new file mode 100644 index 0000000..814c1d1 --- /dev/null +++ b/src/components/sections/UsageMicro.astro @@ -0,0 +1,29 @@ +
+
+

In the popup

+

Three beats

+
+
    +
  1. + 01 +
    +

    Land on the page

    +

    Article, doc, issue—whatever you need to judge quickly.

    +
    +
  2. +
  3. + 02 +
    +

    Open Lede

    +

    Toolbar icon, context menu, or the keyboard shortcut.

    +
    +
  4. +
  5. + 03 +
    +

    Summarize or ask

    +

    Summarize for the lede, or type a question about this tab and press Enter.

    +
    +
  6. +
+
diff --git a/src/data/site.ts b/src/data/site.ts new file mode 100644 index 0000000..fff8958 --- /dev/null +++ b/src/data/site.ts @@ -0,0 +1,2 @@ +/** Canonical extension source (Tangled). */ +export const TANGLED_REPO_URL = "https://tangled.org/ellioth.co/summarizer-extension"; diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 602f4d8..3af8319 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -5,6 +5,8 @@ interface Props { title?: string; description?: string; ogUrl?: string; + /** Absolute URL for Open Graph / Twitter image */ + ogImage?: string; } const { @@ -12,7 +14,10 @@ const { description = "Lede — page summarizer & chat. Don't bury the main point—summarize and discuss any article.", ogUrl = "https://lede.app", + ogImage, } = Astro.props; + +const resolvedOgImage = ogImage ?? `${String(ogUrl).replace(/\/$/, "")}/images/hero-illustration.svg`; --- @@ -27,7 +32,9 @@ const { + + diff --git a/src/pages/index.astro b/src/pages/index.astro index 214c13b..17e3e8c 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,267 +1,38 @@ --- +import { existsSync } from "node:fs"; +import path from "node:path"; import BaseLayout from "../layouts/BaseLayout.astro"; import SiteHeader from "../components/SiteHeader.astro"; - -const tangled = "https://tangled.org/ellioth.co/summarizer-extension"; +import SiteFooter from "../components/SiteFooter.astro"; +import HeroWithProof from "../components/sections/HeroWithProof.astro"; +import InstallJourney from "../components/sections/InstallJourney.astro"; +import EditorialValue from "../components/sections/EditorialValue.astro"; +import UsageMicro from "../components/sections/UsageMicro.astro"; +import PrivacyBand from "../components/sections/PrivacyBand.astro"; +import FAQCompact from "../components/sections/FAQCompact.astro"; +import { TANGLED_REPO_URL } from "../data/site"; + +const ogUrl = "https://lede.app"; +const base = ogUrl.replace(/\/$/, ""); +const imagesDir = path.join(process.cwd(), "public", "images"); +const ogImage = existsSync(path.join(imagesDir, "hero.webp")) + ? `${base}/images/hero.webp` + : existsSync(path.join(imagesDir, "hero.avif")) + ? `${base}/images/hero.avif` + : `${base}/images/hero-illustration.svg`; --- - +
- +
-
-
-
-

- Page summarizer & chat · Chrome & Firefox -

-

- Don't bury the lede -

-

- Put the main point first—then ask anything about the page—with AI. Answers stay tied to - the tab you have open, not a generic chat shell. -

- -

- Keyboard -

-

- Ctrl + Shift + U - - ⌘ + Shift + U on macOS - — Summarize with Lede -

-
- -
-
- -
-
-

Install

-

Get the beta running

-
- -

- Clone the extension, not this site. Lede's source and manifest.json - live in the webai-summarizer repo on Tangled. This repository (lede-website) is only the marketing page. -

- -
-

Start here

-
    -
  1. - 1 Open the repo -

    - Download or clone webai-summarizer from Tangled so you have a local folder - with manifest.json. -

    -

    - Open extension repo → -

    -
  2. -
  3. - 2 Pick a browser -

    Chrome (unpacked) or Firefox (temporary add-on). Detailed clicks are in the panels below.

    -
  4. -
  5. - 3 Load & configure -

    - Point settings at Ollama native or an OpenAI-compatible endpoint, then summarize any tab. -

    -
  6. -
-
- -
-
-
-

Chrome

-
    -
  1. Open chrome://extensions/
  2. -
  3. Enable Developer mode
  4. -
  5. Click Load unpacked
  6. -
  7. Select your local webai-summarizer folder (the one with manifest.json)
  8. -
  9. Optional: shortcuts at chrome://extensions/shortcuts
  10. -
-
-
-

Firefox

-
    -
  1. Open about:debugging#/runtime/this-firefox
  2. -
  3. Click Load Temporary Add-on
  4. -
  5. Choose manifest.json inside webai-summarizer
  6. -
  7. Enable the shortcut via Add-ons → gear → Manage Extension Shortcuts
  8. -
-

- Temporary add-ons last until you fully quit Firefox—plan to reload during active development. -

-
-
-
- -
- Advanced: build per browser -
-

- In the extension repo, you can target a browser with ./build.sh chrome or - ./build.sh firefox if you maintain separate manifests—only if you already - use that workflow. -

-
-
- -

- Open source: - {tangled} -

-
- -
-
- Worth your time? Lede reads the open tab on demand—then puts the verdict up front. -
-
- -
-
-

Product

-

What happens on your tab

-
-
    -
  • - One-click summaries - Pull the lede from long articles, docs, and threads without leaving the page. -
  • -
  • - Follow-up questions - Ask about the page or the summary; answers trace what you were reading. -
  • -
  • - OpenAI-compatible + Ollama - Ollama, OpenAI, Groq, LM Studio—bring the endpoint you trust. -
  • -
  • - Your model, your URL - Pick the model and base URL in settings instead of a locked-in vendor. -
  • -
  • - Quick access - Toolbar icon, context menu, or the keyboard shortcut—whichever fits your flow. -
  • -
-
- -
-
-

In the popup

-

Three beats

-
-
    -
  1. -

    Open the page

    -

    Whatever you need to understand—article, ticket, README.

    -
  2. -
  3. -

    Open Lede

    -

    Toolbar icon or shortcut.

    -
  4. -
  5. -

    Summarize or ask

    -

    Summarize for the lede, or type a question about this tab and press Enter.

    -
  6. -
-
- -
-
-
-

Privacy & APIs

-

Where the words go

-
-
-
-

Ollama native

-

- Uses /api/generate. When the model runs locally, content stays on your - machine. Base URL should not include /v1. -

-
-
-

OpenAI-compatible

-

- Uses /v1/chat/completions for cloud or self-hosted endpoints you configure. - Page text is sent only when you summarize or chat—not from a script that runs on every site. -

-
-
-

- Extraction is on-demand when you ask—nothing leaves the tab until you trigger it. -

-
-
- -
-
-

FAQ

-

If something blocks you

-
-
-
-

Cannot connect to localhost:11434

-

- Run ollama serve, check ollama list, and keep Native - mode on http://localhost:11434 without /v1. -

-
-
-

HTTP 403 or 405

-

- Wrong API mode for the URL: Native → no /v1. OpenAI-compatible → include - /v1 (for example http://localhost:11434/v1 for Ollama - compatibility mode). -

-
-
-
+ + + + + +
- - +
diff --git a/src/styles/global.css b/src/styles/global.css index 15b1e08..3cef76c 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -327,79 +327,6 @@ a:focus-visible { color: var(--color-brand); } -/* ——— Start here (install-first) ——— */ -.install-section__quick { - margin-bottom: var(--space-xl); - padding-block: var(--space-lg); - padding-inline: var(--space-lg); - background: color-mix(in oklch, var(--color-subtle) 50%, var(--color-canvas)); - border: 1px solid var(--color-border); - border-radius: var(--radius-md); -} - -.quickstart-path { - list-style: none; - margin: 0; - padding: 0; - display: grid; - gap: var(--space-md); -} - -@media (min-width: 720px) { - .quickstart-path { - grid-template-columns: repeat(3, 1fr); - gap: var(--space-lg); - } -} - -.quickstart-path li { - display: flex; - flex-direction: column; - gap: var(--space-2xs); -} - -.quickstart-path .step-num { - font-family: var(--font-display); - font-weight: 700; - font-size: var(--text-md); - color: var(--color-brand); - margin-right: 0.25em; -} - -.quickstart-path strong { - font-family: var(--font-display); - font-weight: 600; - font-size: var(--text-sm); - color: var(--color-ink); - display: block; - margin-bottom: var(--space-3xs); -} - -.quickstart-path p { - margin: 0; - font-size: var(--text-sm); - color: var(--color-ink-secondary); - line-height: var(--leading-prose); - max-width: 36ch; -} - -/* Repo + install callouts — full border only (no side-stripe accent) */ -.repo-callout { - margin-bottom: var(--space-lg); - padding: var(--space-md) var(--space-lg); - background: var(--color-surface); - border: 1px solid var(--color-border); - border-radius: var(--radius-md); - font-size: var(--text-sm); - line-height: var(--leading-prose); - color: var(--color-ink-secondary); - max-width: 72ch; -} - -.repo-callout strong { - color: var(--color-ink); -} - .firefox-note { margin-top: var(--space-md); font-size: var(--text-sm); @@ -462,42 +389,6 @@ a:focus-visible { margin-top: var(--space-sm); } -/* ——— Hero ——— */ -.hero { - padding-block: var(--space-3xl) var(--space-2xl); -} - -.hero__grid { - display: grid; - gap: var(--space-xl); - align-items: start; -} - -@media (min-width: 880px) { - .hero__grid { - grid-template-columns: minmax(0, 1.15fr) minmax(220px, 0.55fr); - gap: var(--space-2xl); - } -} - -.hero__aside { - display: flex; - flex-direction: column; - gap: var(--space-md); - padding: var(--space-lg); - background: var(--color-surface); - border: 1px solid var(--color-border); - border-radius: var(--radius-md); - box-shadow: 0 1px 0 color-mix(in oklch, var(--color-ink) 4%, transparent); -} - -@media (min-width: 880px) { - .hero__aside { - margin-top: var(--space-2xl); - transform: translateX(4%); - } -} - .beta-tag { font-family: var(--font-display); font-weight: 700; @@ -507,13 +398,6 @@ a:focus-visible { color: var(--color-brand); } -.beta-note { - font-size: var(--text-sm); - line-height: var(--leading-ui); - color: var(--color-ink-secondary); - margin: 0; -} - /* ——— Buttons ——— */ .actions { display: flex; @@ -593,105 +477,6 @@ a:focus-visible { margin-bottom: var(--space-lg); } -/* Asymmetric pull — full-width rules, no side-stripe accent */ -.pull-quote { - margin: var(--space-2xl) 0; - padding: var(--space-lg) 0; - border-top: 1px solid color-mix(in oklch, var(--color-brand) 45%, var(--color-border)); - border-bottom: 1px solid color-mix(in oklch, var(--color-brand) 45%, var(--color-border)); - font-family: var(--font-display); - font-size: var(--text-lg); - font-weight: 600; - line-height: var(--leading-tight); - color: var(--color-ink); - max-width: min(22em, 100%); -} - -@media (min-width: 720px) { - .pull-quote { - margin-inline-start: 8%; - } -} - -/* Value: typographic list, not icon cards */ -.value-list { - list-style: none; - margin: 0; - padding: 0; - display: flex; - flex-direction: column; - gap: var(--space-lg); -} - -.value-list li { - display: grid; - gap: var(--space-2xs); - padding-bottom: var(--space-lg); - border-bottom: 1px solid var(--color-border); -} - -.value-list li:last-child { - border-bottom: none; - padding-bottom: 0; -} - -.value-list strong { - font-family: var(--font-display); - font-weight: 700; - font-size: var(--text-md); - color: var(--color-ink); -} - -.value-list span { - color: var(--color-ink-secondary); - font-size: var(--text-sm); - line-height: var(--leading-prose); - max-width: var(--content-max); -} - -/* How it works: numbered */ -.steps { - counter-reset: step; - list-style: none; - margin: 0; - padding: 0; - display: grid; - gap: var(--space-md); -} - -@media (min-width: 720px) { - .steps { - grid-template-columns: repeat(3, 1fr); - gap: var(--space-lg); - } -} - -.steps li { - position: relative; - padding: var(--space-lg); - background: var(--color-surface); - border: 1px solid var(--color-border); - border-radius: var(--radius-md); -} - -.steps li::before { - counter-increment: step; - content: counter(step); - font-family: var(--font-display); - font-weight: 700; - font-size: var(--text-lg); - color: var(--color-brand); - display: block; - margin-bottom: var(--space-xs); -} - -.steps p { - margin: 0; - font-size: var(--text-sm); - color: var(--color-ink-secondary); - line-height: var(--leading-prose); -} - /* Privacy dark band */ .section--dark { background: var(--color-dark-canvas); @@ -708,6 +493,10 @@ a:focus-visible { color: var(--color-dark-ink); } +.section--dark .heading-md { + color: var(--color-dark-ink); +} + .section--dark .prose { color: var(--color-dark-ink-secondary); line-height: var(--leading-prose-dark); @@ -782,34 +571,6 @@ a:focus-visible { max-width: 65ch; } -/* FAQ: definition-style, no side stripes */ -.faq { - display: flex; - flex-direction: column; - gap: var(--space-lg); -} - -.faq-item { - padding-bottom: var(--space-lg); - border-bottom: 1px solid var(--color-border); -} - -.faq-item:last-child { - border-bottom: none; - padding-bottom: 0; -} - -.faq-item h3 { - margin: 0 0 var(--space-xs); -} - -.faq-item p { - margin: 0; - font-size: var(--text-sm); - color: var(--color-ink-secondary); - line-height: var(--leading-prose); -} - /* Footer */ .site-footer { padding-block: var(--space-xl); @@ -853,3 +614,345 @@ a:focus-visible { transform: none !important; } } + +/* ========= Redesign: masthead hero + proof, install journey, editorial ========= */ + +.site-header__tagline { + display: none; + margin: 0; + padding-bottom: var(--space-xs); + font-size: var(--text-xs); + font-family: var(--font-display); + font-weight: 600; + letter-spacing: var(--tracking-label); + text-transform: uppercase; + color: var(--color-ink-muted); + border-top: 1px solid color-mix(in oklch, var(--color-border) 70%, transparent); + padding-top: var(--space-2xs); +} + +@media (min-width: 900px) { + .site-header__tagline { + display: block; + } +} + +.deck { + font-family: var(--font-display); + font-size: clamp(1.125rem, 1.5vw + 0.75rem, 1.45rem); + font-weight: 600; + line-height: var(--leading-ui); + letter-spacing: -0.015em; + color: var(--color-ink); + max-width: 28em; + margin: 0 0 var(--space-sm); +} + +.lede--tight { + max-width: 32em; + font-size: var(--text-sm); +} + +.hero-mast { + padding-block: var(--space-2xl) var(--space-3xl); + border-bottom: 1px solid var(--color-border); +} + +.hero-mast__grid { + display: grid; + gap: var(--space-xl); + align-items: stretch; +} + +@media (min-width: 960px) { + .hero-mast__grid { + grid-template-columns: minmax(0, 1fr) minmax(320px, 1.05fr); + gap: var(--space-2xl); + align-items: center; + } +} + +.hero-proof { + margin: 0; + display: flex; + flex-direction: column; + gap: var(--space-sm); +} + +.hero-proof__frame { + border-radius: var(--radius-md); + border: 1px solid var(--color-border); + background: var(--color-surface); + overflow: hidden; + box-shadow: + 0 1px 0 color-mix(in oklch, var(--color-ink) 5%, transparent), + 0 18px 48px color-mix(in oklch, var(--color-ink) 6%, transparent); +} + +.hero-proof__frame img { + width: 100%; + height: auto; + display: block; +} + +@media (prefers-reduced-motion: no-preference) { + .hero-proof__frame { + animation: hero-frame-in 0.85s var(--ease-out) both; + animation-delay: 0.12s; + } + + @keyframes hero-frame-in { + from { + opacity: 0; + transform: translateY(16px) scale(0.985); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } + } +} + +@media (prefers-reduced-motion: reduce) { + .hero-proof__frame { + animation: none; + } +} + +.hero-proof__caption { + display: flex; + flex-wrap: wrap; + align-items: baseline; + gap: var(--space-xs) var(--space-sm); + max-width: 52ch; +} + +.hero-proof__capline { + font-size: var(--text-sm); + line-height: var(--leading-ui); + color: var(--color-ink-secondary); +} + +.section--install { + padding-top: var(--space-3xl); +} + +.section__head--install { + margin-bottom: var(--space-md); +} + +.journey-band { + padding: var(--space-lg); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + margin-bottom: var(--space-md); +} + +.journey-band--callout { + background: color-mix(in oklch, var(--color-subtle) 65%, var(--color-canvas)); +} + +.journey-band__text { + margin: 0; + font-size: var(--text-sm); + line-height: var(--leading-prose); + color: var(--color-ink-secondary); + max-width: 75ch; +} + +.journey-band__text strong { + color: var(--color-ink); +} + +.journey-strip { + display: grid; + gap: var(--space-md); + margin-bottom: var(--space-xl); +} + +@media (min-width: 880px) { + .journey-strip { + grid-template-columns: repeat(3, 1fr); + gap: var(--space-lg); + } +} + +.journey-strip__cell { + padding: var(--space-lg); + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + display: flex; + flex-direction: column; + gap: var(--space-2xs); +} + +.journey-strip__num { + font-family: var(--font-display); + font-weight: 700; + font-size: var(--text-xl); + color: var(--color-brand); + line-height: 1; +} + +.journey-strip__title { + margin: 0; + font-family: var(--font-display); + font-weight: 600; + font-size: var(--text-sm); + color: var(--color-ink); +} + +.journey-strip__body { + margin: 0; + font-size: var(--text-sm); + color: var(--color-ink-secondary); + line-height: var(--leading-prose); + flex: 1; +} + +.journey-strip__cell a { + font-family: var(--font-display); + font-weight: 600; + font-size: 0.8125rem; + margin-top: var(--space-xs); +} + +.section--editorial { + padding-block: var(--space-3xl); +} + +.editorial-grid { + display: grid; + gap: var(--space-xl); +} + +@media (min-width: 800px) { + .editorial-grid { + grid-template-columns: repeat(3, 1fr); + gap: var(--space-lg); + } +} + +.editorial-block { + padding-top: var(--space-md); + border-top: 2px solid color-mix(in oklch, var(--color-brand) 35%, var(--color-border)); +} + +.editorial-block p { + margin: var(--space-xs) 0 0; + font-size: var(--text-sm); + line-height: var(--leading-prose); + color: var(--color-ink-secondary); +} + +.usage-flow { + list-style: none; + margin: 0; + padding: 0; + display: flex; + flex-direction: column; + gap: 0; +} + +.usage-flow li { + display: grid; + grid-template-columns: auto 1fr; + gap: var(--space-md); + padding: var(--space-lg) 0; + border-top: 1px solid var(--color-border); +} + +.usage-flow li:last-child { + border-bottom: 1px solid var(--color-border); +} + +.usage-flow__label { + font-family: var(--font-display); + font-weight: 700; + font-size: var(--text-sm); + color: var(--color-brand); + letter-spacing: 0.04em; +} + +.usage-flow p { + margin: var(--space-2xs) 0 0; + font-size: var(--text-sm); + color: var(--color-ink-secondary); + line-height: var(--leading-prose); +} + +.split--privacy { + margin-top: var(--space-sm); +} + +.prose--dark p { + color: var(--color-dark-ink-secondary); +} + +.privacy-kicker { + margin: var(--space-lg) 0 0; + font-weight: 600; + font-size: var(--text-sm); + max-width: 42ch; +} + +.faq-stack { + display: flex; + flex-direction: column; + gap: var(--space-sm); +} + +.faq-disclosure { + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + background: var(--color-surface); + overflow: hidden; +} + +.faq-disclosure summary { + cursor: pointer; + list-style: none; + padding: var(--space-md) var(--space-lg); + font-family: var(--font-display); + font-weight: 600; + font-size: var(--text-md); + color: var(--color-ink); + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--space-sm); +} + +.faq-disclosure summary::-webkit-details-marker { + display: none; +} + +.faq-disclosure summary::after { + content: "+"; + font-weight: 700; + color: var(--color-brand); + flex-shrink: 0; +} + +.faq-disclosure[open] summary::after { + content: "–"; +} + +.faq-disclosure__body { + padding: 0 var(--space-lg) var(--space-md); + border-top: 1px solid var(--color-border); +} + +.faq-disclosure__body p { + margin: var(--space-sm) 0 0; + font-size: var(--text-sm); + color: var(--color-ink-secondary); + line-height: var(--leading-prose); +} + +.footer-links { + display: flex; + flex-wrap: wrap; + gap: var(--space-sm) var(--space-lg); +} -- 2.51.2