-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathheader-hands-preview.html
More file actions
192 lines (177 loc) · 12.6 KB
/
Copy pathheader-hands-preview.html
File metadata and controls
192 lines (177 loc) · 12.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Header-hands preview — Let's Encode!</title>
<style>
:root{
--orange:#ffa76d; --blue:#6dc3ff; --green:#76de76;
--ink:#1f2433; --ink-soft:#4a5167; --line:#e6e8f0;
--bg:#fff; --bg-alt:#f7f8fb; --accent:#2563c9; --maxw:1080px;
--font:"Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
/* ONE consistent vertical gap on every header, regardless of where its
hand sits (above / below / beside). Minimised to just clear the reach. */
--gap-v:1.25em;
}
*{box-sizing:border-box}
body{margin:0;font-family:var(--font);color:var(--ink);background:var(--bg);line-height:1.6}
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 1.25rem}
section{padding:clamp(2.2rem,4.5vw,3.2rem) 0}
section.alt{background:var(--bg-alt);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.section-head{max-width:60ch}
.section-head.center{margin-left:auto;margin-right:auto;text-align:center}
.section-head .kicker{text-transform:uppercase;letter-spacing:.08em;font-size:.78rem;font-weight:700;color:var(--accent);margin:0 0 .5rem}
h2{font-size:clamp(1.5rem,3vw,2rem);line-height:1.2; margin:var(--gap-v) 0;}
.note{padding:1.1rem 1.25rem;background:#fffbe9;border-bottom:1px solid var(--line);font-size:.9rem;color:#664d03}
.note code{background:#fff5cf;padding:.05rem .35rem;border-radius:4px}
.body{color:var(--ink-soft); max-width:64ch; margin:0}
/* ===================== letter-level hand mechanic =====================
Two-layer hand: .hand is the POSITIONING WRAPPER (holds the resting
placement — size/tilt/position you dial in); .hpic is the IMAGE, which
runs the animation about its OWN pivot (--ox/--oy) so the spin centre is
independent of where the hand rests. No glyph is ever occluded. */
.gx{position:relative; display:inline-block}
.gly{display:inline-block; transition:transform .25s ease}
.hand{position:absolute; z-index:2; pointer-events:none;}
.hpic{display:block; width:auto; height:var(--s,1.4em);
transform-origin:var(--ox,50%) var(--oy,100%); transition:transform .25s ease;}
/* resting placement (on the wrapper) */
.gx.above .hand{ left:calc(var(--hx,50%) + var(--dx,0em)); bottom:calc(100% - var(--dip,.16em));
transform:translateX(-50%) rotate(var(--r,0deg)); transform-origin:50% 100%; }
.gx.below .hand{ left:calc(var(--hx,50%) + var(--dx,0em)); top:calc(100% - var(--dip,.12em));
transform:translateX(-50%) rotate(var(--r,0deg)) scaleX(var(--flip,1)); transform-origin:50% 0%; }
.gx.side .hand{ right:calc(100% - var(--ovl,.06em)); bottom:var(--hb,-.12em);
transform:rotate(var(--r,0deg)); transform-origin:100% 60%; }
/* .r = mirror a side hand to the RIGHT of its glyph (after the word) */
.gx.side.r .hand{ left:calc(100% - var(--ovl,.06em)); right:auto; transform-origin:0% 60%; }
/* under = centred beneath the header text (wrap the whole heading as the glyph).
Absolutely positioned, so it sits in the existing gap without enlarging it. */
.gx.under .hand{ left:calc(50% + var(--dx,0em)); top:calc(100% - var(--dip,.3em)); height:var(--s,1.3em);
transform:translateX(-50%) rotate(var(--r,0deg)); transform-origin:50% 0%; }
.gx.above .gly{transform-origin:50% 92%}
.gx.below .gly{transform-origin:50% 8%}
/* hover holds the pose peak (image animates about --ox/--oy; rest stays put) */
.gx.twiddle:hover .hpic{transform:rotate(calc(var(--spin,1) * -7deg))}
.gx.twiddle:hover .gly{transform:rotate(-7deg)}
.gx.lift:hover .hpic{transform:translateY(-.06em)}
.gx.lift:hover .gly{transform:translateY(-.12em)}
.gx.point:hover .hpic{transform:translateX(.12em)}
.gx.shake:hover .hpic{transform:rotate(-3deg)}
.gx.wag:hover .hpic{transform:rotate(-10deg)}
/* one-shot auto-replay (JS toggles .go ~6–10s, staggered). The image
transforms are ADDITIVE to the wrapper's resting transform — no snap. */
@keyframes glyTwiddle{0%,100%{transform:rotate(0)}35%{transform:rotate(-7deg)}70%{transform:rotate(4deg)}}
@keyframes hpicTwiddle{0%,100%{transform:rotate(0)}35%{transform:rotate(calc(var(--spin,1) * -7deg))}70%{transform:rotate(calc(var(--spin,1) * 5deg))}}
@keyframes glyLift{0%,100%{transform:translateY(0)}45%{transform:translateY(-.12em)}}
@keyframes hpicBob{0%,100%{transform:translateY(0)}45%{transform:translateY(-.06em)}}
@keyframes hpicPoke{0%,100%{transform:translateX(0)}40%{transform:translateX(.12em)}70%{transform:translateX(-.02em)}}
@keyframes hpicShake{0%,100%{transform:rotate(0)}22%{transform:rotate(-3deg)}50%{transform:rotate(2deg)}78%{transform:rotate(-1deg)}}
@keyframes hpicWag{0%,100%{transform:rotate(0)}28%{transform:rotate(-10deg)}58%{transform:rotate(6deg)}}
.gx.twiddle.go .gly{animation:glyTwiddle .60s ease-in-out}
.gx.twiddle.go .hpic{animation:hpicTwiddle .60s ease-in-out}
.gx.lift.go .gly{animation:glyLift .55s cubic-bezier(.34,1.5,.64,1)}
.gx.lift.go .hpic{animation:hpicBob .55s cubic-bezier(.34,1.5,.64,1)}
.gx.point.go .hpic{animation:hpicPoke .60s ease-in-out}
.gx.shake.go .hpic{animation:hpicShake .65s ease-in-out}
.gx.wag.go .hpic{animation:hpicWag .60s ease-in-out}
/* nudge: hand rotates (--hr, default CCW) to push the letter sideways; the
letter rotates in response (--gr, default CW). Both tunable per header. */
@keyframes hpicNudge{0%,100%{transform:rotate(0)}45%{transform:rotate(var(--hr,-8deg))}}
@keyframes glyNudge{0%,100%{transform:rotate(0)}45%{transform:rotate(var(--gr,6deg))}}
.gx.nudge.go .hpic{animation:hpicNudge .55s cubic-bezier(.34,1.5,.64,1)}
.gx.nudge.go .gly{animation:glyNudge .55s cubic-bezier(.34,1.5,.64,1)}
.gx.nudge:hover .hpic{transform:rotate(var(--hr,-8deg))}
.gx.nudge:hover .gly{transform:rotate(var(--gr,6deg))}
/* wave: friendly side-to-side rock about the wrist (--ox/--oy) */
@keyframes hpicWave{0%,100%{transform:rotate(0)}18%{transform:rotate(-10deg)}42%{transform:rotate(8deg)}66%{transform:rotate(-6deg)}86%{transform:rotate(4deg)}}
.gx.wave.go .hpic{animation:hpicWave .9s ease-in-out}
.gx.wave:hover .hpic{transform:rotate(-10deg)}
/* hold: the hand grips a glyph and lifts/lowers it — both move together by
--lift, returning to the resting baseline */
@keyframes glyHold{0%,100%{transform:translateY(0)}50%{transform:translateY(calc(-1 * var(--lift,.16em)))}}
/* lift on the WRAPPER (outermost) = pure screen-Y, even when the hand is rotated */
@keyframes handHold{0%,100%{transform:rotate(var(--r,0deg))}50%{transform:translateY(calc(-1 * var(--lift,.16em))) rotate(var(--r,0deg))}}
.gx.hold.go .gly{animation:glyHold .75s ease-in-out}
.gx.hold.go .hand{animation:handHold .75s ease-in-out}
.gx.hold:hover .gly{transform:translateY(calc(-1 * var(--lift,.16em)))}
.gx.hold:hover .hand{transform:translateY(calc(-1 * var(--lift,.16em))) rotate(var(--r,0deg))}
@media (prefers-reduced-motion:reduce){
.gly,.hpic{transition:none}
.go .gly,.go .hpic{animation:none !important}
}
</style>
</head>
<body>
<!-- 1 · About — blue finger pokes the M (gutter, side) -->
<section>
<div class="wrap"><div class="section-head">
<p class="kicker">About the project</p>
<h2>Making music readable by machine<span class="gx side r hold" style="--s:1.5em;--r:28deg;--hb:-.4em;--ovl:.5em;--lift:.16em"><span class="gly">s</span><span class="hand"><img class="hpic" src="assets/hands/measure-blue.svg" alt="" aria-hidden="true"></span></span></h2>
<p class="body">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div></div>
</section>
<!-- 2 · Goals — orange pinch grips the ascender 'l' top & twiddles it (above).
--ox/--oy place the twiddle pivot toward the fingertip so it tracks the l. -->
<section class="alt">
<div class="wrap"><div class="section-head">
<p class="kicker">What we're working towards</p>
<h2>Project goa<span class="gx above twiddle" style="--s:1.2em;--hx:0%;--dx:.58em;--r:-15deg;--dip:.5em;--ox:50%;--oy:32%;--spin:-1"><span class="gly">l</span><span class="hand"><img class="hpic" src="assets/hands/pinch-orange.svg" alt="" aria-hidden="true"></span></span>s</h2>
<p class="body">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div></div>
</section>
<!-- 3 · Get involved — green thumb lifts the descender 'j' of join (below, centered) -->
<section>
<div class="wrap"><div class="section-head center">
<p class="kicker">Coming soon</p>
<h2>Start or join a cam<span class="gx below nudge" style="--s:1.4em;--hx:60%;--dip:.20em;--ox:50%;--oy:100%;--hr:-8deg;--gr:6deg"><span class="gly">p</span><span class="hand"><img class="hpic" src="assets/hands/thumb-green.svg" alt="" aria-hidden="true"></span></span>aign</h2>
<p class="body">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div></div>
</section>
<!-- 4 · Team — two-tone handshake jostles the T (gutter, side) -->
<section class="alt">
<div class="wrap"><div class="section-head">
<p class="kicker">Who we are</p>
<h2>Tea<span class="gx side r wave" style="--s:1.4em;--r:5deg;--hb:0em;--ovl:-.06em;--ox:110%;--oy:90%"><span class="gly">m</span><span class="hand"><img class="hpic" src="assets/hands/wave-pink.svg" alt="" aria-hidden="true"></span></span></h2>
<p class="body">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div></div>
</section>
<!-- 5 · Advisory — pink raised finger wags by the A (gutter, side) -->
<section>
<div class="wrap"><div class="section-head">
<p class="kicker">Guidance & community voices</p>
<h2><span class="gx under shake" style="--s:1.3em;--r:-2deg;--dip:0em;--ox:150%;--oy:50%"><span class="gly">Advisory board</span><span class="hand"><img class="hpic" src="assets/hands/handshake.svg" alt="" aria-hidden="true"></span></span></h2>
<p class="body">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div></div>
</section>
<!-- 6 · Funding — gold offering palm lifts the whole 'Sup' group (below) -->
<section class="alt">
<div class="wrap"><div class="section-head">
<p class="kicker">Funding & acknowledgements</p>
<h2>Supported by the Austrian Science <span class="gx below lift" style="--s:.95em;--hx:50%;--dx:-.06em;--dip:.35em;--r:10deg"><span class="gly">Fun</span><span class="hand"><img class="hpic" src="assets/hands/palm-gold.svg" alt="" aria-hidden="true"></span></span>d</h2>
<p class="body">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div></div>
</section>
<script>
(function () {
if (matchMedia("(prefers-reduced-motion: reduce)").matches) return;
document.querySelectorAll(".gx").forEach(function (el, idx) {
var timer = null;
function play(){ el.classList.remove("go"); void el.offsetWidth; el.classList.add("go"); }
function schedule(){ timer = setTimeout(function(){ play(); schedule(); }, 6000 + Math.random()*4000); }
el._play = play;
el._pause = function(){ if (timer) clearTimeout(timer); };
el._resume = schedule;
setTimeout(function(){ play(); schedule(); }, 800 + idx*850);
});
// Hover ANYWHERE on a heading reliably replays its hand and suspends that
// hand's auto-timer so the two never collide; leaving resumes the loop.
document.querySelectorAll("h2").forEach(function (h2) {
var gx = h2.querySelector(".gx"); if (!gx) return;
h2.addEventListener("mouseenter", function(){ gx._pause(); gx._play(); });
h2.addEventListener("mouseleave", function(){ gx._pause(); gx._resume(); });
});
})();
</script>
</body>
</html>