diff --git a/src/meshcore_hub/web/templates/base.html b/src/meshcore_hub/web/templates/base.html
index b508ac9..8cf325c 100644
--- a/src/meshcore_hub/web/templates/base.html
+++ b/src/meshcore_hub/web/templates/base.html
@@ -27,6 +27,9 @@
+
+
+
@@ -84,6 +87,69 @@
.prose th { background: oklch(var(--b2)); font-weight: 600; }
.prose hr { border: none; border-top: 1px solid oklch(var(--bc) / 0.2); margin: 2rem 0; }
.prose img { max-width: 100%; height: auto; border-radius: 0.5rem; margin: 1rem 0; }
+
+ /* View Transitions API - Cross-document page transitions */
+ .navbar { view-transition-name: navbar; }
+ main { view-transition-name: main-content; }
+ footer { view-transition-name: footer; }
+
+ /* Subtle slide + fade for main content */
+ ::view-transition-old(main-content) {
+ animation: vt-fade-out 200ms ease-out forwards;
+ }
+ ::view-transition-new(main-content) {
+ animation: vt-slide-up 250ms ease-out forwards;
+ }
+
+ /* Keep navbar and footer stable */
+ ::view-transition-old(navbar),
+ ::view-transition-new(navbar),
+ ::view-transition-old(footer),
+ ::view-transition-new(footer) {
+ animation: none;
+ }
+
+ /* Subtle crossfade for background */
+ ::view-transition-old(root),
+ ::view-transition-new(root) {
+ animation-duration: 150ms;
+ }
+
+ @keyframes vt-fade-out {
+ from { opacity: 1; }
+ to { opacity: 0; }
+ }
+ @keyframes vt-slide-up {
+ from { opacity: 0; transform: translateY(10px); }
+ to { opacity: 1; transform: translateY(0); }
+ }
+
+ /* Card entrance animations */
+ .card {
+ animation: card-fade-in 300ms ease-out backwards;
+ }
+ .card:nth-child(1) { animation-delay: 0ms; }
+ .card:nth-child(2) { animation-delay: 50ms; }
+ .card:nth-child(3) { animation-delay: 100ms; }
+ .card:nth-child(4) { animation-delay: 150ms; }
+ .card:nth-child(5) { animation-delay: 200ms; }
+ .card:nth-child(6) { animation-delay: 250ms; }
+
+ @keyframes card-fade-in {
+ from { opacity: 0; transform: translateY(8px); }
+ to { opacity: 1; transform: translateY(0); }
+ }
+
+ /* Respect reduced motion preferences */
+ @media (prefers-reduced-motion: reduce) {
+ .card,
+ ::view-transition-old(main-content),
+ ::view-transition-new(main-content),
+ ::view-transition-old(root),
+ ::view-transition-new(root) {
+ animation: none !important;
+ }
+ }
{% block extra_head %}{% endblock %}