From e493ca58d38fadaa8de4b254861bed1d1c28037c Mon Sep 17 00:00:00 2001
From: Fuwn <contact@fuwn.net>
Date: Tue, 19 May 2026 01:07:25 +0000
Subject: feat(nav): restore scroll-hide and animate mobile hamburger

Three changes to the mobile floating header:

- Restore the desktop scroll-driven hide/show on the corner button by
  dropping the transform:none override. Override the translate distance
  under 800px so the toggle (44px tall at top:1.25rem) and its 5px
  outline ring fully clear the viewport: translateY(calc(-100% - 2rem))
  instead of -150%, which had been leaving 3px of ring poking through.

- Replace display:none / display:flex on the open panel (uneanimatable)
  with always-rendered panel that flips opacity, transform, visibility,
  and pointer-events. Uses --duration-fast / --ease-out-quart so the
  motion vocabulary matches the rest of the project. transform-origin
  is top right so the scale grows from the toggle position.

- Move per-item styling out of the .menu-open qualifier so items keep
  their block layout even while the panel is faded out, avoiding a
  layout reflow at the moment menu-open flips.
---
 src/routes/+layout.svelte | 32 ++++++++++++++++++++++++--------
 1 file changed, 24 insertions(+), 8 deletions(-)

(limited to 'src/routes/+layout.svelte')

diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 04c155eb..75b755c0 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -474,7 +474,7 @@ $: {
     }
 
     .header.header-hidden {
-      transform: none;
+      transform: translateY(calc(-100% - 2rem));
     }
 
     .menu-toggle {
@@ -526,10 +526,6 @@ $: {
     }
 
     .nav-items {
-      display: none;
-    }
-
-    .header.menu-open .nav-items {
       display: flex;
       flex-direction: column;
       align-items: stretch;
@@ -545,16 +541,36 @@ $: {
         0 0 0 5px var(--base02);
       backdrop-filter: blur(4px);
       -webkit-backdrop-filter: blur(4px);
+      transform-origin: top right;
+      opacity: 0;
+      visibility: hidden;
+      transform: translateY(-8px) scale(0.96);
+      pointer-events: none;
+      transition:
+        opacity var(--duration-fast) var(--ease-out-quart),
+        transform var(--duration-fast) var(--ease-out-quart),
+        visibility 0s linear var(--duration-fast);
+    }
+
+    .header.menu-open .nav-items {
+      opacity: 1;
+      visibility: visible;
+      transform: translateY(0) scale(1);
+      pointer-events: auto;
+      transition:
+        opacity var(--duration-fast) var(--ease-out-quart),
+        transform var(--duration-fast) var(--ease-out-quart),
+        visibility 0s linear 0s;
     }
 
-    .header.menu-open .nav-items :global(.header-item) {
+    .nav-items :global(.header-item) {
       display: block;
       margin: 0;
       padding: 0.6rem 0.75rem;
     }
 
-    .header.menu-open .nav-items :global(.separator),
-    .header.menu-open .nav-items :global(.header-item:has(.avatar)) {
+    .nav-items :global(.separator),
+    .nav-items :global(.header-item:has(.avatar)) {
       display: none;
     }
   }
-- 
cgit v1.2.3

