css-motion-library 0.0.0-stage → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +121 -2
- package/catalog.json +77 -0
- package/examples/001-commerce-storyboard/README.md +19 -0
- package/examples/001-commerce-storyboard/animation.css +167 -0
- package/examples/001-commerce-storyboard/index.html +146 -0
- package/examples/002-commerce-film/README.md +38 -0
- package/examples/002-commerce-film/animation.css +197 -0
- package/examples/002-commerce-film/index.html +73 -0
- package/examples/003-kinetic-headline/README.md +29 -0
- package/examples/003-kinetic-headline/animation.css +276 -0
- package/examples/003-kinetic-headline/index.html +82 -0
- package/examples/004-loading-states/README.md +28 -0
- package/examples/004-loading-states/animation.css +87 -0
- package/examples/004-loading-states/index.html +119 -0
- package/examples/005-orbit-diagram/README.md +30 -0
- package/examples/005-orbit-diagram/animation.css +123 -0
- package/examples/005-orbit-diagram/index.html +66 -0
- package/package.json +31 -4
- package/src/auto.js +2 -0
- package/src/demo.css +12 -0
- package/src/player.js +140 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/* Every picture is HTML, SVG or CSS. The native player controls CSS animation time. */
|
|
2
|
+
.film { --ink:#11150f; --acid:#e5ef46; --paper:#efeee6; --film-duration:30s; background:var(--ink); color:var(--paper); }
|
|
3
|
+
.film__screen { container-type:inline-size; position:relative; width:100%; aspect-ratio:16 / 9; overflow:hidden; isolation:isolate; }
|
|
4
|
+
.film__overview { position:absolute; inset:0; display:flex; flex-direction:column; justify-content:center; padding:8%; background:var(--ink); }
|
|
5
|
+
.film__overview h1 { margin:28px 0; font-size:clamp(34px,8cqw,130px); line-height:1; letter-spacing:-.065em; font-weight:900; }
|
|
6
|
+
.film__overview h1 em { color:var(--acid); }
|
|
7
|
+
.film__overview p { max-width:32em; font-size:clamp(12px,1.7cqw,22px); line-height:1.65; color:#bbc4b1; }
|
|
8
|
+
.film em { font-style:normal; }
|
|
9
|
+
.film__shots, .film__shot { position:absolute; inset:0; }
|
|
10
|
+
.film__shot { display:none; overflow:hidden; background:var(--ink); }
|
|
11
|
+
.film__frame { position:absolute; inset:0 0 auto; z-index:8; display:flex; justify-content:space-between; padding:2.5% 4%; color:#eeeee0; font:clamp(9px,.85cqw,13px) ui-monospace,monospace; letter-spacing:.08em; text-transform:uppercase; mix-blend-mode:difference; pointer-events:none; }
|
|
12
|
+
.film__eyebrow { display:block; font:clamp(10px,1cqw,15px) ui-monospace,monospace; letter-spacing:.12em; text-transform:uppercase; }
|
|
13
|
+
.film__shot-copy { position:absolute; z-index:3; left:7%; top:18%; }
|
|
14
|
+
.film__shot-copy h2 { margin:22px 0; font-size:clamp(40px,10cqw,160px); font-weight:900; line-height:.93; letter-spacing:-.065em; }
|
|
15
|
+
.film__shot-copy h2 em { color:var(--acid); }
|
|
16
|
+
.film__shot-copy p { font-size:clamp(12px,1.45cqw,23px); line-height:1.55; margin:0; }
|
|
17
|
+
.film__corner-note { position:absolute; left:7%; bottom:8%; font:clamp(9px,.9cqw,14px) ui-monospace,monospace; }
|
|
18
|
+
.film.is-ready .film__overview { visibility:hidden; }
|
|
19
|
+
.film.is-ready .film__screen { animation:mvl-clock var(--film-duration) linear infinite paused; }
|
|
20
|
+
.film.is-ready .film__shot { display:block; opacity:0; visibility:hidden; animation:mvl-shot var(--film-duration) linear infinite paused; animation-delay:calc(var(--shot) * 5s); }
|
|
21
|
+
.film.is-ready .film__shot-copy { animation:mvl-copy var(--film-duration) cubic-bezier(.2,.7,.2,1) infinite paused; animation-delay:calc(var(--shot) * 5s); }
|
|
22
|
+
/* 00—05 / Opening: big type, a slow lens move and a running bottom strip. */
|
|
23
|
+
.film__shot--open { background:#11150f; }
|
|
24
|
+
.film__disc { position:absolute; width:58%; aspect-ratio:1; border:1px solid #829141; border-radius:50%; right:-10%; top:-23%; background:radial-gradient(circle at 35% 35%,#394327 0,#172014 65%,#11150f 100%); }
|
|
25
|
+
.film__disc::after { content:''; position:absolute; inset:12%; border:1px solid #a6ba4a; border-radius:50%; }
|
|
26
|
+
.film__intro-label { position:absolute; left:7%; top:20%; color:var(--acid); }
|
|
27
|
+
.film__opening-type { position:absolute; inset:30% 7% auto; font-size:clamp(36px,10.8cqw,174px); font-weight:950; line-height:.95; letter-spacing:-.075em; }
|
|
28
|
+
.film__opening-type > div { overflow:hidden; padding-bottom:.09em; margin-bottom:-.09em; }
|
|
29
|
+
.film__opening-type span { display:block; }
|
|
30
|
+
.film__opening-type em { color:var(--acid); }
|
|
31
|
+
.film__subtitle { position:absolute; left:7%; bottom:17%; font-size:clamp(11px,1.4cqw,21px); color:#aeb9a6; }
|
|
32
|
+
.film__ticker { position:absolute; bottom:0; padding-block:1.3%; width:max-content; font-size:clamp(15px,2.1cqw,34px); font-weight:800; letter-spacing:-.02em; color:var(--ink); background:var(--acid); white-space:nowrap; }
|
|
33
|
+
.film.is-ready .film__opening-type span { animation:mvl-title var(--film-duration) cubic-bezier(.2,.75,.2,1) infinite paused; }
|
|
34
|
+
.film.is-ready .film__opening-type > div:nth-child(2) span { animation-delay:.18s; }
|
|
35
|
+
.film.is-ready .film__ticker { animation:mvl-ticker var(--film-duration) linear infinite paused; }
|
|
36
|
+
.film.is-ready .film__disc { animation:mvl-disc var(--film-duration) ease-in-out infinite paused; }
|
|
37
|
+
/* 05—10 / Audit: full-bleed color cut and a window moving through a scanner. */
|
|
38
|
+
.film__shot--audit { background:var(--acid); color:var(--ink); }
|
|
39
|
+
.film__shot--audit .film__shot-copy h2 em { color:var(--ink); text-decoration:underline; text-decoration-thickness:.035em; text-underline-offset:.1em; }
|
|
40
|
+
.film__backword { position:absolute; bottom:17%; left:3%; color:#11150f12; font-size:19cqw; font-weight:950; letter-spacing:-.08em; white-space:nowrap; }
|
|
41
|
+
.film__audit-window { position:absolute; width:36%; right:6%; top:26%; background:var(--ink); color:var(--paper); padding:2.2%; border:1px solid #414e2a; border-radius:8px; box-shadow:0 30px 0 #11150f22; transform:rotate(-7deg); }
|
|
42
|
+
.film__window-top { display:flex; align-items:center; justify-content:space-between; gap:10px; font:clamp(8px,.85cqw,13px) ui-monospace,monospace; padding-bottom:5%; border-bottom:1px solid #4a543a; }
|
|
43
|
+
.film__audit-item { display:flex; justify-content:space-between; gap:12px; padding-block:8%; border-bottom:1px solid #38432b; font-size:clamp(10px,1.3cqw,20px); }
|
|
44
|
+
.film__audit-item b { align-self:center; padding:4px 8px; font:clamp(8px,.75cqw,12px) ui-monospace,monospace; border:1px solid #596644; color:var(--acid); border-radius:20px; }
|
|
45
|
+
.film__scan-line { position:absolute; left:-5%; right:-5%; top:25%; height:2px; background:var(--acid); box-shadow:0 0 25px 3px #e5ef4677; }
|
|
46
|
+
.film__crosshair { position:absolute; width:8%; aspect-ratio:1; right:10%; top:55%; border:1px solid var(--acid); transform:rotate(45deg); }
|
|
47
|
+
.film.is-ready .film__audit-window { animation:mvl-audit-camera var(--film-duration) cubic-bezier(.16,.7,.2,1) infinite paused; animation-delay:5s; }
|
|
48
|
+
.film.is-ready .film__scan-line { animation:mvl-scan var(--film-duration) linear infinite paused; animation-delay:5s; }
|
|
49
|
+
/* 10—15 / Plan: a moving blueprint, drawing wires and assembling nodes. */
|
|
50
|
+
.film__shot--plan { background:#131e2b; color:#edf2e8; }
|
|
51
|
+
.film__blueprint-grid { position:absolute; inset:-20%; background-image:linear-gradient(#8399ae20 1px,transparent 1px),linear-gradient(90deg,#8399ae20 1px,transparent 1px); background-size:5% 8%; transform:rotate(-15deg) scale(1.1); }
|
|
52
|
+
.film__wires { position:absolute; inset:0; width:100%; height:100%; stroke:#e5ef46; stroke-width:2; fill:none; opacity:.5; stroke-dasharray:2200; }
|
|
53
|
+
.film__plan-node { position:absolute; z-index:2; padding:1.8% 2.5%; border:1px solid #a7bb7b; color:#d8e3b9; background:#182532; font:clamp(8px,1cqw,16px) ui-monospace,monospace; letter-spacing:.08em; }
|
|
54
|
+
.film__plan-node--one { left:62%; top:18%; }
|
|
55
|
+
.film__plan-node--two { left:70%; top:46%; }
|
|
56
|
+
.film__plan-node--three { left:58%; top:76%; }
|
|
57
|
+
.film.is-ready .film__blueprint-grid { animation:mvl-blueprint var(--film-duration) linear infinite paused; animation-delay:10s; }
|
|
58
|
+
.film.is-ready .film__wires { animation:mvl-wires var(--film-duration) ease-out infinite paused; animation-delay:10s; }
|
|
59
|
+
.film.is-ready .film__plan-node { animation:mvl-node var(--film-duration) cubic-bezier(.2,.8,.2,1) infinite paused; animation-delay:10s; }
|
|
60
|
+
.film.is-ready .film__plan-node--two { animation-delay:10.3s; }
|
|
61
|
+
.film.is-ready .film__plan-node--three { animation-delay:10.6s; }
|
|
62
|
+
/* 15—20 / Build: camera pulls through the type into a completed storefront. */
|
|
63
|
+
.film__shot--build { background:var(--paper); color:var(--ink); perspective:1200px; }
|
|
64
|
+
.film__build-label { position:absolute; top:15%; left:7%; }
|
|
65
|
+
.film__build-type { position:absolute; top:24%; left:6%; font-size:14cqw; font-weight:950; letter-spacing:-.085em; line-height:.85; color:#c4c6b5; }
|
|
66
|
+
.film__build-type em { color:#b7c46d; }
|
|
67
|
+
.film__browser { position:absolute; top:21%; left:29%; width:59%; border:1px solid #7c826e; border-radius:8px; background:#f9f8f0; box-shadow:0 25px 50px #27311726; padding:1.5%; transform:rotate(-4deg); transform-origin:center; }
|
|
68
|
+
.film__browser .film__window-top { color:#657054; border-color:#d6d7ca; padding-bottom:2%; font-size:clamp(7px,.7cqw,11px); }
|
|
69
|
+
.film__shop-nav { display:flex; justify-content:space-between; align-items:center; padding-block:4%; gap:12px; font-size:clamp(7px,.8cqw,12px); }
|
|
70
|
+
.film__shop-nav strong { font-size:clamp(9px,1.1cqw,17px); letter-spacing:-.04em; }
|
|
71
|
+
.film__shop { display:grid; grid-template-columns:1fr 1fr; gap:5%; }
|
|
72
|
+
.film__product-art { position:relative; aspect-ratio:1; background:#d4dcbf; overflow:hidden; }
|
|
73
|
+
.film__product-art svg { position:absolute; width:60%; height:90%; left:20%; top:5%; fill:#859b61; stroke:#304c29; stroke-width:2; }
|
|
74
|
+
.film__product-art > span { position:absolute; bottom:7%; left:7%; font:clamp(7px,.65cqw,10px) ui-monospace,monospace; }
|
|
75
|
+
.film__product-info { align-self:center; padding-right:8%; }
|
|
76
|
+
.film__product-info > span { font:clamp(6px,.65cqw,10px) ui-monospace,monospace; }
|
|
77
|
+
.film__product-info h3 { font-size:clamp(16px,2.6cqw,40px); line-height:1; letter-spacing:-.055em; margin:8% 0; }
|
|
78
|
+
.film__product-info i { display:block; width:90%; height:3px; background:#c3c8b6; margin-bottom:5%; }
|
|
79
|
+
.film__product-info i:nth-of-type(2) { width:65%; }
|
|
80
|
+
.film__product-info > div { background:var(--ink); color:var(--paper); font-size:clamp(6px,.65cqw,11px); padding:8% 4%; text-align:center; margin-top:12%; }
|
|
81
|
+
.film.is-ready .film__browser { animation:mvl-browser var(--film-duration) cubic-bezier(.2,.65,.2,1) infinite paused; animation-delay:15s; }
|
|
82
|
+
/* 20—25 / Measure: staggered bars and an oversized orbit. No invented metrics. */
|
|
83
|
+
.film__shot--measure { background:#101510; }
|
|
84
|
+
.film__shot--measure .film__shot-copy { top:15%; }
|
|
85
|
+
.film__shot--measure .film__shot-copy h2 { font-size:9cqw; }
|
|
86
|
+
.film__measure-ring { position:absolute; width:70%; aspect-ratio:1; left:55%; top:-10%; border:1px solid #7a8a45; border-radius:50%; }
|
|
87
|
+
.film__measure-ring::after { content:''; position:absolute; inset:12%; border:1px dashed #414e2d; border-radius:50%; }
|
|
88
|
+
.film__chart { position:absolute; width:36%; right:8%; bottom:20%; }
|
|
89
|
+
.film__chart > span { font:clamp(8px,.85cqw,14px) ui-monospace,monospace; letter-spacing:.05em; color:#abbf7e; }
|
|
90
|
+
.film__bars { height:19cqw; display:flex; align-items:flex-end; gap:7%; border-bottom:1px solid #697d47; margin-block:7% 5%; }
|
|
91
|
+
.film__bars i { display:block; flex:1; height:var(--height); background:#6a8042; transform-origin:bottom; }
|
|
92
|
+
.film__bars i:last-child { background:var(--acid); }
|
|
93
|
+
.film__chart small { display:block; font:clamp(7px,.7cqw,11px) ui-monospace,monospace; color:#a4b293; line-height:1.5; }
|
|
94
|
+
.film.is-ready .film__bars i { animation:mvl-bar var(--film-duration) cubic-bezier(.2,.75,.2,1) infinite paused; animation-delay:calc(20s + var(--bar) * .13s); }
|
|
95
|
+
.film.is-ready .film__measure-ring { animation:mvl-ring var(--film-duration) linear infinite paused; }
|
|
96
|
+
/* 25—30 / Closing title: a deliberate hold, then back to the first frame. */
|
|
97
|
+
.film__shot--end { background:var(--acid); color:var(--ink); padding:12% 7% 6%; }
|
|
98
|
+
.film__end-type { position:relative; font-size:10.2cqw; font-weight:950; line-height:.88; letter-spacing:-.075em; margin-top:4%; }
|
|
99
|
+
.film__end-type em { -webkit-text-stroke:1px var(--ink); color:transparent; }
|
|
100
|
+
.film__shot--end > p { position:relative; margin-top:4%; font-size:clamp(10px,1.3cqw,20px); }
|
|
101
|
+
.film__end-credit { position:absolute; bottom:7%; right:6%; font:clamp(8px,.8cqw,12px) ui-monospace,monospace; }
|
|
102
|
+
.film__end-orbit { position:absolute; width:70%; aspect-ratio:1; right:-20%; top:-10%; border:2px solid #11150f33; border-radius:50%; }
|
|
103
|
+
.film__end-orbit::before, .film__end-orbit::after { content:''; position:absolute; inset:10%; border:1px solid #11150f22; border-radius:50%; }
|
|
104
|
+
.film__end-orbit::after { inset:20%; }
|
|
105
|
+
.film.is-ready .film__end-type { animation:mvl-title var(--film-duration) cubic-bezier(.2,.8,.2,1) infinite paused; animation-delay:25s; }
|
|
106
|
+
.film.is-ready .film__end-orbit { animation:mvl-end-orbit var(--film-duration) ease-out infinite paused; animation-delay:25s; }
|
|
107
|
+
.film__cut { position:absolute; z-index:7; inset:0; background:var(--acid); transform:translateX(-110%); pointer-events:none; }
|
|
108
|
+
.film.is-ready .film__cut { animation:mvl-cut 5s cubic-bezier(.76,0,.24,1) infinite paused; }
|
|
109
|
+
/* The controller overrides paused CSSAnimation objects together via the native API. */
|
|
110
|
+
.film__controls { display:flex; align-items:center; gap:18px; min-height:68px; padding:12px 4%; background:#0c100b; border-top:1px solid #39412d; font-size:11px; }
|
|
111
|
+
.film__controls[hidden] { display:none; }
|
|
112
|
+
.film__controls button { min-height:40px; padding:8px 10px; background:none; border:0; color:#dce5cd; cursor:pointer; white-space:nowrap; }
|
|
113
|
+
.film__controls button:hover { color:var(--acid); }
|
|
114
|
+
.film__controls :focus-visible { outline:2px solid var(--acid); outline-offset:3px; }
|
|
115
|
+
.film__seek-label { flex:1; min-width:40px; display:flex; align-items:center; min-height:40px; }
|
|
116
|
+
.film__controls input[type=range] { appearance:none; -webkit-appearance:none; width:100%; min-width:0; height:4px; border-radius:3px; cursor:pointer; background:linear-gradient(to right,var(--acid) var(--progress,0%),#49543a var(--progress,0%)); }
|
|
117
|
+
.film__controls input::-webkit-slider-thumb { appearance:none; width:12px; height:12px; border-radius:50%; background:var(--acid); }
|
|
118
|
+
.film__controls input::-moz-range-thumb { width:12px; height:12px; border:0; border-radius:50%; background:var(--acid); }
|
|
119
|
+
.film__controls output { font:11px ui-monospace,monospace; color:#b9c4ab; white-space:nowrap; }
|
|
120
|
+
.film__speed select { min-height:40px; background:#0c100b; color:#dce5cd; border:1px solid #49543a; padding:5px; border-radius:4px; }
|
|
121
|
+
.film__sr-only { position:absolute; width:1px; height:1px; overflow:hidden; clip-path:inset(50%); white-space:nowrap; }
|
|
122
|
+
.film.is-reduced .film__overview { visibility:visible; z-index:6; }
|
|
123
|
+
.film.is-reduced .film__shots, .film.is-reduced .film__cut { visibility:hidden; opacity:0; }
|
|
124
|
+
@keyframes mvl-clock { from { outline-color:transparent; } to { outline-color:transparent; } }
|
|
125
|
+
@keyframes mvl-shot { 0%,14.5% { opacity:1; visibility:visible; transform:scale(1); } 16.66%,100% { opacity:0; visibility:hidden; transform:scale(1.035); } }
|
|
126
|
+
@keyframes mvl-copy { 0% { opacity:0; transform:translateY(24px); } 2.2%,13.7% { opacity:1; transform:translateY(0); } 16.6%,100% { opacity:0; transform:translateY(-18px); } }
|
|
127
|
+
@keyframes mvl-title { 0% { transform:translateY(110%); opacity:0; } 2.6%,13.8% { transform:translateY(0); opacity:1; } 16.6%,100% { transform:translateY(-18%); opacity:0; } }
|
|
128
|
+
@keyframes mvl-ticker { from { transform:translateX(0); } to { transform:translateX(-45%); } }
|
|
129
|
+
@keyframes mvl-disc { 0% { transform:scale(.8) translateX(8%); } 16.6%,100% { transform:scale(1.2) translateX(-8%); } }
|
|
130
|
+
@keyframes mvl-audit-camera { 0% { transform:perspective(1000px) rotateY(-30deg) rotate(-10deg) translateX(30%); opacity:0; } 3%,13.5% { transform:perspective(1000px) rotateY(-5deg) rotate(-4deg) translateX(0); opacity:1; } 16.6%,100% { transform:perspective(1000px) rotateY(8deg) rotate(2deg) translateX(-5%); opacity:0; } }
|
|
131
|
+
@keyframes mvl-scan { 0%,2% { transform:translateY(0); opacity:0; } 3% { opacity:1; } 13% { transform:translateY(13cqw); opacity:1; } 16.6%,100% { transform:translateY(13cqw); opacity:0; } }
|
|
132
|
+
@keyframes mvl-blueprint { 0% { transform:rotate(-15deg) scale(1.1) translateX(0); } 16.6%,100% { transform:rotate(-10deg) scale(1.25) translateX(-4%); } }
|
|
133
|
+
@keyframes mvl-wires { 0% { stroke-dashoffset:2200; } 11%,100% { stroke-dashoffset:0; } }
|
|
134
|
+
@keyframes mvl-node { 0% { opacity:0; transform:scale(.75) translateY(15px); } 3%,14% { opacity:1; transform:scale(1) translateY(0); } 16.6%,100% { opacity:0; transform:scale(1.08) translateY(-10px); } }
|
|
135
|
+
@keyframes mvl-browser { 0% { transform:translateY(45%) rotateX(20deg) rotateY(-25deg) rotate(-5deg) scale(.75); opacity:0; } 4% { transform:translateY(0) rotateX(4deg) rotateY(-10deg) rotate(-3deg) scale(1); opacity:1; } 14% { transform:translateY(-3%) rotateX(0) rotateY(0) rotate(-1deg) scale(1.08); opacity:1; } 16.6%,100% { transform:translateY(-8%) scale(1.15); opacity:0; } }
|
|
136
|
+
@keyframes mvl-bar { 0% { transform:scaleY(0); } 4%,14% { transform:scaleY(1); } 16.6%,100% { transform:scaleY(.8); } }
|
|
137
|
+
@keyframes mvl-ring { to { transform:rotate(180deg); } }
|
|
138
|
+
@keyframes mvl-end-orbit { 0% { transform:scale(.65); } 16.6%,100% { transform:scale(1.15); } }
|
|
139
|
+
@keyframes mvl-cut { 0%,90% { transform:translateX(-110%); } 96% { transform:translateX(0); } 100% { transform:translateX(110%); } }
|
|
140
|
+
/* Standalone page: shrink the 16:9 frame so the controls stay on screen. */
|
|
141
|
+
@media (min-width:601px) { html:not(.is-embedded) .film { max-width:max(480px,calc((100svh - 130px) * 16 / 9)); margin-inline:auto; } }
|
|
142
|
+
@media (max-width:600px) {
|
|
143
|
+
.film__screen { aspect-ratio:3 / 4; }
|
|
144
|
+
.film__frame { padding:5% 6%; font-size:8px; }
|
|
145
|
+
.film__eyebrow { font-size:9px; }
|
|
146
|
+
.film__opening-type { top:29%; font-size:11.6cqw; }
|
|
147
|
+
.film__intro-label { top:21%; }
|
|
148
|
+
.film__disc { width:110%; right:-44%; top:-12%; }
|
|
149
|
+
.film__subtitle { font-size:11px; max-width:70%; bottom:24%; }
|
|
150
|
+
.film__ticker { padding-block:3%; font-size:4cqw; }
|
|
151
|
+
.film__shot-copy { top:13%; left:7%; }
|
|
152
|
+
.film__shot-copy h2 { font-size:15cqw; margin:18px 0; }
|
|
153
|
+
.film__shot-copy p { font-size:11px; }
|
|
154
|
+
.film__audit-window { width:65%; right:10%; top:53%; padding:5%; }
|
|
155
|
+
.film__audit-item { padding-block:6%; font-size:11px; }
|
|
156
|
+
.film__audit-item b { font-size:8px; padding:3px 6px; }
|
|
157
|
+
.film__window-top { font-size:8px; }
|
|
158
|
+
.film__backword { bottom:17%; font-size:25cqw; }
|
|
159
|
+
.film__corner-note { font-size:8px; bottom:5%; max-width:75%; }
|
|
160
|
+
.film__wires { top:35%; height:65%; }
|
|
161
|
+
.film__plan-node { font-size:8px; padding:3% 4%; }
|
|
162
|
+
.film__plan-node--one { top:58%; left:14%; }
|
|
163
|
+
.film__plan-node--two { top:73%; left:57%; }
|
|
164
|
+
.film__plan-node--three { top:85%; left:24%; }
|
|
165
|
+
.film__build-label { top:14%; }
|
|
166
|
+
.film__build-type { top:23%; font-size:20cqw; }
|
|
167
|
+
.film__browser { width:86%; left:7%; top:47%; padding:3%; }
|
|
168
|
+
.film__shop-nav { font-size:6px; }
|
|
169
|
+
.film__shop-nav strong { font-size:9px; }
|
|
170
|
+
.film__browser .film__window-top { font-size:6px; }
|
|
171
|
+
.film__product-info h3 { font-size:5cqw; }
|
|
172
|
+
.film__product-info > span, .film__product-info > div { font-size:6px; }
|
|
173
|
+
.film__shot--measure .film__shot-copy { top:13%; }
|
|
174
|
+
.film__shot--measure .film__shot-copy h2 { font-size:15cqw; }
|
|
175
|
+
.film__chart { width:58%; right:10%; bottom:9%; }
|
|
176
|
+
.film__bars { height:25cqw; }
|
|
177
|
+
.film__chart > span { font-size:8px; }
|
|
178
|
+
.film__chart small { font-size:7px; }
|
|
179
|
+
.film__measure-ring { width:125%; top:23%; left:30%; }
|
|
180
|
+
.film__shot--end { padding-top:27%; }
|
|
181
|
+
.film__end-type { font-size:13.3cqw; margin-top:10%; }
|
|
182
|
+
.film__shot--end > p { margin-top:13%; font-size:10px; }
|
|
183
|
+
.film__end-orbit { width:150%; right:-75%; top:4%; }
|
|
184
|
+
.film__end-credit { font-size:8px; }
|
|
185
|
+
.film__controls { gap:8px; padding-inline:3%; flex-wrap:wrap; }
|
|
186
|
+
.film__controls button { font-size:10px; padding-inline:5px; }
|
|
187
|
+
.film__seek-label { order:5; flex-basis:100%; min-height:28px; }
|
|
188
|
+
.film__controls output { margin-left:auto; font-size:10px; }
|
|
189
|
+
.film__speed select { min-height:34px; font-size:10px; }
|
|
190
|
+
.film__overview h1 { font-size:11cqw; }
|
|
191
|
+
.film__overview p { font-size:13px; }
|
|
192
|
+
}
|
|
193
|
+
@media (prefers-reduced-motion:reduce) {
|
|
194
|
+
.film.is-ready .film__overview { visibility:visible; z-index:6; }
|
|
195
|
+
.film .film__shots, .film .film__cut { visibility:hidden; opacity:0; }
|
|
196
|
+
.film__controls { display:none; }
|
|
197
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
+
<meta name="color-scheme" content="dark">
|
|
7
|
+
<title>002 — Commerce Film | CSS Motion Library</title>
|
|
8
|
+
<script>if (new URLSearchParams(location.search).has('embed')) document.documentElement.classList.add('is-embedded');</script>
|
|
9
|
+
<link rel="stylesheet" href="../../src/demo.css">
|
|
10
|
+
<link rel="stylesheet" href="animation.css">
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<nav class="demo-nav"><a href="../../">← Library</a><span>002 / Commerce Film</span><a href="../001-commerce-storyboard/">Original edition ↗</a></nav>
|
|
14
|
+
<main>
|
|
15
|
+
<section class="film" data-motion-player data-duration="30" aria-labelledby="film-title">
|
|
16
|
+
<div class="film__screen" data-motion-stage>
|
|
17
|
+
<div class="film__overview">
|
|
18
|
+
<span class="film__eyebrow">Commerce Film / CSS Motion Library</span>
|
|
19
|
+
<h1 id="film-title">Better commerce.<br><em>By design.</em></h1>
|
|
20
|
+
<p>Audit the store. Make a plan. Build with purpose. Measure and refine.</p>
|
|
21
|
+
</div>
|
|
22
|
+
<div class="film__frame" aria-hidden="true"><span>CSS Motion Library</span><span>Commerce Film / 002</span></div>
|
|
23
|
+
<div class="film__shots" aria-hidden="true">
|
|
24
|
+
<div class="film__shot film__shot--open" style="--shot:0">
|
|
25
|
+
<div class="film__disc"></div>
|
|
26
|
+
<span class="film__eyebrow film__intro-label">A small film. Made of CSS.</span>
|
|
27
|
+
<div class="film__opening-type"><div><span>COMMERCE</span></div><div><span>IN <em>MOTION.</em></span></div></div>
|
|
28
|
+
<p class="film__subtitle">From the first question to what comes next.</p>
|
|
29
|
+
<div class="film__ticker">AUDIT / PLAN / BUILD / MEASURE / AUDIT / PLAN / BUILD / MEASURE /</div>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="film__shot film__shot--audit" style="--shot:1">
|
|
32
|
+
<span class="film__backword">LOOK CLOSER</span>
|
|
33
|
+
<div class="film__shot-copy"><span class="film__eyebrow">01 / Audit</span><h2>Find the<br><em>friction.</em></h2><p>Before changing the store,<br>understand what is in the way.</p></div>
|
|
34
|
+
<div class="film__audit-window"><div class="film__window-top"><span>● ● ●</span><span>Store diagnostics</span></div><div class="film__audit-item"><span>Storefront</span><b>Inspect</b></div><div class="film__audit-item"><span>Checkout</span><b>Inspect</b></div><div class="film__audit-item"><span>Integrations</span><b>Inspect</b></div><div class="film__scan-line"></div><div class="film__crosshair"></div></div>
|
|
35
|
+
<span class="film__corner-note">The right questions come first.</span>
|
|
36
|
+
</div>
|
|
37
|
+
<div class="film__shot film__shot--plan" style="--shot:2">
|
|
38
|
+
<div class="film__blueprint-grid"></div>
|
|
39
|
+
<svg class="film__wires" viewBox="0 0 1000 600" preserveAspectRatio="none"><path d="M0 300H360V120H740V300H1000 M360 300V480H740V300 M740 120V480"/></svg>
|
|
40
|
+
<div class="film__plan-node film__plan-node--one">STOREFRONT</div><div class="film__plan-node film__plan-node--two">CHECKOUT</div><div class="film__plan-node film__plan-node--three">INTEGRATIONS</div>
|
|
41
|
+
<div class="film__shot-copy"><span class="film__eyebrow">02 / Architecture</span><h2>Make<br><em>a plan.</em></h2><p>A clear direction.<br>Every connection considered.</p></div>
|
|
42
|
+
</div>
|
|
43
|
+
<div class="film__shot film__shot--build" style="--shot:3">
|
|
44
|
+
<span class="film__eyebrow film__build-label">03 / Build</span>
|
|
45
|
+
<div class="film__build-type">FROM PLAN<br><em>TO LIVE.</em></div>
|
|
46
|
+
<div class="film__browser"><div class="film__window-top"><span>● ● ●</span><span>YOUR NEXT STORE</span><span>↗</span></div><div class="film__shop-nav"><strong>STUDIO / GOODS</strong><span>Collection About Bag (0)</span></div><div class="film__shop"><div class="film__product-art"><svg viewBox="0 0 200 240"><path d="M65 62V35Q100 5 135 35V62L167 100V217H33V100Z"/><path d="M65 62Q100 89 135 62M66 35Q100 63 134 35"/></svg><span>OBJECT / 001</span></div><div class="film__product-info"><span>MADE FOR EVERY DAY</span><h3>Less noise.<br>More purpose.</h3><i></i><i></i><div>Explore the collection ↗</div></div></div></div>
|
|
47
|
+
<span class="film__corner-note">Design. Development. The details between.</span>
|
|
48
|
+
</div>
|
|
49
|
+
<div class="film__shot film__shot--measure" style="--shot:4">
|
|
50
|
+
<div class="film__measure-ring"></div>
|
|
51
|
+
<div class="film__shot-copy"><span class="film__eyebrow">04 / Measure</span><h2>Learn.<br>Refine.<br><em>Repeat.</em></h2></div>
|
|
52
|
+
<div class="film__chart"><span>OBSERVE → LEARN → REFINE</span><div class="film__bars"><i style="--bar:0;--height:32%"></i><i style="--bar:1;--height:48%"></i><i style="--bar:2;--height:40%"></i><i style="--bar:3;--height:65%"></i><i style="--bar:4;--height:58%"></i><i style="--bar:5;--height:80%"></i></div><small>Illustrative motion graphic · no performance claims</small></div>
|
|
53
|
+
</div>
|
|
54
|
+
<div class="film__shot film__shot--end" style="--shot:5">
|
|
55
|
+
<div class="film__end-orbit"></div><span class="film__eyebrow">A clear path forward.</span><div class="film__end-type">BETTER<br>COMMERCE.<br><em>BY DESIGN.</em></div><p>Audit → Plan → Build → Measure</p><span class="film__end-credit">CSS Motion Library / 002</span>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
<div class="film__cut" aria-hidden="true"></div>
|
|
59
|
+
<span class="film__sr-only">A thirty-second CSS film in six shots: an opening title, store audit, architecture plan, store build, measurement, and a closing title. The chart is illustrative.</span>
|
|
60
|
+
</div>
|
|
61
|
+
<div class="film__controls" data-motion-controls hidden>
|
|
62
|
+
<button type="button" data-motion-toggle aria-label="Pause animation">Ⅱ Pause</button>
|
|
63
|
+
<button type="button" data-motion-restart aria-label="Replay animation from the beginning">↺ Replay</button>
|
|
64
|
+
<label class="film__seek-label"><span class="film__sr-only">Animation position in seconds</span><input data-motion-seek type="range" min="0" max="30" step="0.1" value="0" aria-label="Animation position in seconds"></label>
|
|
65
|
+
<output data-motion-time>0:00 / 0:30</output>
|
|
66
|
+
<label class="film__speed"><span class="film__sr-only">Playback speed</span><select data-motion-speed aria-label="Playback speed"><option value="0.5">0.5×</option><option value="1" selected>1×</option><option value="1.5">1.5×</option></select></label>
|
|
67
|
+
</div>
|
|
68
|
+
</section>
|
|
69
|
+
</main>
|
|
70
|
+
<footer class="demo-footer">30-second CSS film · Six shots · Native playback controls · <a href="animation.css">View CSS</a></footer>
|
|
71
|
+
<script type="module" src="../../src/auto.js"></script>
|
|
72
|
+
</body>
|
|
73
|
+
</html>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# 003 — Kinetic Headline
|
|
2
|
+
|
|
3
|
+
An eight-second hero headline reveal: words rise through overflow masks, a hand-drawn
|
|
4
|
+
SVG underline draws in, then the subline and call to action follow. Pure CSS keyframes
|
|
5
|
+
on one shared timeline, driven by `src/player.js`.
|
|
6
|
+
|
|
7
|
+
| Time | Beat |
|
|
8
|
+
|---|---|
|
|
9
|
+
| 0.2–0.7s | Eyebrow slides in |
|
|
10
|
+
| 0.6–1.7s | Headline words rise one by one |
|
|
11
|
+
| 1.8–2.7s | Underline draws under the last word |
|
|
12
|
+
| 2.2–2.9s | Subline fades up |
|
|
13
|
+
| 2.7–3.5s | CTA pops in |
|
|
14
|
+
| 3.5–7.2s | Hold |
|
|
15
|
+
| 7.2–8s | Everything exits up; loop restarts |
|
|
16
|
+
|
|
17
|
+
## Customize
|
|
18
|
+
|
|
19
|
+
- Theme: `--paper`, `--ink`, `--accent` on `.kh`.
|
|
20
|
+
- Copy: edit both the static `.kh__overview` (no-JS / reduced motion) and the animated
|
|
21
|
+
`.kh__scene`. Keep one `.kh__mask > .kh__word` per word; add `kh__word--N` and a
|
|
22
|
+
matching keyframe if you add words.
|
|
23
|
+
- Use it as a page hero by dropping the `.kh` section in and keeping `src/player.js`, or remove
|
|
24
|
+
the controls block and the player for an autoplay-only headline (keep the reduced-motion rule).
|
|
25
|
+
|
|
26
|
+
## Accessibility
|
|
27
|
+
|
|
28
|
+
The real heading lives in the static overview; the animated copy is `aria-hidden`. Reduced
|
|
29
|
+
motion and no-JS show the finished headline with no movement and no controls.
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/* Theme tokens: --paper background, --ink text, --accent highlight, --surface raised paper, --muted secondary text, --line borders. */
|
|
2
|
+
.kh {
|
|
3
|
+
--paper: #f2f0e8;
|
|
4
|
+
--ink: #121212;
|
|
5
|
+
--accent: #ff5b2e;
|
|
6
|
+
--surface: #fbfaf4;
|
|
7
|
+
--muted: #67645d;
|
|
8
|
+
--line: #12121224;
|
|
9
|
+
box-sizing: border-box;
|
|
10
|
+
width: 100%;
|
|
11
|
+
max-width: calc((100svh - 140px) * 16 / 9);
|
|
12
|
+
margin-inline: auto;
|
|
13
|
+
color: var(--ink);
|
|
14
|
+
color-scheme: light;
|
|
15
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
16
|
+
background: var(--paper);
|
|
17
|
+
}
|
|
18
|
+
.kh, .kh * { box-sizing: border-box; }
|
|
19
|
+
.kh__stage {
|
|
20
|
+
position: relative;
|
|
21
|
+
isolation: isolate;
|
|
22
|
+
width: 100%;
|
|
23
|
+
max-width: calc((100svh - 140px) * 16 / 9);
|
|
24
|
+
aspect-ratio: 16 / 9;
|
|
25
|
+
margin-inline: auto;
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
container-type: inline-size;
|
|
28
|
+
border: 1px solid var(--line);
|
|
29
|
+
border-radius: 1.25rem;
|
|
30
|
+
background: radial-gradient(circle at 82% 20%, #ff5b2e24 0 11%, transparent 36%), linear-gradient(135deg, #faf8f0, var(--paper) 58%, #e8e4d8);
|
|
31
|
+
}
|
|
32
|
+
.kh__stage::before {
|
|
33
|
+
content: "";
|
|
34
|
+
position: absolute;
|
|
35
|
+
z-index: 0;
|
|
36
|
+
top: -24%;
|
|
37
|
+
right: -8%;
|
|
38
|
+
width: 34%;
|
|
39
|
+
aspect-ratio: 1;
|
|
40
|
+
border: 1px solid #12121220;
|
|
41
|
+
border-radius: 50%;
|
|
42
|
+
pointer-events: none;
|
|
43
|
+
}
|
|
44
|
+
.kh__stage::after {
|
|
45
|
+
content: "";
|
|
46
|
+
position: absolute;
|
|
47
|
+
z-index: 0;
|
|
48
|
+
top: 12%;
|
|
49
|
+
right: 7%;
|
|
50
|
+
width: clamp(.55rem, 1.1cqw, 1rem);
|
|
51
|
+
aspect-ratio: 1;
|
|
52
|
+
border-radius: 50%;
|
|
53
|
+
background: var(--accent);
|
|
54
|
+
pointer-events: none;
|
|
55
|
+
}
|
|
56
|
+
.kh__overview, .kh__scene { position: absolute; inset: 0; }
|
|
57
|
+
.kh__overview { display: grid; place-items: center; }
|
|
58
|
+
.kh__scene { display: none; }
|
|
59
|
+
.kh.is-ready:not(.is-reduced) .kh__overview { display: none; }
|
|
60
|
+
.kh.is-ready:not(.is-reduced) .kh__scene { display: grid; place-items: center; }
|
|
61
|
+
.kh__content { position: relative; z-index: 1; width: min(82cqw, 72rem); }
|
|
62
|
+
.kh__eyebrow {
|
|
63
|
+
display: inline-flex;
|
|
64
|
+
align-items: center;
|
|
65
|
+
gap: .7em;
|
|
66
|
+
margin: 0 0 clamp(1rem, 2.6cqw, 2.5rem);
|
|
67
|
+
font-size: clamp(.62rem, 1.15cqw, .78rem);
|
|
68
|
+
font-weight: 700;
|
|
69
|
+
letter-spacing: .18em;
|
|
70
|
+
}
|
|
71
|
+
.kh__eyebrow::before { content: ""; width: 2.4em; height: 2px; background: var(--accent); }
|
|
72
|
+
.kh__headline {
|
|
73
|
+
margin: 0;
|
|
74
|
+
font-size: clamp(1.55rem, 8.3cqw, 6.7rem);
|
|
75
|
+
font-weight: 700;
|
|
76
|
+
line-height: .95;
|
|
77
|
+
letter-spacing: -.055em;
|
|
78
|
+
}
|
|
79
|
+
.kh__line { display: flex; align-items: flex-end; gap: .22em; white-space: nowrap; }
|
|
80
|
+
.kh__line--second { margin-top: .06em; }
|
|
81
|
+
.kh__mask { display: block; overflow: hidden; }
|
|
82
|
+
.kh__word { display: block; }
|
|
83
|
+
.kh__last { position: relative; display: inline-block; }
|
|
84
|
+
.kh__underline {
|
|
85
|
+
position: absolute;
|
|
86
|
+
left: -.02em;
|
|
87
|
+
bottom: -.1em;
|
|
88
|
+
width: 104%;
|
|
89
|
+
height: .25em;
|
|
90
|
+
overflow: visible;
|
|
91
|
+
}
|
|
92
|
+
.kh__underline-path {
|
|
93
|
+
fill: none;
|
|
94
|
+
stroke: var(--accent);
|
|
95
|
+
stroke-width: 4;
|
|
96
|
+
stroke-linecap: round;
|
|
97
|
+
stroke-dasharray: 1;
|
|
98
|
+
stroke-dashoffset: 0;
|
|
99
|
+
}
|
|
100
|
+
.kh__subline {
|
|
101
|
+
max-width: 42ch;
|
|
102
|
+
margin: clamp(1rem, 2.2cqw, 2rem) 0 0;
|
|
103
|
+
color: var(--muted);
|
|
104
|
+
font-size: clamp(.9rem, 1.55cqw, 1.18rem);
|
|
105
|
+
line-height: 1.45;
|
|
106
|
+
}
|
|
107
|
+
.kh__pill {
|
|
108
|
+
display: inline-flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
min-height: 2.8rem;
|
|
111
|
+
margin-top: clamp(1.25rem, 2.4cqw, 2rem);
|
|
112
|
+
padding: .65rem 1.15rem;
|
|
113
|
+
border-radius: 999px;
|
|
114
|
+
color: var(--ink);
|
|
115
|
+
background: var(--accent);
|
|
116
|
+
box-shadow: 0 .35rem 0 var(--ink);
|
|
117
|
+
font-size: clamp(.78rem, 1.35cqw, 1rem);
|
|
118
|
+
font-weight: 700;
|
|
119
|
+
}
|
|
120
|
+
.kh__content--scene { animation: kh-exit 8s cubic-bezier(.4, 0, .2, 1) infinite both; }
|
|
121
|
+
.kh__content--scene .kh__eyebrow { animation: kh-eyebrow 8s cubic-bezier(.22, 1, .36, 1) infinite both; }
|
|
122
|
+
.kh__content--scene .kh__word--1 { animation: kh-word-1 8s cubic-bezier(.22, 1, .36, 1) infinite both; }
|
|
123
|
+
.kh__content--scene .kh__word--2 { animation: kh-word-2 8s cubic-bezier(.22, 1, .36, 1) infinite both; }
|
|
124
|
+
.kh__content--scene .kh__word--3 { animation: kh-word-3 8s cubic-bezier(.22, 1, .36, 1) infinite both; }
|
|
125
|
+
.kh__content--scene .kh__word--4 { animation: kh-word-4 8s cubic-bezier(.22, 1, .36, 1) infinite both; }
|
|
126
|
+
.kh__content--scene .kh__word--5 { animation: kh-word-5 8s cubic-bezier(.22, 1, .36, 1) infinite both; }
|
|
127
|
+
.kh__content--scene .kh__word--6 { animation: kh-word-6 8s cubic-bezier(.22, 1, .36, 1) infinite both; }
|
|
128
|
+
.kh__content--scene .kh__underline-path { animation: kh-underline 8s cubic-bezier(.4, 0, .2, 1) infinite both; }
|
|
129
|
+
.kh__content--scene .kh__subline { animation: kh-subline 8s cubic-bezier(.22, 1, .36, 1) infinite both; }
|
|
130
|
+
.kh__content--scene .kh__pill { animation: kh-cta 8s cubic-bezier(.22, 1, .36, 1) infinite both; }
|
|
131
|
+
@keyframes kh-eyebrow {
|
|
132
|
+
0%, 2% { opacity: 0; transform: translateX(-130%); }
|
|
133
|
+
9%, 100% { opacity: 1; transform: translateX(0); }
|
|
134
|
+
}
|
|
135
|
+
@keyframes kh-word-1 {
|
|
136
|
+
0%, 7% { opacity: 0; transform: translateY(110%); }
|
|
137
|
+
14%, 100% { opacity: 1; transform: translateY(0); }
|
|
138
|
+
}
|
|
139
|
+
@keyframes kh-word-2 {
|
|
140
|
+
0%, 8.5% { opacity: 0; transform: translateY(110%); }
|
|
141
|
+
15.5%, 100% { opacity: 1; transform: translateY(0); }
|
|
142
|
+
}
|
|
143
|
+
@keyframes kh-word-3 {
|
|
144
|
+
0%, 10% { opacity: 0; transform: translateY(110%); }
|
|
145
|
+
17%, 100% { opacity: 1; transform: translateY(0); }
|
|
146
|
+
}
|
|
147
|
+
@keyframes kh-word-4 {
|
|
148
|
+
0%, 11.5% { opacity: 0; transform: translateY(110%); }
|
|
149
|
+
18.5%, 100% { opacity: 1; transform: translateY(0); }
|
|
150
|
+
}
|
|
151
|
+
@keyframes kh-word-5 {
|
|
152
|
+
0%, 13% { opacity: 0; transform: translateY(110%); }
|
|
153
|
+
20%, 100% { opacity: 1; transform: translateY(0); }
|
|
154
|
+
}
|
|
155
|
+
@keyframes kh-word-6 {
|
|
156
|
+
0%, 14.5% { opacity: 0; transform: translateY(110%); }
|
|
157
|
+
21.5%, 100% { opacity: 1; transform: translateY(0); }
|
|
158
|
+
}
|
|
159
|
+
@keyframes kh-underline {
|
|
160
|
+
0%, 22% { opacity: 0; stroke-dashoffset: 1; }
|
|
161
|
+
24% { opacity: 1; }
|
|
162
|
+
34%, 100% { opacity: 1; stroke-dashoffset: 0; }
|
|
163
|
+
}
|
|
164
|
+
@keyframes kh-subline {
|
|
165
|
+
0%, 28% { opacity: 0; transform: translateY(1.1cqw); }
|
|
166
|
+
36%, 100% { opacity: 1; transform: translateY(0); }
|
|
167
|
+
}
|
|
168
|
+
@keyframes kh-cta {
|
|
169
|
+
0%, 34% { opacity: 0; transform: scale(.86); }
|
|
170
|
+
40% { opacity: 1; transform: scale(1.04); }
|
|
171
|
+
44%, 100% { opacity: 1; transform: scale(1); }
|
|
172
|
+
}
|
|
173
|
+
@keyframes kh-exit {
|
|
174
|
+
0%, 90% { opacity: 1; transform: translateY(0); }
|
|
175
|
+
100% { opacity: 0; transform: translateY(-4cqw); }
|
|
176
|
+
}
|
|
177
|
+
@keyframes mvl-clock { to { opacity: 1; } }
|
|
178
|
+
.kh__clock {
|
|
179
|
+
position: absolute;
|
|
180
|
+
width: 0;
|
|
181
|
+
height: 0;
|
|
182
|
+
opacity: 0;
|
|
183
|
+
animation: mvl-clock 8s linear infinite;
|
|
184
|
+
}
|
|
185
|
+
.kh__controls {
|
|
186
|
+
display: flex;
|
|
187
|
+
flex-wrap: wrap;
|
|
188
|
+
align-items: center;
|
|
189
|
+
gap: .5rem .7rem;
|
|
190
|
+
width: 100%;
|
|
191
|
+
min-width: 0;
|
|
192
|
+
margin: .7rem auto 0;
|
|
193
|
+
padding: .48rem .6rem;
|
|
194
|
+
border-radius: .85rem;
|
|
195
|
+
color: var(--paper);
|
|
196
|
+
background: var(--ink);
|
|
197
|
+
color-scheme: dark;
|
|
198
|
+
}
|
|
199
|
+
.kh__controls[hidden] { display: none; }
|
|
200
|
+
.kh__controls button, .kh__controls select {
|
|
201
|
+
min-height: 2rem;
|
|
202
|
+
border: 1px solid #ffffff33;
|
|
203
|
+
border-radius: .55rem;
|
|
204
|
+
color: inherit;
|
|
205
|
+
background: #ffffff0d;
|
|
206
|
+
font: inherit;
|
|
207
|
+
font-size: .78rem;
|
|
208
|
+
}
|
|
209
|
+
.kh__controls button { padding: .38rem .65rem; cursor: pointer; }
|
|
210
|
+
.kh__controls button:hover { background: #ffffff1c; }
|
|
211
|
+
.kh__controls select { padding: .35rem 1.8rem .35rem .55rem; cursor: pointer; }
|
|
212
|
+
.kh__controls option { color: var(--paper); background: var(--ink); }
|
|
213
|
+
.kh__controls label { display: flex; align-items: center; min-width: 0; }
|
|
214
|
+
.kh__controls label:first-of-type { flex: 1 1 9rem; }
|
|
215
|
+
.kh__controls input[type="range"] {
|
|
216
|
+
flex: 1 1 auto;
|
|
217
|
+
width: 100%;
|
|
218
|
+
min-width: 0;
|
|
219
|
+
height: .45rem;
|
|
220
|
+
margin: 0;
|
|
221
|
+
border: 0;
|
|
222
|
+
border-radius: 999px;
|
|
223
|
+
appearance: none;
|
|
224
|
+
background: linear-gradient(to right, var(--accent) var(--progress, 0%), #ffffff33 0);
|
|
225
|
+
cursor: pointer;
|
|
226
|
+
}
|
|
227
|
+
.kh__controls input[type="range"]::-webkit-slider-runnable-track { height: .45rem; background: transparent; }
|
|
228
|
+
.kh__controls input[type="range"]::-webkit-slider-thumb {
|
|
229
|
+
width: 1rem;
|
|
230
|
+
height: 1rem;
|
|
231
|
+
margin-top: -.275rem;
|
|
232
|
+
border: 2px solid var(--paper);
|
|
233
|
+
border-radius: 50%;
|
|
234
|
+
appearance: none;
|
|
235
|
+
background: var(--accent);
|
|
236
|
+
box-shadow: 0 0 0 1px var(--ink);
|
|
237
|
+
}
|
|
238
|
+
.kh__controls input[type="range"]::-moz-range-track { height: .45rem; border: 0; background: transparent; }
|
|
239
|
+
.kh__controls input[type="range"]::-moz-range-thumb {
|
|
240
|
+
width: .85rem;
|
|
241
|
+
height: .85rem;
|
|
242
|
+
border: 2px solid var(--paper);
|
|
243
|
+
border-radius: 50%;
|
|
244
|
+
background: var(--accent);
|
|
245
|
+
box-shadow: 0 0 0 1px var(--ink);
|
|
246
|
+
}
|
|
247
|
+
.kh__controls output { min-width: 4.8rem; font-size: .78rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
248
|
+
.kh__controls :focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
|
|
249
|
+
.kh__sr-only {
|
|
250
|
+
position: absolute !important;
|
|
251
|
+
width: 1px !important;
|
|
252
|
+
height: 1px !important;
|
|
253
|
+
padding: 0 !important;
|
|
254
|
+
margin: -1px !important;
|
|
255
|
+
overflow: hidden !important;
|
|
256
|
+
clip: rect(0, 0, 0, 0) !important;
|
|
257
|
+
white-space: nowrap !important;
|
|
258
|
+
border: 0 !important;
|
|
259
|
+
}
|
|
260
|
+
.kh.is-reduced .kh__overview { display: grid; }
|
|
261
|
+
.kh.is-reduced .kh__scene { display: none; }
|
|
262
|
+
.kh.is-reduced .kh__controls { display: none !important; }
|
|
263
|
+
.kh.is-reduced .kh__scene *, .kh.is-reduced .kh__clock { animation: none !important; }
|
|
264
|
+
@media (max-width: 640px) {
|
|
265
|
+
.kh__stage { aspect-ratio: auto; min-height: min(34rem, calc(100svh - 9rem)); border-radius: 1rem; }
|
|
266
|
+
.kh__content { width: 84cqw; }
|
|
267
|
+
.kh__headline { font-size: clamp(1.55rem, 8.3cqw, 4.4rem); }
|
|
268
|
+
.kh__controls { gap: .5rem; padding: .5rem; }
|
|
269
|
+
.kh__controls output { font-size: .72rem; }
|
|
270
|
+
}
|
|
271
|
+
@media (prefers-reduced-motion: reduce) {
|
|
272
|
+
.kh__overview { display: grid !important; }
|
|
273
|
+
.kh__scene { display: none !important; }
|
|
274
|
+
.kh__controls { display: none !important; }
|
|
275
|
+
.kh__scene *, .kh__clock { animation: none !important; }
|
|
276
|
+
}
|