"use client"; import React, { useEffect, useRef, useState } from "react"; import Footer from "./components/Footer"; import "./assets/main.css"; import "./globals.css"; import NavLink from "./components/NavLink"; import { manrope, newsreader } from "./fonts"; export default function RootLayout({ children }: { children: React.ReactNode }) { const [isMenuOpen, setIsMenuOpen] = useState(false); const menuRef = useRef(null); const burgerRef = useRef(null); const closeTimerRef = useRef | null>(null); const AUTO_CLOSE_MS = 4000; const clearAutoClose = () => { if (closeTimerRef.current) { clearTimeout(closeTimerRef.current); closeTimerRef.current = null; } }; const scheduleAutoClose = () => { clearAutoClose(); closeTimerRef.current = setTimeout(() => setIsMenuOpen(false), AUTO_CLOSE_MS); }; const closeMenu = () => setIsMenuOpen(false); const toggleMenu = () => setIsMenuOpen((v) => !v); useEffect(() => { if (!isMenuOpen) { clearAutoClose(); return; } scheduleAutoClose(); const handleKey = (e: KeyboardEvent) => { if (e.key === "Escape") setIsMenuOpen(false); }; const handleResize = () => { if (window.innerWidth >= 768) setIsMenuOpen(false); }; window.addEventListener("keydown", handleKey); window.addEventListener("resize", handleResize); return () => { clearAutoClose(); window.removeEventListener("keydown", handleKey); window.removeEventListener("resize", handleResize); }; }, [isMenuOpen]); useEffect(() => { if (!isMenuOpen && burgerRef.current) { burgerRef.current.focus({ preventScroll: true }); } }, [isMenuOpen]); // Classes communes pour les liens du drawer mobile : fond container primaire, // radius "tile", hover qui inverse vers fond clair + texte primaire (palette Stitch). const drawerLinkClass = "block px-4 py-2 rounded-tile bg-primary-container/60 text-white transition-colors duration-200 hover:bg-primary-fixed hover:text-primary"; const drawerLinkActive = "bg-primary-fixed text-primary"; // NavLink desktop : état actif souligné, inactif discret (palette Stitch). const desktopLinkActive = "text-primary border-b-2 border-primary-fixed pb-0.5"; const desktopLinkInactive = "text-on-surface-variant hover:text-primary transition-colors"; return ( {/* Material Symbols : chargés via plutôt que via @import CSS qui est strippé par la chaîne PostCSS + Tailwind de Next 15 (diagnostic 2026-04-22). Ressource critique côté UI → preload pour éviter un flash de texte brut sur les icônes des CTAs, du burger et des cartes de la home. */}
{/* Wallpaper plein écran (fondation, ne change pas avec la refonte). */}
{/* Cercles animés : repalette en ton indigo-ardoise (Stitch "Digital Atelier"). */}
{/* Header "No-Line" : pas de bordure pleine, juste un shift tonal + ombre ambient diffuse. */}

Portfolio Gras-Calvet Fernand

{/* Burger ghost (Material Symbols) : plus sobre, couleur primaire, hover tonal. */} {/* Menu desktop : NavLink avec états actif/inactif éditoriaux. */}
{/* Drawer mobile (tiroir gauche, 70 %, fond primaire translucide). */}
{children}
); }