- Folder
- src/components/Intro/
- Props
- profile: the Profile from src/content/profile.ts; name, role, tagline and both button labels come from it
- cvHref: the CV file's URL; omitted, the Full résumé button is not rendered
- Tokens
- Column: sticky at the top, full viewport height (dvh), 96 px block padding; top block and social links pushed apart
- Short viewport: the column scrolls on its own, so the nav list and social links stay reachable by wheel and Tab; 4 px inline padding inside a -4 px margin keeps the focus ring unclipped
- Mark row: LogoLink 44 px and ThemeToggle at either end; the mark is 36 px on phones
- Name: text-display Text, 24 px below the mark; role: text-tagline Text, 12 px below; location: profile.location in a muted Label, 8 px below the role; tagline: text-body Text 2, 16 px below, capped at the lede width; name, role and tagline wrap anywhere
- Buttons: primary Get in touch to #contact and ghost Full résumé, 32 px below, 12 px gap, wrapping
- Desktop: nav list 28 px below the buttons; social links at the bottom of the column
- Phone: static, auto height, 48 px block padding; no nav list; the social links sit 24 px below the buttons, the header's gap
- Motion
- Enter: the six top rows fade in and rise 8 px over 300 ms with the out curve, once on load, 50 ms apart from 50 to 300 ms; the location shares the role's row at 150 ms; on phone the social links take the hidden nav list's 300 ms slot, on desktop they do not animate
- Reduced motion: no enter animation; every row is visible at once
- Accessibility
- A header holding the page's only h1, the name
- The mark is a link named Home; the nav is named In this page; the location is text, so Tab skips it
- Social links: one list on every layout, so Tab reaches GitHub, LinkedIn and Email once, after the buttons on phone and after the nav on desktop
- The CV button is left out, not disabled, when there is no file