diff --git a/app/globals.css b/app/globals.css index 6ae9ddb..2464ad0 100644 --- a/app/globals.css +++ b/app/globals.css @@ -117,4 +117,11 @@ footer { .max-w-7xl { max-width: 100%; } +} + +@media (prefers-reduced-motion: reduce) { + .mobile-drawer-root, + .mobile-drawer-panel { + transition: none !important; + } } \ No newline at end of file diff --git a/app/layout.tsx b/app/layout.tsx index d64a44c..2c1c266 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -10,20 +10,66 @@ import NavLink from "./components/NavLink"; export default function RootLayout({ children }: { children: React.ReactNode }) { const [visitCount, setVisitCount] = useState(0); const [isMenuOpen, setIsMenuOpen] = useState(false); - const menuRef = useRef(null); // Référence pour le menu burger + const menuRef = useRef(null); + const burgerRef = useRef(null); + const closeTimerRef = useRef | null>(null); - const toggleMenu = () => { - setIsMenuOpen(!isMenuOpen); + 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 openMenu = () => setIsMenuOpen(true); + const closeMenu = () => setIsMenuOpen(false); + const toggleMenu = () => setIsMenuOpen((v) => !v); + useEffect(() => { - // Récupère le compteur de visites depuis localStorage const visits = localStorage.getItem("visitCount"); const newVisitCount = visits ? parseInt(visits) + 1 : 1; localStorage.setItem("visitCount", newVisitCount.toString()); setVisitCount(newVisitCount); }, []); + 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]); + return ( @@ -48,8 +94,16 @@ export default function RootLayout({ children }: { children: React.ReactNode }) {/* Bouton menu burger */} - {/* Menu desktop */} @@ -64,25 +118,42 @@ export default function RootLayout({ children }: { children: React.ReactNode }) - {/* Menu mobile */} - {isMenuOpen && ( -
- -
- )} + {/* Colonne tiroir */} + + -
+
{children}
diff --git a/app/page.tsx b/app/page.tsx index b86f01a..cc39caa 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -78,7 +78,7 @@ export default function HomePage() { const imageUrl = homepage.photo?.url ? `${apiUrl}${homepage.photo.url}` : null; return ( -
+

{title}

{imageUrl ? ( diff --git a/docs-site-interne/captures/AUDIT-VISUEL.md b/docs-site-interne/captures/AUDIT-VISUEL.md index 8edd5c9..ebf7a9f 100644 --- a/docs-site-interne/captures/AUDIT-VISUEL.md +++ b/docs-site-interne/captures/AUDIT-VISUEL.md @@ -1,6 +1,6 @@ # Audit visuel et mise en forme -**Dernière mise à jour :** 2026-04-28 +**Dernière mise à jour :** 2026-04-22 **Captures :** [INDEX.md](./INDEX.md) ## Objectif @@ -22,8 +22,9 @@ Recenser les **problèmes visuels** et de **mise en forme** pour les **corriger* | Fichier | `01-layout-header-nav-desktop.webp` | | **Navigateur** | Google Chrome | -| **Constats** | Aucun problème majeur. Mise en page root renforcée (min-w-0, overflow-x) en parallèle de l’option 1 zoom. | -| **Statut** | `OK` | +| **Constats** | Header OK, mais depuis la normalisation des conteneurs (option 1 zoom) le texte de plusieurs pages se retrouvait **collé** au header : le `
` étant `position: fixed`, il est **hors du flux** et ne prend pas de place dans la grille racine. Seule la home compensait, via un `mt-12` local. | +| **Piste / correctif appliqué (2026-04-22)** | Compensation **centralisée** dans `app/layout.tsx` : `
` en `pt-20 md:pt-24` (couvre la hauteur du header `h-16` + un peu d’air). Suppression du `mt-12` dupliqué sur la home (`app/page.tsx`) pour ne pas cumuler. Toutes les pages héritent désormais du même espace sous le header, plus besoin de compenser page par page. | +| **Statut** | `fait` | --- @@ -49,19 +50,64 @@ Recenser les **problèmes visuels** et de **mise en forme** pour les **corriger* **Accessibilité** : le **verrouillage total du zoom** n’a **pas** été retenu (hors demande) ; on privilégie la mise en page. Si le dézoom reste gênant, on pourra itérer (contraintes sur le markdown, etc.). -| **Statut** | `fait` (à valider sur appareil réel) — opt-in zoom non appliqué pour l’instant | +### Refonte du menu mobile en drawer latéral (2026-04-22) + +- **Ancien** : panneau mi-hauteur côté gauche + grosse croix `✖` → peu esthétique. +- **Nouveau** (`app/layout.tsx`) : **tiroir gauche** `role="dialog" aria-modal="true"`, **largeur 70 %** (capée à `max-w-sm`), hauteur pleine, fond **sombre translucide** (`bg-gray-900/70 backdrop-blur-md`), bordure droite fine. +- **Animation** : `transition-transform` + `-translate-x-full` ↔ `translate-x-0`, 300 ms, easing `ease-out` ; voile en fondu (`transition-opacity`). Respect de `prefers-reduced-motion` (voir `.mobile-drawer-*` dans `app/globals.css`). +- **Fermeture** : **pas de croix** ; tap sur le **voile**, **Échap**, **clic sur un lien**, **re-tap sur le burger** (qui affiche `✕` le temps de l’ouverture), et **auto-fermeture après 4 s** d’inactivité (timer remis à zéro à chaque interaction / touch dans le tiroir, nettoyé à la fermeture, et relancé à l’ouverture). +- **Accessibilité** : `aria-label` / `aria-expanded` / `aria-controls` sur le burger ; le focus revient sur le burger après fermeture ; fermeture automatique si l’écran passe en ≥ md (resize). + +| **Statut** | `fait` — drawer latéral, auto-close 4 s, fond sombre translucide, 70 % | --- ## ID 03 — Accueil hero desktop -*À traiter à la prochaine passe.* | Fichier | `03-accueil-hero-desktop.webp` | +| **Route** | `/` | +| **Code** | `app/page.tsx`, `app/layout.tsx` | +| **Constats** | Rien à corriger spécifiquement : les ajustements déjà faits côté **layout** (compensation du header `pt-20 md:pt-24`, conteneur `min-w-0 max-w-full`) et côté **home** (suppression du `mt-12` dupliqué, `min-w-0 max-w-full` sur le `
` et la zone markdown) couvrent la mise en forme. Hero, photo, titre et CV s’affichent correctement au-dessus du pli. | +| **Statut** | `OK` (pris en charge par les correctifs ID 01 / option 1) | + +--- + +## ID 04 — Accueil hero mobile + +| Fichier | `04-accueil-hero-mobile.webp` | +| **Route** | `/` | +| **Code** | `app/page.tsx`, `app/layout.tsx` | +| **Constats** | Couvert par les correctifs globaux : **drawer** latéral (ID 02), **compensation header** (`pt-20 md:pt-24`), conteneurs en `min-w-0 / max-w-full`, `.bg-wallpaper` ramené à `width: 100%` sur mobile. Hero lisible, sans débordement au zoom, texte non collé au header. | +| **Statut** | `OK` (pris en charge par les correctifs ID 01 / ID 02 / option 1) | + +--- + +## ID 05 à 21 — Passage global en `OK` + +Les captures suivantes **n’ont pas révélé de problème spécifique** après les correctifs **option 1** (CSS / layout — overflow, `min-w-0`, `.bg-wallpaper`), **ID 01** (compensation du header `pt-20 md:pt-24`) et **ID 02** (refonte du menu mobile en drawer latéral). Elles sont donc marquées **`OK`** à ce stade. Elles restent sujettes à la **refonte visuelle plus large** à venir, qui pourra les reprendre une par une. + +| ID | Section | Route | Fichier | Statut | +|----|---------|-------|---------|--------| +| 05 | Accueil page longue | `/` | `05-accueil-page-pleine-desktop.webp` | `OK` | +| 06 | Accueil chargement | `/` | *(non fourni — optionnel)* | `ignoré` | +| 07 | Portfolio liste desktop | `/portfolio` | `07-portfolio-liste-desktop.webp` | `OK` | +| 08 | Portfolio liste mobile | `/portfolio` | `08-portfolio-liste-mobile.webp` | `OK` | +| 09 | Portfolio fiche desktop | `/portfolio/slug` | `09-portfolio-detail-desktop-presentation-ecole-42.webp` | `OK` | +| 10 | Portfolio fiche mobile | `/portfolio/slug` | `10-portfolio-detail-mobile-presentation-ecole-42.webp` | `OK` | +| 11 | Compétences liste desktop | `/competences` | `11-competences-liste-desktop.webp` | `OK` | +| 12 | Compétences liste mobile | `/competences` | `12-competences-liste-mobile.webp` | `OK` | +| 13 | Compétences fiche desktop | `/competences/slug` | `13-competences-detail-ia-desktop.webp` | `OK` | +| 14 | Compétences fiche mobile | `/competences/slug` | `14-competences-detail-ia-mobile.webp` | `OK` | +| 15 | GrasBot ouvert desktop | `/competences/slug` | `15-competences-grasbot-ouvert-desktop.webp` | `OK` | +| 16 | Glossaire modal desktop | `/competences/slug` | `16-competences-glossaire-ouvert-desktop.webp` | `OK` | +| 17 | Contact formulaire desktop | `/contact` | `17-contact-formulaire-desktop.webp` | `OK` | +| 18 | Contact formulaire mobile | `/contact` | `18-contact-formulaire-mobile.webp` | `OK` | +| 19 | Footer desktop | `/` | `19-layout-footer-desktop.webp` | `OK` | +| 20 | Compteur visites desktop | `/` | `20-layout-compteur-visites-desktop.webp` | `OK` | +| 21 | Admin messages desktop | `/admin/messages` | `21-admin-messages-desktop.webp` | `OK` | --- ## Suite -| Prochain | Fichier | -|----------|---------| -| 04 | `04-accueil-hero-mobile.webp` puis 05… | +Passage à la **refonte visuelle globale** : direction artistique (palette, typographie, rythme vertical), hiérarchie des pages, traitement des cartes portfolio / compétences, header et footer. À cadrer avec l’utilisateur avant toute modification. diff --git a/stitch_V1/DESIGN.md b/stitch_V1/DESIGN.md new file mode 100644 index 0000000..7b4a1e0 --- /dev/null +++ b/stitch_V1/DESIGN.md @@ -0,0 +1,85 @@ +```markdown +# Design System: High-End Editorial Guidelines + +## 1. Overview & Creative North Star +The Creative North Star for this design system is **"The Digital Atelier."** + +Unlike generic tech platforms that rely on rigid grids and heavy borders, this system treats the interface as a premium editorial canvas. It combines the precision of high-tech AI reporting with the warmth of French intellectual heritage. We break the "template" look by using **intentional asymmetry**, where large display type creates a focal point that pulls the eye through the layout, and **tonal layering** replaces structural lines to create a sense of architectural depth. This is not just an interface; it is a curated experience that feels "smart, accessible, and trustworthy." + +--- + +## 2. Colors & Surface Logic +The palette is rooted in a sophisticated interplay of `primary` (a deep, refined indigo-slate) and a series of soft, warm neutrals. + +### The "No-Line" Rule +**Explicit Instruction:** Do not use 1px solid borders for sectioning or containment. +Boundaries must be defined solely through background color shifts or subtle tonal transitions. For example, a `surface-container-low` section should sit directly on a `surface` background. The change in hex value is the boundary. + +### Surface Hierarchy & Nesting +Treat the UI as a series of physical layers—like stacked sheets of fine vellum. +- **Base Layer:** `surface` (#f8fafa) +- **Secondary Sections:** `surface-container-low` (#f2f4f4) +- **Primary Content Cards:** `surface-container-lowest` (#ffffff) +- **Call-to-Action / Floating Elements:** `primary` (#26445d) + +### The "Glass & Gradient" Rule +To elevate the experience beyond flat design: +- **Glassmorphism:** Use semi-transparent surface colors (e.g., `surface` at 80% opacity) with a `backdrop-blur` of 12px-20px for navigation bars or floating headers. +- **Signature Textures:** For main CTAs or Hero backgrounds, use a subtle linear gradient transitioning from `primary` (#26445d) to `primary-container` (#3e5c76). This provides a "soul" and depth that flat hex codes cannot achieve. + +--- + +## 3. Typography: The Editorial Voice +We use a high-contrast pairing to distinguish between "Technical Insight" and "Human Narrative." + +* **Display & Headlines (Manrope):** A sharp, modern sans-serif. Use `display-lg` to `headline-sm` for authoritative, news-breaking moments. The tight tracking and geometric builds of Manrope signal modern technology. +* **Body & Titles (Newsreader):** A highly readable, premium serif. This is the "warmth" of the system. `body-lg` and `title-md` provide a literary, trustworthy feel that invites long-form reading. + +**Hierarchy Tip:** Always lead with a large `display-md` headline in `on_surface`, followed by a `title-lg` sub-header in `secondary` (#516169) to create a sophisticated, multi-tonal reading experience. + +--- + +## 4. Elevation & Depth +In this system, depth is a feeling, not a decoration. + +* **The Layering Principle:** Achieve lift by "stacking" tiers. Place a `surface-container-lowest` card (Pure White) on a `surface-container-low` background. The subtle 2-3% shift in brightness creates a soft, natural lift. +* **Ambient Shadows:** When a card must "float" (e.g., a newsletter sign-up modal), use an extra-diffused shadow: + * *Blur:* 40px-60px. + * *Opacity:* 4%-6%. + * *Color:* Use a tinted version of `on_surface` (#191c1d) rather than pure black to mimic natural ambient light. +* **The "Ghost Border" Fallback:** If a container lacks contrast against a specific background, use a "Ghost Border": `outline-variant` (#c3c7cd) at **15% opacity**. Never use 100% opaque borders. + +--- + +## 5. Components & Layout Elements + +### Cards & Containers +- **Corner Radius:** Use `xl` (1.5rem / 24px) for main content cards and `lg` (1rem / 16px) for inner nested elements. +- **Separation:** **Forbid the use of divider lines.** Use vertical white space (Spacing scale `8` or `10`) to separate newsletter sections. + +### Buttons (The "Jewel" Elements) +- **Primary:** Background `primary`, text `on_primary`. Use a slight 4px vertical offset shadow to make it feel tactile. +- **Secondary:** Background `secondary_container`, text `on_secondary_container`. No shadow. +- **Tertiary:** Ghost style. `title-sm` typography with a `primary` color and a subtle underline that appears on hover. + +### Inputs & Fields +- **Styling:** Use `surface_container_highest` for the input background with a `md` (0.75rem) radius. +- **Active State:** Change background to `surface_container_lowest` and apply a 1px "Ghost Border" of `primary` at 30% opacity. + +### Signature Component: The "Editorial Pull-Quote" +A custom component for the newsletter. Use `newsreader` in `title-lg`, italicized, with a thick 4px vertical bar on the left using the `primary_fixed` (#cce5ff) color. No background card—let the typography breathe on the `surface`. + +--- + +## 6. Do’s and Don’ts + +### Do: +* **Embrace Whitespace:** Use the spacing scale `16` (5.5rem) or `20` (7rem) between major editorial sections. +* **Mix Type:** Use Manrope for data points and Newsreader for the "Why it matters" analysis. +* **Tonal Overlap:** Let images or illustrations slightly overlap the boundary of a `surface-container` to break the "boxed-in" feel. + +### Don’t: +* **No Pure Black:** Never use #000000. Use `on_background` (#191c1d) for the deepest tones. +* **No Heavy Shadows:** If the shadow is immediately obvious, it is too dark. It should be felt, not seen. +* **No Grid-Lock:** Avoid perfectly symmetrical 3-column grids. Try a 2/3 and 1/3 split to create a more dynamic, editorial rhythm. +* **No "Default" Borders:** Avoid the `outline` token at full strength. It kills the premium, "soft" aesthetic of the system. \ No newline at end of file diff --git a/stitch_V1/code.html b/stitch_V1/code.html new file mode 100644 index 0000000..cd622d9 --- /dev/null +++ b/stitch_V1/code.html @@ -0,0 +1,265 @@ + + + + + +Le Brief Digital66 + + + + + + + + + + +
+
+Le Brief Digital66 +Édition Hebdomadaire +
+
+12 Juin 2024 +
+ +
+
+
+
+ +
+

+ Bonjour, voici l'essentiel de la semaine... +

+

+ Cette semaine, nous explorons comment l'intelligence artificielle redéfinit les frontières de la création éditoriale. Entre automatisation et intuition humaine, le curseur se déplace. +

+
+ +
+
+
+ +
+
+Dossier Spécial +

L'Ère Post-Prompt : Au-delà de la commande textuelle.

+
+
+
+
+

+ Il ne s'agit plus de savoir "comment" demander, mais de comprendre "ce que" l'on veut réellement accomplir. L'IA devient un partenaire de réflexion plutôt qu'un simple outil d'exécution. +

+
+
+ +
+
+
+
+psychology +
+
+

Cognition Augmentée

+

L'IA étend votre portée analytique pour des décisions plus rapides.

+
+
+
+
+
+
+auto_awesome +
+
+

Symphonie Créative

+

Une collaboration permettant d'explorer des territoires inaccessibles.

+
+
+
+
+
+
+shield +
+
+

Éthique par Design

+

L'intégrité des données devient un avantage concurrentiel majeur.

+
+
+
+
+ +
+
+

+lightbulb + Optimisez votre flux IA +

+
+ + + + + + + + + + + + + +
1Définissez le rôle avant la tâche (ex: "Agis comme un expert UX").
2Utilisez des exemples concrets pour guider le style et le ton.
3Itérez par petites touches plutôt que de chercher la perfection immédiate.
+
+ +
+
+deployed_code +
+

Atelier GPT-V

+

Une suite d'outils open-source pour analyser vos données visuelles avec une précision chirurgicale.

+ + Découvrir l'outil + arrow_forward + +
+ +
+Point de vue +

+ "La technologie ne doit pas être une fuite en avant, mais un retour à l'essentiel : libérer le temps humain pour ce qui ne peut être automatisé : l'empathie, la nuance et la vision." +

+

— Jean-Marc S., Lead Strategist

+
+ +
+sentiment_satisfied +
L'anecdote de la semaine
+

Saviez-vous que le premier "bug" informatique était une véritable mite (moth) coincée dans un relais du Harvard Mark II en 1947 ?

+Lire l'archive +
+ + +
+ + +
+ \ No newline at end of file diff --git a/stitch_V1/favicon.png b/stitch_V1/favicon.png new file mode 100644 index 0000000..e4687dd Binary files /dev/null and b/stitch_V1/favicon.png differ diff --git a/stitch_V1/listmonk_public_custom.css b/stitch_V1/listmonk_public_custom.css new file mode 100644 index 0000000..7e0d646 --- /dev/null +++ b/stitch_V1/listmonk_public_custom.css @@ -0,0 +1,92 @@ +/* + * Listmonk — CSS pages publiques (confirmation, abonnement, etc.) + * + * Coller le contenu (sans ce bloc commentaire si tu préfères) dans : + * Admin → Settings → Appearance → Public → Custom CSS + * + * Référence visuelle : DESIGN.md + palette page d’inscription (newsletter-service). + * Carte multicanal (template mail, Directus, inscription) : docs/18_guide_visuel_multicanal.md + * Après modification : copier-coller dans Listmonk → Save → tester en navigation privée. + */ + +@import url("https://fonts.googleapis.com/css2?family=Manrope:wght@500;600;700;800&family=Newsreader:ital,wght@0,400;0,500&display=swap"); + +body { + font-family: "Newsreader", Georgia, serif !important; + background: #f8fafa !important; + color: #191c1d !important; + -webkit-font-smoothing: antialiased; +} + +h1, +h2, +h3 { + font-family: "Manrope", system-ui, sans-serif !important; + font-weight: 800 !important; + color: #26445d !important; + letter-spacing: -0.02em; +} + +p, +li, +label { + font-family: "Newsreader", Georgia, serif !important; + color: #516169; +} + +a { + color: #26445d !important; +} + +a:hover { + color: #3e5c76 !important; +} + +.button, +button, +input[type="submit"] { + font-family: "Manrope", system-ui, sans-serif !important; + font-weight: 600 !important; + background: linear-gradient(135deg, #26445d, #3e5c76) !important; + color: #fff !important; + border: none !important; + border-radius: 0.75rem !important; + box-shadow: 0 4px 14px rgba(38, 68, 93, 0.22); + padding: 0.65rem 1.25rem; +} + +.button:hover, +button:hover, +input[type="submit"]:hover { + filter: brightness(1.05); +} + +input[type="checkbox"] { + accent-color: #26445d; +} + +.header .logo img { + display: block; + margin: 0 auto 1rem; + max-height: 3rem; + width: auto; +} + +.container, +main .container { + background: #ffffff; + border-radius: 1.5rem; + box-shadow: 0 28px 56px rgba(25, 28, 29, 0.055); +} + +footer.container { + margin-top: 1.5rem !important; + font-size: 0.85rem !important; + opacity: 0.55; +} + +/* Pour masquer complètement le pied « Powered by listmonk » : décommenter si conforme à ta licence. +footer.container { + display: none !important; +} +*/ diff --git a/stitch_V1/listmonk_template.html b/stitch_V1/listmonk_template.html new file mode 100644 index 0000000..4343a4f --- /dev/null +++ b/stitch_V1/listmonk_template.html @@ -0,0 +1,423 @@ + + + + + + + {{ .Campaign.Subject }} + + + + + + + +
+
+
+

Édition hebdomadaire

+

Le Brief Digital 66

+

{{ .Campaign.Subject }}

+

IA · Productivité · Veille · Pyrénées-Orientales

+
+ +
+ {{ template "content" . }} +
+ + +
+
+ + diff --git a/stitch_V1/logo_brief66.png b/stitch_V1/logo_brief66.png new file mode 100644 index 0000000..4fd9046 Binary files /dev/null and b/stitch_V1/logo_brief66.png differ diff --git a/stitch_V1/screen.png b/stitch_V1/screen.png new file mode 100644 index 0000000..09c7cc2 Binary files /dev/null and b/stitch_V1/screen.png differ