11---
2- import { hero , motto } from ' ../data/site' ;
3- import GitHubMark from ' ./GitHubMark .astro' ;
2+ import { hero , motto , miniGame } from ' ../data/site' ;
3+ import Logo from ' ./Logo .astro' ;
44
55// Precompute the headline as a trusted HTML string. Keep the H1 visible at
66// first paint: this text is the LCP candidate, so it must not wait for JS reveal.
@@ -64,11 +64,18 @@ const mottoHalf = Array.from({ length: 4 })
6464 <ul class =" hero__badges" role =" list" data-reveal style =" --reveal-delay:720ms" >
6565 { hero .badges .map ((badge ) => <li class = " chip chip--dot" >{ badge } </li >)}
6666 </ul >
67+
68+ <button class =" hero__play" type =" button" data-game-launch data-reveal style =" --reveal-delay:820ms" >
69+ <span class =" hero__play-glyph" aria-hidden =" true" >▶</span >
70+ <span class =" hero__play-text font-pixel" >{ miniGame .launchCta } </span >
71+ <span class =" hero__play-tag font-mono" aria-hidden =" true" >{ miniGame .footerLabel } · 60s</span >
72+ <span class =" visually-hidden" > — { miniGame .footerLabel } , { miniGame .launchHint } </span >
73+ </button >
6774 </div >
6875
6976 <aside class =" hero__crest" data-reveal style =" --reveal-delay:320ms" >
7077 <div class =" crest" >
71- <GitHubMark size ={ 160 } class =" crest__github-mark " />
78+ <Logo size ={ 160 } decorative class =" crest__mark " />
7279 </div >
7380 <pre
7481 class =" crest__status terminal__body font-mono"
@@ -212,6 +219,51 @@ const mottoHalf = Array.from({ length: 4 })
212219 gap: 0.5rem;
213220 margin-top: var(--space-m);
214221 }
222+
223+ /* Arcade launcher — surfaces the signature mini-game in the first viewport
224+ without competing with the primary CTAs. "Insert coin" energy. */
225+ .hero__play {
226+ margin-top: var(--space-m);
227+ display: inline-flex;
228+ align-items: center;
229+ gap: 0.7em;
230+ padding: 0.55em 0.9em;
231+ background: transparent;
232+ color: var(--fg);
233+ border: var(--border-px) solid var(--hairline-strong);
234+ box-shadow: var(--shadow-px-sm);
235+ cursor: pointer;
236+ transition:
237+ transform 0.12s var(--ease-out),
238+ box-shadow 0.12s var(--ease-out),
239+ border-color 0.2s;
240+ }
241+ .hero__play:hover,
242+ .hero__play:focus-visible {
243+ transform: translate(-2px, -2px);
244+ box-shadow: 5px 5px 0 var(--fg);
245+ border-color: var(--fg);
246+ }
247+ .hero__play-glyph {
248+ color: var(--accent);
249+ font-size: 0.8em;
250+ animation: blink 1.1s steps(2, start) infinite;
251+ }
252+ .hero__play-text {
253+ font-size: clamp(0.5rem, 0.42rem + 0.35vw, 0.6rem);
254+ color: var(--fg);
255+ }
256+ .hero__play-tag {
257+ font-size: var(--step--2);
258+ color: var(--fg-faint);
259+ padding-left: 0.7em;
260+ border-left: 1.5px solid var(--hairline-strong);
261+ }
262+ @media (prefers-reduced-motion: reduce) {
263+ .hero__play-glyph {
264+ animation: none;
265+ }
266+ }
215267 .chip--dot::before {
216268 content: '';
217269 width: 7px;
@@ -220,8 +272,9 @@ const mottoHalf = Array.from({ length: 4 })
220272 flex: none;
221273 }
222274
223- /* ── The hero emblem — the GitHub octocat mark on a soft gold halo, with a
224- slim 3-line mono "mission status" caption below it. */
275+ /* ── The hero emblem — the ManagedCode `< >` brand mark on a soft gold halo,
276+ with a slim 3-line mono "mission status" caption below it. Using our own
277+ mark (not GitHub's) keeps the most-judged frame authored and on-brand. */
225278 .hero__crest {
226279 --reveal-y: 0px;
227280 align-self: center;
@@ -237,20 +290,29 @@ const mottoHalf = Array.from({ length: 4 })
237290 max-width: clamp(13rem, 21vw, 18rem);
238291 margin-inline: auto;
239292 }
240- :global(.crest__github-mark ) {
293+ :global(.crest__mark ) {
241294 position: absolute;
242295 top: 50%;
243296 left: 50%;
244297 z-index: 2;
245- width: 54 %;
298+ width: 70 %;
246299 height: auto;
247300 color: var(--fg);
248301 transform: translate(-50%, -50%);
249302 pointer-events: none;
250303 filter: drop-shadow(0 6px 16px color-mix(in srgb, var(--gold) 30%, transparent));
304+ /* smooths the desktop cursor-magnet parallax (app.ts initMagnetic) */
305+ transition: transform 0.3s var(--ease-out);
306+ will-change: transform;
307+ }
308+ @media (prefers-reduced-motion: reduce) {
309+ :global(.crest__mark) {
310+ transition: none;
311+ }
251312 }
252- /* a faint patron-gold halo BEHIND the canvas — a separate layer, so it never
253- blurs the pixel emblem itself */
313+ /* a faint patron-gold halo BEHIND the mark — a separate layer, so it never
314+ blurs the emblem itself. It breathes slowly (composited scale/opacity only):
315+ "the lights are on" — the one subtle, on-brand kinetic beat on the hero. */
254316 .crest::before {
255317 content: '';
256318 position: absolute;
@@ -262,6 +324,24 @@ const mottoHalf = Array.from({ length: 4 })
262324 transparent 68%
263325 );
264326 pointer-events: none;
327+ will-change: transform, opacity;
328+ animation: crest-breathe 5s ease-in-out infinite;
329+ }
330+ @keyframes crest-breathe {
331+ 0%,
332+ 100% {
333+ transform: scale(0.94);
334+ opacity: 0.7;
335+ }
336+ 50% {
337+ transform: scale(1.06);
338+ opacity: 1;
339+ }
340+ }
341+ @media (prefers-reduced-motion: reduce) {
342+ .crest::before {
343+ animation: none;
344+ }
265345 }
266346 :global(:root[data-theme='dark']) .crest::before {
267347 background: radial-gradient(
@@ -356,8 +436,8 @@ const mottoHalf = Array.from({ length: 4 })
356436 max-width: none;
357437 margin-inline: 0;
358438 }
359- :global(.crest__github-mark ) {
360- width: 66 %;
439+ :global(.crest__mark ) {
440+ width: 78 %;
361441 }
362442 .crest__status {
363443 flex: 1 1 auto;
0 commit comments