diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8af33787..d97904cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,6 +39,9 @@ jobs: - name: Check plain (machine UI) coverage run: npm run check:plain + - name: Check teaser scroll regressions + run: npm run check:teaser + - name: Build site # PostHog (heatmaps + session recordings) is initialised in # src/scripts/analytics.ts, but it early-returns unless diff --git a/docs/cloud-teaser.md b/docs/cloud-teaser.md index 3bb67c2f..79b53d75 100644 --- a/docs/cloud-teaser.md +++ b/docs/cloud-teaser.md @@ -1,61 +1,40 @@ # Pilot horizontal teaser -Standalone route: `/cloud-teaser`. This is a `noindex,nofollow` design preview, excluded from the sitemap. It does not replace `/cloud` or `/cloud-landing`. +Standalone route: `/cloud-teaser`. This noindex preview is excluded from the sitemap and does not replace `/cloud` or `/cloud-landing`. -## The story +## Five-scene story -1. **The last chore you’ll ever do.** The friend-group qualifier and an unresolved dinner conversation establish the coordination problem. -2. **First, you need an agent.** Muse, Dots, Grok Bot, Hermes, and OpenClaw lead; MCP-compatible chat apps remain a smaller, explicit alternative. Background operation requires enabled check-ins. -3. **Run your friend group on autopilot.** A two-agent exchange ends in a useful result. The visitor can try plans, updates, introductions, and files. The dinner example asks for approval; the introduction asks permission before connecting people. -4. **Your agent. Meet their agents.** People using different AI apps connect through Pilot, by invitation. -5. **New AI. Same handle.** Switching the sample AI changes the connected app, while the handle, link, and people remain. The profile is clearly an example, not a link to a real user. -6. **Claim your handle. Invite your friends.** `Start now` opens `https://cloud.pilotprotocol.network`; `Learn more` opens `/cloud-landing`. Both people connect an AI. The service is hosted, free to start, and requests require acceptance. +1. **The last chore you’ll ever do.** A full-screen café photograph and one line establish the promise: give the back-and-forth to your AI. +2. **Bring your AI.** Muse, Dots, Grok Bot, Hermes, and OpenClaw surround Pilot. MCP-compatible chat apps remain an explicit alternative. +3. **Your friend group, on autopilot.** Muse and Priya’s Dots arrange one dinner. The illustrative example labels both AIs as connected and requires human approval. +4. **New AI. Same handle.** The visitor can switch the example AI while the handle and link remain. The example is not a real profile. +5. **Less planning. More see you soon.** A reunion photograph closes on the human outcome. Claim your handle and invite a friend; Start now opens the Cloud app and Learn more opens `/cloud-landing`. Both people connect an AI. -The short story deliberately leaves earnings, business-agent coverage, and ecosystem expansion out. Their conditions and roadmap status need more room than a teaser affords. Product qualifications follow `docs/cloud-messaging.md`. +Earnings, future business coverage, and ecosystem expansion are omitted. Their conditions need more room than a teaser affords. Product qualifications follow `docs/cloud-messaging.md`. -## Visual and interaction choices +## Design and performance -One typeface (Inter Tight), cream, clay/coral, soft green, large type, and existing Pilot illustrations. The film contributes full-screen color changes, the dinner exchange, and the portable handle. It contributes no soundtrack, autoplay, or timed reading pressure. Human photography closes on the reason to coordinate: seeing each other. +One Inter Tight typeface, cream/clay colors, unframed photography, and sparse scenes replace the denser six-panel version. The café photograph is licensed stock; the reunion still comes from the existing Higgsfield film footage. Provenance is in `public/cloud/teaser/CREDITS.md`. -The page uses the existing licensed café photo and crops for illustrative avatars. Its source and credit are in `public/cloud/warm/CREDITS.md`. Agent marks come from the existing landing-page assets. `public/cloud/teaser/social.jpg` is a separate social card branded Pilot. +Native vertical document scrolling moves the story horizontally. Mandatory CSS snap points settle on full chapters; there is no wheel or touch interception, synthetic momentum, timed advance, background video, or soundtrack. Previous/next buttons and Left/Right keys are available. Inactive chapters are inert. -Normal vertical document scrolling translates the story horizontally to the next panel on the right. Native mandatory scroll snapping settles on a complete chapter after the gesture; `scroll-snap-stop: always` marks each chapter as a stop for snap-based scrolling. Because the visual panels share a sticky viewport, one non-interactive document-position target per chapter supplies the vertical snap positions. They are disabled in the automatic vertical fallback. The last chapter reserves a complete viewport of scroll room even when mobile browser chrome changes its height. +Supported browsers drive the track with a native CSS scroll timeline. The JavaScript fallback writes only its transform once per animation frame. The previous inherited per-panel custom-property writes and decorative parallax were removed. Chapter state changes only at boundaries; the progress bar does not animate on touch devices. -A passive listener schedules one animation frame per scroll update. There is no wheel/touch interception, synthetic momentum, or automatic advance. The track and small illustration offsets share the same scroll position. Previous/next controls and Left/Right keys offer deliberate chapter navigation; browser-native scrolling keys still work. Resizing settles on the nearest complete chapter. +The stage uses stable small-viewport height. Height-only resize events on touch devices no longer rebuild the layout or call scrollTo when browser chrome expands or collapses. Real width changes remeasure after a short debounce. The final chapter reserves large-viewport scroll space. These changes address identifiable sources of lag; no physical-phone frame-rate measurement is claimed. -Native snapping references: [MDN scroll-snap-type](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/scroll-snap-type) and [MDN scroll-snap-stop](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/scroll-snap-stop). +Reduced motion, short windows, or content that cannot fit automatically use the ordinary vertical page. All chapters are measured before horizontal enhancement enables. There is no reading-mode toggle. Without JavaScript, the complete story and destination links remain available. Local demo controls do not send messages or book anything. -Inactive chapters are inert in horizontal mode, so keyboard focus and screen readers do not visit invisible controls. Chapter status changes only at chapter boundaries. The header contains only Pilot and Start now. Reduced motion, small landscape windows, oversized text, or content that cannot fit automatically use the ordinary vertical page; there is no reading-view toggle or stored mode preference. Compact phone layouts reduce illustration size and simplify the example card while retaining its disclosure and approval control. Without JavaScript, the entire story and both destination links remain available vertically; the sample interaction controls are hidden. - -References: [MDN sticky positioning](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/position), [WAI carousel interaction guidance](https://www.w3.org/WAI/ARIA/apg/patterns/carousel/), [MDN inert](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/inert), and [MDN reduced motion](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/prefers-reduced-motion). - -## Files - -- `src/pages/cloud-teaser.astro`: story, metadata, and static accessible content. -- `src/styles/cloud-teaser.css`: scoped responsive design. -- `src/scripts/cloud-teaser.ts`: scroll snapping, automatic vertical fallback, and local illustrative demos. -- `src/pages/sitemap.xml.ts`: preview exclusion. +Implementation references: [WebKit scroll-driven animations](https://webkit.org/blog/17101/a-guide-to-scroll-driven-animations-with-just-css/), [Chrome scroll-driven animations](https://developer.chrome.com/docs/css-ui/scroll-driven-animations), [MDN scroll snapping](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/scroll-snap-type), and [MDN reduced motion](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/prefers-reduced-motion). ## Verification — 25 October 2026 -- `npm run build`: passed (334 Astro pages plus generated error documents). -- `npm run check:plain`: passed, 100 required pairs. -- `npm run check:site`: passed, 338 HTML files and 24,437 internal references; includes the new image, metadata, preview exclusion, and both CTA destinations. -- Targeted TypeScript check for `cloud-teaser.ts`: passed. Repository-wide `npx tsc --noEmit` still fails in untouched Cloudflare function/worker types, analytics, and the untracked film directory. No errors point to the teaser. -- Chrome at 1280 × 667: all six chapters fit horizontally; plan approval, switching to the updates example, handle switching from Muse to Dots, and chapter controls verified. The example handle and people stayed fixed. -- Chrome at 390 × 844: horizontal story, agent marks, longest introduction example, and final CTA/photo composition visually checked. Native keyboard scrolling reached the final chapter. -- Chrome at 820 × 1180: stacked portrait composition and horizontal enhancement verified. All chapters pass the content-fit check before that enhancement enables. -- Chrome at 320 × 568: ordinary vertical fallback, wrapping, final CTA destinations, and the photo/footer checked. -- Emulated `prefers-reduced-motion: reduce` switches to the full vertical page and removes horizontal controls. Restoring the preference re-enables the story. -- Left/Right chapter navigation and native scrolling verified. Offscreen chapters are absent from Chrome’s accessibility tree while horizontal mode is active. Console showed only Vite development messages during the final pass. -- Contrast pass: cream text on coral measures 4.67:1; small coral-scene text uses that pair. Large peach display text is reserved for headlines. No timed animation, audio, or video runs on this route. - -These are Chrome checks, including device emulation; they are not a claim of physical-device Safari testing. Build output contains the complete static story for the no-JavaScript reading path. - -### Snap and mobile follow-up - -- Removed the reading-mode button and its localStorage behavior as requested. The header is brand plus Start now. -- Desktop partial and larger native scroll gestures settle on complete chapters. Reverse scrolling at 375 × 667 also settles cleanly; no custom wheel handler is used. -- 375 × 667 now fits the horizontal story. The phone-specific layout simplifies the handle card, keeps sample buttons at least 40px tall, and fits the longest introduction example with its disclosure above the chapter controls. The fit check covers every chapter before horizontal mode enables. -- Rechecked 390 × 844 after the follow-up: full chapter snapping remains enabled, including after a resize. A more compact result card keeps the longest introduction example above the controls. Mobile chapter arrows have 44px touch targets. -- Type check of the teaser script, production build, and full site-integrity checks pass after these changes. +- Production build passes: 335 Astro pages plus generated error documents. +- Plain coverage passes: 100 required pairs. +- Site integrity passes: 339 HTML files and 24,447 internal references. +- `check:teaser` exercises the actual TypeScript controller in both native/fallback modes: 50 height-only mobile resize events cause no reconfiguration or scrollTo; 30 scroll frames cause zero native transform writes and exactly one per frame in the fallback; width changes preserve the chapter; reduced motion removes horizontal mode and inert states. The regression check runs in CI. +- Chrome desktop and 390×844 compositions were visually inspected. The 375×667 view fits all five scenes, including the dinner disclosure and final CTA. Native scrolling reaches complete chapters; the Muse-to-Dots switch retains the handle. The root class confirms the native scroll-timeline path is active. +- Chrome’s reduced-motion emulation exposes the full vertical story and removes chapter controls; the preference was restored afterward. +- Console inspection showed development-server messages, without application errors. +- The separate `/pilot-film` page was checked at 375×667 in both formats. It starts paused and provides downloads and the full transcript. No film asset loads on the teaser. + +Browser checks include Chrome device emulation, not physical iPhone/Safari testing. The previous version’s 320×568 check is not claimed as a fresh visual check of this revision; the same short-window fallback remains covered by the controller logic. diff --git a/docs/pilot-film.md b/docs/pilot-film.md new file mode 100644 index 00000000..9a6f0fe3 --- /dev/null +++ b/docs/pilot-film.md @@ -0,0 +1,11 @@ +# Pilot film publication + +`/pilot-film` is a separate noindex viewing page with widescreen/vertical selection, ordinary video controls, downloads, and a text transcript. It has no autoplay. The teaser loads no film files. + +Revision 14: 23.083 seconds at 60fps; 1920×1080 and 1080×1920. The film uses the exact website Inter Tight font, a matching puppy/Pilot lockup, cream/clay/ink palette, Muse and Priya’s Dots, a persistent handle, and the Start now CTA. Original scene boundaries and the one-interval 0:05 scene are retained. Human connection and plan approval remain explicit. Product scenes are labeled illustrative. + +Picture: existing illustrated components and Higgsfield reunion footage (wide job `43933a0b-8a7f-4269-8c5b-6da310ebea55`, vertical job `43a9edd7-b165-4cc2-8980-34a3ed8b14d2`). Typeface and brand marks are reused from the website. + +Audio: user-supplied first seven seconds of Imagine Dragons’ “Believer”, arranged into the existing drum loop, with the retained final fade. No narration. The user requested deployment of all work. This document records provenance, not a representation of a music license. + +Both final files fully decode, contain 1,385 frames, end with black video and zero final-10ms audio RMS, and have 0.999876 correlation to the retained source waveform. This is numerical verification, not independent listening. The production source, previous cuts, generation records, and independent visual review stay in the local `launch-video/drums/output/rhythm-v14/` archive. Only final MP4s, posters, and transcript are published. diff --git a/package.json b/package.json index 4a411635..efeb3ef1 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "optimize:blog-banners": "node scripts/optimize-blog-banners.mjs", "audit:indexability": "node scripts/audit-live-indexability.mjs", "check:plain": "node scripts/check-plain-coverage.mjs", + "check:teaser": "node scripts/check-teaser-scroll.mjs", "check:site": "node scripts/check-site-integrity.mjs" }, "dependencies": { diff --git a/public/cloud/film/pilot-vertical.mp4 b/public/cloud/film/pilot-vertical.mp4 new file mode 100644 index 00000000..24c11382 Binary files /dev/null and b/public/cloud/film/pilot-vertical.mp4 differ diff --git a/public/cloud/film/pilot-wide.mp4 b/public/cloud/film/pilot-wide.mp4 new file mode 100644 index 00000000..b14c4248 Binary files /dev/null and b/public/cloud/film/pilot-wide.mp4 differ diff --git a/public/cloud/film/poster-vertical.jpg b/public/cloud/film/poster-vertical.jpg new file mode 100644 index 00000000..c3fbba3f Binary files /dev/null and b/public/cloud/film/poster-vertical.jpg differ diff --git a/public/cloud/film/poster-wide.jpg b/public/cloud/film/poster-wide.jpg new file mode 100644 index 00000000..fbd7a503 Binary files /dev/null and b/public/cloud/film/poster-wide.jpg differ diff --git a/public/cloud/film/transcript.txt b/public/cloud/film/transcript.txt new file mode 100644 index 00000000..8412019d --- /dev/null +++ b/public/cloud/film/transcript.txt @@ -0,0 +1,42 @@ +# Pilot — The last chore + +23.083 seconds · 60fps · same copy and timing in widescreen and vertical. **No narration.** Original-tempo loop from the user-supplied first seven seconds of “Believer”. Audio fades 21.083–23.083s; picture fades 22.033–23.083s. + +Times describe the first visible frame, quantized to 60fps. The soundtrack’s attacks can fall between frames. + +| Time | On-screen text | Picture / action | +|---|---|---| +| 0.000–3.117 | Your messages | Clearly human conversation, with You and Priya portraits. | +| 0.000–3.117 | You / Dinner soon? | Opening message is present at frame zero. It fills coral at 0.233. | +| 0.717–3.117 | Priya / When works? | Reply enters on the drum; fills coral at 1.183. | +| 1.667–3.117 | You / Let me check… | More availability work, still no settled time. | +| 2.150–3.117 | Still planning. | The problem is explicit. | +| 3.117–5.033 | The last chore / you’ll ever do. | Whole chosen hook stays together. Palette inversion 3.917; underline 4.550. | +| 5.033–6.950 | The AI you already use. / Connected to theirs. | You / Muse and Priya / Dots, linked by Pilot. Connector solid at 5.517; palette impact 5.833. | +| 6.950–9.833 | Share your / handle link. | Your AI → Their AI. “cloud.pilotprotocol.network/” + “@maya”. Transfer starts 7.433 and lands 7.750. | +| 7.750–8.383 | Accept connection | Human pointer appears at 7.917. | +| 8.383–9.833 | Connection approved | The connection is accepted before agents act. | +| 9.833–14.633 | Let the agents / do the back and forth. | One persistent headline through negotiation and approval. | +| 9.833–11.750 | Your AI / Dinner Thursday? | The agents work on the same dinner request. | +| 9.833–10.783 | Their AI / … | Response dots brighten at 10.317. | +| 10.783–12.717 | Their AI / After 7. | Reply persists while the first AI suggests a time; fades during the final transition. | +| 11.750–13.667 | 7:30? | From 12.500–12.717, the same message grows into the proposal in place. | +| 12.717–14.633 | Dinner with Priya / Thursday / You approve. | Plan context and human control appear. | +| 12.717–13.667 | Approve plan | Human pointer appears at 13.183. | +| 13.667–14.633 | Plan confirmed / 7:30 | Check appears; question mark disappears; persistent context chip gains the confirmed time. | +| 14.633–17.517 | New AI. / Same handle. | @maya and its URL remain in place. Confirmed dinner stays in the context chip. | +| 14.633–15.583 | Muse | Existing app. | +| 15.583–17.517 | Muse → Dots | AI changes, while the handle and confirmed plan remain. | +| 17.517–19.433 | No main headline or CTA | Full-screen Higgsfield reunion. Picture punches in at 18.467. | +| 19.433–23.083 | Less planning. / More see you soon. / Claim your handle. Invite a friend. / Start now / cloud.pilotprotocol.network | One emotional payoff, handle/invitation instruction, and Start now CTA. Palette inverts at 20.383. Full reading hold until picture fade at 22.033. | + +Persistent context and disclosure: + +- “Pilot” appears throughout. +- “Dinner with Priya” stays fixed from 0–17.517s. After human approval at 13.667, the same chip additionally shows a check and “Thu · 7:30”. +- “Illustrative conversation” appears during the opening, 0–3.117s. +- “Illustrative · Both AIs connected” appears during product demonstration, 5.033–17.517s. +- “You approve connections and plans.” appears from 17.517s through the end fade. + +This is an illustrative example, not a real-user chat or an app screen recording. It does not imply private calendar access, automatic consent or a restaurant booking. Human messages come first, connection approval precedes the agents’ exchange, and human plan approval precedes confirmation. + diff --git a/public/cloud/teaser/CREDITS.md b/public/cloud/teaser/CREDITS.md new file mode 100644 index 00000000..ef3e1b7c --- /dev/null +++ b/public/cloud/teaser/CREDITS.md @@ -0,0 +1,7 @@ +# Pilot teaser imagery + +- Café photography: existing licensed image and source attribution in `../warm/CREDITS.md`. +- `reunion-wide.webp` and `reunion-vertical.webp`: optimized stills from the existing Higgsfield-generated Pilot reunion footage, at 1.2 seconds. Wide job `43933a0b-8a7f-4269-8c5b-6da310ebea55`; vertical job `43a9edd7-b165-4cc2-8980-34a3ed8b14d2`. Illustrative people, not customers or testimonials. No new generation or credit usage. +- `social.jpg`: Pilot typography and logo composed over that reunion still. + +The published teaser uses static WebP images, not background video. diff --git a/public/cloud/teaser/reunion-vertical.webp b/public/cloud/teaser/reunion-vertical.webp new file mode 100644 index 00000000..692c4bf1 Binary files /dev/null and b/public/cloud/teaser/reunion-vertical.webp differ diff --git a/public/cloud/teaser/reunion-wide.webp b/public/cloud/teaser/reunion-wide.webp new file mode 100644 index 00000000..b0b494ae Binary files /dev/null and b/public/cloud/teaser/reunion-wide.webp differ diff --git a/public/cloud/teaser/social.jpg b/public/cloud/teaser/social.jpg index e056f5f3..dfc6dcab 100644 Binary files a/public/cloud/teaser/social.jpg and b/public/cloud/teaser/social.jpg differ diff --git a/scripts/check-teaser-scroll.mjs b/scripts/check-teaser-scroll.mjs new file mode 100644 index 00000000..2d3ba369 --- /dev/null +++ b/scripts/check-teaser-scroll.mjs @@ -0,0 +1,52 @@ +// Regression checks for the actual scroll script: mobile toolbar resizes must +// not reset the story, and scroll frames must not invalidate every panel. +import assert from 'node:assert/strict'; +import { readFileSync } from 'node:fs'; +import { stripTypeScriptTypes } from 'node:module'; +import vm from 'node:vm'; + +const source = stripTypeScriptTypes(readFileSync(new URL('../src/scripts/cloud-teaser.ts', import.meta.url), 'utf8')).replace('export {};', ''); +for (const nativeTimeline of [true, false]) { + const writes = []; + const resets = []; + const scrolls = []; + const events = {}; + const frames = []; + let timer; + const style = () => new Proxy({ setProperty(key, value) { writes.push([key, value]); }, removeProperty() {} }, { set(target, key, value) { writes.push([key, value]); target[key] = value; return true; } }); + const element = () => ({ style: style(), dataset: {}, hidden: false, inert: false, contains: () => false, setAttribute() {}, addEventListener() {}, append() {}, prepend() {}, focus() {}, scrollIntoView() {} }); + const root = element(); + const classes = new Set(); + root.classList = { toggle(key, on) { on ? classes.add(key) : classes.delete(key); }, remove(...keys) { resets.push(keys); keys.forEach(key => classes.delete(key)); } }; + const stage = { ...element(), clientHeight: 660, get clientWidth() { return browser.innerWidth; } }; + const story = { ...element(), getBoundingClientRect: () => ({ top: -browser.scrollY }) }; + const track = element(); + const panels = Array.from({ length: 5 }, (_, i) => ({ ...element(), dataset: { name: `Scene ${i}`, tone: 'light' }, querySelector: () => ({ clientHeight: 660, scrollHeight: 660, getBoundingClientRect: () => ({ top: 0, bottom: 660 }), children: [{ getBoundingClientRect: () => ({ top: 150, bottom: 250 }) }] }) })); + const reduced = { matches: false, addEventListener(type, callback) { this.change = callback; } }; + const browser = { innerWidth: 390, innerHeight: 700, scrollY: 0, matchMedia: query => query.includes('reduced') ? reduced : { matches: true }, addEventListener: (name, fn) => { events[name] = fn; }, scrollTo: options => { scrolls.push(options); browser.scrollY = options.top; }, clearTimeout() { timer = undefined; }, setTimeout(fn) { timer = fn; return 1; } }; + const nodes = { '.teaser-story': story, '.teaser-stage': stage, '.teaser-track': track, '.teaser-controls': element(), '[data-previous]': element(), '[data-next]': element(), '[data-chapter]': element(), '[data-story-status]': element(), '[data-scroll-cue]': element(), '.story-progress > span': element() }; + const document = { documentElement: root, activeElement: null, querySelector: selector => nodes[selector] ?? null, querySelectorAll: selector => selector === '.teaser-panel' ? panels : [], createElement: element, addEventListener() {}, fonts: { ready: Promise.resolve() } }; + vm.runInNewContext(source, { document, window: browser, CSS: { supports: () => nativeTimeline }, requestAnimationFrame: fn => frames.push(fn), getComputedStyle: () => ({ paddingTop: '80', paddingBottom: '80', position: 'static' }) }); + await Promise.resolve(); + assert.equal(classes.has('teaser-horizontal'), true); + assert.equal(classes.has('teaser-native'), nativeTimeline); + writes.length = resets.length = scrolls.length = 0; + for (let i = 0; i < 50; i++) { browser.innerHeight = 700 + i; events.resize(); } + assert.equal(timer, undefined, 'toolbar-only resize must not schedule a layout reset'); + assert.equal(resets.length, 0); + assert.equal(scrolls.length, 0, 'toolbar resize must not jump or snap the page'); + for (let i = 0; i < 30; i++) { browser.scrollY = i * 8; events.scroll(); frames.splice(0).forEach(fn => fn()); } + assert.equal(writes.some(([key]) => key.startsWith('--')), false, 'scroll must not write inherited custom properties'); + assert.equal(writes.length, nativeTimeline ? 0 : 30, 'native scroll has no per-frame style writes; fallback has only the track transform'); + browser.innerWidth = 430; + events.resize(); + assert.equal(typeof timer, 'function', 'a real width change must remeasure the layout'); + timer(); + assert.equal(scrolls.length, 1); + reduced.matches = true; + reduced.change(); + assert.equal(classes.has('teaser-horizontal'), false); + assert.equal(classes.has('teaser-native'), false); + assert.equal(panels.every(panel => !panel.inert), true); +} +console.log('Teaser scroll regression checks passed: native/fallback, toolbar resizing, width changes, reduced motion.'); diff --git a/src/pages/cloud-teaser.astro b/src/pages/cloud-teaser.astro index 1a0375a1..a97218ee 100644 --- a/src/pages/cloud-teaser.astro +++ b/src/pages/cloud-teaser.astro @@ -20,7 +20,7 @@ const chats = [ description="Connect the AI you already use to your people. Let the agents handle plans, updates, and introductions. Claim your Pilot handle and invite a friend." canonicalUrl="https://pilotprotocol.network/cloud-teaser" ogImage="https://pilotprotocol.network/cloud/teaser/social.jpg" - ogImageAlt="Pilot. Your friend group, on autopilot. Claim your handle. Invite your friends." + ogImageAlt="Pilot. Less planning. More see you soon. Claim your handle. Invite a friend." robots="noindex,nofollow" /> @@ -42,155 +42,82 @@ const chats = [ Skip to the story
Pilot -
- Start now -
+ Start now
-
+ Two friends laughing over coffee +
-

For your friend group

-

The last
chore you’ll
ever do.

-

Connect your AI once.
Let it handle the back-and-forth.

-
-
- - - -
Dinner soon?Priya · just now
-
Yes! When works?
-
Let me check…
- Pilot, a puppy carrying a letter - Good friends. So much admin. +

The last chore
you’ll ever do.

+

Give the back-and-forth to your AI.

+
- -
+
+
-
-

01 / Bring your AI

-

First, you
need an
agent.

-

The one you already use.
Pilot gives it a way to reach your people.

-
+

Bring
your AI.

It’s about to meet your people.

-

Made for your background agent

-
- {agents.map(([name, logo], index) =>
- - {name} -
)} -
-

With background check-ins enabled,
they can pick up replies while you’re away.

-
-
{chats.map(([name, logo]) => {name})}
-

Or a chat app. Any AI with MCP.
Chat apps work while you chat.

+
+ Pilot carrying a letter + {agents.map(([name, logo], index) =>
{name}
)}
+

Or your chat app, via MCP.

+
{chats.map(([name, logo]) => {name})}
- -
+
-
-

02 / Hand off the back-and-forth

-

Run your
friend group
on autopilot.

-

Let the agents do the back-and-forth.
You get the part worth showing up for.

- -
+

Your friend group,
on autopilot.

Let the agents do the back-and-forth.

-
-
Your Musevia Pilot

Dinner with Priya on Thursday?

- -
Priya’s Dotsvia Pilot

After 7 works for Priya. How’s 7:30?

-
- -
A plan, ready for your OK

Thursday, 7:30.

Dinner with Priya. Finally.

- -
-
-

Illustrative example · Both AIs connected.
Your agent uses the context and permissions you give it.

+
Your Muse

Dinner Thursday?

+
Priya’s Dots

After 7. Shall we say 7:30?

+
Dinner with Priya

Thursday, 7:30.

+

Illustrative · Both AIs connected.
You approve connections and plans.

- -
-
-
-

03 / Different AIs. Your people.

-

Your agent.
Meet their
agents.

-

Pilot connects your AI to theirs.
Make a plan. Ask for an intro.
Get an update. Send a file.

-

By invitation. You decide who’s in.

-
-
- -
YouMuse
-
Pilot
-
PriyaDots
-
SamHermes
-
Dinner? Sorted.
-
Deck? Delivered.
-
-
-
-
+
-
-

04 / One link to reach you

-

New AI.
Same
handle.

-

Share your handle link with your friends.
Switch your AI whenever you like.
Your people come with you.

-
+

New AI.
Same handle.

One link. Your people. Any AI.

-
-
Yours to keep
-

@maya

-

cloud.pilotprotocol.network/@maya

-
Connected toMuse
-
Same friends. Same connections.
-
- -

Example handle · Connect a new AI to the same Pilot account.

+

@maya

+

cloud.pilotprotocol.network/@maya

+

Connected to Muse

+ +

Example handle. Your connections stay with you.

-
+ Friends greeting each other with a hug +
-

Less planning. More see you soon.

-

Claim your
handle.
Invite your
friends.

+

Less planning.
More see
you soon.

+

Claim your handle. Invite a friend.

-

Free to start. Hosted for you.
You both connect an AI. No Pilot software to install.
Accept requests, then choose each person’s circle.

+

Free. Hosted for you. You both connect an AI.

-
-
Two friends laughing together over coffee at a caféActually
seeing you
soon. ♡
-
That’s the whole point.
- -
- +
- + diff --git a/src/pages/pilot-film.astro b/src/pages/pilot-film.astro new file mode 100644 index 00000000..79b464a3 --- /dev/null +++ b/src/pages/pilot-film.astro @@ -0,0 +1,59 @@ +--- +import BaseHead from '../components/BaseHead.astro'; +import transcript from '../../public/cloud/film/transcript.txt?raw'; +--- + + + + + + + diff --git a/src/pages/sitemap.xml.ts b/src/pages/sitemap.xml.ts index 07175562..e7357943 100644 --- a/src/pages/sitemap.xml.ts +++ b/src/pages/sitemap.xml.ts @@ -28,7 +28,7 @@ function routeFromKey(key: string): string { const REFERENCE = new Set(['error-codes', 'troubleshooting', 'diagnostics', 'configuration']); const LEGAL = new Set(['/privacy', '/cookies', '/terms', '/aup', '/publisher-agreement']); // Standalone design previews are intentionally noindex and shared by direct link. -const PREVIEWS = new Set(['/cloud-landing', '/cloud-teaser']); +const PREVIEWS = new Set(['/cloud-landing', '/cloud-teaser', '/pilot-film']); // The four offerings: the protocol (home), the service agents, the App Store // and Pilot Cloud. diff --git a/src/scripts/cloud-teaser.ts b/src/scripts/cloud-teaser.ts index 1e8b3b49..d410aa36 100644 --- a/src/scripts/cloud-teaser.ts +++ b/src/scripts/cloud-teaser.ts @@ -11,7 +11,10 @@ const next = document.querySelector('[data-next]'); const chapter = document.querySelector('[data-chapter]'); const status = document.querySelector('[data-story-status]'); const cue = document.querySelector('[data-scroll-cue]'); +const progressFill = document.querySelector('.story-progress > span'); const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)'); +const touchDevice = window.matchMedia('(hover: none), (pointer: coarse)'); +const nativeTimeline = CSS.supports('animation-timeline', 'scroll(root block)') && CSS.supports('animation-range', '0px 1px'); let horizontal = false; let active = 0; let lastPainted = -1; @@ -26,6 +29,7 @@ function setActive(index: number) { active = index; lastPainted = index; root.dataset.tone = panels[index]?.dataset.tone || 'light'; + root.dataset.chapter = String(index); panels.forEach((panel, i) => { const inactive = horizontal && i !== index; if (inactive && panel.contains(document.activeElement)) stage?.focus({ preventScroll: true }); @@ -42,9 +46,10 @@ function paint() { pendingFrame = 0; if (!horizontal || !track || !stageHeight) return; const progress = Math.max(0, Math.min(panels.length - 1, (window.scrollY - startY) / stageHeight)); - track.style.transform = `translate3d(${-progress * stageWidth}px, 0, 0)`; - stage?.style.setProperty('--progress', String(progress / (panels.length - 1))); - panels.forEach((panel, i) => panel.style.setProperty('--travel', String(Math.max(-1, Math.min(1, progress - i))))); + // Supported browsers animate the track on their scroll timeline. The JS + // fallback changes one transform, never inherited styles on every panel. + if (!nativeTimeline) track.style.transform = `translate3d(${-progress * stageWidth}px, 0, 0)`; + if (progressFill && !touchDevice.matches) progressFill.style.transform = `translateX(${progress * 100}%)`; setActive(Math.round(progress)); } @@ -65,15 +70,15 @@ function configure(keepPlace = false) { : active; const priorProgress = wasHorizontal && stageHeight ? (window.scrollY - startY) / stageHeight : priorIndex; // Don't let a transient measurement layout become a new native snap position. - root.classList.remove('teaser-snapping'); + root.classList.remove('teaser-snapping', 'teaser-native'); // Small landscape windows and large text need a page that can grow naturally. - const eligible = !reducedMotion.matches && window.innerHeight >= 660; + const eligible = !reducedMotion.matches && window.innerHeight >= 600; horizontal = eligible; root.classList.toggle('teaser-horizontal', eligible); story.style.height = ''; track.style.transform = ''; controls.hidden = !eligible; - panels.forEach(panel => { panel.inert = false; panel.style.removeProperty('--travel'); }); + panels.forEach(panel => { panel.inert = false; }); lastPainted = -1; if (eligible) { stageHeight = stage.clientHeight; @@ -99,9 +104,11 @@ function configure(keepPlace = false) { controls.hidden = true; } else { story.style.setProperty('--teaser-step', `${stageHeight}px`); - // The last snap target needs a full viewport of scroll room, including - // when mobile browser chrome makes innerHeight differ from 100svh. - story.style.height = `${stageHeight * (panels.length - 1) + window.innerHeight}px`; + story.style.setProperty('--teaser-distance', `${stageHeight * (panels.length - 1)}px`); + story.style.setProperty('--teaser-shift', `${-100 * (panels.length - 1)}%`); + // Reserve the large viewport once. Collapsing mobile browser chrome must + // not rebuild the story or make the last chapter unreachable. + story.style.height = `calc(${stageHeight * (panels.length - 1)}px + 100lvh)`; startY = story.getBoundingClientRect().top + window.scrollY; } } @@ -112,6 +119,7 @@ function configure(keepPlace = false) { if (horizontal) paint(); else { root.dataset.tone = 'light'; panels.forEach(panel => panel.inert = false); } root.classList.toggle('teaser-snapping', horizontal); + root.classList.toggle('teaser-native', horizontal && nativeTimeline); } if (story && stage && track && panels.length && controls) { @@ -145,10 +153,17 @@ if (story && stage && track && panels.length && controls) { stage.focus({ preventScroll: true }); if (horizontal) goTo(0); else story.scrollIntoView(); }); - let resizeFrame = 0; + let resizeTimer = 0; + let viewportWidth = window.innerWidth; + let viewportHeight = window.innerHeight; window.addEventListener('resize', () => { - cancelAnimationFrame(resizeFrame); - resizeFrame = requestAnimationFrame(() => configure(true)); + const width = window.innerWidth; + const height = window.innerHeight; + if (width === viewportWidth && (touchDevice.matches || height === viewportHeight)) return; + viewportWidth = width; + viewportHeight = height; + window.clearTimeout(resizeTimer); + resizeTimer = window.setTimeout(() => configure(true), 150); }, { passive: true }); reducedMotion.addEventListener('change', () => configure(true)); configure(); @@ -156,44 +171,18 @@ if (story && stage && track && panels.length && controls) { document.fonts.ready.then(() => configure(true)); } -const examples = { - plans: { ask: 'Dinner with Priya on Thursday?', agent: 'Priya’s Dots', logo: 'dots.webp', reply: 'After 7 works for Priya. How’s 7:30?', eyebrow: 'A plan, ready for your OK', title: 'Thursday, 7:30.', detail: 'Dinner with Priya. Finally.', action: 'Looks good', done: 'That’s a plan. See you Thursday!', approved: 'Plan approved · Example' }, - updates: { ask: 'Sam, how’s the launch coming along?', agent: 'Sam’s Hermes', logo: 'hermes.png', reply: 'Sam’s latest update: on track for Friday.', eyebrow: 'The answer, without the follow-up', title: 'Friday. On track.', detail: 'One less person to chase.', action: 'Got it', done: 'Update noted. Back to your day.', approved: 'Update received · Example' }, - intros: { ask: 'Does Priya know a good designer?', agent: 'Priya’s Dots', logo: 'dots.webp', reply: 'She knows Alex. Shall I ask if he’s open to an intro?', eyebrow: 'An introduction starts with permission', title: 'A good connection.', detail: 'Ask first. Connect when everyone agrees.', action: 'Ask Alex', done: 'The request goes to Alex. He gets to decide.', approved: 'Intro request · Example' }, - files: { ask: 'Send Sam the latest deck from this chat.', agent: 'Sam’s Hermes', logo: 'hermes.png', reply: 'Got it. I have the latest version for Sam.', eyebrow: 'The right file, in the right hands', title: 'Deck. Delivered.', detail: 'No hunting through old messages.', action: 'All sorted', done: 'The latest version is with Sam’s agent.', approved: 'File received · Example' }, -}; -type Example = keyof typeof examples; -let currentExample: Example = 'plans'; -const exampleButtons = Array.from(document.querySelectorAll('[data-example]')); +// A local illustration, not a booking or a message sent to another person. const approve = document.querySelector('.result-approve'); -function showExample(key: Example) { - const example = examples[key]; - currentExample = key; - for (const field of ['ask', 'agent', 'reply', 'eyebrow', 'title', 'detail'] as const) { - const element = document.querySelector(`[data-example-${field}]`); - if (element) element.textContent = example[field]; - } - const logo = document.querySelector('[data-example-logo]'); - if (logo) logo.src = `/cloud/logos/${example.logo}`; - exampleButtons.forEach(button => button.setAttribute('aria-pressed', String(button.dataset.example === key))); - if (approve) { approve.textContent = `${example.action} ✓`; approve.dataset.approved = 'false'; } -} -exampleButtons.forEach(button => button.addEventListener('click', () => showExample(button.dataset.example as Example))); if (approve) { approve.hidden = false; approve.addEventListener('click', () => { - if (approve.dataset.approved === 'true') { showExample(currentExample); return; } - const example = examples[currentExample]; - const detail = document.querySelector('[data-example-detail]'); - const eyebrow = document.querySelector('[data-example-eyebrow]'); - if (detail) detail.textContent = example.done; - if (eyebrow) eyebrow.textContent = example.approved; - approve.textContent = 'Replay example ↺'; - approve.dataset.approved = 'true'; + const approved = approve.dataset.approved !== 'true'; + approve.dataset.approved = String(approved); + approve.textContent = approved ? 'Replay example ↺' : 'Looks good ✓'; + const label = document.querySelector('.result-label'); + if (label) label.textContent = approved ? 'Approved by you. See you Thursday!' : 'Dinner with Priya'; }); } -const choices = document.querySelector('.example-choices'); -if (choices) choices.hidden = false; const identityButtons = Array.from(document.querySelectorAll('[data-identity]')); identityButtons.forEach(button => button.addEventListener('click', () => { diff --git a/src/styles/cloud-teaser.css b/src/styles/cloud-teaser.css index 158f1b93..c21d99a6 100644 --- a/src/styles/cloud-teaser.css +++ b/src/styles/cloud-teaser.css @@ -1,523 +1,228 @@ html.pilot-teaser { - --cream: #faf7f2; - --coral: #b94e36; - --ink: #392f29; - --peach: #efd8c7; - --muted: #75655c; + --cream: #faf7f2; --coral: #b94e36; --ink: #392f29; --peach: #efd8c7; --sans: 'Inter Tight', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; - --mono: var(--sans); - --serif: var(--sans); - --bg: var(--cream); - --bg-elevated: #fffdf9; - --text: var(--ink); - --text-muted: var(--muted); - --accent: var(--coral); - --accent-text: var(--coral); - --accent-ink: var(--cream); - --ink-dim: var(--muted); - --bg-2: #f1e2d5; - --line: #d9cabe; - --border: #d9cabe; - color-scheme: light; - background: var(--cream); - scroll-behavior: auto; - overflow-x: clip; + --mono: var(--sans); --serif: var(--sans); --bg: var(--cream); --text: var(--ink); + color-scheme: light; background: var(--cream); scroll-behavior: auto; overflow-x: clip; } .pilot-teaser body { margin: 0; background: var(--cream); color: var(--ink); font-family: var(--sans); -webkit-font-smoothing: antialiased; overflow-x: clip; transition: none; } .pilot-teaser *, .pilot-teaser *::before, .pilot-teaser *::after { box-sizing: border-box; } -.pilot-teaser button, .pilot-teaser a { -webkit-tap-highlight-color: transparent; } .pilot-teaser :where(button) { font: inherit; cursor: pointer; } -.pilot-teaser button:disabled { cursor: default; } +.pilot-teaser button, .pilot-teaser a { -webkit-tap-highlight-color: transparent; } .pilot-teaser a { color: inherit; text-decoration: none; } -.pilot-teaser a:hover { color: inherit; } .pilot-teaser button:focus-visible, .pilot-teaser a:focus-visible { outline: 3px solid currentColor; outline-offset: 5px; } +.pilot-teaser button:disabled { opacity: .25; cursor: default; } .pilot-teaser [hidden] { display: none !important; } -.pilot-teaser .visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; } -.teaser-skip { position: fixed; z-index: 110; left: 20px; top: -100px; padding: 12px 20px; background: var(--cream); border-radius: 20px; } +.pilot-teaser :where(h1,h2,h3,p,figure) { margin: 0; } +.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; } +.teaser-skip { position: fixed; z-index: 100; left: 20px; top: -100px; padding: 12px 20px; background: var(--cream); border-radius: 30px; } .teaser-skip:focus { top: 14px; } -.teaser-header { position: absolute; z-index: 20; inset: 0 0 auto; height: 104px; padding: 0 clamp(24px, 4.5vw, 84px); display: flex; align-items: center; justify-content: space-between; color: var(--ink); pointer-events: none; } +.teaser-header { position: fixed; z-index: 20; inset: 0 0 auto; height: 98px; padding: 0 4.5vw; display: flex; align-items: center; justify-content: space-between; pointer-events: none; } .teaser-header > * { pointer-events: auto; } -html:not(.teaser-horizontal) .teaser-header { position: fixed; background: var(--cream); } -.teaser-brand { display: inline-flex; gap: 10px; align-items: center; font-size: 31px; font-weight: 650; letter-spacing: -1.6px; } +html:not(.teaser-horizontal) .teaser-header { background: var(--cream); } +.teaser-brand { display: flex; align-items: center; gap: 9px; font-size: 31px; font-weight: 650; letter-spacing: -1.6px; } .teaser-brand img { object-fit: contain; } -.teaser-header-actions { display: flex; align-items: center; gap: 25px; } -.teaser-start { padding: 13px 21px; background: var(--ink); color: var(--cream) !important; border-radius: 100px; display: inline-flex; align-items: center; gap: 24px; font-size: 15px; font-weight: 600; } -.teaser-start:hover { background: #574338; } -.teaser-start span { font-size: 20px; line-height: 1; } +.teaser-start, .primary-cta { display: inline-flex; align-items: center; gap: 22px; border-radius: 100px; font-size: 15px; font-weight: 550; min-height: 46px; padding: 12px 21px; background: var(--ink); color: var(--cream) !important; } +.teaser-start span, .primary-cta span { font-size: 22px; line-height: 1; } .teaser-story { position: relative; } -.teaser-story:focus { outline: none; } +.teaser-story:focus, .teaser-stage:focus { outline: none; } .teaser-snap-points { display: none; } -.teaser-panel { background: var(--cream); min-height: 100svh; position: relative; isolation: isolate; color: var(--ink); } -.panel-inner { width: min(100%, 1600px); min-height: 100svh; margin: 0 auto; padding: 125px clamp(28px, 6vw, 110px) 100px; display: grid; grid-template-columns: 1.04fr 1fr; gap: clamp(28px, 4vw, 78px); align-items: center; position: relative; } -.panel-copy { position: relative; z-index: 2; } -.teaser-kicker { font-size: 13px; line-height: 1.4; letter-spacing: .025em; font-weight: 550; margin: 0 0 25px; display: flex; align-items: center; gap: 9px; } -.teaser-kicker > span { font-size: 22px; line-height: 1; } -.pilot-teaser :where(h1, h2, h3, p, figure) { margin-top: 0; } -.pilot-teaser h1, .pilot-teaser h2 { font: 560 clamp(62px, 6.9vw, 112px)/.97 var(--sans); letter-spacing: -.065em; margin-bottom: 28px; text-wrap: balance; } -.pilot-teaser h1 { font-size: clamp(70px, 7.9vw, 128px); } -.pilot-teaser h3 { font-family: var(--sans); } +.teaser-panel { min-height: 100svh; position: relative; isolation: isolate; background: var(--cream); color: var(--ink); overflow: clip; } +.panel-inner { position: relative; z-index: 2; width: min(100%, 1640px); min-height: 100svh; margin: auto; padding: 130px 6vw 115px; display: grid; grid-template-columns: 1.05fr 1fr; align-items: center; gap: 5vw; } +.pilot-teaser h1, .pilot-teaser h2 { font: 560 clamp(64px, 7.3vw, 118px)/.98 var(--sans); letter-spacing: -.065em; text-wrap: balance; } +.pilot-teaser h1 { font-size: clamp(75px, 8.3vw, 133px); } .coral-text { color: var(--coral); } .soft-text { color: #f5d5bd; } -.teaser-description { font-size: clamp(17px, 1.5vw, 22px); line-height: 1.5; letter-spacing: -.015em; margin-bottom: 0; color: var(--muted); } -.panel-agents, .panel-handle { background: var(--coral); color: var(--cream); } -.panel-agents .teaser-description, .panel-handle .teaser-description { color: var(--cream); } -.panel-plans { background: #f1e2d5; } -.panel-people { background: #f0f0e6; } -.chore-scene { height: 510px; position: relative; width: 100%; } -.chore-orbit { position: absolute; inset: 65px -15px 20px; border-radius: 50%; background: #eed8c6; transform: rotate(-10deg); } -.chore-orbit::after { content: ''; position: absolute; inset: -16px 9px 16px -9px; border: 1px solid #d1b6a3; border-radius: 50%; transform: rotate(14deg); } -.chore-pup { position: absolute; width: 70%; height: auto; left: 10%; bottom: 44px; z-index: 2; transform: translateY(calc(var(--travel, 0) * -22px)) rotate(calc(var(--travel, 0) * -7deg)); } -.loose-message { position: absolute; z-index: 3; background: #fffdfa; border: 1px solid #f2e7df; box-shadow: 0 12px 28px #5f352a0c; padding: 16px 20px; border-radius: 22px; display: flex; align-items: center; gap: 15px; font-size: clamp(17px, 1.65vw, 24px); letter-spacing: -.02em; white-space: nowrap; } -.message-first { top: 25px; left: 4%; transform: rotate(-7deg) translateY(calc(var(--travel, 0) * -30px)); } -.message-first small { display: block; font-size: 11px; color: var(--muted); margin-top: 3px; letter-spacing: 0; } -.message-first > span:last-child { font-size: 31px; color: var(--coral); margin-left: 14px; } -.message-second { top: 145px; right: -2%; transform: rotate(7deg) translateY(calc(var(--travel, 0) * 40px)); background: #e0e7d5; } -.message-third { top: 270px; right: 0; transform: rotate(-4deg) translateX(calc(var(--travel, 0) * 28px)); z-index: 4; } -.person-avatar, .person-portrait, .friend-stack i { display: block; flex-shrink: 0; border-radius: 50%; background-image: url('/cloud/warm/friends-cafe-small.webp'); background-size: auto 235%; background-repeat: no-repeat; } -.person-avatar { width: 42px; height: 42px; } -.person-you { background-position: 37% 24%; } -.person-priya { background-position: 92% 12%; } -.typing-dots { display: flex; gap: 4px; margin-left: 5px; } -.typing-dots i { width: 5px; height: 5px; background: #bba89b; border-radius: 50%; } -.scene-star { position: absolute; color: var(--coral); line-height: 1; } -.star-one { right: 3%; top: 64px; font-size: 58px; transform: rotate(calc(var(--travel, 0) * 45deg)); } -.star-two { left: -4%; top: 190px; font-size: 34px; } -.scene-caption { position: absolute; bottom: 0; left: 0; right: 0; text-align: center; font-size: 13px; color: var(--muted); } -.agent-scene { text-align: center; max-width: 540px; } -.scene-label { font-size: 13px; margin: 0 0 24px; } -.agent-grid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 16px; max-width: 470px; margin: auto; } -.agent-tile { grid-column: span 2; aspect-ratio: 1; background: var(--cream); color: var(--ink); border-radius: 26px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 13px; font-size: 15px; font-weight: 550; box-shadow: 0 6px 0 #92392344; } -.agent-tile img { width: 55%; height: 55%; max-width: 72px; max-height: 72px; object-fit: contain; } -.agent-tile-0 { transform: rotate(-7deg) translateY(calc(var(--travel, 0) * 25px)); } -.agent-tile-1 { transform: translateY(-7px); } -.agent-tile-2 { transform: rotate(7deg) translateY(calc(var(--travel, 0) * -25px)); } -.agent-tile-3 { grid-column: 2 / span 2; transform: rotate(4deg); } -.agent-tile-4 { transform: rotate(-5deg); } -.agent-note { font-size: 13px; line-height: 1.5; margin: 23px 0 22px; color: var(--cream); } -.chat-fallback { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 13px; padding-top: 21px; border-top: 1px solid #f3ddd33a; } -.chat-logos { display: flex; gap: 9px; padding: 10px 13px; background: var(--cream); border-radius: 99px; } +.teaser-description { font-size: clamp(17px, 1.55vw, 23px); line-height: 1.5; letter-spacing: -.02em; margin-top: 28px !important; } +.panel-chore .panel-inner, .panel-start .panel-inner { grid-template-columns: 1fr; } +.panel-chore .panel-copy { max-width: 880px; } +.scene-photo { position: absolute; z-index: 0; right: 0; top: 0; height: 100%; width: 74%; object-fit: cover; } +.cafe-photo { object-position: 59% 50%; } +.photo-wash { position: absolute; z-index: 1; inset: 0; background: linear-gradient(90deg,#faf7f2 0%,#faf7f2f2 23%,#faf7f2b0 42%,#faf7f200 73%); } +.photo-note { position: absolute; z-index: 2; right: 11%; bottom: 23%; padding: 19px 26px; background: #fffdf5; color: var(--ink); font-size: clamp(20px,2.1vw,32px); border-radius: 5px 20px 20px 20px; rotate: -7deg; box-shadow: 0 7px 30px #392f2912; } +.photo-note span { margin-left: 22px; color: var(--coral); } +.panel-agents { background: #f0f0e6; } +.ambient-circle { position: absolute; width: 75vw; height: 75vw; right: -16vw; top: 50%; translate: 0 -50%; border-radius: 50%; background: radial-gradient(circle,#e8cfb899 0%,#e8cfb830 48%,transparent 68%); } +.agent-scene { text-align: center; width: 100%; max-width: 590px; justify-self: center; } +.agent-orbit { position: relative; height: clamp(330px,32vw,500px); } +.orbit-pilot { position: absolute; width: 50%; height: 62%; object-fit: contain; left: 25%; top: 24%; } +.agent-mark { position: absolute; display: flex; flex-direction: column; align-items: center; gap: 10px; font-size: 14px; font-weight: 550; } +.agent-mark img { width: clamp(54px,6vw,82px); height: clamp(54px,6vw,82px); object-fit: contain; } +.agent-mark-0 { left: 9%; top: 12%; rotate: -8deg; } +.agent-mark-1 { right: 6%; top: 20%; rotate: 8deg; } +.agent-mark-2 { left: 40%; top: 0; rotate: 2deg; } +.agent-mark-3 { right: 6%; bottom: 8%; rotate: -7deg; } +.agent-mark-4 { left: 6%; bottom: 4%; rotate: 5deg; } +.agent-note { font-size: 15px; margin-top: 22px !important; } +.chat-logos { display: flex; justify-content: center; align-items: center; gap: 14px; margin-top: 16px; } .chat-logos img { object-fit: contain; } -.chat-fallback p { margin: 0; font-size: 13px; line-height: 1.5; text-align: left; } -.chat-fallback p span { color: var(--cream); font-size: 12px; } -.panel-plans h2 { font-size: clamp(55px, 5.6vw, 90px); } -.example-choices { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 30px; } -.example-choices button { border: 1px solid #cbb7a6; background: transparent; padding: 10px 16px; border-radius: 99px; color: var(--ink); font-size: 13px; } -.example-choices button[aria-pressed='true'] { background: var(--ink); border-color: var(--ink); color: var(--cream); } -.example-choices button:hover { border-color: var(--ink); } -.plan-scene { max-width: 520px; width: 100%; } -.exchange-message { border-radius: 24px; background: #fffdf9; padding: 20px 23px; box-shadow: 0 8px 30px #6b463307; } -.your-agent { margin-right: 35px; transform: rotate(-2deg); } -.their-agent { margin-left: 35px; transform: rotate(2deg); background: #e4e8d8; } -.message-author { display: flex; align-items: center; gap: 9px; font-size: 13px; color: #60544a; } +.panel-plans { background: #efddcb; } +.panel-plans h2 { font-size: clamp(58px,6.5vw,102px); } +.plan-scene { width: 100%; max-width: 550px; justify-self: center; } +.exchange-message { padding: 20px 25px; border-radius: 28px; width: 90%; background: #fffdf6; } +.your-agent { rotate: -3deg; } +.their-agent { margin: 23px 0 0 auto; rotate: 3deg; background: #dce5d0; } +.message-author { display: flex; align-items: center; gap: 9px; font-size: 13px; } .message-author img { object-fit: contain; } -.via-pilot { font-size: 11px; margin-left: auto; color: #776b60; } -.exchange-message p { font-size: clamp(17px, 1.65vw, 23px); line-height: 1.35; margin: 14px 0 0; letter-spacing: -.015em; } -.exchange-connector { display: flex; align-items: center; justify-content: center; height: 38px; gap: 10px; color: #aa7c60; font-size: 22px; } -.exchange-connector span { width: 25px; height: 1px; background: #c9ae98; } -.plan-result { position: relative; display: grid; grid-template-columns: 43px 1fr; gap: 15px; align-items: center; padding: 22px; background: var(--coral); color: var(--cream); border-radius: 24px; margin-top: 24px; box-shadow: 0 12px 20px #b94e3612; } -.result-icon { width: 43px; height: 43px; display: grid; place-items: center; background: #ffffff1a; border-radius: 50%; font-size: 25px; } -.result-eyebrow { font-size: 11px; color: var(--cream); } -.plan-result h3 { font-size: clamp(26px, 2.8vw, 40px); letter-spacing: -.04em; line-height: 1.1; font-weight: 550; margin: 5px 0; } -.plan-result p { margin: 0; font-size: 14px; color: var(--cream); } -.result-approve { grid-column: 2; justify-self: start; border: 0; border-radius: 100px; padding: 10px 17px; background: var(--cream); color: var(--ink); font-size: 13px; display: flex; gap: 25px; } -.example-disclosure { font-size: 11px; line-height: 1.6; text-align: center; color: var(--muted); margin: 18px 0 0; } -.permission-note { margin: 24px 0 0; font-size: 13px; color: #665f52; display: flex; align-items: center; gap: 9px; } -.permission-note span { font-size: 24px; color: var(--coral); } -.people-scene { position: relative; width: 100%; aspect-ratio: 560 / 460; } -.people-lines { width: 100%; height: 100%; position: absolute; inset: 0; fill: none; stroke: #bf9c80; stroke-width: 2; stroke-linecap: round; stroke-dasharray: 6 7; } -.person-card { position: absolute; width: 29%; border-radius: 28px; background: #fffdf8; text-align: center; display: flex; flex-direction: column; align-items: center; padding: 20px 10px 16px; gap: 7px; box-shadow: 0 10px 30px #54452e08; } -.person-card strong { font-weight: 550; font-size: 19px; } -.person-portrait { width: 76px; height: 76px; } -.you-card { left: 0; top: 30%; transform: rotate(-5deg); } -.priya-card { right: 0; top: 0; transform: rotate(6deg); } -.sam-card { right: 0; bottom: 0; transform: rotate(-5deg); } -.person-agent { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); } -.person-agent img { object-fit: contain; } -.sam-avatar { background: #ebc6ad; color: #9c4c2e; font-size: 39px; font-weight: 550; display: grid; place-items: center; position: relative; } -.sam-avatar span { position: absolute; right: -7px; top: -7px; font-size: 26px; color: #9c4c2e; } -.pilot-hub { position: absolute; width: 25%; left: 36%; top: 36%; aspect-ratio: 1; background: #e9d0b7; border-radius: 50%; display: flex; align-items: center; justify-content: center; flex-direction: column; border: 8px solid #f0f0e6; } -.pilot-hub img { width: 76%; height: 70%; object-fit: contain; } -.pilot-hub span { font-size: 12px; font-weight: 600; margin-bottom: 5px; } -.connection-label { position: absolute; font-size: 12px; padding: 10px 14px; border-radius: 99px; background: #dce5ce; white-space: nowrap; } -.connection-label span { padding-left: 9px; color: #566544; } -.label-plan { top: 20%; left: 25%; transform: rotate(-6deg); } -.label-file { bottom: 14%; left: 24%; transform: rotate(6deg); } -.handle-scene { width: 100%; max-width: 520px; } -.handle-card { background: var(--cream); border-radius: 30px; color: var(--ink); padding: 30px; transform: rotate(-3deg); box-shadow: 0 18px 0 #92392355; } -.handle-card-top { display: flex; justify-content: space-between; align-items: center; } -.handle-card-top .person-portrait { width: 62px; height: 62px; } -.handle-tag { font-size: 12px; display: flex; gap: 14px; align-items: center; color: var(--muted); } -.handle-tag > span { color: var(--coral); font-size: 32px; } -.handle-name { display: flex; align-items: center; justify-content: space-between; font-size: clamp(60px, 6.5vw, 92px); letter-spacing: -.07em; font-weight: 550; line-height: 1.1; margin: 20px 0 4px; } -.handle-name > span { font-size: .65em; color: var(--coral); } -.handle-url { margin: 0 0 28px; font-size: clamp(12px, 1.2vw, 17px); color: var(--muted); letter-spacing: -.01em; overflow-wrap: anywhere; } -.handle-connected { border-top: 1px solid #ded2c7; border-bottom: 1px solid #ded2c7; padding: 17px 0; display: flex; align-items: center; justify-content: space-between; gap: 15px; font-size: 13px; } -.handle-connected > span { color: var(--muted); } -.handle-connected strong { display: flex; align-items: center; gap: 8px; font-weight: 550; } -.handle-connected img { object-fit: contain; } -.connection-dot { width: 6px; height: 6px; border-radius: 50%; background: #6d8355; margin-left: 9px; } -.handle-friends { display: flex; align-items: center; gap: 12px; padding-top: 20px; font-size: 12px; } -.handle-friends > span:last-child { margin-left: auto; color: var(--coral); font-size: 25px; } -.friend-stack { display: flex; padding-right: 7px; } -.friend-stack i { width: 29px; height: 29px; margin-right: -7px; border: 2px solid var(--cream); font-style: normal; } -.friend-stack .small-sam, .friend-stack i:last-child { background: #ebc6ad; display: grid; place-items: center; font-size: 11px; } -.friend-stack i:last-child { background: #dfe5d3; } -.identity-picker { margin-top: 39px; text-align: center; } -.identity-picker p { font-size: 12px; margin-bottom: 12px; } -.identity-picker p span { margin-left: 6px; } -.identity-picker > div { display: flex; justify-content: center; gap: 8px; } -.identity-picker button { background: transparent; border: 1px solid #f4d2c475; color: var(--cream); border-radius: 99px; display: flex; gap: 8px; align-items: center; padding: 10px 15px; font-size: 13px; } -.identity-picker button[aria-pressed='true'] { background: var(--cream); color: var(--ink); border-color: var(--cream); } -.identity-picker button:hover { border-color: var(--cream); } +.exchange-message p { font-size: clamp(22px,2vw,31px); letter-spacing: -.025em; margin-top: 10px; } +.plan-result { text-align: center; margin-top: 39px; } +.result-label { font-size: 13px; } +.plan-result h3 { font-size: clamp(40px,4.2vw,64px); font-weight: 550; letter-spacing: -.05em; margin: 8px 0 16px; } +.result-approve { border: 0; border-radius: 100px; padding: 12px 23px; min-height: 44px; background: var(--coral); color: var(--cream); font-size: 14px; } +.example-disclosure { margin-top: 22px !important; text-align: center; font-size: 11px; line-height: 1.5; color: #6d5c4f; } +.panel-handle { background: var(--coral); color: var(--cream); } +.handle-flower { position: absolute; font-size: min(80vw,1050px); line-height: 1; right: -17%; bottom: -40%; color: #f5d5bd16; rotate: -12deg; pointer-events: none; } +.handle-scene { position: relative; text-align: center; width: 100%; } +.handle-name { display: flex; align-items: center; justify-content: center; gap: 25px; font-size: clamp(83px,10vw,160px); font-weight: 550; letter-spacing: -.07em; line-height: 1.1; } +.handle-name > span { font-size: .6em; } +.handle-url { font-size: 14px; margin-top: 7px !important; overflow-wrap: anywhere; } +.handle-connected { margin: 35px 0 !important; display: flex; align-items: center; justify-content: center; gap: 13px; font-size: 14px; } +.handle-connected strong { display: flex; align-items: center; gap: 7px; font-weight: 550; } +.handle-connected img { object-fit: contain; background: var(--cream); padding: 3px; border-radius: 6px; } +.identity-picker p { font-size: 13px; margin-bottom: 12px; } +.identity-picker > div { display: flex; justify-content: center; gap: 10px; } +.identity-picker button { min-height: 46px; display: flex; align-items: center; gap: 8px; border: 1px solid #f4d2c475; background: transparent; color: var(--cream); border-radius: 100px; padding: 10px 17px; font-size: 13px; } .identity-picker img { object-fit: contain; } -.handle-note { text-align: center; font-size: 10px; color: var(--cream); margin: 20px 0 0; } -.panel-start h2 { font-size: clamp(58px, 5.9vw, 94px); } -.final-actions { display: flex; gap: 28px; align-items: center; margin-top: 30px; } -.primary-cta { display: inline-flex; align-items: center; gap: 36px; border-radius: 100px; background: var(--coral); color: var(--cream) !important; padding: 18px 26px; font-size: 18px; font-weight: 550; } -.primary-cta:hover { background: #a9412c; } -.primary-cta span { font-size: 24px; line-height: 1; } -.learn-more { font-size: 15px; display: flex; gap: 10px; align-items: center; text-underline-offset: 5px; } -.learn-more:hover { text-decoration: underline; } -.start-details { font-size: 12px; line-height: 1.7; color: var(--muted); margin: 20px 0 0; } -.start-details strong { color: var(--ink); font-weight: 550; } -.reunion-scene { position: relative; margin: 0; padding: 16px 16px 0; border-radius: 28px; background: #ead6c4; transform: rotate(3deg); } -.reunion-photo { position: relative; aspect-ratio: 1.06; border-radius: 17px; } -.reunion-photo > img { width: 100%; height: 100%; object-fit: cover; object-position: 52% center; border-radius: inherit; } -.photo-sticker { position: absolute; right: -29px; top: 8%; background: #e2e8d3; width: 146px; height: 146px; border-radius: 50%; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; color: #415239; font-size: 22px; line-height: 1.03; letter-spacing: -.04em; transform: rotate(13deg); } -.photo-sticker > span { font-size: 28px; } -.reunion-scene figcaption { display: flex; justify-content: space-between; align-items: center; padding: 21px 7px 22px; font-size: 16px; letter-spacing: -.02em; } -.reunion-scene figcaption > span:last-child { font-size: 27px; } -.reunion-pup { position: absolute; width: 32%; height: auto; bottom: -6px; right: 10%; transform: rotate(-3deg); } -.teaser-legal { position: absolute; inset: auto clamp(28px, 6vw, 110px) 33px; display: flex; align-items: center; justify-content: space-between; font-size: 10px; color: var(--muted); } -.teaser-legal > span:last-child { display: flex; gap: 18px; } -.teaser-legal a:hover { text-decoration: underline; text-underline-offset: 3px; } -.teaser-controls { position: absolute; bottom: 0; left: 0; right: 0; height: 85px; display: flex; align-items: center; padding: 0 clamp(24px, 4.5vw, 84px); gap: 40px; color: var(--ink); } -.scroll-cue { display: flex; align-items: center; gap: 12px; font-size: 12px; min-width: 165px; margin: 0; } -.scroll-symbol { border: 1px solid #aa8a6c77; width: 29px; height: 38px; display: grid; place-items: center; border-radius: 99px; font-size: 18px; } -.story-progress { height: 2px; background: currentColor; opacity: .35; flex: 1; max-width: 420px; margin: 0 auto; position: relative; } -.story-progress > span { position: absolute; left: 0; top: -1px; height: 4px; width: 16.6667%; background: currentColor; border-radius: 2px; transform: translateX(calc(var(--progress, 0) * 500%)); } -.chapter-controls { display: flex; align-items: center; gap: 9px; } -.chapter-count { font-size: 12px; font-variant-numeric: tabular-nums; margin-right: 12px; display: flex; gap: 12px; } -.count-divider { opacity: .4; } -.chapter-controls button { width: 43px; height: 43px; border: 1px solid currentColor; border-radius: 50%; background: transparent; color: inherit; font-size: 21px; line-height: 1; } -.chapter-controls button:hover:not(:disabled) { background: #a17e5c20; } -.chapter-controls button:disabled { opacity: .25; } -.teaser-horizontal .teaser-header { position: fixed; } +.identity-picker button[aria-pressed='true'] { background: var(--cream); color: var(--ink); border-color: var(--cream); } +.handle-note { margin-top: 24px !important; font-size: 11px; line-height: 1.5; } +.reunion-photo { width: 75%; object-position: 62% center; } +.panel-start .photo-wash { background: linear-gradient(90deg,#faf7f2 0%,#faf7f2f0 27%,#faf7f270 53%,#faf7f200 80%); } +.panel-start .panel-copy { max-width: 770px; } +.panel-start h2 { font-size: clamp(66px,7vw,108px); } +.final-actions { display: flex; gap: 28px; align-items: center; margin-top: 28px; } +.primary-cta { background: var(--coral); padding: 16px 25px; font-size: 17px; } +.learn-more { display: inline-flex; align-items: center; gap: 12px; min-height: 44px; font-size: 15px; } +.learn-more:hover { text-decoration: underline; text-underline-offset: 5px; } +.start-details { margin-top: 18px !important; font-size: 12px; line-height: 1.5; } +.teaser-legal { position: absolute; bottom: 90px; left: 6vw; right: 6vw; display: flex; justify-content: space-between; font-size: 10px; } +.teaser-legal > span { display: flex; gap: 18px; } +.teaser-controls { position: absolute; z-index: 5; bottom: 0; inset-inline: 0; height: 78px; padding: 0 4.5vw; display: flex; align-items: center; gap: 35px; } +.teaser-horizontal[data-chapter='0'] .teaser-controls, .teaser-horizontal[data-chapter='4'] .teaser-controls { background: linear-gradient(0deg,#faf7f2f5,#faf7f280); } +.teaser-legal > span { background: #faf7f2e0; padding: 5px 9px; border-radius: 20px; } +.scroll-cue { display: flex; align-items: center; gap: 12px; font-size: 12px; } +.scroll-cue > span:first-child { font-size: 25px; } +.story-progress { height: 1px; background: #392f2940; flex: 1; max-width: 380px; margin-inline: auto; position: relative; overflow: hidden; } +.story-progress > span { position: absolute; left: 0; top: 0; height: 1px; width: 20%; background: currentColor; } +.chapter-controls { display: flex; align-items: center; gap: 9px; margin-left: auto; } +.chapter-count { display: flex; gap: 12px; margin-right: 12px; font-size: 12px; font-variant-numeric: tabular-nums; } +.count-divider { opacity: .5; } +.chapter-controls button { width: 44px; height: 44px; border: 1px solid currentColor; border-radius: 50%; color: inherit; background: transparent; font-size: 22px; } html.teaser-horizontal.teaser-snapping { scroll-snap-type: y mandatory; } .teaser-horizontal .teaser-snap-points { display: block; position: absolute; inset: 0; pointer-events: none; } -.teaser-horizontal .teaser-snap-point { position: absolute; top: calc(var(--chapter) * var(--teaser-step, 100svh)); left: 0; width: 100%; height: 1px; scroll-snap-align: start; scroll-snap-stop: always; } +.teaser-horizontal .teaser-snap-point { position: absolute; top: calc(var(--chapter) * var(--teaser-step,100svh)); left: 0; width: 100%; height: 1px; scroll-snap-align: start; scroll-snap-stop: always; } .teaser-horizontal .teaser-stage { position: sticky; top: 0; width: 100%; height: 100svh; overflow: clip; } .teaser-horizontal .teaser-track { display: flex; height: 100%; width: 100%; will-change: transform; } -.teaser-horizontal .teaser-panel { flex: 0 0 100%; min-width: 0; height: 100%; min-height: 0; } +.teaser-horizontal .teaser-panel { flex: 0 0 100%; min-width: 0; height: 100%; min-height: 0; contain: layout paint; } .teaser-horizontal .panel-inner { height: 100%; min-height: 0; } -.teaser-horizontal .teaser-controls { position: absolute; } -.teaser-horizontal .teaser-legal { bottom: 90px; } .teaser-horizontal[data-tone='coral'] .teaser-header, .teaser-horizontal[data-tone='coral'] .teaser-controls { color: var(--cream); } .teaser-horizontal[data-tone='coral'] .teaser-start { background: var(--cream); color: var(--ink) !important; } -.teaser-horizontal[data-tone='coral'] .scroll-symbol { border-color: #f6d6c888; } -@media (min-width: 901px) and (max-height: 800px) { - .panel-inner { padding-top: 108px; padding-bottom: 95px; } - .teaser-header { height: 90px; } - .pilot-teaser h1 { font-size: min(7.5vw, 104px); } - .pilot-teaser h2 { font-size: min(6.7vw, 90px); } - .panel-plans h2, .panel-start h2 { font-size: min(5.6vw, 76px); } - .panel-start h2 { font-size: min(5vw, 65px); margin-bottom: 20px; } - .panel-start .final-actions { margin-top: 20px; } - .panel-start .start-details { font-size: 11px; line-height: 1.6; margin-top: 17px; } - .teaser-kicker { margin-bottom: 18px; } - .teaser-description { font-size: 18px; } - .chore-scene { height: 450px; } - .agent-grid { max-width: 390px; gap: 12px; } - .agent-tile { border-radius: 23px; } - .agent-note { margin: 18px 0; } - .scene-label { margin-bottom: 19px; } - .chat-fallback { padding-top: 16px; } - .people-scene { max-width: 480px; } - .reunion-scene { max-width: 390px; justify-self: end; } - .handle-card { padding: 22px; } - .handle-name { font-size: 68px; margin-top: 12px; } - .handle-url { margin-bottom: 20px; } - .handle-card-top .person-portrait { width: 44px; height: 44px; } - .handle-connected { padding-block: 12px; } - .handle-friends { padding-top: 16px; } - .identity-picker { margin-top: 24px; } - .handle-note { margin-top: 14px; } - .exchange-message { padding: 12px 18px; } - .message-author { font-size: 12px; } - .message-author img { width: 26px; height: 26px; } - .exchange-message p { font-size: 18px; line-height: 1.3; margin-top: 6px; } - .exchange-connector { height: 24px; } - .plan-result { grid-template-columns: 1fr auto; padding: 18px; gap: 12px; margin-top: 18px; } - .result-icon { display: none; } - .plan-result h3 { font-size: 31px; } - .plan-result p { font-size: 12px; } - .result-approve { grid-column: 2; grid-row: 1; gap: 9px; padding: 10px 13px; font-size: 12px; } - .example-disclosure { margin-top: 14px; } -} -@media (max-width: 1000px) and (min-width: 761px) { - .panel-inner { padding-inline: 5vw; gap: 30px; } - .pilot-teaser h1 { font-size: 8vw; } - .pilot-teaser h2 { font-size: 7.3vw; } - .panel-plans h2, .panel-start h2 { font-size: 6.4vw; } - .chore-scene { height: 400px; } - .loose-message { padding: 13px; gap: 8px; } - .message-first { left: -10px; } - .message-first > span:last-child { margin-left: 0; } - .message-second { top: 130px; } - .message-third { top: 230px; } - .chore-pup { width: 80%; left: 0; bottom: 30px; } - .agent-grid { gap: 10px; } - .agent-tile { border-radius: 20px; font-size: 13px; gap: 7px; } - .chat-fallback { gap: 10px; } - .chat-fallback p { text-align: center; } - .person-card { padding: 14px 7px; border-radius: 23px; } - .person-portrait { width: 60px; height: 60px; } - .person-card strong { font-size: 16px; } - .person-agent { font-size: 11px; } - .connection-label { font-size: 10px; padding: 8px 10px; } - .handle-card { padding: 23px; } - .handle-name { font-size: 65px; } - .handle-url { font-size: 11px; } - .handle-friends { font-size: 10px; gap: 8px; } - .identity-picker button { padding: 9px 12px; gap: 5px; } - .reunion-photo { aspect-ratio: .8; } - .photo-sticker { width: 115px; height: 115px; font-size: 18px; right: -15px; } - .photo-sticker > span { font-size: 23px; } - .primary-cta { padding: 16px 21px; gap: 20px; font-size: 16px; } - .final-actions { gap: 20px; } - .learn-more { font-size: 13px; } - .exchange-message { padding: 17px; } - .plan-result { padding: 18px; gap: 10px; } - .plan-result h3 { font-size: 30px; } -} -@media (max-width: 760px), (max-width: 1000px) and (orientation: portrait) { - .teaser-header { height: 78px; padding: 0 23px; } +.teaser-horizontal.teaser-native .teaser-track { animation: teaser-pan 1s linear both; animation-timeline: scroll(root block); animation-range: 0px var(--teaser-distance); } +@keyframes teaser-pan { from { transform: translate3d(0,0,0); } to { transform: translate3d(var(--teaser-shift),0,0); } } +@media (max-width: 1000px) and (orientation: portrait), (max-width: 760px) { + .teaser-header { height: 78px; padding-inline: 24px; } .teaser-brand { font-size: 27px; gap: 6px; } .teaser-brand img { width: 34px; height: 34px; } - .teaser-header-actions { gap: 14px; } - .teaser-start { padding: 11px 16px; gap: 15px; font-size: 13px; } - .panel-inner { grid-template-columns: 1fr; gap: 27px; padding: 103px 28px 90px; align-content: center; } - .panel-copy { width: 100%; } - .teaser-kicker { font-size: 11px; margin-bottom: 15px; } - .teaser-kicker > span { font-size: 17px; } - .pilot-teaser h1, .pilot-teaser h2 { font-size: clamp(52px, 12.7vw, 83px); line-height: .98; letter-spacing: -.06em; margin-bottom: 17px; } - .teaser-description { font-size: 15px; line-height: 1.5; } - .panel-chore .panel-inner { gap: 5px; } - .chore-scene { max-width: 370px; justify-self: center; height: 270px; } - .chore-orbit { inset: 18px 12px 25px; } - .chore-pup { width: 57%; left: 12%; bottom: 19px; } - .loose-message { padding: 10px 13px; gap: 9px; border-radius: 17px; font-size: 15px; } - .person-avatar { width: 29px; height: 29px; } - .message-first { top: 5px; left: 0; } - .message-first small { font-size: 9px; } - .message-first > span:last-child { font-size: 23px; margin-left: 3px; } - .message-second { top: 80px; right: -3px; } - .message-third { top: 159px; right: 0; } - .star-one { font-size: 35px; right: 8px; top: 13px; } - .star-two { top: 122px; left: 0; font-size: 23px; } - .scene-caption { font-size: 10px; bottom: 1px; } - .panel-agents h2 br:nth-child(2), .panel-handle h2 .soft-text br { display: none; } - .panel-agents h2 { font-size: clamp(49px, 12vw, 76px); } - .agent-scene { max-width: 420px; justify-self: center; width: 100%; } - .scene-label { font-size: 10px; margin-bottom: 15px; } - .agent-grid { max-width: 300px; gap: 10px 12px; } - .agent-tile { border-radius: 19px; gap: 5px; font-size: 11px; } - .agent-note { font-size: 10px; line-height: 1.4; margin: 14px 0; } - .chat-fallback { padding-top: 13px; flex-wrap: nowrap; gap: 12px; } - .chat-logos { padding: 8px 10px; gap: 6px; } - .chat-logos img { width: 19px; height: 19px; } - .chat-fallback p { font-size: 10px; } - .chat-fallback p span { font-size: 9px; } - .panel-plans .panel-inner { gap: 18px; } - .panel-plans h2 { font-size: clamp(45px, 11vw, 66px); } - .panel-plans h2 br:first-child { display: none; } - .panel-plans .teaser-description { font-size: 14px; } - .example-choices { margin-top: 17px; gap: 6px; } - .example-choices button { padding: 8px 13px; font-size: 12px; min-height: 40px; } - .plan-scene { max-width: 430px; justify-self: center; } - .exchange-message { padding: 13px 16px; border-radius: 19px; } - .your-agent { margin-right: 20px; } - .their-agent { margin-left: 20px; } - .message-author { font-size: 10px; gap: 6px; } + .teaser-start { font-size: 13px; gap: 14px; min-height: 44px; padding: 10px 17px; } + .panel-inner { padding: 100px 28px 90px; grid-template-columns: 1fr; align-content: center; gap: 32px; } + .pilot-teaser h1 { font-size: clamp(53px,13vw,96px); } + .pilot-teaser h2 { font-size: clamp(52px,12vw,86px); } + .teaser-description { font-size: 16px; margin-top: 20px !important; } + .panel-chore .panel-inner { align-content: start; padding-top: 130px; } + .panel-chore .scene-photo { width: 100%; height: 67%; top: auto; bottom: 0; object-position: 65% center; } + .panel-chore .photo-wash { background: linear-gradient(180deg,#faf7f2 0%,#faf7f2 32%,#faf7f2c0 43%,#faf7f200 62%,#faf7f240 89%,#faf7f2 100%); } + .photo-note { right: 9%; bottom: 20%; padding: 14px 19px; font-size: 22px; } + .agent-scene { max-width: 430px; } + .agent-orbit { height: 300px; } + .agent-mark { gap: 6px; font-size: 12px; } + .agent-mark img { width: 56px; height: 56px; } + .agent-note { font-size: 13px; margin-top: 16px !important; } + .chat-logos { gap: 12px; margin-top: 13px; } + .chat-logos img { width: 22px; height: 22px; } + .ambient-circle { width: 150vw; height: 150vw; right: -30vw; top: 70%; } + .panel-plans h2 { font-size: clamp(41px,10.5vw,70px); } + .panel-plans .panel-inner { gap: 27px; } + .panel-plans .teaser-description { font-size: 15px; margin-top: 17px !important; } + .plan-scene { max-width: 430px; } + .exchange-message { padding: 15px 18px; border-radius: 23px; } + .message-author { font-size: 11px; gap: 7px; } .message-author img { width: 23px; height: 23px; } - .via-pilot { font-size: 9px; } - .exchange-message p { font-size: 16px; margin-top: 8px; } - .exchange-connector { height: 20px; font-size: 18px; } - .plan-result { margin-top: 16px; padding: 15px 17px; grid-template-columns: 30px 1fr; gap: 7px 10px; border-radius: 20px; } - .result-icon { width: 30px; height: 30px; font-size: 21px; } - .result-eyebrow { font-size: 9px; } - .plan-result h3 { font-size: 29px; margin: 3px 0; } - .plan-result p { font-size: 12px; } - .result-approve { font-size: 12px; padding: 8px 13px; gap: 18px; min-height: 40px; white-space: nowrap; } - .example-disclosure { font-size: 9px; margin-top: 12px; line-height: 1.5; } - .panel-people h2 { font-size: clamp(50px, 12.4vw, 76px); } - .panel-people h2 .coral-text br { display: none; } - .panel-people .teaser-description br:nth-of-type(2) { display: none; } - .permission-note { margin-top: 16px; font-size: 11px; } - .permission-note span { font-size: 20px; } - .people-scene { width: 100%; max-width: 360px; justify-self: center; } - .person-card { padding: 14px 6px 12px; gap: 5px; border-radius: 21px; } - .person-portrait { width: 49px; height: 49px; } - .person-card strong { font-size: 14px; } - .person-agent { font-size: 10px; gap: 4px; } - .person-agent img { width: 16px; height: 16px; } - .sam-avatar { font-size: 28px; } - .sam-avatar span { font-size: 21px; } - .pilot-hub { border-width: 5px; } - .pilot-hub span { font-size: 9px; margin-bottom: 3px; } - .connection-label { padding: 7px 9px; font-size: 9px; } - .connection-label span { padding-left: 3px; } - .handle-scene { max-width: 420px; justify-self: center; padding: 0 6px; } - .handle-card { padding: 21px; border-radius: 25px; box-shadow: 0 11px 0 #92392355; } - .handle-card-top .person-portrait { width: 43px; height: 43px; } - .handle-tag { font-size: 10px; gap: 9px; } - .handle-tag > span { font-size: 26px; } - .handle-name { font-size: 61px; margin-top: 15px; } - .handle-url { font-size: 11px; margin-bottom: 16px; } - .handle-connected { font-size: 11px; padding: 12px 0; } - .handle-connected img { width: 23px; height: 23px; } - .handle-friends { font-size: 9px; gap: 9px; padding-top: 14px; } - .friend-stack i { width: 24px; height: 24px; } - .identity-picker { margin-top: 27px; } - .identity-picker p { font-size: 10px; margin-bottom: 9px; } - .identity-picker button { padding: 8px 12px; font-size: 12px; gap: 6px; min-height: 40px; } + .exchange-message p { font-size: 20px; margin-top: 7px; } + .their-agent { margin-top: 15px; } + .plan-result { margin-top: 26px; } + .result-label { font-size: 12px; } + .plan-result h3 { font-size: 39px; margin: 6px 0 12px; } + .result-approve { font-size: 13px; padding: 11px 21px; } + .example-disclosure { font-size: 10px; margin-top: 16px !important; } + .handle-name { font-size: clamp(82px,21vw,142px); gap: 16px; } + .handle-url { font-size: 12px; } + .handle-connected { margin: 24px 0 !important; font-size: 13px; } + .identity-picker button { padding: 10px 13px; gap: 6px; font-size: 12px; } .identity-picker img { width: 21px; height: 21px; } - .handle-note { font-size: 10px; margin-top: 13px; } - .panel-start .panel-inner { gap: 26px; } - .panel-start h2 { font-size: clamp(47px, 11.7vw, 72px); } - .panel-start h2 > br:first-of-type, .panel-start h2 .coral-text br { display: none; } - .final-actions { margin-top: 22px; gap: 25px; } - .primary-cta { font-size: 15px; padding: 14px 21px; gap: 25px; } - .primary-cta span { font-size: 21px; } + .handle-note { font-size: 10px; margin-top: 18px !important; } + .handle-flower { font-size: 180vw; bottom: -13%; right: -85%; } + .panel-start .panel-inner { align-content: end; padding-bottom: 133px; } + .panel-start h2 { font-size: clamp(48px,12vw,82px); } + .panel-start h2 br:last-child { display: none; } + .reunion-photo { width: 100%; height: 100%; object-position: 57% 20%; } + .panel-start .photo-wash { background: linear-gradient(180deg,#faf7f266 0%,#faf7f200 22%,#faf7f2a0 40%,#faf7f2f5 65%,#faf7f2 100%); } + .panel-start .teaser-description { font-size: 16px; margin-top: 18px !important; } + .final-actions { gap: 24px; margin-top: 22px; } + .primary-cta { font-size: 15px; padding: 13px 23px; } .learn-more { font-size: 13px; } - .start-details { font-size: 10px; margin-top: 16px; } - .reunion-scene { width: min(100%, 340px); justify-self: center; padding: 10px 10px 0; border-radius: 20px; } - .reunion-photo { aspect-ratio: 1.7; border-radius: 12px; } - .photo-sticker { width: 95px; height: 95px; right: -10px; top: 8px; font-size: 15px; } - .photo-sticker > span { font-size: 20px; } - .reunion-scene figcaption { padding: 11px 7px; font-size: 12px; } - .reunion-scene figcaption > span:last-child { font-size: 20px; } - .reunion-pup { width: 28%; right: 13%; } - .teaser-legal { inset: auto 28px 25px; font-size: 9px; } - .teaser-horizontal .teaser-legal { bottom: 77px; } - .teaser-controls { height: 65px; padding: 0 23px; gap: 15px; } - .scroll-cue { font-size: 10px; gap: 8px; min-width: 0; } - .scroll-symbol { width: 23px; height: 30px; font-size: 15px; } - .story-progress { max-width: 80px; } + .start-details { font-size: 11px; margin-top: 14px !important; } + .teaser-legal { bottom: 85px; inset-inline: 28px; font-size: 9px; } + .teaser-controls { height: 70px; padding-inline: 24px; gap: 16px; } + .scroll-cue { font-size: 11px; gap: 8px; } + .story-progress { display: none; } + .chapter-count { font-size: 11px; margin-right: 4px; gap: 8px; } .chapter-controls { gap: 7px; } - .chapter-controls button { width: 44px; height: 44px; font-size: 18px; } - .chapter-count { font-size: 10px; gap: 7px; margin-right: 4px; } + .chapter-controls button { font-size: 19px; } } @media (min-width: 761px) and (max-width: 1000px) and (orientation: portrait) { - .teaser-header { height: 104px; padding-inline: 40px; } - .teaser-brand { font-size: 31px; gap: 10px; } - .teaser-brand img { width: 42px; height: 42px; } - .teaser-header-actions { gap: 25px; } - .teaser-start { padding: 13px 21px; font-size: 15px; } - .panel-inner { padding: 125px 70px 100px; gap: 36px; } - .panel-copy { max-width: 580px; justify-self: center; } - .pilot-teaser h1 { font-size: 90px; } - .pilot-teaser h2 { font-size: 76px; } - .teaser-kicker { font-size: 13px; margin-bottom: 20px; } - .teaser-description { font-size: 20px; } - .chore-scene { height: 340px; max-width: 430px; } - .chore-pup { width: 63%; bottom: 25px; } - .message-second { top: 110px; } - .message-third { top: 210px; } - .loose-message { font-size: 18px; } - .agent-grid { max-width: 390px; gap: 13px; } - .agent-tile { font-size: 14px; } - .scene-label, .agent-note, .chat-fallback p { font-size: 12px; } - .panel-plans h2 { font-size: 67px; } - .panel-plans .teaser-description { font-size: 18px; } - .panel-plans .panel-inner { gap: 28px; } - .people-scene { max-width: 430px; } - .handle-card { padding: 28px; } - .handle-name { font-size: 76px; } - .handle-url { font-size: 14px; } - .reunion-scene { width: 430px; } - .panel-start h2 { font-size: 72px; } - .start-details { font-size: 12px; } - .primary-cta { font-size: 18px; } - .learn-more { font-size: 15px; } - .teaser-controls { padding-inline: 40px; height: 80px; } - .story-progress { max-width: 240px; } - .teaser-horizontal .teaser-legal { bottom: 90px; } + .panel-inner { padding-inline: 70px; gap: 48px; } + .panel-copy { width: 100%; max-width: 620px; justify-self: center; } + .agent-orbit { height: 370px; } + .agent-mark img { width: 75px; height: 75px; } + .panel-start .panel-copy { max-width: none; } } -@media (max-width: 480px) { - .story-progress { display: none; } - .chapter-controls { margin-left: auto; } +@media (max-width: 760px) and (max-height: 740px) { + .panel-inner { padding: 94px 24px 80px; gap: 21px; } + .pilot-teaser h1 { font-size: 12.5vw; } + .pilot-teaser h2 { font-size: 45px; } + .panel-chore .panel-inner { padding-top: 116px; } + .teaser-description { font-size: 14px; margin-top: 16px !important; } + .agent-orbit { height: 230px; } + .agent-mark img { width: 46px; height: 46px; } + .agent-mark { font-size: 11px; } + .agent-note { margin-top: 12px !important; font-size: 12px; } + .panel-plans h2 { font-size: 38px; } + .panel-plans .panel-inner { gap: 19px; } + .panel-plans .teaser-description { font-size: 14px; margin-top: 12px !important; } + .exchange-message { padding: 11px 15px; } + .exchange-message p { font-size: 18px; margin-top: 5px; } + .plan-result { margin-top: 20px; } + .plan-result h3 { font-size: 34px; } + .example-disclosure { margin-top: 12px !important; font-size: 9px; } + .handle-connected { margin: 19px 0 !important; } + .identity-picker p { margin-bottom: 10px; font-size: 12px; } + .panel-start h2 { font-size: 43px; } + .panel-start .panel-inner { padding-bottom: 128px; } + .panel-start .teaser-description { font-size: 14px; } + .final-actions { margin-top: 17px; } } -@media (max-width: 380px) { - .panel-inner { padding-inline: 22px; } - .teaser-header { padding-inline: 19px; } - .teaser-header-actions { gap: 11px; } - .teaser-start { padding: 10px 13px; } - .chat-fallback { gap: 8px; } - .chat-logos { gap: 5px; padding: 7px; } - .chat-logos img { width: 17px; height: 17px; } - .handle-card { padding: 18px; } - .handle-url { font-size: 10px; } - .handle-friends { gap: 6px; } - .teaser-controls { padding-inline: 20px; } - .teaser-legal { inset-inline: 22px; } +@media (min-width: 1001px) and (max-height: 740px) { + .panel-inner { padding-top: 108px; padding-bottom: 95px; } + .pilot-teaser h1 { font-size: 8vw; } + .pilot-teaser h2 { font-size: 6.5vw; } + .panel-plans h2 { font-size: 5.8vw; } + .panel-start h2 { font-size: 6.3vw; } + .agent-orbit { height: 320px; } + .teaser-description { margin-top: 22px !important; } + .plan-result { margin-top: 24px; } + .exchange-message { padding: 15px 22px; } + .their-agent { margin-top: 17px; } + .plan-result h3 { font-size: 48px; } + .example-disclosure { margin-top: 16px !important; } } @media (prefers-reduced-motion: reduce) { .pilot-teaser *, .pilot-teaser *::before, .pilot-teaser *::after { scroll-behavior: auto !important; animation: none !important; transition: none !important; } } -@media (max-width: 760px) and (min-height: 741px) and (max-height: 900px) { - .panel-plans h2 { font-size: clamp(37px, 10.5vw, 44px); } - .panel-plans .panel-inner { padding-block: 96px 80px; } - .plan-result { grid-template-columns: 1fr auto; gap: 8px; } - .result-icon { display: none; } - .plan-result h3 { font-size: 25px; } - .result-approve { grid-column: 2; grid-row: 1; padding-inline: 11px; gap: 5px; font-size: 11px; } -} -@media (max-width: 760px) and (max-height: 740px) { - .panel-inner { padding: 90px 24px 74px; gap: 18px; } - .teaser-kicker { margin-bottom: 12px; font-size: 10px; } - .pilot-teaser h1 { font-size: clamp(44px, 12.5vw, 52px); } - .pilot-teaser h2 { font-size: 44px; margin-bottom: 14px; } - .teaser-description { font-size: 14px; } - .chore-scene { height: 230px; } - .chore-pup { bottom: 21px; width: 53%; } - .message-second { top: 72px; } - .message-third { top: 142px; } - .agent-grid { max-width: 250px; gap: 8px; } - .agent-tile { border-radius: 16px; } - .agent-note { margin-block: 12px; } - .chat-fallback { padding-top: 10px; } - .panel-plans h2 { font-size: clamp(30px, 8.9vw, 36px); } - .plans-payoff { display: none; } - .panel-plans .panel-inner { gap: 14px; } - .example-choices { margin-top: 12px; } - .example-choices button { padding: 7px 12px; } - .exchange-message { padding: 10px 14px; } - .exchange-message p { margin-top: 6px; font-size: 15px; } - .plan-result { grid-template-columns: 1fr auto; padding: 12px; gap: 8px; margin-top: 13px; } - .result-icon { display: none; } - .plan-result h3 { font-size: 24px; } - .plan-result p { font-size: 11px; } - .result-approve { grid-column: 2; grid-row: 1; padding: 9px 11px; gap: 5px; font-size: 11px; } - .example-disclosure { margin-top: 10px; } - .people-scene { max-width: 290px; } - .permission-note { margin-top: 12px; } - .handle-card { padding: 17px; } - .handle-card-top { display: none; } - .handle-name { font-size: 52px; margin-top: 0; } - .handle-url { margin-bottom: 12px; } - .handle-connected { padding-block: 10px; } - .handle-friends { padding-top: 12px; } - .identity-picker { margin-top: 18px; } - .identity-picker p { display: none; } - .handle-note { margin-top: 10px; } - .panel-start h2 { font-size: 40px; } - .panel-start .panel-inner { gap: 18px; } - .final-actions { margin-top: 17px; } - .start-details { margin-top: 12px; } - .reunion-scene { width: min(100%, 300px); } - .reunion-photo { aspect-ratio: 2.1; } - .reunion-scene figcaption { padding-block: 9px; } - .photo-sticker { width: 80px; height: 80px; font-size: 13px; } - .photo-sticker > span { font-size: 17px; } -}