diff --git a/docs/SITE_DESIGN.md b/docs/SITE_DESIGN.md index 129e3cd..cf7b103 100644 --- a/docs/SITE_DESIGN.md +++ b/docs/SITE_DESIGN.md @@ -36,6 +36,15 @@ crossed out). has no dark artboard, make the dark copy from the canvas's own palettes (WinDashboard's `light`/`dark` tables for Windows screens, AndHome's for Android), mapping each light color to its dark role. +## Film + +A 12-second muted loop right after the hero shows four features in motion (clipboard, notifications, files, +mirroring). It's rendered from the owner's Remotion project (`OrbitIntro`, outside this repo): compositions +`OrbitLoop` (dark) and `OrbitLoopLight` (light), at 1280x720, as MP4 (H.264, plays everywhere) and a poster JPEG +each, saved in `site/media/` (`npm run render:web` in that project, then copy from `out/web/`). It plays only while on screen, swaps with the theme, loads nothing until +it's near, has a Pause button (WCAG 2.2.2), and starts paused on its poster under reduced motion. Re-render it +when a feature it shows changes. + ## System - **Palette (light / dark):** ground `#F5F5F8` / `#0C0C12`, ink `#121219` / `#F1F1F6`, muted `#55566A` / `#A6A7BA`, @@ -53,6 +62,7 @@ crossed out). ``` hero badge, h1, one line, download buttons / Windows dashboard with the Android home screen in front +film the 12 s feature loop, framed 16:9, with a Pause button features bento of screens: clipboard, files (share sheet), mirroring (full width), notifications, earbuds, tray, phone shortcuts connect one line / the route race diff --git a/site/index.html b/site/index.html index 3e8aabb..9b31fd9 100644 --- a/site/index.html +++ b/site/index.html @@ -88,6 +88,18 @@

Your phone and PC, in one orbit.

+ +
+
+

Orbit at work

+
+ + + +
+
+
+
diff --git a/site/media/orbit-loop-dark.jpg b/site/media/orbit-loop-dark.jpg new file mode 100644 index 0000000..38867bd Binary files /dev/null and b/site/media/orbit-loop-dark.jpg differ diff --git a/site/media/orbit-loop-dark.mp4 b/site/media/orbit-loop-dark.mp4 new file mode 100644 index 0000000..2ba0efe Binary files /dev/null and b/site/media/orbit-loop-dark.mp4 differ diff --git a/site/media/orbit-loop-light.jpg b/site/media/orbit-loop-light.jpg new file mode 100644 index 0000000..2a55a89 Binary files /dev/null and b/site/media/orbit-loop-light.jpg differ diff --git a/site/media/orbit-loop-light.mp4 b/site/media/orbit-loop-light.mp4 new file mode 100644 index 0000000..ffe0d41 Binary files /dev/null and b/site/media/orbit-loop-light.mp4 differ diff --git a/site/site.css b/site/site.css index 21cfcf2..171f01c 100644 --- a/site/site.css +++ b/site/site.css @@ -197,6 +197,17 @@ footer{border-top:1px solid var(--line);padding-block:56px 40px;content-visibili .phn{grid-column:10/-1;grid-row:1;margin-bottom:-28px} @media (max-width:760px){.win{grid-column:1/-1}.phn{grid-column:8/-1;grid-row:2;margin:-34% 4px 0 0;padding:5px;border-radius:30px}.phn img{border-radius:25px}} +/* Film: the features in motion (rendered from the OrbitIntro Remotion project, one per theme) */ +.v-film{padding-block:clamp(16px,3vw,40px) 0} +.film{position:relative;margin:0;border-radius:24px;overflow:hidden;border:1px solid var(--line-strong);box-shadow:var(--shadow);background:var(--surface);aspect-ratio:16/9} +.film-v{display:block;width:100%;height:100%;object-fit:cover} +.film-btn{position:absolute;right:16px;bottom:16px;display:inline-flex;align-items:center;gap:8px;min-height:40px;padding:0 14px;border-radius:999px;border:1px solid var(--line-strong);background:color-mix(in srgb,var(--surface) 88%,transparent);color:var(--ink);font:700 13px/1 var(--f);cursor:pointer;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);transition:border-color .3s,scale .2s} +@media (hover:hover){.film-btn:hover{border-color:var(--accent)}} +.film-btn:active{scale:.96} +.film-btn .i-play{display:none} +.film-btn[aria-pressed="true"] .i-play{display:block}.film-btn[aria-pressed="true"] .i-pause{display:none} +@media (max-width:640px){.film{border-radius:16px}.film-btn{right:8px;bottom:8px;min-height:32px;padding:0 9px}.film-btn-l{display:none}} + /* Features: one screen per tile */ .bento{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--gut);margin-top:clamp(32px,4vw,56px)} .tile{position:relative;overflow:hidden;border-radius:24px;background:var(--surface);border:1px solid var(--line);display:flex;flex-direction:column;min-height:420px;transition:box-shadow .5s var(--ease),opacity .9s var(--ease),translate .9s var(--ease)} diff --git a/site/site.js b/site/site.js index 3d51136..2076af2 100644 --- a/site/site.js +++ b/site/site.js @@ -97,6 +97,33 @@ .catch(function () { /* keep the Releases page links */ }); } + // Film: plays only while on screen and in the current theme; never loads before it's near. A pause button + // stops it for good (WCAG 2.2.2); under reduced motion it starts paused on its poster. + var film = document.querySelector('.film'); + if (film) { + var vids = [].slice.call(film.querySelectorAll('video')), btn = film.querySelector('.film-btn'); + var label = btn.querySelector('.film-btn-l'), stopped = reduce, near = false, seen = false; + var current = function () { for (var i = 0; i < vids.length; i++) if (vids[i].offsetParent) return vids[i]; return vids[0]; }; + var sync = function () { + var v = current(); + vids.forEach(function (o) { if (o !== v && !o.paused) o.pause(); }); + btn.setAttribute('aria-pressed', String(stopped)); + label.textContent = stopped ? 'Play' : 'Pause'; + btn.setAttribute('aria-label', stopped ? 'Play the video' : 'Pause the video'); + if (!near) return; + if (v.preload !== 'auto') v.preload = 'auto'; + if (!stopped && seen) { var p = v.play(); if (p && p.catch) p.catch(function () {}); } else if (!v.paused) v.pause(); + }; + btn.addEventListener('click', function () { stopped = !stopped; near = true; seen = true; sync(); }); + if (hasIO) { + new IntersectionObserver(function (e) { near = near || e[0].isIntersecting; sync(); }, { rootMargin: '400px 0px' }).observe(film); + new IntersectionObserver(function (e) { seen = e[0].isIntersecting; sync(); }, { threshold: 0.35 }).observe(film); + } else { near = seen = true; } + if (themeBtn) themeBtn.addEventListener('click', function () { setTimeout(sync, 0); }); + matchMedia('(prefers-color-scheme: dark)').addEventListener('change', sync); + sync(); + } + // Feature tiles slide up as they arrive (tiles already on screen stay put). if (hasIO && !reduce) { var tio = new IntersectionObserver(function (entries) {