diff --git a/WEBSITE/README.md b/WEBSITE/README.md index 4075822ff7..9c341ce763 100644 --- a/WEBSITE/README.md +++ b/WEBSITE/README.md @@ -35,7 +35,7 @@ and open . ## The phone The phone is drawn in HTML at 390 x 844 and scaled to fit, four times over: a looping teaser in -the hero, one driven by the scroll position through the seven "How it works" chapters +the hero, one driven by the scroll position through the eight "How it works" chapters (`storyState()` in `script.js`), one in the playground that answers to touch and mouse, and the list phone of the race (the playground's controller, locked to the app list). All of them render the same state object, described in `blank()`. The 40 app names and icons on it are generic @@ -49,7 +49,9 @@ Other moving parts, all in `script.js`: wave, drag to jump between sections, tap to scroll there. On phones it shows while scrolling. - **Detail-card switches** (`setupLook`): left-handed alphabet, comfy rows and icon shape, applied to every phone on the page. -- **Under the glass** (`setupAnatomy`): the phone pulled apart into its layers as the section scrolls. +- **Every layer, pulled apart** (`setupAnatomy`): the story's eighth chapter. The story phone is + swapped for a double built from separate layers (it looks the same closed), which then comes + apart in 3D with a labelled tag per layer and goes back together. - **Race** (`setupRace`): find an app in a shuffled grid of 40, then in the list with the alphabet. - **Magnetic buttons and the finger cursor** (`setupPointerFx`), desktop only. - **Easter eggs**: scrub to F in the playground, or type "flexera" anywhere. diff --git a/WEBSITE/index.html b/WEBSITE/index.html index 789b24e2c4..d2b0b8adf5 100644 --- a/WEBSITE/index.html +++ b/WEBSITE/index.html @@ -169,16 +169,27 @@
-

01 / 07

+

01 / 08

Home, minus the noise.

Pages, folders and widgets, in the Android layout you already know. No feed, no ads, nothing you didn't put there yourself.

Gesture None. Just look.

@@ -186,7 +197,7 @@
-

02 / 07

+

02 / 08

Swipe up. A to Z.

Every app in one clean column, straight over your wallpaper. New messages show up under the app's name, so you see them before you open anything.

Gesture Swipe up

@@ -194,7 +205,7 @@
-

03 / 07

+

03 / 08

Ride the wave.

Slide your thumb along the letters on the edge. They swell around it like a wave, and the list drops that letter into the middle of the screen, right where your thumb already is. Swipe up and keep holding to scrub straight from home.

Gesture Slide on the edge

@@ -202,7 +213,7 @@
-

04 / 07

+

04 / 08

Folders in focus.

Open a folder and the rest of the screen melts into a soft blur, wallpaper included. Just the apps you came for.

Gesture Tap

@@ -210,7 +221,7 @@
-

05 / 07

+

05 / 08

Swipe into nothing.

There's no page left of your first one. Swipe there anyway and your camera opens. Or any app, or any shortcut you pick. Works past your last page too.

Gesture Swipe past the edge

@@ -218,7 +229,7 @@
-

06 / 07

+

06 / 08

Widgets that fit in.

A clock that lines up with your icons: the date, a one-line forecast, left, center or right, thin to bold. Next to it, a picture frame in your icon shape that turns to the next photo every ten seconds.

Gesture Hold, then edit

@@ -226,41 +237,28 @@
-

07 / 07

+

07 / 08

Out of sight.

Hold any app in the list and tap Hide app. Gone from the list and from search. Changed your mind? Undo, or bring it back from Settings whenever you like.

Gesture Hold, then hide

+
+
+

08 / 08

+

Every layer. Pulled apart.

+

Under the glass sit five layers: your wallpaper, the widgets, icons and folders, the app list with its wave alphabet, and the glass on top. No feed and no ads hiding in between.

+

Gesture Keep scrolling

+
+
- -
-
-
-

[ 02 ] Under the glass

-

- Every layer. - Pulled apart. -

-
- -
    -
  1. GlassNo feed. No ads.
  2. -
  3. App listA to Z, wave alphabet on the edge.
  4. -
  5. Icons & foldersBlur behind every open folder.
  6. -
  7. WidgetsClock, weather, pictures.
  8. -
  9. WallpaperYours. Untouched.
  10. -
-
-
-
-

[ 03 ] The details

+

[ 02 ] The details

Small things. Done properly. @@ -327,7 +325,7 @@
-

[ 04 ] Privacy

+

[ 03 ] Privacy

It goes online for exactly two things.

@@ -348,7 +346,7 @@
-

[ 05 ] Playground

+

[ 04 ] Playground

Go on. Touch it. @@ -385,7 +383,7 @@
-

[ 06 ] Race

+

[ 05 ] Race

Find it. Faster. @@ -415,7 +413,7 @@
-

[ 07 ] Get it

+

[ 06 ] Get it

Get Flexera. diff --git a/WEBSITE/script.js b/WEBSITE/script.js index 2f74fe3f38..2ece5e06bb 100644 --- a/WEBSITE/script.js +++ b/WEBSITE/script.js @@ -123,6 +123,8 @@ const MENU_X = 120; const CLOCK_W = 4 * CW - 36; const DEFAULT_WEIGHT = 300; + /** The story runs from 0 to 9: chapters 1 to 7 take one unit each, chapter 8 two. */ + const STORY_END = 9; /** Icon shapes, as border radii for icons and for the picture widget. */ const SHAPES = { squircle: { icon: '30%', widget: '30px' }, @@ -525,7 +527,17 @@ */ function storyState(ph, P) { const s = blank(); - P = clamp(P, 0, 7); + P = clamp(P, 0, STORY_END); + if (P >= 7) { + // Chapter 8, two units long: the list closes and the phone is home again. From there on the + // layered phone (setupAnatomy) takes its place and comes apart; this one is hidden. + const t = (P - 7) / 2; + s.drawer = 1 - E(t, 0, 0.1); + s.list = ph.scrollFor(L('P')); + s.hidden = { Podcasts: 1 }; + s.snack = 1 - E(t, 0, 0.08); + return s; + } const ch = Math.min(6, Math.floor(P)); const t = P - ch; const F = s.finger; @@ -636,7 +648,11 @@ return s; } - function setupStory(ph) { + /** Chapter 8, from its start (0) to its end (1): when the phones swap, and how far apart the layers are. */ + const SWAP_AT = 0.12; + const layersApart = (t) => smooth(seg(t, 0.14, 0.42)) * (1 - smooth(seg(t, 0.74, 0.94))); + + function setupStory(ph, layered) { const box = document.querySelector('.story__steps'); const steps = [...document.querySelectorAll('[data-step]')]; const num = document.querySelector('[data-story-num]'); @@ -644,14 +660,22 @@ let lastChapter = -1; let lastP = -1; return function update(force) { + // In chapters, not window heights: on phones a chapter is the small viewport height, while + // the window grows when the browser's address bar slides away. const vh = window.innerHeight; - const P = clamp(-box.getBoundingClientRect().top / vh + 0.5, 0, 7); - const ch = Math.min(6, Math.floor(P)); - // Without motion, each chapter shows its finished picture. - const shown = reduced ? ch + 0.985 : P; + const unit = steps[0].offsetHeight || vh; + const P = clamp((-box.getBoundingClientRect().top + vh / 2) / unit, 0, STORY_END); + const ch = P >= 7 ? 7 : Math.floor(P); + // Without motion, each chapter shows its finished picture (chapter 8: pulled apart). + const shown = reduced ? (ch === 7 ? 7.98 : ch + 0.985) : P; if (force || Math.abs(shown - lastP) > 0.0002) { lastP = shown; ph.render(storyState(ph, shown)); + if (layered) { + const t = shown >= 7 ? (shown - 7) / 2 : 0; + const swapped = shown >= 7 && t >= SWAP_AT; + layered.set(swapped ? layersApart(t) : 0, swapped, force); + } } if (ch !== lastChapter) { lastChapter = ch; @@ -1294,6 +1318,10 @@ el.style.setProperty('--shape', shape.icon); el.style.setProperty('--shape-w', shape.widget); }); + document.querySelectorAll('.xphone').forEach((el) => { + el.classList.toggle('is-lefty', look.lefty); + el.classList.toggle('is-comfy', look.comfy); + }); rerender(); sync(); toast(message); @@ -1556,35 +1584,48 @@

`; } - function setupAnatomy() { - const sec = document.querySelector('.anatomy'); + /** + * The story phone's double, built from separate layers so that it can come apart in 3D (the + * drawn phone clips its contents and cannot). It sits exactly over the story phone; closed, it + * shows the same home screen, so swapping the two is not seen. + */ + function setupAnatomy(storyPhone) { const host = document.querySelector('[data-xphone]'); - if (!sec || !host) return null; + if (!host || !storyPhone) return null; host.innerHTML = xphoneMarkup(); const xp = host.querySelector('.xphone'); const layers = [...xp.querySelectorAll('.xl')]; // Labels from the top: glass, list, icons, widgets, wallpaper. const pins = [5, 4, 3, 2, 1].map((i) => layers[i].querySelector('.xl__pin')); const labels = [...document.querySelectorAll('[data-xlabels] li')]; - const sticky = sec.querySelector('.anatomy__sticky'); + const stage = host.closest('.story__stage'); + const rail = stage.querySelector('[data-story-rail]'); + const pics = [...xp.querySelectorAll('.pic')]; + const svg = stage.querySelector('[data-xlines]'); + const NS = 'http://www.w3.org/2000/svg'; + const lines = labels.map(() => { + const path = document.createElementNS(NS, 'path'); + const dot = document.createElementNS(NS, 'circle'); + dot.setAttribute('r', '4.5'); + svg.append(path, dot); + return { path, dot }; + }); let scale = 1; - const fit = () => { scale = host.clientWidth / 414; }; - fit(); - if ('ResizeObserver' in window) new ResizeObserver(fit).observe(host); let lastE = -1; - return function update(force) { - const rc = sec.getBoundingClientRect(); - const vh = window.innerHeight; - if (!force && (rc.bottom < -50 || rc.top > vh + 50)) return; - const p = clamp(-rc.top / Math.max(1, rc.height - vh)); - let e = smooth(seg(p, 0.08, 0.4)) * (1 - smooth(seg(p, 0.8, 0.98))); - if (reduced) e = p > 0.04 && p < 0.96 ? 1 : 0; - if (!force && Math.abs(e - lastE) < 0.0005) return; - lastE = e; + let swapped = null; + /** Same picture as the story phone shows, so the swap is not seen. */ + function syncPictures() { + pics.forEach((p, i) => p.classList.toggle('on', i === storyPhone.picIndex)); + } + /** Puts the layers where e (0 closed, 1 fully apart) wants them. */ + function arrange(e) { const GAP = 150; // between layers, in the phone's pixels const tilt = 56 * e; - const sc = scale * (1 - 0.28 * e); - const ox = 207 * (scale - sc); + const sc = scale * (1 - 0.36 * e); + const wide = window.innerWidth > 900; + // Opening, the stack moves left to leave room for its labels. + const shift = wide ? -e * Math.min(140, stage.clientWidth * 0.17) : 0; + const ox = 207 * (scale - sc) + shift; // The layers rise as they separate; lower the whole stack by half of that, to keep it centred. const oy = 434 * (scale - sc) + e * 2.5 * GAP * Math.sin((tilt * Math.PI) / 180) * sc; xp.style.setProperty('--e', e.toFixed(3)); @@ -1594,19 +1635,66 @@ }); // Flat, it is just a home screen: the app list layer only shows once the stack opens. layers[4].style.opacity = smooth(seg(e, 0.15, 0.6)).toFixed(3); - const wide = window.innerWidth > 900; - const base = sticky.getBoundingClientRect(); - let prevY = -Infinity; - labels.forEach((li, k) => { - li.style.opacity = seg(e, 0.55, 0.95).toFixed(3); - if (!wide) return; - const pr = pins[k].getBoundingClientRect(); - const x = Math.min(pr.left - base.left + 16, base.width - 250); - const y = Math.max(pr.top - base.top - 12, prevY + 60); // never on top of the one above - prevY = y; - li.style.transform = `translate(${x.toFixed(1)}px, ${y.toFixed(1)}px)`; + } + /** The labels: one column beside the stack, evenly spaced, each joined to its layer's edge. */ + function label(e) { + const shown = seg(e, 0.55, 0.95); + svg.style.opacity = shown.toFixed(3); + labels.forEach((li) => { li.style.opacity = shown.toFixed(3); }); + if (window.innerWidth <= 900 || shown <= 0) return; + const base = stage.getBoundingClientRect(); + let right = -Infinity; + for (const l of layers) right = Math.max(right, l.getBoundingClientRect().right); + const LABEL_W = 214; + const colX = clamp(right - base.left + 34, 0, base.width - LABEL_W - 8); + const pts = pins.map((pin) => { + const r = pin.getBoundingClientRect(); + return { x: r.left - base.left, y: r.top - base.top }; }); + const ys = []; + let prev = -Infinity; + for (const pt of pts) { + const y = Math.max(pt.y, prev + 76); // never closer than one tag's height + ys.push(y); + prev = y; + } + const spill = ys[ys.length - 1] + 44 - base.height; + if (spill > 0) for (let k = 0; k < ys.length; k++) ys[k] -= spill; + labels.forEach((li, k) => { + li.style.transform = `translate(${colX.toFixed(1)}px, ${ys[k].toFixed(1)}px)`; + const { x, y } = pts[k]; + const bend = Math.max(x + 16, colX - 26); + lines[k].path.setAttribute('d', `M${x.toFixed(1)} ${y.toFixed(1)} L${bend.toFixed(1)} ${ys[k].toFixed(1)} L${colX.toFixed(1)} ${ys[k].toFixed(1)}`); + lines[k].dot.setAttribute('cx', x.toFixed(1)); + lines[k].dot.setAttribute('cy', y.toFixed(1)); + }); + } + const fit = () => { + scale = host.clientWidth / 414; + arrange(Math.max(0, lastE)); // scaled from the start: at full size it would widen the page }; + fit(); + if ('ResizeObserver' in window) new ResizeObserver(fit).observe(host); + function set(e, on, force) { + if (on !== swapped) { + swapped = on; + host.style.visibility = on ? 'visible' : 'hidden'; + storyPhone.host.style.visibility = on ? 'hidden' : ''; + if (on) syncPictures(); + lastE = -1; + } + if (!on) { + label(0); + rail.style.opacity = ''; + return; + } + if (!force && Math.abs(e - lastE) < 0.0005) return; + lastE = e; + arrange(e); + rail.style.opacity = (1 - e).toFixed(3); + label(e); + } + return { set, syncPictures, element: xp }; } /* ------------------------------------------------------------------ the race */ @@ -1816,11 +1904,11 @@ document.querySelectorAll('.xl [data-date]').forEach((el) => { el.textContent = date; }); } - const story = phones.story ? setupStory(phones.story) : null; + const layered = setupAnatomy(phones.story); + const story = phones.story ? setupStory(phones.story, layered) : null; const play = phones.play ? setupPlay(phones.play, { caption: document.querySelector('[data-caption]'), demos: document.querySelector('.play'), egg: true }) : null; - const anatomy = setupAnatomy(); const race = phones.race ? setupRace(phones.race) : null; tick(); setInterval(tick, 10000); @@ -1829,7 +1917,6 @@ if (story) story(true); if (play) play.render(); if (race) race.render(); - if (anatomy) anatomy(true); }; setupLook(phones, rerender); const pageWave = setupPageWave(); @@ -1838,7 +1925,12 @@ setupEggs(); // Picture widgets turn to the next picture now and then. - if (!reduced) setInterval(() => Object.values(phones).forEach((p) => p.nextPicture()), 3800); + if (!reduced) { + setInterval(() => { + Object.values(phones).forEach((p) => p.nextPicture()); + if (layered) layered.syncPictures(); + }, 3800); + } // Fonts change nothing that is measured, but measure again once they are in, to be sure. if (document.fonts && document.fonts.ready) { @@ -1882,7 +1974,6 @@ } } if (story) story(); - if (anatomy) anatomy(); pageWave(); } diff --git a/WEBSITE/styles.css b/WEBSITE/styles.css index f3405e871f..38859d85ab 100644 --- a/WEBSITE/styles.css +++ b/WEBSITE/styles.css @@ -289,7 +289,12 @@ section { position: relative; } color: rgba(245, 244, 255, .045); /* filled, not outlined, for the same reason as .hero__ghost */ pointer-events: none; user-select: none; } -.story .phone-host { height: min(84vh, 880px); height: min(84svh, 880px); position: relative; z-index: 1; } +.story__phones { position: relative; z-index: 1; height: min(84vh, 880px); height: min(84svh, 880px); aspect-ratio: 414 / 868; } +.story__phones .phone-host, .story__phones .xhost { position: absolute; inset: 0; height: auto; } +.story__phones .xhost { visibility: hidden; } +/* Chapter 8 is two screens long; its text stays put while the phone comes apart. */ +.step.step--long { min-height: 200vh; min-height: 200svh; align-items: flex-start; } +.step.step--long .step__card { position: sticky; top: max(96px, calc(50vh - 170px)); } .story__rail { position: absolute; right: 0; top: 50%; translate: 0 -50%; display: flex; flex-direction: column; gap: 10px; margin: 0; padding: 0; list-style: none; } .story__rail li { width: 12px; height: 34px; border: var(--b) solid var(--fg); transition: background .3s, height .3s; } .story__rail li.done { background: var(--fg); } @@ -655,12 +660,12 @@ section { position: relative; } .row__p { margin-top: 3px; font: 400 13px/1.2 var(--ui); color: #cfcbef; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .row.flash { background: rgba(255, 255, 255, .12); } /* Settings from the detail cards. */ -.screen.is-comfy .row { height: 66px; } -.screen.is-comfy .row--note { height: 78px; } -.screen.is-comfy .row .ic { width: 48px; height: 48px; } -.screen.is-comfy .row__n { font-size: 19.5px; } -.screen.is-lefty .list { padding: 0 20px 0 58px; } -.screen.is-lefty .alpha { right: auto; left: 8px; } +.is-comfy .row { height: 66px; } +.is-comfy .row--note { height: 78px; } +.is-comfy .row .ic { width: 48px; height: 48px; } +.is-comfy .row__n { font-size: 19.5px; } +.is-lefty .list { padding: 0 20px 0 58px; } +.is-lefty .alpha { right: auto; left: 8px; } .row.held { background: rgba(255, 255, 255, .1); } .alpha { position: absolute; right: 8px; bottom: 112px; width: 30px; display: flex; flex-direction: column; align-items: center; z-index: 2; } @@ -767,30 +772,34 @@ section { position: relative; } .over-phone .phone-host, .over-phone .phone-host * { cursor: none !important; } .btn, .chip { transition: transform .14s ease, box-shadow .14s ease, background .2s, color .2s, translate .35s cubic-bezier(.2, .8, .2, 1); } -/* ---------- under the glass: the phone pulled apart ---------- */ -.anatomy { position: relative; height: 320vh; height: 320svh; } -.anatomy__sticky { - position: sticky; top: 0; height: 100vh; height: 100svh; overflow: hidden; - display: grid; grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr); align-items: center; - max-width: var(--max); margin: 0 auto; padding: 70px var(--pad) 30px; -} -.anatomy__stage { position: relative; display: grid; place-items: center; height: 100%; } -.xhost { position: relative; height: min(68vh, 720px); height: min(68svh, 720px); aspect-ratio: 414 / 868; perspective: 2600px; } +/* ---------- chapter 8: the phone pulled apart ---------- */ +.xhost { perspective: 2600px; } .xphone { position: absolute; left: 0; top: 0; width: 414px; height: 868px; transform-origin: 0 0; transform-style: preserve-3d; --e: 0; } .xl { position: absolute; left: 12px; top: 12px; width: 390px; height: 844px; border-radius: 48px; overflow: hidden; font-family: var(--ui); color: #fff; box-shadow: 0 0 0 2px rgba(118, 250, 252, calc(var(--e) * .55)); } .xl * { box-sizing: border-box; } .xl .ic svg, .xl .gl { fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; } -.xl--body { left: 0; top: 0; width: 414px; height: 868px; border-radius: 60px; background: linear-gradient(150deg, #34324d, #121122 45%, #08070f); box-shadow: inset 0 0 0 2px #4a4767, 0 50px 90px -30px rgba(101, 61, 240, .7); } +.xl--body::before, .xl--body::after { content: ""; position: absolute; right: -4px; width: 4px; border-radius: 0 3px 3px 0; background: #2b2940; } +.xl--body::before { top: 190px; height: 70px; } +.xl--body::after { top: 290px; height: 110px; } +.xl--body { overflow: visible; left: 0; top: 0; width: 414px; height: 868px; border-radius: 60px; background: linear-gradient(150deg, #34324d, #121122 45%, #08070f); box-shadow: inset 0 0 0 2px #4a4767, inset 0 0 0 5px #0a0914, 0 50px 90px -30px rgba(101, 61, 240, .7), 0 0 0 2px #000; } .xl--list { background: rgba(5, 4, 20, calc(.35 + var(--e) * .3)); } .xl--list .list { top: 46px; } .xl--list .alpha { bottom: 112px; } -.xl--glass { background: linear-gradient(125deg, rgba(255, 255, 255, .2), rgba(255, 255, 255, 0) 38%, rgba(255, 255, 255, .07) 68%, rgba(255, 255, 255, 0)); } -.xl__pin { position: absolute; right: 0; top: 46%; width: 1px; height: 1px; } +.xl--glass::before { content: ""; position: absolute; inset: 0; opacity: var(--e); background: linear-gradient(125deg, rgba(255, 255, 255, .2), rgba(255, 255, 255, 0) 38%, rgba(255, 255, 255, .07) 68%, rgba(255, 255, 255, 0)); } +.xl__pin { position: absolute; right: 0; top: 30%; width: 1px; height: 1px; } +.anatomy__lines { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; z-index: 2; opacity: 0; } +.anatomy__lines path { fill: none; stroke: var(--cyan); stroke-width: 2; } +.anatomy__lines circle { fill: var(--bg); stroke: var(--cyan); stroke-width: 2.5; } .anatomy__labels { list-style: none; margin: 0; padding: 0; } -.anatomy__labels li { position: absolute; left: 0; top: 0; width: 240px; padding-left: 66px; opacity: 0; pointer-events: none; will-change: transform; } -.anatomy__labels li::before { content: ""; position: absolute; left: 0; top: .55em; width: 56px; height: 2px; background: var(--cyan); } -.anatomy__labels b { display: block; font: 900 17px/1.1 var(--display); text-transform: uppercase; letter-spacing: -.02em; } -.anatomy__labels span { display: block; margin-top: 5px; font: 500 14px/1.35 var(--body); color: var(--dim); } +.anatomy__labels li { + position: absolute; left: 0; top: 0; z-index: 3; width: 214px; translate: 0 -50%; + padding: 9px 12px 10px; background: rgba(7, 7, 13, .94); + border: var(--b) solid var(--fg); box-shadow: 4px 4px 0 var(--violet); + opacity: 0; pointer-events: none; will-change: transform; +} +.anatomy__labels i { margin-right: 8px; font: 700 11px/1 var(--mono); font-style: normal; color: var(--cyan); } +.anatomy__labels b { font: 900 13px/1.15 var(--display); text-transform: uppercase; letter-spacing: -.01em; } +.anatomy__labels span { display: block; margin-top: 6px; font: 500 12px/1.3 var(--mono); color: var(--dim); white-space: nowrap; } /* ---------- race ---------- */ .race__grid { @@ -856,8 +865,10 @@ section { position: relative; } .spinner { width: 100px; height: 100px; left: 2%; } .story__body { display: block; padding: 0; } - .story__stage { position: sticky; top: 0; place-items: start center; padding-top: 70px; } - .story .phone-host { height: 52vh; height: 52svh; } + .story__stage { position: sticky; top: 0; place-items: start center; padding-top: 70px; overflow: hidden; } /* nothing the phones do may widen the page */ + .story__phones { height: 52vh; height: 52svh; } + .step.step--long { align-items: flex-end; } + .step.step--long .step__card { position: sticky; top: auto; bottom: 4svh; } .story__num { top: 32%; font-size: 58vw; } .story__rail { right: 14px; top: 32%; gap: 6px; } .story__rail li { width: 8px; height: 20px; } @@ -892,14 +903,7 @@ section { position: relative; } .pagewave a { height: 25px; } .pagewave__bubble { right: 58px; } - .anatomy { height: 260svh; } - .anatomy__sticky { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr) auto; padding-top: 74px; gap: 8px; } - .anatomy__head .h2 { font-size: clamp(32px, 9vw, 48px); } - .xhost { height: 44svh; } - .anatomy__labels { display: flex; flex-wrap: wrap; gap: 6px; padding-bottom: 6px; } - .anatomy__labels li { position: static; width: auto; padding: 7px 10px; border: var(--b) solid var(--fg); transform: none !important; font-size: 12px; } - .anatomy__labels li::before, .anatomy__labels span { display: none; } - .anatomy__labels b { font-size: 11px; } + .anatomy__labels, .anatomy__lines { display: none; } /* the chapter's text names the layers */ .race__grid { grid-template-columns: minmax(0, 1fr); } .race__side { order: -1; }