chore: scaffold Astro 5 project with token/style layer

- Astro 5 static config (trailing-slash canonical, i18n en-root/no-prefixed)
- Tailwind 4 over CSS custom-property tokens (both themes via [data-theme])
- design tokens: colour/spacing/type/radius/motion per Phase 1 specs
- motion layer with reduced-motion overrides
- strict TypeScript, ESLint flat config, Prettier
- self-hosted variable fonts (Space Grotesk / Inter / JetBrains Mono)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
cesnimda
2026-07-04 00:51:15 +02:00
parent 1f695d3932
commit ff27b918ae
12 changed files with 6712 additions and 0 deletions
+131
View File
@@ -0,0 +1,131 @@
/*
Motion layer (ANIMATION_SPEC). Only transform / opacity / stroke-dashoffset animate.
Reduced-motion is a single global override — not per-component JS (ANIMATION_SPEC §1).
*/
/* ---- Reveal (A2): opacity + 12px rise, staggered by --reveal-index ---- */
[data-reveal] {
opacity: 0;
transform: translateY(12px);
transition:
opacity var(--dur-entrance) var(--ease-out),
transform var(--dur-entrance) var(--ease-out);
transition-delay: calc(var(--reveal-index, 0) * 60ms);
}
[data-reveal].is-revealed {
opacity: 1;
transform: none;
}
/* ---- Trace draw (A1) ---- */
@keyframes trace-draw {
from {
stroke-dashoffset: var(--trace-len, 600);
}
to {
stroke-dashoffset: 0;
}
}
@keyframes dot-blink {
0%,
100% {
opacity: 1;
}
40% {
opacity: 0.2;
}
}
.trace-line {
stroke-dasharray: var(--trace-len, 600);
stroke-dashoffset: var(--trace-len, 600);
animation: trace-draw var(--dur-signature) var(--ease-in-out) forwards;
}
[data-seen] .trace-line {
animation: none;
stroke-dashoffset: 0;
}
.trace-dot {
animation: dot-blink 900ms var(--ease-out) 700ms 1;
}
/* ---- Status chip pulse (A4): 2 iterations, ~1Hz ---- */
@keyframes chip-pulse {
0% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(1.4);
opacity: 0.55;
}
100% {
transform: scale(1);
opacity: 1;
}
}
.is-revealed .status-dot--active {
animation: chip-pulse 900ms var(--ease-out) 2;
}
/* ---- Timeline spine grow (A8) ---- */
.timeline-spine {
transform: scaleY(0);
transform-origin: top;
transition: transform var(--dur-entrance) var(--ease-out);
}
.is-revealed .timeline-spine {
transform: scaleY(1);
}
/* ---- 404 fray (A10) ---- */
@keyframes fray {
from {
stroke-dashoffset: 0;
}
to {
stroke-dashoffset: 8;
}
}
/* ---- Check-draw for form success (A9) ---- */
@keyframes check-draw {
to {
stroke-dashoffset: 0;
}
}
.check-path {
stroke-dasharray: 24;
stroke-dashoffset: 24;
animation: check-draw var(--dur-standard) var(--ease-out) forwards;
}
/* ---- View-transition language/route cross-fade (A6/A7) ---- */
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: var(--dur-quick);
}
/* ============================================================
Reduced motion: durations collapse, translations disabled,
animated states render at their final frame (no content lost).
============================================================ */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 1ms !important;
animation-iteration-count: 1 !important;
transition-duration: 1ms !important;
scroll-behavior: auto !important;
}
[data-reveal] {
opacity: 1;
transform: none;
}
.trace-line {
stroke-dashoffset: 0;
}
.timeline-spine {
transform: scaleY(1);
}
}