mirror of
https://github.com/Ladebeze66/devsite.git
synced 2026-05-11 16:56:26 +02:00
finauditvisuel
This commit is contained in:
parent
d0224df2fc
commit
2ff2f4bf42
@ -118,3 +118,10 @@ footer {
|
|||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.mobile-drawer-root,
|
||||||
|
.mobile-drawer-panel {
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
113
app/layout.tsx
113
app/layout.tsx
@ -10,20 +10,66 @@ import NavLink from "./components/NavLink";
|
|||||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||||
const [visitCount, setVisitCount] = useState(0);
|
const [visitCount, setVisitCount] = useState(0);
|
||||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||||
const menuRef = useRef(null); // Référence pour le menu burger
|
const menuRef = useRef<HTMLElement | null>(null);
|
||||||
|
const burgerRef = useRef<HTMLButtonElement | null>(null);
|
||||||
|
const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||||
|
|
||||||
const toggleMenu = () => {
|
const AUTO_CLOSE_MS = 4000;
|
||||||
setIsMenuOpen(!isMenuOpen);
|
|
||||||
|
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(() => {
|
useEffect(() => {
|
||||||
// Récupère le compteur de visites depuis localStorage
|
|
||||||
const visits = localStorage.getItem("visitCount");
|
const visits = localStorage.getItem("visitCount");
|
||||||
const newVisitCount = visits ? parseInt(visits) + 1 : 1;
|
const newVisitCount = visits ? parseInt(visits) + 1 : 1;
|
||||||
localStorage.setItem("visitCount", newVisitCount.toString());
|
localStorage.setItem("visitCount", newVisitCount.toString());
|
||||||
setVisitCount(newVisitCount);
|
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 (
|
return (
|
||||||
<html lang="fr">
|
<html lang="fr">
|
||||||
<body className="min-w-0 overflow-x-hidden antialiased">
|
<body className="min-w-0 overflow-x-hidden antialiased">
|
||||||
@ -48,8 +94,16 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
|||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
{/* Bouton menu burger */}
|
{/* Bouton menu burger */}
|
||||||
<button className="md:hidden p-2 bg-gray-300 rounded" onClick={toggleMenu}>
|
<button
|
||||||
☰
|
ref={burgerRef}
|
||||||
|
type="button"
|
||||||
|
className="md:hidden p-2 bg-gray-300 rounded"
|
||||||
|
onClick={toggleMenu}
|
||||||
|
aria-label={isMenuOpen ? "Fermer le menu" : "Ouvrir le menu"}
|
||||||
|
aria-expanded={isMenuOpen}
|
||||||
|
aria-controls="mobile-drawer"
|
||||||
|
>
|
||||||
|
{isMenuOpen ? "✕" : "☰"}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{/* Menu desktop */}
|
{/* Menu desktop */}
|
||||||
@ -64,25 +118,42 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{/* Menu mobile */}
|
{/* Drawer mobile (tiroir gauche, 70%, fond sombre translucide) */}
|
||||||
{isMenuOpen && (
|
<div
|
||||||
<div ref={menuRef} className="fixed inset-0 bg-black/50 z-40 flex items-start justify-left p-4">
|
className={`mobile-drawer-root fixed inset-0 z-40 md:hidden transition-opacity duration-300 ease-out ${
|
||||||
<nav className="w-[60%] max-w-sm h-auto min-h-[50vh] max-h-[50vh] bg-gray-800/90 backdrop-blur-lg flex flex-col items-center justify-center space-y-4 z-50 md:hidden text-white font-orbitron-24-bold tracking-wide shadow-lg overflow-y-auto rounded-lg p-6">
|
isMenuOpen ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"
|
||||||
{/* Bouton de fermeture */}
|
}`}
|
||||||
<button className="absolute top-4 right-4 text-2xl text-white" onClick={toggleMenu}>
|
aria-hidden={!isMenuOpen}
|
||||||
✖
|
>
|
||||||
</button>
|
{/* Voile : tap pour fermer */}
|
||||||
|
<div
|
||||||
|
className="absolute inset-0 bg-black/40 backdrop-blur-sm"
|
||||||
|
onClick={closeMenu}
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Liens du menu */}
|
{/* Colonne tiroir */}
|
||||||
<NavLink text="Accueil" path="/" onClick={toggleMenu} className="text-lg text-white hover:text-gray-900 px-4 py-2 bg-gray-700 rounded-lg transition-all duration-300 hover:bg-gray-500" />
|
<nav
|
||||||
<NavLink text="Portfolio" path="/portfolio" onClick={toggleMenu} className="text-lg text-white hover:text-gray-900 px-4 py-2 bg-gray-700 rounded-lg transition-all duration-300 hover:bg-gray-500" />
|
id="mobile-drawer"
|
||||||
<NavLink text="Compétences" path="/competences" onClick={toggleMenu} className="text-lg text-white hover:text-gray-900 px-4 py-2 bg-gray-700 rounded-lg transition-all duration-300 hover:bg-gray-500" />
|
ref={menuRef}
|
||||||
<NavLink text="Contact" path="/contact" onClick={toggleMenu} className="text-lg text-white hover:text-gray-900 px-4 py-2 bg-gray-700 rounded-lg transition-all duration-300 hover:bg-gray-500" />
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-label="Menu de navigation"
|
||||||
|
className={`mobile-drawer-panel relative z-10 h-full w-[70%] max-w-sm bg-gray-900/70 backdrop-blur-md border-r border-white/10 shadow-2xl flex flex-col gap-3 px-6 pt-20 pb-8 text-white font-orbitron-24-bold tracking-wide transition-transform duration-300 ease-out ${
|
||||||
|
isMenuOpen ? "translate-x-0" : "-translate-x-full"
|
||||||
|
}`}
|
||||||
|
onClick={scheduleAutoClose}
|
||||||
|
onTouchStart={scheduleAutoClose}
|
||||||
|
onTouchMove={scheduleAutoClose}
|
||||||
|
>
|
||||||
|
<NavLink text="Accueil" path="/" onClick={closeMenu} className="text-lg text-white hover:text-gray-900 px-4 py-2 bg-gray-700/80 rounded-lg transition-all duration-300 hover:bg-gray-500" />
|
||||||
|
<NavLink text="Portfolio" path="/portfolio" onClick={closeMenu} className="text-lg text-white hover:text-gray-900 px-4 py-2 bg-gray-700/80 rounded-lg transition-all duration-300 hover:bg-gray-500" />
|
||||||
|
<NavLink text="Compétences" path="/competences" onClick={closeMenu} className="text-lg text-white hover:text-gray-900 px-4 py-2 bg-gray-700/80 rounded-lg transition-all duration-300 hover:bg-gray-500" />
|
||||||
|
<NavLink text="Contact" path="/contact" onClick={closeMenu} className="text-lg text-white hover:text-gray-900 px-4 py-2 bg-gray-700/80 rounded-lg transition-all duration-300 hover:bg-gray-500" />
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
<main className="relative z-10 w-full min-w-0 max-w-full min-h-0">
|
<main className="relative z-10 w-full min-w-0 max-w-full min-h-0 pt-20 md:pt-24">
|
||||||
{children}
|
{children}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
@ -78,7 +78,7 @@ export default function HomePage() {
|
|||||||
const imageUrl = homepage.photo?.url ? `${apiUrl}${homepage.photo.url}` : null;
|
const imageUrl = homepage.photo?.url ? `${apiUrl}${homepage.photo.url}` : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="mx-auto mb-3 mt-12 flex w-full min-w-0 max-w-full flex-col items-center justify-center rounded-lg bg-white/55 p-4 sm:max-w-2xl sm:p-6 md:max-w-3xl lg:max-w-4xl xl:max-w-5xl">
|
<main className="mx-auto mb-3 flex w-full min-w-0 max-w-full flex-col items-center justify-center rounded-lg bg-white/55 p-4 sm:max-w-2xl sm:p-6 md:max-w-3xl lg:max-w-4xl xl:max-w-5xl">
|
||||||
<h1 className="text-3xl font-orbitron-24-bold-italic text-gray-800 mb-4">{title}</h1>
|
<h1 className="text-3xl font-orbitron-24-bold-italic text-gray-800 mb-4">{title}</h1>
|
||||||
|
|
||||||
{imageUrl ? (
|
{imageUrl ? (
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# Audit visuel et mise en forme
|
# 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)
|
**Captures :** [INDEX.md](./INDEX.md)
|
||||||
|
|
||||||
## Objectif
|
## 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` |
|
| Fichier | `01-layout-header-nav-desktop.webp` |
|
||||||
| **Navigateur** | Google Chrome |
|
| **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. |
|
| **Constats** | Header OK, mais depuis la normalisation des conteneurs (option 1 zoom) le texte de plusieurs pages se retrouvait **collé** au header : le `<header>` é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. |
|
||||||
| **Statut** | `OK` |
|
| **Piste / correctif appliqué (2026-04-22)** | Compensation **centralisée** dans `app/layout.tsx` : `<main>` 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.).
|
**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
|
## ID 03 — Accueil hero desktop
|
||||||
|
|
||||||
*À traiter à la prochaine passe.*
|
|
||||||
| Fichier | `03-accueil-hero-desktop.webp` |
|
| 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 `<main>` 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
|
## Suite
|
||||||
|
|
||||||
| Prochain | Fichier |
|
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.
|
||||||
|----------|---------|
|
|
||||||
| 04 | `04-accueil-hero-mobile.webp` puis 05… |
|
|
||||||
|
|||||||
85
stitch_V1/DESIGN.md
Normal file
85
stitch_V1/DESIGN.md
Normal file
@ -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.
|
||||||
265
stitch_V1/code.html
Normal file
265
stitch_V1/code.html
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html class="light" lang="fr"><head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
||||||
|
<title>Le Brief Digital66</title>
|
||||||
|
<!-- Material Symbols -->
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
|
||||||
|
<!-- Google Fonts: Manrope & Newsreader -->
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;600;700;800&family=Newsreader:ital,wght@0,400;0,500;1,400;1,500&display=swap" rel="stylesheet"/>
|
||||||
|
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
||||||
|
<script id="tailwind-config">
|
||||||
|
tailwind.config = {
|
||||||
|
darkMode: "class",
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
"on-tertiary-fixed-variant": "#384858",
|
||||||
|
"on-error": "#ffffff",
|
||||||
|
"on-surface-variant": "#42474d",
|
||||||
|
"tertiary-fixed": "#d3e4f7",
|
||||||
|
"outline-variant": "#c3c7cd",
|
||||||
|
"secondary-fixed-dim": "#b9c9d3",
|
||||||
|
"on-primary-container": "#b5d4f2",
|
||||||
|
"background": "#f8fafa",
|
||||||
|
"secondary-container": "#d2e2ec",
|
||||||
|
"tertiary-container": "#4a5b6b",
|
||||||
|
"on-background": "#191c1d",
|
||||||
|
"on-surface": "#191c1d",
|
||||||
|
"on-error-container": "#93000a",
|
||||||
|
"on-tertiary": "#ffffff",
|
||||||
|
"surface-tint": "#43617c",
|
||||||
|
"on-tertiary-fixed": "#0b1d2b",
|
||||||
|
"secondary": "#516169",
|
||||||
|
"error-container": "#ffdad6",
|
||||||
|
"inverse-surface": "#2e3131",
|
||||||
|
"surface-dim": "#d8dada",
|
||||||
|
"surface": "#f8fafa",
|
||||||
|
"inverse-primary": "#abcae8",
|
||||||
|
"surface-variant": "#e1e3e3",
|
||||||
|
"on-secondary-fixed": "#0e1d25",
|
||||||
|
"on-secondary-fixed-variant": "#3a4951",
|
||||||
|
"tertiary": "#334453",
|
||||||
|
"surface-container-lowest": "#ffffff",
|
||||||
|
"primary": "#26445d",
|
||||||
|
"surface-container": "#eceeee",
|
||||||
|
"on-tertiary-container": "#c1d2e5",
|
||||||
|
"surface-container-low": "#f2f4f4",
|
||||||
|
"on-primary-fixed-variant": "#2b4963",
|
||||||
|
"surface-container-high": "#e6e8e9",
|
||||||
|
"error": "#ba1a1a",
|
||||||
|
"on-primary-fixed": "#001d31",
|
||||||
|
"on-secondary": "#ffffff",
|
||||||
|
"primary-fixed": "#cce5ff",
|
||||||
|
"primary-fixed-dim": "#abcae8",
|
||||||
|
"tertiary-fixed-dim": "#b7c8db",
|
||||||
|
"outline": "#73777d",
|
||||||
|
"on-secondary-container": "#55656d",
|
||||||
|
"on-primary": "#ffffff",
|
||||||
|
"surface-bright": "#f8fafa",
|
||||||
|
"secondary-fixed": "#d5e5ef",
|
||||||
|
"inverse-on-surface": "#eff1f1",
|
||||||
|
"primary-container": "#3e5c76",
|
||||||
|
"surface-container-highest": "#e1e3e3"
|
||||||
|
},
|
||||||
|
fontFamily: {
|
||||||
|
"headline": ["Manrope"],
|
||||||
|
"body": ["Newsreader"],
|
||||||
|
"label": ["Manrope"]
|
||||||
|
},
|
||||||
|
borderRadius: {"DEFAULT": "0.25rem", "lg": "0.5rem", "xl": "1.5rem", "full": "9999px"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.material-symbols-outlined {
|
||||||
|
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 1;
|
||||||
|
text-transform: none;
|
||||||
|
letter-spacing: normal;
|
||||||
|
word-wrap: normal;
|
||||||
|
white-space: nowrap;
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
body { -webkit-font-smoothing: antialiased; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="bg-surface text-on-surface font-body selection:bg-primary-fixed selection:text-on-primary-fixed">
|
||||||
|
<!-- 1. Header / Brand Block -->
|
||||||
|
<header class="bg-surface border-b border-outline-variant px-6 py-6 max-w-xl mx-auto flex justify-between items-center">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<span class="text-xl font-black tracking-tighter text-primary font-headline">Le Brief Digital66</span>
|
||||||
|
<span class="font-headline font-bold text-[10px] tracking-[0.2em] uppercase text-secondary mt-1">Édition Hebdomadaire</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<span class="font-headline font-bold text-[11px] uppercase text-secondary">12 Juin 2024</span>
|
||||||
|
<div class="w-10 h-10 rounded-full bg-secondary-container overflow-hidden border border-outline-variant">
|
||||||
|
<img class="w-full h-full object-cover" data-alt="professional portrait of a creative director" src="https://lh3.googleusercontent.com/aida-public/AB6AXuAG_2MabCQMZJ20eMCX-gQdAYzd1STuDfFnru-n-Gb-HizW1maLaedIU4moaArLFDjsWE0whuEG8sqnXPMkYv2PnYhGyrMQ33LjIJ_pH63teIhH2j31ymrkgRM1mdzhhN-cMMUhEWjqHW2nl-Ksd-mU71FxRgbJ-E6Y9M_OrWUIqR1nR6ys25cUJhY9EBf1bmjLYWv4Y1xkxihF8us6IfSuSI8mvx2P6s8cBeytILeYcg-GcLd01z3Dg7KBgVx3DVoGYzXZIxPScRA"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<main class="max-w-xl mx-auto px-6 py-12">
|
||||||
|
<!-- 2. Intro Section -->
|
||||||
|
<section class="mb-20">
|
||||||
|
<h1 class="font-headline font-extrabold text-4xl mb-8 tracking-tight text-on-surface leading-[1.1]">
|
||||||
|
Bonjour, voici l'essentiel de la semaine...
|
||||||
|
</h1>
|
||||||
|
<p class="text-2xl leading-relaxed text-secondary italic font-body">
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
<!-- 3. Main Topic Section -->
|
||||||
|
<section class="mb-24">
|
||||||
|
<div class="bg-primary p-1 rounded-xl mb-8">
|
||||||
|
<div class="relative rounded-lg overflow-hidden">
|
||||||
|
<img class="w-full h-72 object-cover block" data-alt="abstract visualization of neural networks" src="https://lh3.googleusercontent.com/aida-public/AB6AXuCn3hjW5ImhkEpemDHQKwRMabDzaChOQJ4zWR6ZBwk-vOi_1nTeox9JlfG4Buufnb8RiaEYJ2aMJPh3erKq-2si2HHDBw8pyu04mgpVhhO5YdGC16eafBz9HolVYRSG12pfHBOyzMpEmD5rdkoxb9JCQDpSS8QGIK5Lehi6Q-nCFh2cgAq5oMp4kDpYIeY07j60fVdUxvyDciMwc-z4TH2QfuoIMs1UT4NLqVrs4UpGB8rX4pHxI3CPSX5gJoxWlNAvnqZHvnaAHmk"/>
|
||||||
|
<div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div>
|
||||||
|
<div class="absolute bottom-0 left-0 p-8 w-full">
|
||||||
|
<span class="inline-block px-4 py-1.5 bg-primary-fixed text-on-primary-fixed text-xs font-headline font-extrabold uppercase tracking-widest rounded-full mb-4">Dossier Spécial</span>
|
||||||
|
<h2 class="font-headline font-bold text-3xl text-white leading-tight">L'Ère Post-Prompt : Au-delà de la commande textuelle.</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="px-2">
|
||||||
|
<p class="text-xl leading-relaxed text-on-surface">
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- 4. Key Takeaway Cards (Compact & Safe) -->
|
||||||
|
<section class="mb-24 space-y-4">
|
||||||
|
<div class="bg-surface-container-low border border-outline-variant p-5 rounded-xl">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<div class="bg-primary text-white w-10 h-10 rounded flex items-center justify-center shrink-0">
|
||||||
|
<span class="material-symbols-outlined text-xl">psychology</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-headline font-bold text-lg text-primary">Cognition Augmentée</h3>
|
||||||
|
<p class="text-secondary text-sm">L'IA étend votre portée analytique pour des décisions plus rapides.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-surface-container-low border border-outline-variant p-5 rounded-xl">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<div class="bg-primary text-white w-10 h-10 rounded flex items-center justify-center shrink-0">
|
||||||
|
<span class="material-symbols-outlined text-xl">auto_awesome</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-headline font-bold text-lg text-primary">Symphonie Créative</h3>
|
||||||
|
<p class="text-secondary text-sm">Une collaboration permettant d'explorer des territoires inaccessibles.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-surface-container-low border border-outline-variant p-5 rounded-xl">
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<div class="bg-primary text-white w-10 h-10 rounded flex items-center justify-center shrink-0">
|
||||||
|
<span class="material-symbols-outlined text-xl">shield</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-headline font-bold text-lg text-primary">Éthique par Design</h3>
|
||||||
|
<p class="text-secondary text-sm">L'intégrité des données devient un avantage concurrentiel majeur.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- 5. Actionable Tip Block (Simple Layout) -->
|
||||||
|
<section class="bg-primary text-white p-8 rounded-xl mb-24">
|
||||||
|
<div class="mb-8 border-b border-primary-container pb-4">
|
||||||
|
<h3 class="font-headline font-extrabold text-xl flex items-center gap-3">
|
||||||
|
<span class="material-symbols-outlined text-primary-fixed">lightbulb</span>
|
||||||
|
Optimisez votre flux IA
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<table class="w-full border-collapse">
|
||||||
|
<tbody><tr class="align-top">
|
||||||
|
<td class="pr-4 py-3"><span class="w-6 h-6 rounded-full bg-primary-fixed text-on-primary-fixed flex items-center justify-center font-headline font-bold text-[10px]">1</span></td>
|
||||||
|
<td class="py-3 text-on-primary-container text-sm leading-relaxed">Définissez le rôle avant la tâche (ex: "Agis comme un expert UX").</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="align-top">
|
||||||
|
<td class="pr-4 py-3"><span class="w-6 h-6 rounded-full bg-primary-fixed text-on-primary-fixed flex items-center justify-center font-headline font-bold text-[10px]">2</span></td>
|
||||||
|
<td class="py-3 text-on-primary-container text-sm leading-relaxed">Utilisez des exemples concrets pour guider le style et le ton.</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="align-top">
|
||||||
|
<td class="pr-4 py-3"><span class="w-6 h-6 rounded-full bg-primary-fixed text-on-primary-fixed flex items-center justify-center font-headline font-bold text-[10px]">3</span></td>
|
||||||
|
<td class="py-3 text-on-primary-container text-sm leading-relaxed">Itérez par petites touches plutôt que de chercher la perfection immédiate.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody></table>
|
||||||
|
</section>
|
||||||
|
<!-- 6. Tool / Resource Block -->
|
||||||
|
<section class="mb-24 text-center bg-surface-container-lowest border border-outline-variant p-10 rounded-xl">
|
||||||
|
<div class="w-16 h-16 bg-primary-container/10 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||||
|
<span class="material-symbols-outlined text-primary text-3xl">deployed_code</span>
|
||||||
|
</div>
|
||||||
|
<h4 class="font-headline font-bold text-2xl mb-3 text-primary">Atelier GPT-V</h4>
|
||||||
|
<p class="text-secondary mb-8 text-base max-w-sm mx-auto">Une suite d'outils open-source pour analyser vos données visuelles avec une précision chirurgicale.</p>
|
||||||
|
<a class="inline-flex items-center justify-center gap-3 px-10 py-4 bg-primary text-white font-headline font-bold rounded-lg hover:bg-primary/90 transition-colors" href="#">
|
||||||
|
Découvrir l'outil
|
||||||
|
<span class="material-symbols-outlined text-sm">arrow_forward</span>
|
||||||
|
</a>
|
||||||
|
</section>
|
||||||
|
<!-- 7. Critical Reflection Block -->
|
||||||
|
<section class="mb-24 border-l-4 border-primary pl-10 py-4">
|
||||||
|
<span class="font-headline font-bold text-primary text-[10px] uppercase tracking-[0.2em] mb-4 block">Point de vue</span>
|
||||||
|
<p class="font-body italic text-2xl text-on-surface leading-tight">
|
||||||
|
"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."
|
||||||
|
</p>
|
||||||
|
<p class="mt-6 font-headline font-bold text-secondary text-sm">— Jean-Marc S., Lead Strategist</p>
|
||||||
|
</section>
|
||||||
|
<!-- 8. Light Moment Block -->
|
||||||
|
<section class="bg-surface-container-high p-8 rounded-xl mb-24 text-center">
|
||||||
|
<span class="material-symbols-outlined text-tertiary mb-3 text-3xl">sentiment_satisfied</span>
|
||||||
|
<h5 class="font-headline font-bold text-on-surface mb-2 text-lg italic">L'anecdote de la semaine</h5>
|
||||||
|
<p class="text-secondary text-sm leading-relaxed mb-6">Saviez-vous que le premier "bug" informatique était une véritable mite (moth) coincée dans un relais du Harvard Mark II en 1947 ?</p>
|
||||||
|
<a class="text-primary font-headline font-bold text-xs uppercase tracking-widest border-b-2 border-primary/20 pb-1 hover:border-primary transition-colors" href="#">Lire l'archive</a>
|
||||||
|
</section>
|
||||||
|
<!-- 9. Premium Footer -->
|
||||||
|
<footer class="pt-16 pb-12 border-t border-outline-variant text-center">
|
||||||
|
<div class="mb-10">
|
||||||
|
<div class="font-headline font-black text-2xl text-primary tracking-tighter mb-2">Le Brief Digital66</div>
|
||||||
|
<p class="font-body italic text-sm text-secondary">La prospective technologique au service de l'humain.</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-center gap-10 mb-10 text-xs font-headline font-bold uppercase tracking-widest text-primary">
|
||||||
|
<a class="hover:text-secondary transition-colors" href="#">Confidentialité</a>
|
||||||
|
<a class="hover:text-secondary transition-colors" href="#">Contact</a>
|
||||||
|
</div>
|
||||||
|
<div class="mb-10 flex justify-center gap-4">
|
||||||
|
<a class="w-10 h-10 border border-outline-variant rounded-full flex items-center justify-center text-secondary hover:bg-surface-container hover:text-primary transition-colors" href="#">
|
||||||
|
<span class="material-symbols-outlined text-lg">share</span>
|
||||||
|
</a>
|
||||||
|
<a class="w-10 h-10 border border-outline-variant rounded-full flex items-center justify-center text-secondary hover:bg-surface-container hover:text-primary transition-colors" href="#">
|
||||||
|
<span class="material-symbols-outlined text-lg">mail</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="py-8 bg-surface-container-low rounded-xl">
|
||||||
|
<p class="text-[10px] text-secondary font-headline font-semibold mb-3 uppercase tracking-widest">Vous recevez cet email car vous êtes abonné à Digital66</p>
|
||||||
|
<a class="text-[10px] text-error font-headline font-bold uppercase tracking-widest underline decoration-error/30 hover:decoration-error" href="#">Se désabonner de cette liste</a>
|
||||||
|
</div>
|
||||||
|
<div class="mt-12 text-[10px] uppercase tracking-[0.3em] text-outline font-headline font-bold">
|
||||||
|
Perpignan • France
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</main>
|
||||||
|
<!-- Bottom Nav (UI Only, simplified for mobile feel) -->
|
||||||
|
<nav class="fixed bottom-0 left-0 w-full z-50 flex justify-around items-center px-4 pb-8 pt-4 bg-white/95 border-t border-outline-variant backdrop-blur-md">
|
||||||
|
<a class="flex flex-col items-center justify-center text-primary" href="#">
|
||||||
|
<span class="material-symbols-outlined">newspaper</span>
|
||||||
|
<span class="font-headline text-[9px] font-bold uppercase tracking-widest mt-1">Direct</span>
|
||||||
|
</a>
|
||||||
|
<a class="flex flex-col items-center justify-center text-secondary opacity-60" href="#">
|
||||||
|
<span class="material-symbols-outlined">auto_stories</span>
|
||||||
|
<span class="font-headline text-[9px] font-bold uppercase tracking-widest mt-1">Dossiers</span>
|
||||||
|
</a>
|
||||||
|
<a class="flex flex-col items-center justify-center text-secondary opacity-60" href="#">
|
||||||
|
<span class="material-symbols-outlined">bookmark</span>
|
||||||
|
<span class="font-headline text-[9px] font-bold uppercase tracking-widest mt-1">Favoris</span>
|
||||||
|
</a>
|
||||||
|
<a class="flex flex-col items-center justify-center text-secondary opacity-60" href="#">
|
||||||
|
<span class="material-symbols-outlined">settings</span>
|
||||||
|
<span class="font-headline text-[9px] font-bold uppercase tracking-widest mt-1">Profil</span>
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
<div class="h-24"></div> <!-- Spacer for fixed nav -->
|
||||||
|
</body></html>
|
||||||
BIN
stitch_V1/favicon.png
Normal file
BIN
stitch_V1/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
92
stitch_V1/listmonk_public_custom.css
Normal file
92
stitch_V1/listmonk_public_custom.css
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
*/
|
||||||
423
stitch_V1/listmonk_template.html
Normal file
423
stitch_V1/listmonk_template.html
Normal file
@ -0,0 +1,423 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<!-- Listmonk : sujet de campagne -->
|
||||||
|
<title>{{ .Campaign.Subject }}</title>
|
||||||
|
<!-- Stitch / DESIGN.md : Manrope (titres) + Newsreader (corps) -->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;600;700;800&family=Newsreader:ital,wght@0,400;0,500;1,400&display=swap" rel="stylesheet" />
|
||||||
|
<style>
|
||||||
|
/* --- Tokens alignés DESIGN.md (Stitch V1) — pas de #000 --- */
|
||||||
|
:root {
|
||||||
|
--surface: #f8fafa;
|
||||||
|
--on-surface: #191c1d;
|
||||||
|
--primary: #26445d;
|
||||||
|
--primary-container: #3e5c76;
|
||||||
|
--on-primary: #ffffff;
|
||||||
|
--on-primary-container: #c1d2e5;
|
||||||
|
--secondary: #516169;
|
||||||
|
--primary-fixed: #cce5ff;
|
||||||
|
--surface-container-low: #f2f4f4;
|
||||||
|
--surface-container: #eceeee;
|
||||||
|
--surface-container-high: #e6e8e9;
|
||||||
|
--surface-lowest: #ffffff;
|
||||||
|
--outline-variant: #c3c7cd;
|
||||||
|
--shadow: rgba(25, 28, 29, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background-color: var(--surface);
|
||||||
|
font-family: "Newsreader", Georgia, "Times New Roman", serif;
|
||||||
|
font-size: 17px;
|
||||||
|
line-height: 1.65;
|
||||||
|
color: var(--on-surface);
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
.outer {
|
||||||
|
width: 100%;
|
||||||
|
background-color: var(--surface);
|
||||||
|
padding: 40px 16px 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 640px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: var(--surface-lowest);
|
||||||
|
border-radius: 24px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 40px 60px var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* En-tête éditorial : gradient primary → primary-container (Stitch) */
|
||||||
|
.header {
|
||||||
|
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-container) 100%);
|
||||||
|
color: var(--on-primary);
|
||||||
|
padding: 36px 40px 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-kicker {
|
||||||
|
font-family: "Manrope", -apple-system, BlinkMacSystemFont, sans-serif;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.2em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: rgba(255, 255, 255, 0.75);
|
||||||
|
margin: 0 0 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand {
|
||||||
|
font-family: "Manrope", -apple-system, BlinkMacSystemFont, sans-serif;
|
||||||
|
font-size: 26px;
|
||||||
|
font-weight: 800;
|
||||||
|
letter-spacing: -0.03em;
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
line-height: 1.15;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subject-line {
|
||||||
|
font-family: "Manrope", sans-serif;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.4;
|
||||||
|
color: rgba(255, 255, 255, 0.92);
|
||||||
|
margin: 0 0 14px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tagline {
|
||||||
|
margin: 0;
|
||||||
|
font-family: "Manrope", sans-serif;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(255, 255, 255, 0.72);
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Zone contenu : fragment Directus (.nd-issue) */
|
||||||
|
.content {
|
||||||
|
padding: 40px 36px 48px;
|
||||||
|
background: var(--surface-lowest);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-issue {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Séparation sans « ligne dure » : espace + léger décalage de fond (règle DESIGN) */
|
||||||
|
.content .nd-section {
|
||||||
|
margin: 0 0 40px 0;
|
||||||
|
padding: 0 0 36px 0;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section__title {
|
||||||
|
font-family: "Manrope", sans-serif;
|
||||||
|
margin: 0 0 14px 0;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.25;
|
||||||
|
color: var(--on-surface);
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section__body {
|
||||||
|
font-size: 1.05rem;
|
||||||
|
line-height: 1.7;
|
||||||
|
color: var(--on-surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section__body p {
|
||||||
|
margin: 0 0 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section__body p:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section__body a {
|
||||||
|
color: var(--primary);
|
||||||
|
text-decoration: underline;
|
||||||
|
text-decoration-color: rgba(38, 68, 93, 0.35);
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Accroche + libellé sujet (fragment : `accroche · Tag` — issue_export._render_hook_line_html) */
|
||||||
|
.content .nd-section__body p.nd-hook {
|
||||||
|
font-family: "Manrope", sans-serif;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1.08rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
color: var(--on-surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-topic-tag {
|
||||||
|
display: inline-block;
|
||||||
|
font-family: "Manrope", sans-serif;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 0.72rem;
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--primary);
|
||||||
|
background: var(--surface-container);
|
||||||
|
border: 1px solid var(--outline-variant);
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
margin-left: 8px;
|
||||||
|
vertical-align: middle;
|
||||||
|
white-space: nowrap;
|
||||||
|
max-width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bloc « Pour aller plus loin » — barre type pull-quote (primary_fixed) */
|
||||||
|
.content .nd-more {
|
||||||
|
margin-top: 16px;
|
||||||
|
padding: 14px 16px 14px 18px;
|
||||||
|
background: var(--surface-container-low);
|
||||||
|
border-left: 4px solid var(--primary-fixed);
|
||||||
|
border-radius: 0 12px 12px 0;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.55;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-more__label {
|
||||||
|
font-family: "Manrope", sans-serif;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 11px;
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--primary);
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Par rôle (fragment issue_export.py data-role) — ordre éditorial :
|
||||||
|
light_moment → intro → main_topic → key_takeaway_* → critical_reflection → actionable_tip --- */
|
||||||
|
|
||||||
|
.content .nd-section[data-role="light_moment"] {
|
||||||
|
background: var(--surface-container-high);
|
||||||
|
padding: 24px 22px;
|
||||||
|
border-radius: 16px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role="light_moment"] .nd-section__title {
|
||||||
|
font-style: italic;
|
||||||
|
color: var(--on-surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role="light_moment"] .nd-section__body {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: var(--secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role="intro"] .nd-section__title {
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 800;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.14em;
|
||||||
|
color: var(--secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role="intro"] .nd-section__body p:first-of-type {
|
||||||
|
font-family: "Manrope", sans-serif;
|
||||||
|
font-size: 1.35rem;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.2;
|
||||||
|
color: var(--on-surface);
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role="intro"] .nd-section__body p + p {
|
||||||
|
font-size: 1.15rem;
|
||||||
|
font-style: italic;
|
||||||
|
color: var(--secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role="main_topic"] {
|
||||||
|
padding: 28px 24px 32px;
|
||||||
|
margin-left: -8px;
|
||||||
|
margin-right: -8px;
|
||||||
|
background: var(--surface-container-low);
|
||||||
|
border-radius: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role="main_topic"] .nd-section__title {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role^="key_takeaway"] {
|
||||||
|
background: var(--surface-container-low);
|
||||||
|
padding: 22px 22px 20px;
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px solid rgba(195, 199, 205, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role^="key_takeaway"] .nd-section__title {
|
||||||
|
font-size: 1.05rem;
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role="critical_reflection"] {
|
||||||
|
border-left: 4px solid var(--primary);
|
||||||
|
padding: 8px 0 8px 24px;
|
||||||
|
margin-left: 4px;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role="critical_reflection"] .nd-section__title {
|
||||||
|
font-size: 0.65rem;
|
||||||
|
letter-spacing: 0.18em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role="critical_reflection"] .nd-section__body {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-style: italic;
|
||||||
|
line-height: 1.35;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role="actionable_tip"] {
|
||||||
|
background: linear-gradient(145deg, var(--primary) 0%, var(--primary-container) 100%);
|
||||||
|
color: var(--on-primary);
|
||||||
|
padding: 28px 24px;
|
||||||
|
border-radius: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role="actionable_tip"] .nd-section__title {
|
||||||
|
color: var(--on-primary);
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
padding-bottom: 12px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role="actionable_tip"] .nd-section__body {
|
||||||
|
color: var(--on-primary-container);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role="actionable_tip"] .nd-section__body a {
|
||||||
|
color: #3d4f63;
|
||||||
|
text-decoration-color: rgba(61, 79, 99, 0.45);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
background: var(--surface-container-low);
|
||||||
|
padding: 28px 36px 32px;
|
||||||
|
border-top: 1px solid rgba(195, 199, 205, 0.45);
|
||||||
|
font-family: "Manrope", sans-serif;
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--secondary);
|
||||||
|
line-height: 1.65;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-brand {
|
||||||
|
font-weight: 800;
|
||||||
|
font-size: 18px;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
color: var(--primary);
|
||||||
|
margin: 0 0 6px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-tagline {
|
||||||
|
font-family: "Newsreader", Georgia, serif;
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 13px;
|
||||||
|
margin: 0 0 18px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer a {
|
||||||
|
color: var(--primary);
|
||||||
|
font-weight: 700;
|
||||||
|
text-decoration: underline;
|
||||||
|
text-decoration-color: rgba(38, 68, 93, 0.35);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-legal {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 18px 16px;
|
||||||
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 10px;
|
||||||
|
letter-spacing: 0.06em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track {
|
||||||
|
margin-top: 16px;
|
||||||
|
font-size: 1px;
|
||||||
|
line-height: 0;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.outer {
|
||||||
|
padding: 24px 12px 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header,
|
||||||
|
.content,
|
||||||
|
.footer {
|
||||||
|
padding-left: 22px;
|
||||||
|
padding-right: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding-top: 32px;
|
||||||
|
padding-bottom: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .nd-section[data-role="main_topic"] .nd-section__title {
|
||||||
|
font-size: 1.35rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="outer">
|
||||||
|
<div class="container">
|
||||||
|
<div class="header">
|
||||||
|
<p class="header-kicker">Édition hebdomadaire</p>
|
||||||
|
<h1 class="brand">Le Brief Digital 66</h1>
|
||||||
|
<p class="subject-line">{{ .Campaign.Subject }}</p>
|
||||||
|
<p class="tagline">IA · Productivité · Veille · Pyrénées-Orientales</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
{{ template "content" . }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
<p class="footer-brand">Le Brief Digital 66</p>
|
||||||
|
<p class="footer-tagline">La prospective technologique au service de l'humain.</p>
|
||||||
|
<p>Vous recevez cet e-mail car vous êtes inscrit à la newsletter.</p>
|
||||||
|
<p>
|
||||||
|
<a href="{{ MessageURL }}">Voir dans le navigateur</a>
|
||||||
|
·
|
||||||
|
<a href="{{ UnsubscribeURL }}">Se désabonner</a>
|
||||||
|
</p>
|
||||||
|
<div class="footer-legal">
|
||||||
|
Perpignan · France · Newsletter locale
|
||||||
|
</div>
|
||||||
|
<div class="track">{{ TrackView }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
stitch_V1/logo_brief66.png
Normal file
BIN
stitch_V1/logo_brief66.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 MiB |
BIN
stitch_V1/screen.png
Normal file
BIN
stitch_V1/screen.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 127 KiB |
Loading…
x
Reference in New Issue
Block a user