diff --git a/shared/base.css b/shared/base.css index 9a8bb2a..1e39065 100644 --- a/shared/base.css +++ b/shared/base.css @@ -332,6 +332,40 @@ a:hover { display: block; } +/* Page-load reveal. The header is the first thing a user sees — a + short staggered fade-in over ~360ms turns "instant pop-in" into a + subtle "the tool is composing itself for you" beat. Pure CSS, no + JS; respects prefers-reduced-motion. The stagger order (logo → + title → action buttons → right-side icons) mirrors the reading + order of the chrome itself. */ +@keyframes zddc-header-rise { + from { opacity: 0; transform: translateY(-4px); } + to { opacity: 1; transform: translateY(0); } +} + +.app-header__logo, +.header-title-group, +.header-left > .btn, +.header-right > * { + animation: zddc-header-rise 360ms cubic-bezier(0.2, 0.7, 0.2, 1) both; +} + +.app-header__logo { animation-delay: 0ms; } +.header-title-group { animation-delay: 60ms; } +.header-left > .btn { animation-delay: 120ms; } +.header-right > *:nth-child(1) { animation-delay: 180ms; } +.header-right > *:nth-child(2) { animation-delay: 220ms; } +.header-right > *:nth-child(3) { animation-delay: 260ms; } + +@media (prefers-reduced-motion: reduce) { + .app-header__logo, + .header-title-group, + .header-left > .btn, + .header-right > * { + animation: none; + } +} + /* ── Build timestamp ──────────────────────────────────────────────────────── */ .build-timestamp { font-size: 0.55rem; diff --git a/zddc/internal/handler/tables.html b/zddc/internal/handler/tables.html index 91f3d7a..3758357 100644 --- a/zddc/internal/handler/tables.html +++ b/zddc/internal/handler/tables.html @@ -371,6 +371,40 @@ a:hover { display: block; } +/* Page-load reveal. The header is the first thing a user sees — a + short staggered fade-in over ~360ms turns "instant pop-in" into a + subtle "the tool is composing itself for you" beat. Pure CSS, no + JS; respects prefers-reduced-motion. The stagger order (logo → + title → action buttons → right-side icons) mirrors the reading + order of the chrome itself. */ +@keyframes zddc-header-rise { + from { opacity: 0; transform: translateY(-4px); } + to { opacity: 1; transform: translateY(0); } +} + +.app-header__logo, +.header-title-group, +.header-left > .btn, +.header-right > * { + animation: zddc-header-rise 360ms cubic-bezier(0.2, 0.7, 0.2, 1) both; +} + +.app-header__logo { animation-delay: 0ms; } +.header-title-group { animation-delay: 60ms; } +.header-left > .btn { animation-delay: 120ms; } +.header-right > *:nth-child(1) { animation-delay: 180ms; } +.header-right > *:nth-child(2) { animation-delay: 220ms; } +.header-right > *:nth-child(3) { animation-delay: 260ms; } + +@media (prefers-reduced-motion: reduce) { + .app-header__logo, + .header-title-group, + .header-left > .btn, + .header-right > * { + animation: none; + } +} + /* ── Build timestamp ──────────────────────────────────────────────────────── */ .build-timestamp { font-size: 0.55rem; @@ -1207,7 +1241,7 @@ body.help-open .app-header {