Restructuration sections, contenu administrable, shadoks, palette été
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

- Structure par section : /numerique, /economique, /citoyenne (plus de /gestation)
- Chaque section a index + sous-pages avec contenu YAML administrable
- API content supporte les chemins imbriqués ([...path])
- Admin : liste des pages + éditeur par section
- Page /economique : monnaie libre (picto Ğ1), modèle éco, productions collectives, commande livre
- Page /citoyenne : decision (CTA Glibredecision), tarifs-eau (CTA SejeteralO)
- BookActions : composant partagé (player, PDF, chapitres, commande) sur home, eco et modele-eco
- GrateWizard remonté dans la section économique de la home
- Palette été par défaut, choix persisté en localStorage
- Fix lisibilité été (text-white/65 + variables CSS)
- Shadoks thématiques sur toutes les pages (8-10 par page, métiers variés)
- Redirections 301 : /gestation/*, /modele-eco/*, /decision, /lire/*
- README, CONTRIBUTING, CLAUDE.md mis à jour

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-03-14 16:13:46 +01:00
parent c564e7be5f
commit 9caf11c8ab
48 changed files with 4576 additions and 1071 deletions

View File

@@ -14,26 +14,36 @@ Site vitrine du projet Le Librodrome — livre + chansons sur l'économie du don
```
app/
pages/ # Routes : index, lire/, ecouter/, autonomie, evenement, gratewizard, a-propos, admin/
components/ # admin, book, content, home, layout, player, song, ui
composables/ # useAudioPlayer, useBookData, useGrateWizard, usePlaylist, usePageContent, useSiteContent...
assets/css/ # main.css (UnoCSS)
data/
pages/ # Contenu YAML par page (home, lire, ecouter, autonomie, evenement...)
site.yml # Config globale du site
pages/
numerique/ # Autonomie numérique (index + [slug] détail)
economique/ # Autonomie économique (index, monnaie-libre, commande, productions-collectives)
modele-eco/ # Livre : sommaire + chapitres [slug]
citoyenne/ # Autonomie citoyenne (index + [slug] détail)
en-musique/ # Player audio
evenement.vue # Événement
admin/ # Back-office (pages/, book/, songs, messages, media)
components/
book/Actions.vue # Boutons partagés livre (player, PDF, chapitres, commande)
home/ # BookSection, AxisBlock, AxisGrid, HeroSection, Messages
admin/, player/, song/, ui/
composables/ # useAudioPlayer, useBookData, useGrateWizard, usePageContent...
stores/palette.ts # 4 palettes saisonnières (été par défaut, persisté localStorage)
assets/css/ # main.css (UnoCSS + overrides light mode)
site/
pages/ # Contenu YAML par section (numerique/, economique/, citoyenne/)
site.yml # Config globale (nav, footer, GrateWizard)
bookplayer.config.yml # Config player/chapitres
server/
api/ # Endpoints API (admin, health)
middleware/ # Auth middleware
api/content/pages/[...path].get.ts # GET pages YAML (chemins imbriqués)
api/admin/content/pages/[...path].put.ts # PUT pages YAML
api/admin/content/pages.get.ts # Liste toutes les pages
middleware/redirects.ts # 301 : /gestation, /modele-eco, /decision, /lire
docker/
Dockerfile # Build multi-stage (dev + prod)
docker-compose.yml # Production (Traefik)
docker-compose.dev.yml # Dev Docker
Dockerfile, docker-compose.yml, docker-compose.dev.yml
```
## Ports dev (CRITIQUE)
Chaque projet a un port fixe pour éviter les conflits Nuxt auto-increment :
| Projet | Port | Config |
|--------|------|--------|
| **librodrome** | **3000** | `nuxt.config.ts``devServer.port: 3000` |
@@ -41,32 +51,32 @@ Chaque projet a un port fixe pour éviter les conflits Nuxt auto-increment :
| **SejeteralO frontend** | **3009** | `frontend/nuxt.config.ts``devServer.port: 3009` |
| **SejeteralO backend** | **8000** | Makefile → `uvicorn --port 8000` |
Script de gestion : `/home/yvv/Documents/PROD/DEV/dev-ports.sh` (status/kill/clean/start)
**Ne jamais changer ces ports.** Si un port est occupé, tuer le process parasite plutôt que laisser Nuxt auto-incrémenter.
**Ne jamais changer ces ports.**
## Intégration GrateWizard
- URL dev configurée dans `app/app.config.ts``localhost:3001`
- URL dev : `app/app.config.ts``localhost:3001`
- URL prod : `https://gratewizard.axiom-team.fr`
- Ouverture en popup via `composables/useGrateWizard.ts`
- GrateWizard est un projet Next.js séparé (`/home/yvv/Documents/PROD/DEV/GrateWizard`)
- Bloc GrateWizard dans la section économique de la home
## Contenu
## Contenu administrable
Le contenu des pages est dans `data/pages/*.yml` et chargé via `composables/usePageContent.ts`. Le contenu riche (articles) utilise Nuxt Content avec des fichiers Markdown.
- YAML dans `site/pages/` organisé par section (sous-dossiers)
- API supporte les chemins imbriqués (`numerique/logiciel-libre`)
- Admin : `/admin/pages` liste toutes les pages, `/admin/pages/{path}` édite en YAML
- Git sync auto en prod (ADMIN_GIT_SYNC=true)
## Commandes
```bash
pnpm dev # Dev server sur :3000
pnpm build # Build production
pnpm generate # Génération statique
```
## Conventions
- Langue du site : français
- Commits en français, style concis
- CSS via UnoCSS (utility-first), pas de framework CSS externe
- CSS via UnoCSS (utility-first) + variables CSS palettes
- Composants Vue SFC avec `<script setup lang="ts">`
- Shadoks SVG inline thématiques sur chaque page (hidden mobile)

77
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,77 @@
# Contributing — Le Librodrome
## Architecture
```
app/
pages/
numerique/ # Section autonomie numérique
index.vue # Vue d'ensemble (3 piliers)
[slug].vue # Détail pilier (contenu YAML)
economique/ # Section autonomie économique
index.vue # Vue d'ensemble (monnaie libre, livre, productions)
monnaie-libre.vue
commande.vue # Commande du livre (Bookelis + librairie)
productions-collectives.vue
modele-eco/
index.vue # Couverture livre + sommaire chapitres
[slug].vue # Lecteur de chapitre (Nuxt Content)
citoyenne/ # Section autonomie citoyenne
index.vue # Vue d'ensemble (decision, tarifs-eau)
[slug].vue # Détail (contenu YAML)
en-musique/ # Player audio
evenement.vue
admin/ # Back-office protégé
pages/
index.vue # Liste toutes les pages YAML
[...path].vue # Éditeur YAML (supporte les sous-dossiers)
components/
book/Actions.vue # Boutons partagés du livre (player, PDF, chapitres, commande)
home/BookSection.vue # Bloc couverture + CTAs (utilise BookActions)
home/AxisBlock.vue # Bloc axe sur la home (supporte actions lien via `to`)
home/AxisGrid.vue # Grille 3 axes + GrateWizard
stores/palette.ts # 4 palettes saisonnières (été par défaut)
```
## Contenu YAML
API : `GET /api/content/pages/{path}` — supporte les chemins imbriqués (`numerique/logiciel-libre`).
Admin : `PUT /api/admin/content/pages/{path}` + `GET /api/admin/content/pages` (liste).
Les fichiers YAML sont dans `site/pages/`, organisés en sous-dossiers par section.
## Palettes
4 palettes dans `stores/palette.ts` : automne, hiver, printemps, été.
- Défaut : **été** (premier visiteur)
- Persisté en `localStorage('palette')` pour les visites suivantes
- CSS : variables `--color-primary`, `--color-accent`, etc. + classe `.palette-light`/`.palette-dark`
- Overrides light mode dans `main.css` (`.palette-light .text-white` → couleur adaptive)
## Shadoks
Illustrations SVG inline sur chaque page, thématiques par section :
- Numérique : métiers tech/industrie (codeuse, électricien, soudeuse...)
- Économique : artisanat/agriculture (boulangère, potier, forgeron...)
- Citoyenne : navigation/justice/théâtre (capitaine, avocate, comédien...)
- Modèle éco : livre/édition (typographe, calligraphe, conteuse...)
- Événement : spectacle (funambule, accordéoniste, jongleur...)
Règles : corps compact, longues pattes, grands pieds plats, bec pointu, postures variées.
CSS : `position: absolute`, `pointer-events: none`, `opacity 0.18-0.28`, animation float, `display: none` sur mobile.
## Redirections
`server/middleware/redirects.ts` :
- `/gestation/*` → section appropriée
- `/modele-eco/*``/economique/modele-eco/*`
- `/decision``/citoyenne/decision`
- `/lire/*``/economique/modele-eco/*`
- `/ecouter/*``/en-musique/*`
## Conventions
- Commits en français, concis
- Build prod vérifié avant push (`PORT=3099 node .output/server/index.mjs`)
- Port dev : 3000 (fixe, jamais de fallback)

118
README.md
View File

@@ -1,75 +1,63 @@
# Nuxt Minimal Starter
# Le Librodrome
Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
Site vitrine du projet Le Librodrome — livre + chansons sur l'économie du don.
## Setup
## Navigation
Make sure to install dependencies:
Le site est organisé en 3 grandes sections :
| Section | Route | Contenu |
|---------|-------|---------|
| **Numérique** | `/numerique` | Autonomie numérique : logiciel libre, authentification WoT, cloud libre |
| **Économique** | `/economique` | Création monétaire, monnaie libre, modèle économique (livre + chapitres), productions collectives |
| **Citoyenne** | `/citoyenne` | Décision collective (Glibredecision), tarifs de l'eau (SejeteralO) |
Autres pages : `/en-musique` (player audio), `/evenement`, `/a-propos`, `/messages`.
Chaque section a une page index et des sous-pages de détail (`/numerique/logiciel-libre`, `/economique/modele-eco`, etc.).
## Le livre
- **Lire** : lecteur PDF intégré, chapitres Markdown sous `/economique/modele-eco/[slug]`
- **Écouter** : player audio avec 9 morceaux sous `/en-musique`
- **Commander** : page `/economique/commande` (Bookelis + librairie)
## Stack
- **Nuxt 4** (Vue 3, TypeScript, Nitro)
- **UnoCSS** (utility-first) + palettes saisonnières (été par défaut)
- **Nuxt Content** pour les chapitres du livre
- **Pinia** pour l'état (palette, player)
- **pnpm** comme package manager
## Contenu administrable
Le contenu des pages est dans `site/pages/` en YAML, organisé par section :
```
site/pages/
home.yml # Page d'accueil
numerique.yml # Index numérique
numerique/*.yml # Sous-pages
economique.yml # Index économique
economique/*.yml # Sous-pages (modele-eco, monnaie-libre, commande...)
citoyenne.yml # Index citoyenne
citoyenne/*.yml # Sous-pages (decision, tarifs-eau)
en-musique.yml, evenement.yml, gratewizard.yml
```
Administration via `/admin/pages` (éditeur YAML, authentifié).
## Développement
```bash
# npm
npm install
# pnpm
pnpm install
# yarn
yarn install
# bun
bun install
pnpm dev # Dev server sur :3000
pnpm build # Build production
```
## Development Server
Port réservé : **3000** (ne pas changer).
Start the development server on `http://localhost:3000`:
## Déploiement
```bash
# npm
npm run dev
# pnpm
pnpm dev
# yarn
yarn dev
# bun
bun run dev
```
## Production
Build the application for production:
```bash
# npm
npm run build
# pnpm
pnpm build
# yarn
yarn build
# bun
bun run build
```
Locally preview production build:
```bash
# npm
npm run preview
# pnpm
pnpm preview
# yarn
yarn preview
# bun
bun run preview
```
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
Docker + Traefik, CI via Woodpecker. Domaine : `librodrome.org`.

View File

@@ -104,6 +104,7 @@ a {
.palette-light .text-white\/45 { color: hsl(var(--color-text) / 0.52) !important; }
.palette-light .text-white\/50 { color: hsl(var(--color-text) / 0.58) !important; }
.palette-light .text-white\/60 { color: hsl(var(--color-text) / 0.68) !important; }
.palette-light .text-white\/65 { color: hsl(var(--color-text) / 0.73) !important; }
.palette-light .text-white\/70 { color: hsl(var(--color-text) / 0.78) !important; }
.palette-light .text-white\/80 { color: hsl(var(--color-text) / 0.88) !important; }
.palette-light .text-white\/85 { color: hsl(var(--color-text) / 0.92) !important; }

View File

@@ -23,13 +23,25 @@
</NuxtLink>
<p class="sidebar-section">Pages</p>
<NuxtLink to="/admin/pages" class="sidebar-link" exact-active-class="sidebar-link--active">
<div class="i-lucide-file-text h-4 w-4" />
Toutes les pages
</NuxtLink>
<NuxtLink to="/admin/pages/home" class="sidebar-link" active-class="sidebar-link--active">
<div class="i-lucide-home h-4 w-4" />
Accueil
</NuxtLink>
<NuxtLink to="/admin/pages/modele-eco" class="sidebar-link" active-class="sidebar-link--active">
<div class="i-lucide-book-open h-4 w-4" />
Modèle éco
<NuxtLink to="/admin/pages/numerique" class="sidebar-link" active-class="sidebar-link--active">
<div class="i-lucide-monitor h-4 w-4" />
Numérique
</NuxtLink>
<NuxtLink to="/admin/pages/economique" class="sidebar-link" active-class="sidebar-link--active">
<div class="i-lucide-coins h-4 w-4" />
Économique
</NuxtLink>
<NuxtLink to="/admin/pages/citoyenne" class="sidebar-link" active-class="sidebar-link--active">
<div class="i-lucide-landmark h-4 w-4" />
Citoyenne
</NuxtLink>
<NuxtLink to="/admin/pages/en-musique" class="sidebar-link" active-class="sidebar-link--active">
<div class="i-lucide-headphones h-4 w-4" />

View File

@@ -0,0 +1,33 @@
<template>
<div class="mt-8 flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:gap-4">
<UiBaseButton @click="$emit('open-player')">
<div class="i-lucide-play mr-2 h-5 w-5" />
Présentation musicale
</UiBaseButton>
<UiBaseButton variant="accent" @click="$emit('open-pdf')">
<div class="i-lucide-book-open mr-2 h-5 w-5" />
Lire le livre
</UiBaseButton>
<UiBaseButton v-if="showChapters" variant="ghost" to="/economique/modele-eco">
<div class="i-lucide-list mr-2 h-5 w-5" />
Présentation des chapitres
</UiBaseButton>
<UiBaseButton variant="ghost" to="/economique/commande">
<div class="i-lucide-shopping-bag mr-2 h-5 w-5" />
Commandez le livre
</UiBaseButton>
</div>
</template>
<script setup lang="ts">
withDefaults(defineProps<{
showChapters?: boolean
}>(), {
showChapters: true,
})
defineEmits<{
'open-player': []
'open-pdf': []
}>()
</script>

View File

@@ -6,7 +6,7 @@
<ul class="flex flex-col gap-1">
<li v-for="chapter in chapters" :key="chapter.path">
<NuxtLink
:to="`/modele-eco/${chapter.stem?.split('/').pop()}`"
:to="`/economique/modele-eco/${chapter.stem?.split('/').pop()}`"
class="flex items-center gap-3 rounded-lg px-3 py-2 text-sm transition-colors hover:bg-white/5"
active-class="bg-primary/10 text-primary font-medium"
>

View File

@@ -56,15 +56,17 @@
</div>
<!-- Secondary row -->
<div v-if="secondaryActions(item.actions).length" class="axis-actions-secondary">
<button
<component
:is="action.to ? resolveComponent('NuxtLink') : 'button'"
v-for="action in secondaryActions(item.actions)"
:key="action.id"
:key="action.label"
:to="action.to"
class="axis-action-btn axis-action-btn--secondary"
@click.stop="handleAction(action.id)"
@click.stop="!action.to && handleAction(action.id)"
>
<div :class="iconClass(action.icon)" class="h-3.5 w-3.5" />
{{ action.label }}
</button>
</component>
</div>
</div>
</div>
@@ -79,6 +81,7 @@ interface AxisAction {
icon: string
highlight?: boolean
secondary?: boolean
to?: string
}
interface AxisItem {

View File

@@ -25,6 +25,24 @@
@open-pdf="$emit('open-pdf')"
@launch-gratewizard="launchGW"
/>
<!-- Bloc GrateWizard dans la section économique -->
<button v-if="gw" class="gw-block mt-4" @click="launchGW">
<div class="gw-icon">
<div class="i-lucide-sparkles h-5 w-5" />
</div>
<div class="gw-text">
<h3 class="font-display text-base font-bold text-white sm:text-lg">
{{ gw.title }}
</h3>
<p class="text-white/55 text-xs sm:text-sm mt-0.5">
{{ gw.subtitle }}
</p>
</div>
<div class="gw-arrow">
<div class="i-lucide-arrow-up-right h-4 w-4" />
</div>
</button>
</div>
</UiScrollReveal>
@@ -40,26 +58,6 @@
</div>
</UiScrollReveal>
<!-- Bloc GrateWizard -->
<UiScrollReveal v-if="gw" :delay="250">
<button class="gw-block" @click="launchGW">
<div class="gw-icon">
<div class="i-lucide-sparkles h-7 w-7" />
</div>
<div class="gw-text">
<h2 class="font-display text-xl font-bold text-white sm:text-2xl">
{{ gw.title }}
</h2>
<p class="text-white/55 text-sm sm:text-base mt-0.5">
{{ gw.subtitle }}
</p>
</div>
<div class="gw-arrow">
<div class="i-lucide-arrow-up-right h-5 w-5" />
</div>
</button>
</UiScrollReveal>
<!-- Bloc Événement -->
<UiScrollReveal v-if="evenement" :delay="350">
<NuxtLink :to="evenement.to" class="event-block">
@@ -160,10 +158,10 @@ function launchGW() {
.gw-block {
display: flex;
align-items: center;
gap: 1.25rem;
gap: 1rem;
width: 100%;
padding: 1.75rem 2rem;
border-radius: 1rem;
padding: 1.25rem 1.5rem;
border-radius: 0.75rem;
border: none;
background: linear-gradient(135deg, hsl(280 50% 20% / 0.35), hsl(260 40% 15% / 0.25));
box-shadow: 0 0 40px hsl(280 60% 50% / 0.06), inset 0 1px 0 hsl(280 60% 70% / 0.08);
@@ -187,9 +185,9 @@ function launchGW() {
display: flex;
align-items: center;
justify-content: center;
width: 3.5rem;
height: 3.5rem;
border-radius: 0.875rem;
width: 2.5rem;
height: 2.5rem;
border-radius: 0.625rem;
background: hsl(280 60% 55% / 0.18);
color: hsl(280 60% 72%);
flex-shrink: 0;
@@ -205,8 +203,8 @@ function launchGW() {
display: flex;
align-items: center;
justify-content: center;
width: 2.5rem;
height: 2.5rem;
width: 2rem;
height: 2rem;
border-radius: 50%;
background: hsl(280 60% 55% / 0.1);
color: hsl(280 60% 65%);

View File

@@ -5,23 +5,6 @@
<!-- Book cover -->
<UiScrollReveal>
<div class="book-cover-wrapper relative">
<!-- Shadok pumper -->
<svg class="shadok-pumper" viewBox="0 0 200 240" fill="none" aria-hidden="true">
<ellipse cx="100" cy="130" rx="55" ry="65" fill="currentColor" opacity="0.9"/>
<ellipse cx="100" cy="60" rx="30" ry="28" fill="currentColor" opacity="0.85"/>
<circle cx="88" cy="54" r="6" fill="currentColor" opacity="0.2"/>
<circle cx="112" cy="54" r="6" fill="currentColor" opacity="0.2"/>
<circle cx="90" cy="53" r="2.5" fill="currentColor" opacity="0.5"/>
<circle cx="114" cy="53" r="2.5" fill="currentColor" opacity="0.5"/>
<polygon points="100,68 115,78 85,78" fill="currentColor" opacity="0.6"/>
<line x1="80" y1="192" x2="70" y2="230" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.7"/>
<line x1="120" y1="192" x2="130" y2="230" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.7"/>
<line x1="70" y1="230" x2="55" y2="232" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.5"/>
<line x1="130" y1="230" x2="145" y2="232" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.5"/>
<line x1="155" y1="110" x2="190" y2="90" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.6"/>
<line x1="190" y1="90" x2="190" y2="120" stroke="currentColor" stroke-width="4" stroke-linecap="round" opacity="0.6"/>
<rect x="180" y="118" width="18" height="40" rx="3" fill="currentColor" opacity="0.4"/>
</svg>
<div class="book-cover-3d">
<img
:src="content?.book.coverImage"
@@ -48,16 +31,11 @@
</UiScrollReveal>
<UiScrollReveal :delay="200">
<div class="mt-8 flex flex-col gap-3 sm:flex-row sm:gap-4">
<UiBaseButton @click="$emit('open-player')">
<div class="i-lucide-play mr-2 h-5 w-5" />
{{ content?.book.cta.player }}
</UiBaseButton>
<UiBaseButton variant="accent" @click="$emit('open-pdf')">
<div class="i-lucide-book-open mr-2 h-5 w-5" />
{{ content?.book.cta.pdf }}
</UiBaseButton>
</div>
<BookActions
:show-chapters="showChapters"
@open-player="$emit('open-player')"
@open-pdf="$emit('open-pdf')"
/>
</UiScrollReveal>
</div>
</div>
@@ -66,6 +44,12 @@
</template>
<script setup lang="ts">
withDefaults(defineProps<{
showChapters?: boolean
}>(), {
showChapters: true,
})
defineEmits<{
'open-player': []
'open-pdf': []
@@ -111,25 +95,4 @@ const { data: content } = await usePageContent('home')
.heading-section {
font-size: clamp(1.625rem, 4vw, 2.125rem);
}
.shadok-pumper {
position: absolute;
right: 3%;
bottom: 8%;
width: clamp(90px, 12vw, 180px);
opacity: 0.28;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-float 10s ease-in-out infinite;
z-index: 1;
}
@keyframes shadok-float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
@media (max-width: 768px) {
.shadok-pumper { display: none; }
}
</style>

View File

@@ -9,8 +9,8 @@
<p class="text-sm text-white/50">Identité, navigation, footer</p>
</NuxtLink>
<NuxtLink to="/admin/pages/home" class="dash-card">
<div class="i-lucide-home h-8 w-8 text-primary mb-2" />
<NuxtLink to="/admin/pages" class="dash-card">
<div class="i-lucide-file-text h-8 w-8 text-primary mb-2" />
<h2 class="text-lg font-semibold text-white">Pages</h2>
<p class="text-sm text-white/50">Contenus des pages publiques</p>
</NuxtLink>

View File

@@ -2,11 +2,11 @@
<div>
<div class="flex items-center justify-between mb-6">
<div>
<NuxtLink to="/admin" class="text-sm text-white/40 hover:text-white/60 transition-colors">
Dashboard
<NuxtLink to="/admin/pages" class="text-sm text-white/40 hover:text-white/60 transition-colors">
Pages
</NuxtLink>
<h1 class="font-display text-2xl font-bold text-white mt-1">
Page : {{ pageName }}
Page : {{ pagePath }}
</h1>
</div>
<AdminSaveButton :saving="saving" :saved="saved" @save="save" />
@@ -40,9 +40,12 @@ definePageMeta({
})
const route = useRoute()
const pageName = computed(() => route.params.name as string)
const pagePath = computed(() => {
const p = route.params.path
return Array.isArray(p) ? p.join('/') : p
})
const { data, error } = await useFetch(() => `/api/content/pages/${pageName.value}`)
const { data, error } = await useFetch(() => `/api/content/pages/${pagePath.value}`)
const yamlContent = ref('')
@@ -60,7 +63,7 @@ async function save() {
saved.value = false
try {
const parsed = yaml.parse(yamlContent.value)
await $fetch(`/api/admin/content/pages/${pageName.value}`, {
await $fetch(`/api/admin/content/pages/${pagePath.value}`, {
method: 'PUT',
body: parsed,
})

View File

@@ -0,0 +1,97 @@
<template>
<div>
<div class="flex items-center justify-between mb-6">
<div>
<NuxtLink to="/admin" class="text-sm text-white/40 hover:text-white/60 transition-colors">
Dashboard
</NuxtLink>
<h1 class="font-display text-2xl font-bold text-white mt-1">Pages</h1>
</div>
</div>
<div v-if="pages" class="flex flex-col gap-6">
<!-- Root pages -->
<div v-if="rootPages.length">
<h2 class="font-display text-lg font-semibold text-white/80 mb-3">Pages principales</h2>
<div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
<NuxtLink
v-for="page in rootPages"
:key="page.path"
:to="`/admin/pages/${page.path}`"
class="page-card"
>
<div class="i-lucide-file-text h-5 w-5 text-primary mb-1" />
<span class="font-mono text-sm text-white">{{ page.label }}</span>
</NuxtLink>
</div>
</div>
<!-- Section pages -->
<div v-for="[section, sectionPages] in sections" :key="section">
<h2 class="font-display text-lg font-semibold text-white/80 mb-3">
<span class="i-lucide-folder h-4 w-4 inline-block mr-1 text-accent" />
{{ section }}
</h2>
<div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
<NuxtLink
v-for="page in sectionPages"
:key="page.path"
:to="`/admin/pages/${page.path}`"
class="page-card"
>
<div class="i-lucide-file-text h-5 w-5 text-primary/60 mb-1" />
<span class="font-mono text-sm text-white">{{ page.label }}</span>
</NuxtLink>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
definePageMeta({
layout: 'admin',
middleware: 'admin',
})
interface PageEntry {
path: string
label: string
section?: string
}
const { data: pages } = await useFetch<PageEntry[]>('/api/admin/content/pages')
const rootPages = computed(() =>
(pages.value ?? []).filter(p => !p.section),
)
const sections = computed(() => {
const map = new Map<string, PageEntry[]>()
for (const p of pages.value ?? []) {
if (p.section) {
if (!map.has(p.section)) map.set(p.section, [])
map.get(p.section)!.push(p)
}
}
return Array.from(map.entries())
})
</script>
<style scoped>
.page-card {
display: flex;
flex-direction: column;
padding: 1rem;
border-radius: 0.5rem;
border: 1px solid hsl(20 8% 14%);
background: hsl(20 8% 6%);
text-decoration: none;
transition: all 0.2s;
}
.page-card:hover {
border-color: hsl(12 76% 48% / 0.3);
background: hsl(20 8% 8%);
}
</style>

View File

@@ -0,0 +1,159 @@
<template>
<div class="section-padding">
<div class="container-content">
<div class="mx-auto max-w-2xl">
<div class="section-icon mx-auto mb-6">
<div :class="`i-lucide-${content?.icon ?? 'landmark'}`" class="h-12 w-12" />
</div>
<p class="mb-2 font-mono text-sm tracking-widest text-primary uppercase text-center">
{{ content?.kicker }}
</p>
<h1 class="font-display text-3xl font-bold mb-4 text-center" style="color: hsl(var(--color-text))">
{{ content?.title ?? slug }}
</h1>
<p class="text-lg leading-relaxed mb-8 text-center" style="color: hsl(var(--color-text-muted))">
{{ content?.description }}
</p>
<!-- Features grid (for decision page) -->
<div v-if="content?.features" class="grid gap-4 sm:grid-cols-2 mb-12">
<div v-for="feature in content.features" :key="feature.title" class="feature-card">
<div class="feature-icon">
<div :class="`i-lucide-${feature.icon} h-5 w-5`" />
</div>
<h3 class="font-display font-semibold mb-1" style="color: hsl(var(--color-text))">{{ feature.title }}</h3>
<p class="text-sm leading-relaxed" style="color: hsl(var(--color-text-muted))">{{ feature.text }}</p>
</div>
</div>
<!-- Project card -->
<div v-if="content?.project" class="project-card mb-8">
<div class="project-icon">
<div class="i-lucide-rocket h-5 w-5" />
</div>
<h2 class="font-display text-xl font-semibold mb-2" style="color: hsl(var(--color-text))">
{{ content.project.name }}
</h2>
<p style="color: hsl(var(--color-text-muted))" class="leading-relaxed">
{{ content.project.text }}
</p>
<span v-if="content?.gestation" class="gestation-badge mt-3">
<div class="i-lucide-flask-conical h-3 w-3" />
En gestation
</span>
</div>
<!-- Extended content -->
<div v-if="content?.content" class="prose-block mb-10">
<p class="leading-relaxed whitespace-pre-line" style="color: hsl(var(--color-text-muted))">
{{ content.content }}
</p>
</div>
<div class="text-center flex flex-col items-center gap-3 sm:flex-row sm:justify-center">
<UiBaseButton v-if="slug === 'decision'" :href="decisionUrl" target="_blank">
<div class="i-lucide-external-link mr-2 h-4 w-4" />
Ouvrir Glibredecision
</UiBaseButton>
<UiBaseButton v-if="slug === 'tarifs-eau'" :href="sejeteral0Url" target="_blank">
<div class="i-lucide-external-link mr-2 h-4 w-4" />
Lancer SejeteralO
</UiBaseButton>
<UiBaseButton variant="ghost" to="/citoyenne">
<div class="i-lucide-arrow-left mr-2 h-4 w-4" />
Autonomie citoyenne
</UiBaseButton>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
const route = useRoute()
const slug = route.params.slug as string
const { data: content } = await usePageContent(`citoyenne/${slug}`)
const appConfig = useAppConfig()
const decisionUrl = (appConfig.libredecision as { url: string })?.url ?? '#'
const sejeteral0Url = (appConfig.sejeteral0 as { url: string })?.url ?? '#'
useHead({
title: content.value?.meta?.title ?? slug,
})
</script>
<style scoped>
.section-icon {
display: flex;
align-items: center;
justify-content: center;
width: 5rem;
height: 5rem;
border-radius: 1rem;
background: hsl(var(--color-primary) / 0.1);
border: 1px solid hsl(var(--color-primary) / 0.2);
color: hsl(var(--color-primary));
}
.feature-card {
padding: 1.25rem;
border-radius: 0.75rem;
border: 1px solid hsl(var(--color-text) / 0.08);
background: hsl(var(--color-surface));
}
.feature-icon {
display: flex;
align-items: center;
justify-content: center;
width: 2.25rem;
height: 2.25rem;
border-radius: 0.5rem;
background: hsl(var(--color-primary) / 0.1);
color: hsl(var(--color-primary));
margin-bottom: 0.75rem;
}
.project-card {
padding: 1.5rem;
border-radius: 0.75rem;
border: 1px solid hsl(var(--color-primary) / 0.15);
background: hsl(var(--color-surface));
}
.project-icon {
display: flex;
align-items: center;
justify-content: center;
width: 2.5rem;
height: 2.5rem;
border-radius: 0.5rem;
background: hsl(var(--color-primary) / 0.1);
color: hsl(var(--color-primary));
margin-bottom: 1rem;
}
.gestation-badge {
display: inline-flex;
align-items: center;
gap: 0.25rem;
padding: 0.125rem 0.5rem;
border-radius: 9999px;
background: hsl(var(--color-accent) / 0.12);
color: hsl(var(--color-accent));
font-size: 0.7rem;
font-weight: 500;
font-family: var(--font-mono);
}
.prose-block {
padding: 1.5rem;
border-radius: 0.75rem;
background: hsl(var(--color-surface));
}
</style>

View File

@@ -0,0 +1,631 @@
<template>
<div class="relative overflow-hidden section-padding">
<!-- 1. Shadok Capitaine (top-left, profile at ship's wheel, telescope) -->
<svg class="shadok shadok-capitaine" viewBox="0 0 170 210" fill="none" xmlns="http://www.w3.org/2000/svg">
<g>
<!-- ship's wheel -->
<circle cx="50" cy="130" r="28" stroke="currentColor" stroke-width="3" fill="none" opacity="0.35"/>
<line x1="50" y1="102" x2="50" y2="158" stroke="currentColor" stroke-width="2.5" opacity="0.3"/>
<line x1="22" y1="130" x2="78" y2="130" stroke="currentColor" stroke-width="2.5" opacity="0.3"/>
<line x1="30" y1="110" x2="70" y2="150" stroke="currentColor" stroke-width="2.5" opacity="0.3"/>
<line x1="70" y1="110" x2="30" y2="150" stroke="currentColor" stroke-width="2.5" opacity="0.3"/>
<!-- wheel spokes knobs -->
<circle cx="50" cy="100" r="3" fill="currentColor" opacity="0.4"/>
<circle cx="50" cy="160" r="3" fill="currentColor" opacity="0.4"/>
<circle cx="20" cy="130" r="3" fill="currentColor" opacity="0.4"/>
<circle cx="80" cy="130" r="3" fill="currentColor" opacity="0.4"/>
<!-- body (small oval, profile facing right) -->
<ellipse cx="85" cy="110" rx="22" ry="28" fill="currentColor" opacity="0.25"/>
<!-- head -->
<circle cx="92" cy="68" r="16" fill="currentColor" opacity="0.3"/>
<!-- captain hat -->
<rect x="76" y="52" width="32" height="8" rx="4" fill="currentColor" opacity="0.4"/>
<rect x="80" y="46" width="24" height="8" rx="3" fill="currentColor" opacity="0.3"/>
<!-- hat brim detail -->
<ellipse cx="92" cy="60" rx="18" ry="3" fill="currentColor" opacity="0.2"/>
<!-- eyes (looking right through telescope) -->
<circle cx="98" cy="65" r="2.5" fill="currentColor" opacity="0.6"/>
<circle cx="90" cy="66" r="2" fill="currentColor" opacity="0.5"/>
<!-- beak (pointy, profile right) -->
<polygon points="108,68 120,65 108,72" fill="currentColor" opacity="0.35"/>
<!-- left arm on wheel -->
<line x1="65" y1="100" x2="55" y2="115" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- right arm holding telescope -->
<line x1="105" y1="95" x2="130" y2="72" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- telescope -->
<rect x="128" y="66" width="30" height="7" rx="3.5" fill="currentColor" opacity="0.4"/>
<rect x="155" y="64" width="10" height="11" rx="3" fill="currentColor" opacity="0.3"/>
<!-- left leg (long, forward) -->
<line x1="75" y1="135" x2="60" y2="190" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- left foot -->
<ellipse cx="55" cy="193" rx="9" ry="4" fill="currentColor" opacity="0.3"/>
<!-- right leg (long, back) -->
<line x1="92" y1="136" x2="100" y2="192" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- right foot -->
<ellipse cx="103" cy="195" rx="9" ry="4" fill="currentColor" opacity="0.3"/>
</g>
</svg>
<!-- 2. Shadok Avocate (top-right robe, scroll, arm up) -->
<svg class="shadok shadok-avocate" viewBox="0 0 160 210" fill="none" xmlns="http://www.w3.org/2000/svg">
<g>
<!-- body (small oval) -->
<ellipse cx="80" cy="115" rx="22" ry="30" fill="currentColor" opacity="0.25"/>
<!-- robe/gown flowing -->
<path d="M58 100 Q55 145 48 175 L112 175 Q105 145 102 100 Z" fill="currentColor" opacity="0.18"/>
<!-- robe collar -->
<path d="M68 88 Q80 96 92 88" stroke="currentColor" stroke-width="2.5" fill="none" opacity="0.35"/>
<!-- head -->
<circle cx="80" cy="70" r="16" fill="currentColor" opacity="0.3"/>
<!-- eyes (looking up-left) -->
<circle cx="74" cy="67" r="2.5" fill="currentColor" opacity="0.6"/>
<circle cx="83" cy="68" r="2" fill="currentColor" opacity="0.5"/>
<!-- beak (3/4 view, slight left) -->
<polygon points="68,72 56,69 66,76" fill="currentColor" opacity="0.35"/>
<!-- left arm up dramatically -->
<line x1="60" y1="100" x2="30" y2="55" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- open hand at top -->
<line x1="30" y1="55" x2="24" y2="46" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.35"/>
<line x1="30" y1="55" x2="28" y2="44" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.35"/>
<line x1="30" y1="55" x2="34" y2="46" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.35"/>
<!-- right arm holding scroll -->
<line x1="100" y1="102" x2="125" y2="90" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- scroll document (big) -->
<rect x="120" y="72" width="28" height="40" rx="3" fill="currentColor" opacity="0.25"/>
<!-- scroll curl top -->
<ellipse cx="134" cy="72" rx="14" ry="5" fill="currentColor" opacity="0.2"/>
<!-- scroll curl bottom -->
<ellipse cx="134" cy="112" rx="12" ry="4" fill="currentColor" opacity="0.2"/>
<!-- scroll text lines -->
<line x1="126" y1="82" x2="142" y2="82" stroke="currentColor" stroke-width="1.5" opacity="0.2"/>
<line x1="126" y1="88" x2="140" y2="88" stroke="currentColor" stroke-width="1.5" opacity="0.2"/>
<line x1="126" y1="94" x2="143" y2="94" stroke="currentColor" stroke-width="1.5" opacity="0.2"/>
<line x1="126" y1="100" x2="138" y2="100" stroke="currentColor" stroke-width="1.5" opacity="0.2"/>
<!-- left leg (long) -->
<line x1="72" y1="142" x2="62" y2="195" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<ellipse cx="58" cy="198" rx="9" ry="4" fill="currentColor" opacity="0.3"/>
<!-- right leg -->
<line x1="88" y1="142" x2="95" y2="196" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<ellipse cx="99" cy="199" rx="9" ry="4" fill="currentColor" opacity="0.3"/>
</g>
</svg>
<!-- 3. Shadok Vigie (left crow's nest, looking far) -->
<svg class="shadok shadok-vigie" viewBox="0 0 140 220" fill="none" xmlns="http://www.w3.org/2000/svg">
<g>
<!-- mast pole -->
<line x1="70" y1="90" x2="70" y2="218" stroke="currentColor" stroke-width="4" opacity="0.3"/>
<!-- crow's nest platform -->
<path d="M38 88 L42 100 L98 100 L102 88 Z" fill="currentColor" opacity="0.25"/>
<line x1="36" y1="88" x2="104" y2="88" stroke="currentColor" stroke-width="3" opacity="0.35"/>
<!-- nest railing -->
<line x1="40" y1="78" x2="40" y2="100" stroke="currentColor" stroke-width="2.5" opacity="0.3"/>
<line x1="100" y1="78" x2="100" y2="100" stroke="currentColor" stroke-width="2.5" opacity="0.3"/>
<line x1="40" y1="78" x2="100" y2="78" stroke="currentColor" stroke-width="2" opacity="0.25"/>
<!-- body (small, inside nest) -->
<ellipse cx="70" cy="72" rx="20" ry="22" fill="currentColor" opacity="0.25"/>
<!-- head -->
<circle cx="70" cy="38" r="15" fill="currentColor" opacity="0.3"/>
<!-- eyes (squinting, looking right far) -->
<circle cx="78" cy="35" r="2.5" fill="currentColor" opacity="0.6"/>
<circle cx="70" cy="36" r="2" fill="currentColor" opacity="0.4"/>
<!-- beak (profile right) -->
<polygon points="83,38 96,35 84,42" fill="currentColor" opacity="0.35"/>
<!-- right hand shielding eyes -->
<line x1="88" y1="55" x2="98" y2="35" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="96" y1="33" x2="108" y2="30" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.35"/>
<!-- left arm resting on railing -->
<line x1="52" y1="60" x2="42" y2="78" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- legs dangling below nest (long!) -->
<line x1="60" y1="98" x2="52" y2="160" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<ellipse cx="48" cy="163" rx="8" ry="4" fill="currentColor" opacity="0.3"/>
<line x1="80" y1="98" x2="86" y2="158" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<ellipse cx="90" cy="161" rx="8" ry="4" fill="currentColor" opacity="0.3"/>
</g>
</svg>
<!-- 4. Shadok Comedien (right theater masks, cape, leg lifted) -->
<svg class="shadok shadok-comedien" viewBox="0 0 170 210" fill="none" xmlns="http://www.w3.org/2000/svg">
<g>
<!-- dramatic cape -->
<path d="M65 85 Q40 120 35 180 L115 180 Q110 120 95 85 Z" fill="currentColor" opacity="0.15"/>
<path d="M95 85 Q120 100 135 160 Q130 165 115 180" fill="currentColor" opacity="0.1"/>
<!-- body (small oval) -->
<ellipse cx="80" cy="105" rx="20" ry="26" fill="currentColor" opacity="0.25"/>
<!-- head -->
<circle cx="80" cy="62" r="16" fill="currentColor" opacity="0.3"/>
<!-- eyes (different directions dramatic!) -->
<circle cx="74" cy="59" r="2.5" fill="currentColor" opacity="0.6"/>
<circle cx="86" cy="61" r="2.5" fill="currentColor" opacity="0.55"/>
<!-- beak -->
<polygon points="72,66 60,63 70,70" fill="currentColor" opacity="0.35"/>
<!-- left arm up holding comedy mask -->
<line x1="62" y1="92" x2="32" y2="55" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- comedy mask (big, smiling) -->
<circle cx="25" cy="42" r="16" fill="currentColor" opacity="0.2"/>
<path d="M17 46 Q25 56 33 46" stroke="currentColor" stroke-width="2" fill="none" opacity="0.4"/>
<circle cx="20" cy="38" r="2" fill="currentColor" opacity="0.5"/>
<circle cx="30" cy="38" r="2" fill="currentColor" opacity="0.5"/>
<!-- right arm out holding tragedy mask -->
<line x1="98" y1="92" x2="135" y2="65" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- tragedy mask (big, frowning) -->
<circle cx="145" cy="55" r="16" fill="currentColor" opacity="0.2"/>
<path d="M137 62 Q145 54 153 62" stroke="currentColor" stroke-width="2" fill="none" opacity="0.4"/>
<circle cx="140" cy="50" r="2" fill="currentColor" opacity="0.5"/>
<circle cx="150" cy="50" r="2" fill="currentColor" opacity="0.5"/>
<!-- left leg (long, planted) -->
<line x1="72" y1="128" x2="62" y2="190" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<ellipse cx="58" cy="193" rx="9" ry="4" fill="currentColor" opacity="0.3"/>
<!-- right leg (lifted dramatically!) -->
<line x1="88" y1="126" x2="115" y2="165" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<ellipse cx="120" cy="167" rx="8" ry="4" transform="rotate(-25 120 167)" fill="currentColor" opacity="0.3"/>
</g>
</svg>
<!-- 5. Shadok Cartographe (bottom-left sitting, map, compass) -->
<svg class="shadok shadok-cartographe" viewBox="0 0 180 190" fill="none" xmlns="http://www.w3.org/2000/svg">
<g>
<!-- table -->
<rect x="20" y="125" width="140" height="6" rx="2" fill="currentColor" opacity="0.3"/>
<line x1="35" y1="131" x2="30" y2="185" stroke="currentColor" stroke-width="3" opacity="0.25"/>
<line x1="145" y1="131" x2="150" y2="185" stroke="currentColor" stroke-width="3" opacity="0.25"/>
<!-- big map spread on table -->
<rect x="30" y="108" width="110" height="18" rx="2" fill="currentColor" opacity="0.2"/>
<!-- map details -->
<path d="M45 112 Q65 108 85 115 Q105 110 125 114" stroke="currentColor" stroke-width="1" fill="none" opacity="0.25"/>
<circle cx="75" cy="115" r="3" stroke="currentColor" stroke-width="1" fill="none" opacity="0.2"/>
<line x1="95" y1="110" x2="95" y2="122" stroke="currentColor" stroke-width="0.8" opacity="0.2"/>
<!-- body (small, hunched over map) -->
<ellipse cx="90" cy="88" rx="22" ry="25" fill="currentColor" opacity="0.25" transform="rotate(10 90 88)"/>
<!-- head (bent down looking at map) -->
<circle cx="78" cy="60" r="15" fill="currentColor" opacity="0.3"/>
<!-- eyes (looking down at map) -->
<circle cx="74" cy="64" r="2" fill="currentColor" opacity="0.6"/>
<circle cx="83" cy="65" r="2" fill="currentColor" opacity="0.5"/>
<!-- beak (pointing down) -->
<polygon points="72,70 65,78 78,72" fill="currentColor" opacity="0.35"/>
<!-- right arm holding compass tool -->
<line x1="110" y1="92" x2="130" y2="105" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- compass/divider tool (big V shape) -->
<line x1="130" y1="105" x2="125" y2="125" stroke="currentColor" stroke-width="2.5" opacity="0.4"/>
<line x1="130" y1="105" x2="140" y2="125" stroke="currentColor" stroke-width="2.5" opacity="0.4"/>
<circle cx="130" cy="103" r="3" fill="currentColor" opacity="0.3"/>
<!-- left arm holding magnifying glass -->
<line x1="70" y1="90" x2="48" y2="100" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- magnifying glass (big) -->
<circle cx="38" cy="96" r="12" stroke="currentColor" stroke-width="2.5" fill="none" opacity="0.35"/>
<line x1="48" y1="103" x2="55" y2="112" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- legs (sitting, bent under table) -->
<line x1="78" y1="110" x2="65" y2="145" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<line x1="65" y1="145" x2="50" y2="148" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3"/>
<ellipse cx="45" cy="150" rx="8" ry="3.5" fill="currentColor" opacity="0.3"/>
<line x1="100" y1="110" x2="110" y2="145" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<line x1="110" y1="145" x2="122" y2="148" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3"/>
<ellipse cx="127" cy="150" rx="8" ry="3.5" fill="currentColor" opacity="0.3"/>
</g>
</svg>
<!-- 6. Shadok Juge (bottom-right on bench, gavel, wig) -->
<svg class="shadok shadok-juge" viewBox="0 0 160 210" fill="none" xmlns="http://www.w3.org/2000/svg">
<g>
<!-- elevated bench/podium -->
<rect x="30" y="145" width="100" height="55" rx="4" fill="currentColor" opacity="0.2"/>
<rect x="25" y="138" width="110" height="10" rx="3" fill="currentColor" opacity="0.28"/>
<!-- bench front panel detail -->
<rect x="55" y="155" width="50" height="35" rx="3" fill="currentColor" opacity="0.1"/>
<!-- body (small, seated) -->
<ellipse cx="80" cy="112" rx="22" ry="28" fill="currentColor" opacity="0.25"/>
<!-- head -->
<circle cx="80" cy="68" r="16" fill="currentColor" opacity="0.3"/>
<!-- judge wig (curly puffs) -->
<circle cx="66" cy="60" r="6" fill="currentColor" opacity="0.2"/>
<circle cx="94" cy="60" r="6" fill="currentColor" opacity="0.2"/>
<circle cx="72" cy="54" r="5" fill="currentColor" opacity="0.18"/>
<circle cx="88" cy="54" r="5" fill="currentColor" opacity="0.18"/>
<circle cx="80" cy="52" r="5.5" fill="currentColor" opacity="0.2"/>
<!-- wig curls hanging -->
<circle cx="63" cy="70" r="4.5" fill="currentColor" opacity="0.15"/>
<circle cx="97" cy="70" r="4.5" fill="currentColor" opacity="0.15"/>
<!-- eyes (stern, both forward) -->
<circle cx="74" cy="66" r="2.5" fill="currentColor" opacity="0.65"/>
<circle cx="86" cy="66" r="2.5" fill="currentColor" opacity="0.65"/>
<!-- stern eyebrows -->
<line x1="71" y1="62" x2="77" y2="63" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.4"/>
<line x1="89" y1="63" x2="83" y2="62" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.4"/>
<!-- beak (small, stern) -->
<polygon points="80,74 72,78 80,80" fill="currentColor" opacity="0.35"/>
<!-- right arm raising gavel -->
<line x1="100" y1="98" x2="130" y2="60" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- gavel (big!) -->
<rect x="120" y="44" width="26" height="12" rx="4" fill="currentColor" opacity="0.4"/>
<line x1="133" y1="56" x2="133" y2="38" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- left arm on bench -->
<line x1="60" y1="100" x2="40" y2="130" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- legs (dangling from bench, long) -->
<line x1="72" y1="138" x2="62" y2="200" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<ellipse cx="58" cy="203" rx="9" ry="4" fill="currentColor" opacity="0.3"/>
<line x1="88" y1="138" x2="96" y2="198" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<ellipse cx="100" cy="201" rx="9" ry="4" fill="currentColor" opacity="0.3"/>
</g>
</svg>
<!-- 7. Shadok Matelot (center-bottom pulling rope, leaning back, anchor) -->
<svg class="shadok shadok-matelot" viewBox="0 0 160 200" fill="none" xmlns="http://www.w3.org/2000/svg">
<g>
<!-- rope going up and off -->
<path d="M30 20 Q35 50 55 70 Q65 78 68 85" stroke="currentColor" stroke-width="3" fill="none" opacity="0.3"/>
<!-- body (leaning back, tilted) -->
<ellipse cx="85" cy="108" rx="20" ry="27" fill="currentColor" opacity="0.25" transform="rotate(-15 85 108)"/>
<!-- head -->
<circle cx="95" cy="68" r="15" fill="currentColor" opacity="0.3"/>
<!-- bandana -->
<path d="M80 62 Q95 55 110 62" stroke="currentColor" stroke-width="3" fill="currentColor" opacity="0.2"/>
<line x1="108" y1="60" x2="118" y2="55" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.25"/>
<line x1="108" y1="62" x2="116" y2="60" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.2"/>
<!-- eyes (straining, squinting) -->
<circle cx="90" cy="66" r="2" fill="currentColor" opacity="0.6"/>
<circle cx="100" cy="65" r="2.5" fill="currentColor" opacity="0.55"/>
<!-- beak -->
<polygon points="104,70 115,67 105,74" fill="currentColor" opacity="0.35"/>
<!-- both arms pulling rope -->
<line x1="68" y1="95" x2="55" y2="78" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="75" y1="98" x2="62" y2="82" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- left leg (long, bracing forward) -->
<line x1="72" y1="130" x2="48" y2="185" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<ellipse cx="43" cy="188" rx="10" ry="4" fill="currentColor" opacity="0.3"/>
<!-- right leg (long, back) -->
<line x1="92" y1="132" x2="110" y2="188" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<ellipse cx="114" cy="191" rx="10" ry="4" fill="currentColor" opacity="0.3"/>
<!-- anchor nearby -->
<line x1="135" y1="140" x2="135" y2="185" stroke="currentColor" stroke-width="3" opacity="0.3"/>
<circle cx="135" cy="138" r="5" stroke="currentColor" stroke-width="2" fill="none" opacity="0.25"/>
<path d="M120 180 Q135 195 150 180" stroke="currentColor" stroke-width="3" fill="none" opacity="0.3"/>
<line x1="120" y1="180" x2="117" y2="174" stroke="currentColor" stroke-width="2.5" opacity="0.3"/>
<line x1="150" y1="180" x2="153" y2="174" stroke="currentColor" stroke-width="2.5" opacity="0.3"/>
</g>
</svg>
<!-- 8. Shadok Mime (right pushing invisible wall, striped shirt, beret) -->
<svg class="shadok shadok-mime" viewBox="0 0 150 210" fill="none" xmlns="http://www.w3.org/2000/svg">
<g>
<!-- body (small oval) -->
<ellipse cx="70" cy="112" rx="22" ry="28" fill="currentColor" opacity="0.2"/>
<!-- striped shirt lines -->
<line x1="52" y1="96" x2="88" y2="96" stroke="currentColor" stroke-width="2" opacity="0.2"/>
<line x1="50" y1="102" x2="90" y2="102" stroke="currentColor" stroke-width="2" opacity="0.2"/>
<line x1="50" y1="108" x2="90" y2="108" stroke="currentColor" stroke-width="2" opacity="0.2"/>
<line x1="50" y1="114" x2="90" y2="114" stroke="currentColor" stroke-width="2" opacity="0.2"/>
<line x1="52" y1="120" x2="88" y2="120" stroke="currentColor" stroke-width="2" opacity="0.2"/>
<line x1="54" y1="126" x2="86" y2="126" stroke="currentColor" stroke-width="2" opacity="0.2"/>
<!-- head (white face = lighter) -->
<circle cx="75" cy="65" r="16" fill="currentColor" opacity="0.2"/>
<!-- white face highlight -->
<circle cx="75" cy="65" r="13" fill="currentColor" opacity="0.08"/>
<!-- beret -->
<ellipse cx="75" cy="50" rx="18" ry="6" fill="currentColor" opacity="0.3"/>
<circle cx="75" cy="46" r="3" fill="currentColor" opacity="0.25"/>
<!-- eyes (expressive, wide) -->
<circle cx="69" cy="62" r="3" fill="currentColor" opacity="0.55"/>
<circle cx="81" cy="62" r="3" fill="currentColor" opacity="0.55"/>
<!-- raised eyebrows (surprised) -->
<path d="M66 57 Q69 54 72 57" stroke="currentColor" stroke-width="1.5" fill="none" opacity="0.4"/>
<path d="M78 57 Q81 54 84 57" stroke="currentColor" stroke-width="1.5" fill="none" opacity="0.4"/>
<!-- beak (small) -->
<polygon points="75,72 68,76 75,78" fill="currentColor" opacity="0.3"/>
<!-- both arms pushing against invisible wall (to the right) -->
<line x1="90" y1="100" x2="125" y2="85" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="90" y1="115" x2="125" y2="110" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- flat hands pressed against wall -->
<rect x="124" y="78" width="12" height="15" rx="3" fill="currentColor" opacity="0.2"/>
<rect x="124" y="103" width="12" height="15" rx="3" fill="currentColor" opacity="0.2"/>
<!-- invisible wall hint (faint line) -->
<line x1="138" y1="50" x2="138" y2="180" stroke="currentColor" stroke-width="1" stroke-dasharray="4 6" opacity="0.12"/>
<!-- left leg (long, leaning forward) -->
<line x1="60" y1="138" x2="45" y2="195" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<ellipse cx="40" cy="198" rx="9" ry="4" fill="currentColor" opacity="0.3"/>
<!-- right leg (long, back) -->
<line x1="80" y1="138" x2="95" y2="194" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<ellipse cx="99" cy="197" rx="9" ry="4" fill="currentColor" opacity="0.3"/>
</g>
</svg>
<div class="container-content">
<header class="mb-12 text-center">
<p class="mb-2 font-mono text-sm tracking-widest text-primary uppercase">{{ content?.kicker }}</p>
<h1 class="page-title font-display font-bold tracking-tight" style="color: hsl(var(--color-text))">
{{ content?.title }}
</h1>
<p class="mt-4 mx-auto max-w-2xl leading-relaxed" style="color: hsl(var(--color-text-muted))">
{{ content?.description }}
</p>
</header>
<div class="mx-auto max-w-3xl flex flex-col gap-6">
<!-- Decision collective -->
<div class="item-card">
<NuxtLink to="/citoyenne/decision" class="item-body group">
<div class="item-header">
<div class="item-icon">
<div class="i-lucide-gavel h-5 w-5" />
</div>
<h2 class="font-display text-xl font-bold" style="color: hsl(var(--color-text))">
Décision collective
</h2>
</div>
<p class="leading-relaxed mt-3" style="color: hsl(var(--color-text-muted))">
Se donner les moyens de la décision collective.
</p>
<div class="mt-3 inline-flex items-center gap-1 text-sm text-primary group-hover:text-primary/80 transition-colors">
En savoir plus
<div class="i-lucide-arrow-right h-3.5 w-3.5" />
</div>
</NuxtLink>
<div class="item-actions">
<a :href="decisionUrl" target="_blank" rel="noopener" class="action-btn action-btn--primary">
<div class="i-lucide-external-link h-3.5 w-3.5" />
Ouvrir Glibredecision
</a>
</div>
</div>
<!-- Tarifs de l'eau -->
<div class="item-card">
<NuxtLink to="/citoyenne/tarifs-eau" class="item-body group">
<div class="item-header">
<div class="item-icon">
<div class="i-lucide-droplets h-5 w-5" />
</div>
<h2 class="font-display text-xl font-bold" style="color: hsl(var(--color-text))">
Tarifs de l'eau
</h2>
<span class="gestation-badge">
<div class="i-lucide-flask-conical h-3 w-3" />
En gestation
</span>
</div>
<p class="leading-relaxed mt-3" style="color: hsl(var(--color-text-muted))">
Application pour obtenir justice sociale et incitation dynamique à la réduction.
Permet de confier la décision à la population des communes.
</p>
<div class="mt-3 inline-flex items-center gap-1 text-sm text-primary group-hover:text-primary/80 transition-colors">
En savoir plus
<div class="i-lucide-arrow-right h-3.5 w-3.5" />
</div>
</NuxtLink>
<div class="item-actions">
<a :href="sejeteral0Url" target="_blank" rel="noopener" class="action-btn action-btn--primary">
<div class="i-lucide-external-link h-3.5 w-3.5" />
Lancer SejeteralO
</a>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
definePageMeta({
layout: 'default',
})
const { data: content } = await usePageContent('citoyenne')
const appConfig = useAppConfig()
const decisionUrl = (appConfig.libredecision as { url: string })?.url ?? '#'
const sejeteral0Url = (appConfig.sejeteral0 as { url: string })?.url ?? '#'
useHead({
title: content.value?.meta?.title ?? 'Autonomie citoyenne',
})
</script>
<style scoped>
.page-title {
font-size: clamp(2rem, 5vw, 2.75rem);
}
.item-card {
border-radius: 0.75rem;
border: 1px solid hsl(var(--color-text) / 0.08);
background: hsl(var(--color-surface));
transition: border-color 0.2s;
overflow: hidden;
}
.item-card:hover {
border-color: hsl(var(--color-primary) / 0.2);
}
.item-body {
display: block;
padding: 1.5rem;
text-decoration: none;
color: inherit;
}
.item-header {
display: flex;
align-items: center;
gap: 0.75rem;
}
.item-icon {
display: flex;
align-items: center;
justify-content: center;
width: 2.25rem;
height: 2.25rem;
border-radius: 0.5rem;
background: hsl(var(--color-primary) / 0.15);
color: hsl(var(--color-primary));
box-shadow: 0 0 12px hsl(var(--color-primary) / 0.12);
flex-shrink: 0;
}
.gestation-badge {
display: inline-flex;
align-items: center;
gap: 0.25rem;
margin-left: auto;
padding: 0.125rem 0.5rem;
border-radius: 9999px;
background: hsl(var(--color-accent) / 0.12);
color: hsl(var(--color-accent));
font-size: 0.7rem;
font-weight: 500;
font-family: var(--font-mono);
}
.item-actions {
display: flex;
flex-wrap: wrap;
gap: 0.375rem;
padding: 0.75rem 1.5rem;
border-top: 1px solid hsl(var(--color-text) / 0.06);
background: hsl(var(--color-bg) / 0.4);
}
.action-btn {
display: inline-flex;
align-items: center;
gap: 0.375rem;
padding: 0.375rem 0.75rem;
border-radius: 0.5rem;
font-size: 0.8rem;
font-weight: 500;
text-decoration: none;
transition: all 0.2s;
cursor: pointer;
}
.action-btn--primary {
color: hsl(var(--color-primary));
background: hsl(var(--color-primary) / 0.12);
border: 1px solid hsl(var(--color-primary) / 0.25);
}
.action-btn--primary:hover {
background: hsl(var(--color-primary) / 0.2);
border-color: hsl(var(--color-primary) / 0.4);
}
/* Shadok illustrations */
.shadok {
position: absolute;
pointer-events: none;
width: clamp(70px, 10vw, 140px);
z-index: 0;
}
.shadok-capitaine {
top: 2%;
left: 2%;
color: hsl(var(--color-primary));
opacity: 0.22;
animation: shadok-float-1 9s ease-in-out infinite;
}
.shadok-avocate {
top: 1%;
right: 2%;
color: hsl(var(--color-accent));
opacity: 0.2;
animation: shadok-float-2 11s ease-in-out infinite;
}
.shadok-vigie {
left: 2%;
top: 38%;
color: hsl(var(--color-primary));
opacity: 0.24;
animation: shadok-float-3 10s ease-in-out infinite;
}
.shadok-comedien {
right: 3%;
top: 35%;
color: hsl(var(--color-accent));
opacity: 0.2;
animation: shadok-float-4 8s ease-in-out infinite;
}
.shadok-cartographe {
bottom: 10%;
left: 1%;
color: hsl(var(--color-accent));
opacity: 0.22;
animation: shadok-float-5 12s ease-in-out infinite;
}
.shadok-juge {
bottom: 6%;
right: 1%;
color: hsl(var(--color-primary));
opacity: 0.24;
animation: shadok-float-6 9.5s ease-in-out infinite;
}
.shadok-matelot {
bottom: 2%;
left: 50%;
transform: translateX(-50%);
color: hsl(var(--color-primary));
opacity: 0.18;
animation: shadok-float-7 7s ease-in-out infinite;
}
.shadok-mime {
right: 2%;
top: 55%;
color: hsl(var(--color-accent));
opacity: 0.28;
animation: shadok-float-8 10.5s ease-in-out infinite;
}
@keyframes shadok-float-1 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
}
@keyframes shadok-float-2 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
@keyframes shadok-float-3 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-7px); }
}
@keyframes shadok-float-4 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-9px); }
}
@keyframes shadok-float-5 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-6px); }
}
@keyframes shadok-float-6 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
}
@keyframes shadok-float-7 {
0%, 100% { transform: translateX(-50%) translateY(0); }
50% { transform: translateX(-50%) translateY(-7px); }
}
@keyframes shadok-float-8 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
@media (max-width: 768px) {
.shadok {
display: none;
}
}
</style>

View File

@@ -1,104 +0,0 @@
<template>
<div class="section-padding">
<div class="container-content">
<div class="mx-auto max-w-3xl">
<!-- Header -->
<div class="text-center mb-12">
<div class="decision-icon mx-auto mb-6">
<div class="i-lucide-gavel h-10 w-10" />
</div>
<h1 class="font-display text-4xl font-bold text-white mb-4">Plateforme Décision</h1>
<p class="text-lg text-white/60 leading-relaxed">
Se donner les moyens de la décision collective.
</p>
</div>
<!-- Features -->
<div class="grid gap-4 sm:grid-cols-2 mb-12">
<div v-for="feature in features" :key="feature.title" class="feature-card">
<div class="feature-icon">
<div :class="`i-lucide-${feature.icon} h-5 w-5`" />
</div>
<h3 class="font-display font-semibold text-white mb-1">{{ feature.title }}</h3>
<p class="text-sm text-white/50 leading-relaxed">{{ feature.text }}</p>
</div>
</div>
<!-- CTA -->
<div class="text-center flex flex-col items-center gap-3 sm:flex-row sm:justify-center">
<UiBaseButton :href="decisionUrl" target="_blank">
<div class="i-lucide-external-link mr-2 h-4 w-4" />
Ouvrir Glibredecision
</UiBaseButton>
<UiBaseButton variant="ghost" to="/">
<div class="i-lucide-arrow-left mr-2 h-4 w-4" />
Retour à l'accueil
</UiBaseButton>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
useHead({ title: 'Décision collective' })
const appConfig = useAppConfig()
const decisionUrl = (appConfig.libredecision as { url: string }).url
const features = [
{
icon: 'vote',
title: 'Décisions on-chain',
text: 'Des décisions transparentes et vérifiables, inscrites sur la blockchain.',
},
{
icon: 'scroll-text',
title: 'Les Mandats',
text: 'Formaliser et suivre les mandats confiés aux personnes désignées.',
},
{
icon: 'scroll-text',
title: 'Documents de référence',
text: 'Les textes fondateurs et documents qui encadrent la prise de décision.',
},
{
icon: 'git-branch',
title: 'Les Protocoles',
text: 'Les règles et processus qui structurent la décision collective.',
},
]
</script>
<style scoped>
.decision-icon {
display: flex;
align-items: center;
justify-content: center;
width: 5rem;
height: 5rem;
border-radius: 1rem;
background: hsl(var(--color-primary) / 0.1);
border: 1px solid hsl(var(--color-primary) / 0.2);
color: hsl(var(--color-primary));
}
.feature-card {
padding: 1.25rem;
border-radius: 0.75rem;
border: 1px solid hsl(var(--color-text) / 0.08);
background: hsl(var(--color-surface));
}
.feature-icon {
display: flex;
align-items: center;
justify-content: center;
width: 2.25rem;
height: 2.25rem;
border-radius: 0.5rem;
background: hsl(var(--color-primary) / 0.1);
color: hsl(var(--color-primary));
margin-bottom: 0.75rem;
}
</style>

View File

@@ -0,0 +1,453 @@
<template>
<div class="relative overflow-hidden section-padding">
<!-- Shadok 1 : Libraire behind counter, 3/4 view, glasses, recommending a book -->
<svg class="shadok-libraire" viewBox="0 0 160 210" fill="none" aria-hidden="true">
<!-- Body (small oval) -->
<ellipse cx="75" cy="95" rx="22" ry="28" fill="currentColor" opacity="0.25"/>
<!-- Head -->
<circle cx="75" cy="58" r="16" fill="currentColor" opacity="0.3"/>
<!-- Eyes looking right (recommending) -->
<circle cx="80" cy="55" r="2" fill="currentColor" opacity="0.6"/>
<circle cx="86" cy="54" r="2" fill="currentColor" opacity="0.6"/>
<!-- Glasses on beak -->
<circle cx="80" cy="55" r="5" stroke="currentColor" stroke-width="1.2" fill="none" opacity="0.4"/>
<circle cx="86" cy="54" r="5" stroke="currentColor" stroke-width="1.2" fill="none" opacity="0.4"/>
<line x1="85" y1="55" x2="81" y2="54" stroke="currentColor" stroke-width="1" opacity="0.3"/>
<!-- Beak (pointy, triangular) -->
<polygon points="90,58 102,55 90,52" fill="currentColor" opacity="0.35"/>
<!-- Arm holding book out to customer -->
<line x1="97" y1="88" x2="125" y2="78" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Book in hand (big, detailed) -->
<rect x="120" y="70" width="18" height="24" rx="2" fill="currentColor" opacity="0.35"/>
<rect x="122" y="73" width="14" height="3" rx="1" fill="currentColor" opacity="0.2"/>
<line x1="129" y1="70" x2="129" y2="94" stroke="currentColor" stroke-width="1" opacity="0.2"/>
<!-- Other arm resting on counter -->
<line x1="53" y1="90" x2="35" y2="108" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Counter (big) -->
<rect x="10" y="120" width="140" height="10" rx="2" fill="currentColor" opacity="0.3"/>
<rect x="15" y="130" width="130" height="6" rx="1" fill="currentColor" opacity="0.15"/>
<!-- Stack of books on counter -->
<rect x="25" y="105" width="22" height="15" rx="2" fill="currentColor" opacity="0.3"/>
<rect x="28" y="98" width="18" height="7" rx="1" fill="currentColor" opacity="0.25"/>
<rect x="30" y="93" width="14" height="5" rx="1" fill="currentColor" opacity="0.2"/>
<!-- Legs (long!) -->
<line x1="65" y1="123" x2="55" y2="185" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<line x1="85" y1="123" x2="95" y2="185" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- Big flat feet -->
<ellipse cx="50" cy="188" rx="10" ry="4" fill="currentColor" opacity="0.3"/>
<ellipse cx="100" cy="188" rx="10" ry="4" fill="currentColor" opacity="0.3"/>
</svg>
<!-- Shadok 2 : Factrice running profile, letter carrier bag, letters flying, cap -->
<svg class="shadok-factrice" viewBox="0 0 180 200" fill="none" aria-hidden="true">
<!-- Body (small oval, leaning forward) -->
<ellipse cx="80" cy="80" rx="20" ry="26" fill="currentColor" opacity="0.25" transform="rotate(-15 80 80)"/>
<!-- Head -->
<circle cx="95" cy="48" r="15" fill="currentColor" opacity="0.3"/>
<!-- Cap -->
<rect x="82" y="34" width="28" height="7" rx="3" fill="currentColor" opacity="0.4"/>
<rect x="106" y="36" width="10" height="5" rx="2" fill="currentColor" opacity="0.3"/>
<!-- Eyes (determined, looking forward) -->
<circle cx="101" cy="46" r="1.8" fill="currentColor" opacity="0.6"/>
<circle cx="106" cy="45" r="1.8" fill="currentColor" opacity="0.6"/>
<!-- Beak (pointy, profile) -->
<polygon points="110,48 125,44 110,42" fill="currentColor" opacity="0.35"/>
<!-- Carrier bag (big, on shoulder) -->
<rect x="55" y="62" width="28" height="35" rx="4" fill="currentColor" opacity="0.3"/>
<line x1="60" y1="62" x2="75" y2="55" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.3"/>
<!-- Letters flying out of bag -->
<rect x="42" y="55" width="12" height="9" rx="1" fill="currentColor" opacity="0.2" transform="rotate(-20 48 59)"/>
<rect x="35" y="45" width="10" height="7" rx="1" fill="currentColor" opacity="0.15" transform="rotate(-35 40 48)"/>
<rect x="48" y="42" width="11" height="8" rx="1" fill="currentColor" opacity="0.18" transform="rotate(10 53 46)"/>
<!-- Arm swinging back -->
<line x1="65" y1="72" x2="45" y2="90" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- Running legs (long strides!) -->
<line x1="72" y1="106" x2="40" y2="170" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<line x1="88" y1="106" x2="130" y2="165" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- Big flat feet -->
<ellipse cx="35" cy="174" rx="11" ry="4" fill="currentColor" opacity="0.3"/>
<ellipse cx="135" cy="168" rx="11" ry="4" fill="currentColor" opacity="0.3"/>
</svg>
<!-- Shadok 3 : Cartonnier assembling cardboard box, tape gun, flat boxes nearby -->
<svg class="shadok-cartonnier" viewBox="0 0 170 220" fill="none" aria-hidden="true">
<!-- Body (small, leaning over work) -->
<ellipse cx="70" cy="100" rx="22" ry="27" fill="currentColor" opacity="0.25" transform="rotate(8 70 100)"/>
<!-- Head (looking down at box) -->
<circle cx="78" cy="65" r="15" fill="currentColor" opacity="0.3"/>
<!-- Eyes (focused, looking down) -->
<circle cx="83" cy="67" r="1.8" fill="currentColor" opacity="0.6"/>
<circle cx="88" cy="68" r="1.8" fill="currentColor" opacity="0.6"/>
<!-- Beak pointing down -->
<polygon points="88,72 98,78 86,76" fill="currentColor" opacity="0.35"/>
<!-- Arm holding tape gun -->
<line x1="90" y1="95" x2="130" y2="105" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- Tape gun (big, detailed) -->
<circle cx="138" cy="102" r="8" fill="currentColor" opacity="0.25"/>
<rect x="132" y="99" width="18" height="6" rx="1" fill="currentColor" opacity="0.35"/>
<polygon points="150,100 158,102 150,104" fill="currentColor" opacity="0.3"/>
<!-- Other arm holding box flap -->
<line x1="50" y1="92" x2="35" y2="118" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- Box being assembled (big, 3D perspective) -->
<rect x="25" y="118" width="45" height="35" rx="2" fill="currentColor" opacity="0.2"/>
<polygon points="25,118 15,108 60,108 70,118" fill="currentColor" opacity="0.15"/>
<polygon points="70,118 60,108 60,143 70,153" fill="currentColor" opacity="0.12"/>
<!-- Flap open -->
<polygon points="25,118 15,108 15,98 25,108" fill="currentColor" opacity="0.18"/>
<!-- Flat boxes nearby -->
<rect x="90" y="145" width="35" height="4" rx="1" fill="currentColor" opacity="0.2"/>
<rect x="88" y="150" width="38" height="4" rx="1" fill="currentColor" opacity="0.15"/>
<rect x="92" y="155" width="32" height="4" rx="1" fill="currentColor" opacity="0.12"/>
<!-- Legs (long!) -->
<line x1="60" y1="127" x2="48" y2="192" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<line x1="80" y1="127" x2="92" y2="192" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- Big flat feet -->
<ellipse cx="43" cy="196" rx="10" ry="4" fill="currentColor" opacity="0.3"/>
<ellipse cx="97" cy="196" rx="10" ry="4" fill="currentColor" opacity="0.3"/>
</svg>
<!-- Shadok 4 : Cycliste livreur on bicycle, package on rack, profile leaning forward -->
<svg class="shadok-cycliste" viewBox="0 0 180 200" fill="none" aria-hidden="true">
<!-- Back wheel -->
<circle cx="35" cy="160" r="22" stroke="currentColor" stroke-width="2.5" fill="none" opacity="0.25"/>
<circle cx="35" cy="160" r="3" fill="currentColor" opacity="0.3"/>
<!-- Front wheel -->
<circle cx="145" cy="160" r="22" stroke="currentColor" stroke-width="2.5" fill="none" opacity="0.25"/>
<circle cx="145" cy="160" r="3" fill="currentColor" opacity="0.3"/>
<!-- Frame -->
<line x1="35" y1="160" x2="80" y2="120" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.3"/>
<line x1="80" y1="120" x2="120" y2="120" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.3"/>
<line x1="120" y1="120" x2="145" y2="160" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.3"/>
<line x1="35" y1="160" x2="80" y2="140" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.2"/>
<line x1="80" y1="140" x2="120" y2="120" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.2"/>
<!-- Handlebars -->
<line x1="120" y1="120" x2="130" y2="105" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.3"/>
<line x1="125" y1="105" x2="135" y2="105" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.3"/>
<!-- Saddle -->
<rect x="72" y="116" width="16" height="5" rx="2" fill="currentColor" opacity="0.3"/>
<!-- Package on rear rack (big!) -->
<rect x="15" y="125" width="30" height="22" rx="3" fill="currentColor" opacity="0.3"/>
<line x1="30" y1="125" x2="30" y2="147" stroke="currentColor" stroke-width="1" opacity="0.2"/>
<line x1="15" y1="136" x2="45" y2="136" stroke="currentColor" stroke-width="1" opacity="0.2"/>
<!-- Rear rack -->
<line x1="35" y1="147" x2="35" y2="155" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.25"/>
<line x1="15" y1="147" x2="55" y2="147" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.25"/>
<!-- Body (small, leaning forward on bike) -->
<ellipse cx="90" cy="100" rx="18" ry="24" fill="currentColor" opacity="0.25" transform="rotate(-20 90 100)"/>
<!-- Head -->
<circle cx="108" cy="68" r="14" fill="currentColor" opacity="0.3"/>
<!-- Eyes (focused ahead) -->
<circle cx="115" cy="65" r="1.8" fill="currentColor" opacity="0.6"/>
<circle cx="120" cy="64" r="1.8" fill="currentColor" opacity="0.6"/>
<!-- Beak -->
<polygon points="122,68 134,64 122,62" fill="currentColor" opacity="0.35"/>
<!-- Arms to handlebars -->
<line x1="100" y1="90" x2="130" y2="105" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- Legs pedaling -->
<line x1="82" y1="118" x2="72" y2="145" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<line x1="88" y1="120" x2="95" y2="148" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- Feet on pedals -->
<ellipse cx="70" cy="148" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
<ellipse cx="97" cy="150" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
</svg>
<!-- Shadok 5 : Lectrice satisfaite sitting in armchair, open book, wrapping paper on floor -->
<svg class="shadok-lectrice" viewBox="0 0 160 210" fill="none" aria-hidden="true">
<!-- Armchair (big!) -->
<path d="M20 100 Q20 80 35 80 L115 80 Q130 80 130 100 L130 150 L20 150 Z" fill="currentColor" opacity="0.15"/>
<!-- Armrests -->
<rect x="10" y="90" width="16" height="55" rx="6" fill="currentColor" opacity="0.2"/>
<rect x="124" y="90" width="16" height="55" rx="6" fill="currentColor" opacity="0.2"/>
<!-- Chair legs -->
<line x1="25" y1="150" x2="22" y2="165" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.2"/>
<line x1="125" y1="150" x2="128" y2="165" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.2"/>
<!-- Body (sitting, small) -->
<ellipse cx="75" cy="120" rx="20" ry="25" fill="currentColor" opacity="0.25"/>
<!-- Head (tilted, reading happily) -->
<circle cx="75" cy="82" r="16" fill="currentColor" opacity="0.3"/>
<!-- Happy eyes (curved) -->
<path d="M66 79 Q69 76 72 79" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.5"/>
<path d="M80 78 Q83 75 86 78" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.5"/>
<!-- Small smile -->
<path d="M70 88 Q75 93 80 88" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.3"/>
<!-- Beak (small, happy) -->
<polygon points="88,83 98,80 88,78" fill="currentColor" opacity="0.3"/>
<!-- Arms holding open book -->
<line x1="55" y1="112" x2="40" y2="125" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<line x1="95" y1="112" x2="110" y2="125" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- Open book (big, in lap) -->
<rect x="38" y="125" width="28" height="20" rx="1" fill="currentColor" opacity="0.3"/>
<rect x="66" y="125" width="28" height="20" rx="1" fill="currentColor" opacity="0.25"/>
<line x1="66" y1="125" x2="66" y2="145" stroke="currentColor" stroke-width="1.5" opacity="0.35"/>
<!-- Text lines on book pages -->
<line x1="42" y1="131" x2="62" y2="131" stroke="currentColor" stroke-width="0.8" opacity="0.15"/>
<line x1="42" y1="135" x2="60" y2="135" stroke="currentColor" stroke-width="0.8" opacity="0.15"/>
<line x1="70" y1="131" x2="90" y2="131" stroke="currentColor" stroke-width="0.8" opacity="0.15"/>
<line x1="70" y1="135" x2="88" y2="135" stroke="currentColor" stroke-width="0.8" opacity="0.15"/>
<!-- Legs (long, dangling from chair) -->
<line x1="62" y1="145" x2="50" y2="195" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<line x1="88" y1="145" x2="100" y2="195" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- Big flat feet -->
<ellipse cx="45" cy="198" rx="10" ry="4" fill="currentColor" opacity="0.3"/>
<ellipse cx="105" cy="198" rx="10" ry="4" fill="currentColor" opacity="0.3"/>
<!-- Wrapping paper on floor -->
<path d="M30 175 Q45 170 55 178 Q60 182 50 185" stroke="currentColor" stroke-width="1.5" fill="currentColor" opacity="0.12"/>
<path d="M100 180 Q115 172 125 180 Q120 188 108 185" stroke="currentColor" stroke-width="1.5" fill="currentColor" opacity="0.1"/>
</svg>
<!-- Shadok 6 : Empileur balancing tower of books on head, arms out, worried eyes -->
<svg class="shadok-empileur" viewBox="0 0 140 220" fill="none" aria-hidden="true">
<!-- Precarious tower of books on head (big, detailed!) -->
<rect x="48" y="8" width="24" height="7" rx="1" fill="currentColor" opacity="0.2" transform="rotate(3 60 11)"/>
<rect x="46" y="16" width="28" height="7" rx="1" fill="currentColor" opacity="0.25" transform="rotate(-2 60 19)"/>
<rect x="44" y="24" width="32" height="7" rx="1" fill="currentColor" opacity="0.2" transform="rotate(4 60 27)"/>
<rect x="47" y="32" width="26" height="7" rx="1" fill="currentColor" opacity="0.28" transform="rotate(-3 60 35)"/>
<rect x="50" y="40" width="22" height="6" rx="1" fill="currentColor" opacity="0.22" transform="rotate(2 61 43)"/>
<!-- Head -->
<circle cx="65" cy="58" r="14" fill="currentColor" opacity="0.3"/>
<!-- Worried eyes (looking up at books) -->
<circle cx="60" cy="54" r="2.2" fill="currentColor" opacity="0.6"/>
<circle cx="70" cy="54" r="2.2" fill="currentColor" opacity="0.6"/>
<!-- Tiny worried pupils (looking up) -->
<circle cx="60" cy="53" r="1" fill="currentColor" opacity="0.35"/>
<circle cx="70" cy="53" r="1" fill="currentColor" opacity="0.35"/>
<!-- Worried eyebrows -->
<line x1="56" y1="50" x2="63" y2="51" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" opacity="0.4"/>
<line x1="74" y1="51" x2="67" y2="50" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" opacity="0.4"/>
<!-- Beak (slightly open, worried) -->
<polygon points="74,60 86,57 74,55" fill="currentColor" opacity="0.3"/>
<line x1="76" y1="58" x2="83" y2="58" stroke="currentColor" stroke-width="0.8" opacity="0.2"/>
<!-- Body (small oval, upright, tense) -->
<ellipse cx="65" cy="95" rx="20" ry="26" fill="currentColor" opacity="0.25"/>
<!-- Arms out wide for balance -->
<line x1="45" y1="88" x2="10" y2="82" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<line x1="85" y1="88" x2="120" y2="82" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- Hands (small circles at arm ends) -->
<circle cx="8" cy="82" r="3" fill="currentColor" opacity="0.25"/>
<circle cx="122" cy="82" r="3" fill="currentColor" opacity="0.25"/>
<!-- Legs (long!) -->
<line x1="55" y1="121" x2="45" y2="192" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<line x1="75" y1="121" x2="85" y2="192" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- Big flat feet -->
<ellipse cx="40" cy="196" rx="10" ry="4" fill="currentColor" opacity="0.3"/>
<ellipse cx="90" cy="196" rx="10" ry="4" fill="currentColor" opacity="0.3"/>
</svg>
<div class="container-content">
<div class="mx-auto max-w-2xl">
<div class="section-icon mx-auto mb-6">
<div class="i-lucide-shopping-bag h-12 w-12" />
</div>
<p class="mb-2 font-mono text-sm tracking-widest text-primary uppercase text-center">
{{ content?.kicker }}
</p>
<h1 class="font-display text-3xl font-bold mb-4 text-center" style="color: hsl(var(--color-text))">
{{ content?.title }}
</h1>
<p class="text-lg leading-relaxed mb-10 text-center" style="color: hsl(var(--color-text-muted))">
{{ content?.description }}
</p>
<!-- Bookelis CTA -->
<div class="cta-block mb-8">
<div class="cta-icon">
<div class="i-lucide-globe h-5 w-5" />
</div>
<div class="flex-1">
<h2 class="font-display text-lg font-semibold mb-1" style="color: hsl(var(--color-text))">
Commander en ligne
</h2>
<p class="text-sm mb-3" style="color: hsl(var(--color-text-muted))">
Impression à la demande, livraison chez vous.
</p>
<a
:href="content?.bookelis?.url"
target="_blank"
rel="noopener"
class="order-btn"
>
<div class="i-lucide-external-link h-4 w-4" />
{{ content?.bookelis?.label }}
</a>
</div>
</div>
<!-- Librairie -->
<div class="cta-block mb-10">
<div class="cta-icon cta-icon--accent">
<div class="i-lucide-store h-5 w-5" />
</div>
<div class="flex-1">
<h2 class="font-display text-lg font-semibold mb-2" style="color: hsl(var(--color-text))">
{{ content?.librairie?.title }}
</h2>
<p class="leading-relaxed whitespace-pre-line" style="color: hsl(var(--color-text-muted))">
{{ content?.librairie?.text }}
</p>
</div>
</div>
<div class="text-center">
<UiBaseButton variant="ghost" to="/economique">
<div class="i-lucide-arrow-left mr-2 h-4 w-4" />
Autonomie économique
</UiBaseButton>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
const { data: content } = await usePageContent('economique/commande')
useHead({
title: content.value?.meta?.title ?? 'Commander le livre',
})
</script>
<style scoped>
.section-icon {
display: flex;
align-items: center;
justify-content: center;
width: 5rem;
height: 5rem;
border-radius: 1rem;
background: hsl(var(--color-primary) / 0.1);
border: 1px solid hsl(var(--color-primary) / 0.2);
color: hsl(var(--color-primary));
}
.cta-block {
display: flex;
gap: 1rem;
padding: 1.5rem;
border-radius: 0.75rem;
border: 1px solid hsl(var(--color-text) / 0.08);
background: hsl(var(--color-surface));
}
.cta-icon {
display: flex;
align-items: center;
justify-content: center;
width: 2.5rem;
height: 2.5rem;
border-radius: 0.5rem;
background: hsl(var(--color-primary) / 0.12);
color: hsl(var(--color-primary));
flex-shrink: 0;
margin-top: 0.125rem;
}
.cta-icon--accent {
background: hsl(var(--color-accent) / 0.12);
color: hsl(var(--color-accent));
}
.order-btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
border-radius: 20px;
font-size: 0.85rem;
font-weight: 600;
text-decoration: none;
background: hsl(var(--color-primary));
color: white;
transition: all 0.2s;
}
.order-btn:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px hsl(var(--color-primary) / 0.3);
}
.shadok-libraire {
position: absolute;
left: 2%;
top: 5%;
width: clamp(70px, 10vw, 140px);
opacity: 0.22;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-float-1 9s ease-in-out infinite;
}
.shadok-factrice {
position: absolute;
right: 2%;
top: 4%;
width: clamp(70px, 10vw, 140px);
opacity: 0.24;
pointer-events: none;
color: hsl(var(--color-accent));
animation: shadok-float-2 11s ease-in-out infinite;
}
.shadok-cartonnier {
position: absolute;
left: 3%;
top: 45%;
width: clamp(70px, 10vw, 130px);
opacity: 0.2;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-float-3 10s ease-in-out infinite;
}
.shadok-cycliste {
position: absolute;
left: 3%;
bottom: 8%;
width: clamp(75px, 10vw, 140px);
opacity: 0.18;
pointer-events: none;
color: hsl(var(--color-accent));
animation: shadok-float-4 8s ease-in-out infinite;
}
.shadok-lectrice {
position: absolute;
right: 2%;
bottom: 10%;
width: clamp(70px, 10vw, 135px);
opacity: 0.28;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-float-5 12s ease-in-out infinite;
}
.shadok-empileur {
position: absolute;
left: 50%;
bottom: 2%;
transform: translateX(-50%);
width: clamp(70px, 10vw, 130px);
opacity: 0.2;
pointer-events: none;
color: hsl(var(--color-accent));
animation: shadok-float-6 7s ease-in-out infinite;
}
@keyframes shadok-float-1 { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
@keyframes shadok-float-2 { 0%, 100% { transform: translateY(0) rotate(0deg); } 50% { transform: translateY(-10px) rotate(2deg); } }
@keyframes shadok-float-3 { 0%, 100% { transform: translateY(0) rotate(0deg); } 50% { transform: translateY(-12px) rotate(-1deg); } }
@keyframes shadok-float-4 { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px) rotate(1deg); } }
@keyframes shadok-float-5 { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@keyframes shadok-float-6 { 0%, 100% { transform: translateX(-50%) translateY(0); } 50% { transform: translateX(-50%) translateY(-9px); } }
@media (max-width: 768px) {
.shadok-libraire,
.shadok-factrice,
.shadok-cartonnier,
.shadok-cycliste,
.shadok-lectrice,
.shadok-empileur { display: none; }
}
</style>

View File

@@ -0,0 +1,647 @@
<template>
<div class="relative overflow-hidden section-padding">
<!-- Shadok boulangère (top-left, walking profile, carrying bread tray) -->
<svg class="shadok shadok-boulangere" viewBox="0 0 160 200" fill="none" xmlns="http://www.w3.org/2000/svg">
<g stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<!-- body tilted forward walking -->
<ellipse cx="85" cy="105" rx="22" ry="28" fill="currentColor" opacity="0.25" transform="rotate(-8 85 105)" />
<!-- head -->
<circle cx="80" cy="65" r="16" fill="currentColor" opacity="0.3" />
<!-- eyes looking forward -->
<circle cx="88" cy="62" r="2" fill="currentColor" />
<circle cx="88" cy="68" r="1.5" fill="currentColor" />
<!-- beak pointing right -->
<path d="M94 64 L108 62 L94 68" stroke="currentColor" stroke-width="2" fill="currentColor" opacity="0.2" />
<!-- arms up holding tray -->
<line x1="75" y1="88" x2="60" y2="42" stroke-width="3" />
<line x1="95" y1="88" x2="110" y2="42" stroke-width="3" />
<!-- big bread tray -->
<rect x="48" y="32" width="74" height="12" rx="3" fill="currentColor" opacity="0.25" />
<!-- bread loaves on tray -->
<ellipse cx="62" cy="30" rx="10" ry="6" fill="currentColor" opacity="0.3" />
<ellipse cx="85" cy="28" rx="11" ry="7" fill="currentColor" opacity="0.3" />
<ellipse cx="108" cy="30" rx="9" ry="6" fill="currentColor" opacity="0.3" />
<!-- score marks on loaves -->
<line x1="58" y1="28" x2="60" y2="32" opacity="0.4" />
<line x1="64" y1="27" x2="66" y2="31" opacity="0.4" />
<line x1="82" y1="26" x2="84" y2="30" opacity="0.4" />
<line x1="88" y1="25" x2="90" y2="29" opacity="0.4" />
<!-- flour apron -->
<path d="M70 95 Q85 92 100 95 L97 125 Q85 128 73 125 Z" fill="currentColor" opacity="0.1" />
<!-- flour dots -->
<circle cx="78" cy="100" r="1" fill="currentColor" opacity="0.3" />
<circle cx="92" cy="108" r="1.2" fill="currentColor" opacity="0.25" />
<circle cx="83" cy="115" r="0.8" fill="currentColor" opacity="0.3" />
<!-- long legs walking stride -->
<line x1="78" y1="132" x2="58" y2="185" stroke-width="3" />
<line x1="92" y1="132" x2="112" y2="180" stroke-width="3" />
<!-- big flat feet -->
<ellipse cx="52" cy="188" rx="12" ry="4" fill="currentColor" opacity="0.3" />
<ellipse cx="118" cy="183" rx="12" ry="4" fill="currentColor" opacity="0.3" />
</g>
</svg>
<!-- Shadok potier (top-right, sitting at wheel) -->
<svg class="shadok shadok-potier" viewBox="0 0 170 200" fill="none" xmlns="http://www.w3.org/2000/svg">
<g stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<!-- body sitting, slightly hunched -->
<ellipse cx="70" cy="100" rx="23" ry="26" fill="currentColor" opacity="0.25" transform="rotate(5 70 100)" />
<!-- head looking down at wheel -->
<circle cx="65" cy="65" r="15" fill="currentColor" opacity="0.3" />
<!-- eyes looking down -->
<circle cx="60" cy="68" r="2" fill="currentColor" />
<circle cx="72" cy="70" r="1.8" fill="currentColor" />
<!-- beak pointing down-right -->
<path d="M68 76 L80 82 L66 82" stroke="currentColor" stroke-width="2" fill="currentColor" opacity="0.2" />
<!-- arms reaching to vase -->
<line x1="50" y1="92" x2="110" y2="115" stroke-width="3" />
<line x1="90" y1="90" x2="120" y2="110" stroke-width="3" />
<!-- hands on vase -->
<circle cx="112" cy="113" r="4" fill="currentColor" opacity="0.2" />
<circle cx="122" cy="108" r="4" fill="currentColor" opacity="0.2" />
<!-- vase being shaped -->
<path d="M108 95 Q102 108 106 125 Q115 135 124 125 Q128 108 122 95" fill="currentColor" opacity="0.2" stroke="currentColor" stroke-width="2" />
<!-- vase opening -->
<ellipse cx="115" cy="95" rx="8" ry="3" fill="currentColor" opacity="0.15" />
<!-- pottery wheel -->
<ellipse cx="115" cy="140" rx="28" ry="8" fill="currentColor" opacity="0.2" />
<line x1="115" y1="148" x2="115" y2="170" stroke-width="3" />
<line x1="100" y1="170" x2="130" y2="170" stroke-width="3" />
<!-- spinning motion lines -->
<path d="M88 138 Q85 135 88 132" fill="none" opacity="0.35" />
<path d="M142 138 Q145 135 142 132" fill="none" opacity="0.35" />
<path d="M90 145 Q86 143 90 140" fill="none" opacity="0.25" />
<!-- legs folded sitting -->
<line x1="60" y1="124" x2="40" y2="165" stroke-width="3" />
<line x1="80" y1="124" x2="75" y2="170" stroke-width="3" />
<!-- flat feet -->
<ellipse cx="34" cy="168" rx="11" ry="4" fill="currentColor" opacity="0.3" />
<ellipse cx="70" cy="173" rx="11" ry="4" fill="currentColor" opacity="0.3" />
</g>
</svg>
<!-- Shadok apicultrice (left, 40% down, with smoker and bees) -->
<svg class="shadok shadok-apicultrice" viewBox="0 0 160 210" fill="none" xmlns="http://www.w3.org/2000/svg">
<g stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<!-- body upright -->
<ellipse cx="75" cy="110" rx="20" ry="27" fill="currentColor" opacity="0.25" />
<!-- head -->
<circle cx="75" cy="70" r="15" fill="currentColor" opacity="0.3" />
<!-- beekeeping hat brim -->
<ellipse cx="75" cy="56" rx="22" ry="5" fill="currentColor" opacity="0.2" />
<!-- hat top -->
<path d="M58 56 Q58 42 75 40 Q92 42 92 56" fill="currentColor" opacity="0.15" />
<!-- veil hanging down -->
<path d="M53 56 L53 82 Q75 88 97 82 L97 56" fill="none" stroke-dasharray="3 2" opacity="0.3" />
<!-- eyes behind veil -->
<circle cx="70" cy="68" r="2" fill="currentColor" />
<circle cx="82" cy="66" r="1.8" fill="currentColor" />
<!-- beak -->
<path d="M80 74 L94 72 L82 78" stroke="currentColor" stroke-width="2" fill="currentColor" opacity="0.2" />
<!-- arm left holding smoker -->
<line x1="56" y1="100" x2="28" y2="85" stroke-width="3" />
<!-- smoker device (big) -->
<rect x="10" y="72" width="22" height="20" rx="4" fill="currentColor" opacity="0.25" />
<path d="M14 72 L14 62 Q21 58 28 62 L28 72" fill="currentColor" opacity="0.15" />
<!-- smoke puffs -->
<circle cx="18" cy="55" r="5" fill="currentColor" opacity="0.12" />
<circle cx="24" cy="48" r="4" fill="currentColor" opacity="0.08" />
<circle cx="16" cy="42" r="3" fill="currentColor" opacity="0.06" />
<!-- arm right -->
<line x1="94" y1="100" x2="110" y2="90" stroke-width="3" />
<!-- buzzing bees (small detailed dots) -->
<circle cx="120" cy="60" r="2.5" fill="currentColor" opacity="0.35" />
<line x1="118" y1="58" x2="115" y2="56" opacity="0.3" />
<line x1="122" y1="58" x2="125" y2="55" opacity="0.3" />
<circle cx="135" cy="75" r="2" fill="currentColor" opacity="0.3" />
<line x1="133" y1="73" x2="131" y2="71" opacity="0.25" />
<line x1="137" y1="73" x2="139" y2="71" opacity="0.25" />
<circle cx="110" cy="48" r="2.2" fill="currentColor" opacity="0.25" />
<line x1="108" y1="46" x2="106" y2="44" opacity="0.2" />
<line x1="112" y1="46" x2="114" y2="43" opacity="0.2" />
<circle cx="140" cy="55" r="1.8" fill="currentColor" opacity="0.2" />
<circle cx="128" cy="42" r="2" fill="currentColor" opacity="0.22" />
<!-- long legs -->
<line x1="66" y1="136" x2="55" y2="192" stroke-width="3" />
<line x1="84" y1="136" x2="95" y2="192" stroke-width="3" />
<!-- flat feet -->
<ellipse cx="49" cy="195" rx="11" ry="4" fill="currentColor" opacity="0.3" />
<ellipse cx="101" cy="195" rx="11" ry="4" fill="currentColor" opacity="0.3" />
</g>
</svg>
<!-- Shadok forgeron (right, 35%, swinging hammer on anvil) -->
<svg class="shadok shadok-forgeron" viewBox="0 0 180 210" fill="none" xmlns="http://www.w3.org/2000/svg">
<g stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<!-- body leaning forward, muscular feel -->
<ellipse cx="90" cy="105" rx="24" ry="30" fill="currentColor" opacity="0.3" transform="rotate(-12 90 105)" />
<!-- head in profile -->
<circle cx="100" cy="65" r="16" fill="currentColor" opacity="0.3" />
<!-- eyes focused, intense -->
<circle cx="108" cy="62" r="2.5" fill="currentColor" />
<circle cx="108" cy="70" r="2" fill="currentColor" />
<!-- beak pointing right -->
<path d="M114 65 L130 62 L114 70" stroke="currentColor" stroke-width="2" fill="currentColor" opacity="0.2" />
<!-- big arm swinging hammer UP -->
<line x1="72" y1="90" x2="40" y2="40" stroke-width="3.5" />
<!-- hammer head (big!) -->
<rect x="22" y="22" width="38" height="18" rx="3" fill="currentColor" opacity="0.3" />
<!-- hammer handle end -->
<line x1="40" y1="40" x2="42" y2="30" stroke-width="4" />
<!-- other arm resting on anvil -->
<line x1="110" y1="92" x2="140" y2="130" stroke-width="3" />
<!-- anvil (big detailed) -->
<path d="M120 135 L160 135 L168 145 L112 145 Z" fill="currentColor" opacity="0.25" />
<rect x="128" y="145" width="24" height="20" fill="currentColor" opacity="0.2" />
<rect x="122" y="165" width="36" height="6" rx="2" fill="currentColor" opacity="0.25" />
<!-- hot metal on anvil -->
<rect x="132" y="130" width="20" height="5" rx="1" fill="currentColor" opacity="0.35" />
<!-- sparks flying -->
<line x1="138" y1="128" x2="132" y2="118" opacity="0.4" />
<line x1="145" y1="126" x2="150" y2="116" opacity="0.35" />
<line x1="152" y1="128" x2="160" y2="120" opacity="0.3" />
<circle cx="130" cy="115" r="1.5" fill="currentColor" opacity="0.35" />
<circle cx="155" cy="112" r="1.2" fill="currentColor" opacity="0.3" />
<circle cx="162" cy="118" r="1" fill="currentColor" opacity="0.25" />
<!-- long legs wide stance -->
<line x1="78" y1="133" x2="55" y2="190" stroke-width="3" />
<line x1="100" y1="133" x2="120" y2="192" stroke-width="3" />
<!-- flat feet -->
<ellipse cx="48" cy="193" rx="13" ry="4" fill="currentColor" opacity="0.3" />
<ellipse cx="127" cy="195" rx="13" ry="4" fill="currentColor" opacity="0.3" />
</g>
</svg>
<!-- Shadok maraîchère (bottom-left, pushing wheelbarrow) -->
<svg class="shadok shadok-maraichere" viewBox="0 0 180 200" fill="none" xmlns="http://www.w3.org/2000/svg">
<g stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<!-- body leaning forward pushing -->
<ellipse cx="120" cy="95" rx="21" ry="26" fill="currentColor" opacity="0.25" transform="rotate(-20 120 95)" />
<!-- head tilted forward -->
<circle cx="130" cy="58" r="14" fill="currentColor" opacity="0.3" />
<!-- eyes looking down at path -->
<circle cx="136" cy="56" r="2" fill="currentColor" />
<circle cx="136" cy="63" r="1.5" fill="currentColor" />
<!-- beak pointing right-down -->
<path d="M140 60 L154 64 L140 66" stroke="currentColor" stroke-width="2" fill="currentColor" opacity="0.2" />
<!-- arms pushing wheelbarrow handles -->
<line x1="104" y1="86" x2="72" y2="110" stroke-width="3" />
<line x1="108" y1="80" x2="72" y2="100" stroke-width="3" />
<!-- wheelbarrow body (big!) -->
<path d="M10 80 L70 80 L75 120 L5 120 Z" fill="currentColor" opacity="0.2" />
<path d="M10 80 L70 80 L75 120 L5 120 Z" />
<!-- wheelbarrow handles -->
<line x1="70" y1="90" x2="72" y2="110" stroke-width="3" />
<line x1="70" y1="100" x2="72" y2="100" stroke-width="2" />
<!-- wheel -->
<circle cx="12" cy="128" r="12" fill="currentColor" opacity="0.15" />
<circle cx="12" cy="128" r="12" />
<circle cx="12" cy="128" r="3" fill="currentColor" opacity="0.3" />
<!-- vegetables in wheelbarrow -->
<circle cx="22" cy="72" r="7" fill="currentColor" opacity="0.3" />
<circle cx="38" cy="70" r="8" fill="currentColor" opacity="0.25" />
<circle cx="55" cy="73" r="6" fill="currentColor" opacity="0.3" />
<ellipse cx="30" cy="76" rx="5" ry="8" fill="currentColor" opacity="0.2" transform="rotate(15 30 76)" />
<!-- carrot tops -->
<line x1="22" y1="66" x2="18" y2="58" opacity="0.35" />
<line x1="22" y1="66" x2="25" y2="57" opacity="0.35" />
<line x1="55" y1="67" x2="52" y2="60" opacity="0.3" />
<line x1="55" y1="67" x2="58" y2="59" opacity="0.3" />
<!-- long legs striding -->
<line x1="112" y1="118" x2="100" y2="180" stroke-width="3" />
<line x1="128" y1="118" x2="150" y2="178" stroke-width="3" />
<!-- flat feet -->
<ellipse cx="94" cy="183" rx="12" ry="4" fill="currentColor" opacity="0.3" />
<ellipse cx="156" cy="181" rx="12" ry="4" fill="currentColor" opacity="0.3" />
</g>
</svg>
<!-- Shadok tisserand (bottom-right, sitting at loom) -->
<svg class="shadok shadok-tisserand" viewBox="0 0 170 200" fill="none" xmlns="http://www.w3.org/2000/svg">
<g stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<!-- body sitting upright -->
<ellipse cx="55" cy="100" rx="20" ry="25" fill="currentColor" opacity="0.25" />
<!-- head looking down at loom -->
<circle cx="55" cy="65" r="15" fill="currentColor" opacity="0.3" />
<!-- eyes focused downward -->
<circle cx="62" cy="66" r="2" fill="currentColor" />
<circle cx="60" cy="72" r="1.5" fill="currentColor" />
<!-- beak pointing right-down -->
<path d="M66 70 L78 74 L64 76" stroke="currentColor" stroke-width="2" fill="currentColor" opacity="0.2" />
<!-- arms reaching to loom -->
<line x1="72" y1="92" x2="100" y2="80" stroke-width="3" />
<line x1="74" y1="100" x2="105" y2="100" stroke-width="3" />
<!-- loom frame (big detailed) -->
<rect x="95" y="55" width="60" height="80" rx="3" fill="none" />
<!-- vertical loom posts -->
<line x1="95" y1="55" x2="95" y2="135" stroke-width="3" />
<line x1="155" y1="55" x2="155" y2="135" stroke-width="3" />
<!-- top beam -->
<line x1="95" y1="55" x2="155" y2="55" stroke-width="3" />
<!-- warp threads (vertical) -->
<line x1="105" y1="55" x2="105" y2="135" opacity="0.3" />
<line x1="115" y1="55" x2="115" y2="135" opacity="0.3" />
<line x1="125" y1="55" x2="125" y2="135" opacity="0.3" />
<line x1="135" y1="55" x2="135" y2="135" opacity="0.3" />
<line x1="145" y1="55" x2="145" y2="135" opacity="0.3" />
<!-- weft threads (horizontal, partial = work in progress) -->
<line x1="95" y1="70" x2="155" y2="70" opacity="0.25" />
<line x1="95" y1="80" x2="155" y2="80" opacity="0.25" />
<line x1="95" y1="90" x2="145" y2="90" opacity="0.25" />
<line x1="95" y1="100" x2="135" y2="100" opacity="0.2" />
<!-- shuttle in hand -->
<ellipse cx="105" cy="100" rx="8" ry="3" fill="currentColor" opacity="0.3" transform="rotate(-5 105 100)" />
<!-- woven fabric area -->
<rect x="97" y="62" width="56" height="28" fill="currentColor" opacity="0.08" />
<!-- legs folded sitting on stool -->
<line x1="45" y1="123" x2="30" y2="178" stroke-width="3" />
<line x1="65" y1="123" x2="70" y2="180" stroke-width="3" />
<!-- flat feet -->
<ellipse cx="24" cy="181" rx="11" ry="4" fill="currentColor" opacity="0.3" />
<ellipse cx="76" cy="183" rx="11" ry="4" fill="currentColor" opacity="0.3" />
<!-- stool -->
<rect x="38" y="124" width="30" height="6" rx="2" fill="currentColor" opacity="0.15" />
<line x1="42" y1="130" x2="40" y2="148" stroke-width="2" opacity="0.3" />
<line x1="64" y1="130" x2="66" y2="148" stroke-width="2" opacity="0.3" />
</g>
</svg>
<!-- Shadok berger (center-bottom, walking with sheep) -->
<svg class="shadok shadok-berger" viewBox="0 0 180 200" fill="none" xmlns="http://www.w3.org/2000/svg">
<g stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<!-- body walking, slight lean -->
<ellipse cx="85" cy="90" rx="20" ry="26" fill="currentColor" opacity="0.25" transform="rotate(-5 85 90)" />
<!-- head 3/4 view -->
<circle cx="88" cy="52" r="16" fill="currentColor" opacity="0.3" />
<!-- eyes looking ahead, slightly different directions -->
<circle cx="94" cy="48" r="2" fill="currentColor" />
<circle cx="96" cy="56" r="1.8" fill="currentColor" />
<!-- beak -->
<path d="M100 52 L114 50 L100 56" stroke="currentColor" stroke-width="2" fill="currentColor" opacity="0.2" />
<!-- arm holding staff -->
<line x1="68" y1="82" x2="50" y2="60" stroke-width="3" />
<!-- shepherd's crook (big, detailed) -->
<line x1="50" y1="60" x2="44" y2="10" stroke-width="3" />
<path d="M44 10 Q44 0 54 0 Q62 0 62 10 Q62 18 54 18" fill="none" stroke-width="3" />
<!-- other arm relaxed -->
<line x1="104" y1="84" x2="118" y2="95" stroke-width="3" />
<!-- long legs walking -->
<line x1="76" y1="114" x2="60" y2="175" stroke-width="3" />
<line x1="94" y1="114" x2="110" y2="172" stroke-width="3" />
<!-- flat feet -->
<ellipse cx="54" cy="178" rx="12" ry="4" fill="currentColor" opacity="0.3" />
<ellipse cx="116" cy="175" rx="12" ry="4" fill="currentColor" opacity="0.3" />
<!-- sheep 1 (following) -->
<ellipse cx="140" cy="160" rx="14" ry="10" fill="currentColor" opacity="0.18" />
<circle cx="150" cy="152" r="6" fill="currentColor" opacity="0.15" />
<circle cx="153" cy="150" r="1" fill="currentColor" />
<line x1="132" y1="170" x2="132" y2="180" stroke-width="2" opacity="0.3" />
<line x1="148" y1="170" x2="148" y2="180" stroke-width="2" opacity="0.3" />
<!-- sheep 2 -->
<ellipse cx="158" cy="172" rx="12" ry="8" fill="currentColor" opacity="0.14" />
<circle cx="166" cy="166" r="5" fill="currentColor" opacity="0.12" />
<circle cx="168" cy="164" r="0.8" fill="currentColor" />
<line x1="152" y1="180" x2="152" y2="188" stroke-width="1.5" opacity="0.25" />
<line x1="164" y1="180" x2="164" y2="188" stroke-width="1.5" opacity="0.25" />
<!-- sheep 3 (smaller, behind) -->
<ellipse cx="170" cy="178" rx="9" ry="6" fill="currentColor" opacity="0.1" />
<circle cx="176" cy="174" r="4" fill="currentColor" opacity="0.08" />
<!-- dog at side -->
<ellipse cx="125" cy="170" rx="8" ry="5" fill="currentColor" opacity="0.2" />
<circle cx="130" cy="164" r="4" fill="currentColor" opacity="0.18" />
<circle cx="132" cy="163" r="1" fill="currentColor" />
<line x1="118" y1="168" x2="112" y2="165" stroke-width="1.5" opacity="0.3" />
<line x1="120" y1="175" x2="120" y2="182" stroke-width="1.5" opacity="0.25" />
<line x1="130" y1="175" x2="130" y2="182" stroke-width="1.5" opacity="0.25" />
</g>
</svg>
<!-- Shadok vigneronne (right, 55%, carrying grape basket) -->
<svg class="shadok shadok-vigneronne" viewBox="0 0 170 210" fill="none" xmlns="http://www.w3.org/2000/svg">
<g stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<!-- body seen from 3/4 back, leaning under weight -->
<ellipse cx="80" cy="105" rx="22" ry="28" fill="currentColor" opacity="0.25" transform="rotate(10 80 105)" />
<!-- head turned slightly -->
<circle cx="72" cy="65" r="15" fill="currentColor" opacity="0.3" />
<!-- eyes looking to the side -->
<circle cx="64" cy="62" r="2" fill="currentColor" />
<circle cx="66" cy="69" r="1.5" fill="currentColor" />
<!-- beak pointing left -->
<path d="M58 65 L44 62 L58 69" stroke="currentColor" stroke-width="2" fill="currentColor" opacity="0.2" />
<!-- arm back holding basket strap -->
<line x1="98" y1="92" x2="115" y2="75" stroke-width="3" />
<!-- arm front with pruning shears -->
<line x1="62" y1="95" x2="38" y2="80" stroke-width="3" />
<!-- pruning shears (big) -->
<line x1="38" y1="80" x2="26" y2="68" stroke-width="3" />
<line x1="38" y1="80" x2="28" y2="78" stroke-width="3" />
<circle cx="36" cy="78" r="3" fill="currentColor" opacity="0.2" />
<!-- blade shapes -->
<path d="M26 68 Q22 72 28 74" fill="none" stroke-width="2" />
<path d="M28 78 Q22 76 24 72" fill="none" stroke-width="2" />
<!-- big basket on back with grapes -->
<path d="M100 60 L130 60 L135 120 L95 120 Z" fill="currentColor" opacity="0.2" />
<path d="M100 60 L130 60 L135 120 L95 120 Z" />
<!-- basket weave texture -->
<line x1="100" y1="75" x2="133" y2="75" opacity="0.2" />
<line x1="98" y1="90" x2="134" y2="90" opacity="0.2" />
<line x1="97" y1="105" x2="135" y2="105" opacity="0.2" />
<!-- grapes overflowing -->
<circle cx="108" cy="55" r="4" fill="currentColor" opacity="0.3" />
<circle cx="116" cy="53" r="4.5" fill="currentColor" opacity="0.3" />
<circle cx="124" cy="55" r="4" fill="currentColor" opacity="0.25" />
<circle cx="112" cy="48" r="3.5" fill="currentColor" opacity="0.25" />
<circle cx="120" cy="47" r="3.5" fill="currentColor" opacity="0.2" />
<circle cx="105" cy="52" r="3" fill="currentColor" opacity="0.2" />
<!-- grape stems -->
<line x1="115" y1="43" x2="115" y2="36" opacity="0.3" />
<line x1="113" y1="36" x2="117" y2="36" opacity="0.3" />
<!-- grapevine nearby -->
<line x1="148" y1="30" x2="148" y2="130" stroke-width="2" opacity="0.2" />
<path d="M148 50 Q158 45 162 55" fill="none" opacity="0.2" />
<path d="M148 75 Q160 70 165 80" fill="none" opacity="0.2" />
<circle cx="160" cy="58" r="3" fill="currentColor" opacity="0.12" />
<circle cx="163" cy="83" r="3" fill="currentColor" opacity="0.1" />
<!-- grape leaf -->
<path d="M148 90 Q155 85 158 90 Q160 95 155 98 Q150 95 148 90" fill="currentColor" opacity="0.12" />
<!-- long legs -->
<line x1="70" y1="132" x2="55" y2="192" stroke-width="3" />
<line x1="90" y1="132" x2="105" y2="190" stroke-width="3" />
<!-- flat feet -->
<ellipse cx="49" cy="195" rx="12" ry="4" fill="currentColor" opacity="0.3" />
<ellipse cx="111" cy="193" rx="12" ry="4" fill="currentColor" opacity="0.3" />
</g>
</svg>
<div class="container-content">
<!-- Header -->
<header class="mb-12 text-center">
<p class="mb-2 font-mono text-sm tracking-widest text-primary uppercase">{{ content?.kicker }}</p>
<h1 class="page-title font-display font-bold tracking-tight" style="color: hsl(var(--color-text))">
{{ content?.title }}
</h1>
<p class="mt-4 mx-auto max-w-2xl leading-relaxed" style="color: hsl(var(--color-text-muted))">
{{ content?.description }}
</p>
</header>
<div class="mx-auto max-w-3xl flex flex-col gap-8">
<!-- Monnaie libre -->
<NuxtLink to="/economique/monnaie-libre" class="item-card group">
<div class="item-header">
<div class="item-icon">
<span class="g1-icon">Ğ1</span>
</div>
<h2 class="font-display text-xl font-bold" style="color: hsl(var(--color-text))">
Monnaie libre
</h2>
</div>
<p class="leading-relaxed mt-3" style="color: hsl(var(--color-text-muted))">
La Ğ1 (June) : une monnaie co-créée par ses membres, sans dette ni intérêt. Le dividende universel comme base.
</p>
<div class="mt-3 inline-flex items-center gap-1 text-sm text-primary group-hover:text-primary/80 transition-colors">
En savoir plus
<div class="i-lucide-arrow-right h-3.5 w-3.5" />
</div>
</NuxtLink>
<!-- Modèle économique — bloc livre -->
<div class="book-block">
<HomeBookSection
@open-player="showBookPlayer = true"
@open-pdf="showPdfReader = true"
/>
</div>
<!-- Productions collectives -->
<NuxtLink to="/economique/productions-collectives" class="item-card group">
<div class="item-header">
<div class="item-icon">
<div class="i-lucide-users h-5 w-5" />
</div>
<h2 class="font-display text-xl font-bold" style="color: hsl(var(--color-text))">
Productions collectives
</h2>
<span class="gestation-badge">
<div class="i-lucide-flask-conical h-3 w-3" />
En gestation
</span>
</div>
<p class="leading-relaxed mt-3" style="color: hsl(var(--color-text-muted))">
Une plateforme pour faciliter la création d'équipes et la réalisation de productions à l'échelle des bassins de vie. Passer la seconde.
</p>
<div class="mt-3 inline-flex items-center gap-1 text-sm text-primary group-hover:text-primary/80 transition-colors">
En savoir plus
<div class="i-lucide-arrow-right h-3.5 w-3.5" />
</div>
</NuxtLink>
</div>
</div>
<BookPlayer v-model="showBookPlayer" />
<BookPdfReader v-model="showPdfReader" />
</div>
</template>
<script setup lang="ts">
definePageMeta({
layout: 'default',
})
const { data: content } = await usePageContent('economique')
useHead({
title: content.value?.meta?.title ?? 'Autonomie économique',
})
const showBookPlayer = ref(false)
const showPdfReader = ref(false)
</script>
<style scoped>
.page-title {
font-size: clamp(2rem, 5vw, 2.75rem);
}
.item-card {
display: block;
padding: 1.5rem;
border-radius: 0.75rem;
border: 1px solid hsl(var(--color-text) / 0.08);
background: hsl(var(--color-surface));
transition: border-color 0.2s, transform 0.12s ease;
text-decoration: none;
}
.item-card:hover {
border-color: hsl(var(--color-primary) / 0.2);
transform: translateY(-3px);
box-shadow: 0 8px 24px hsl(var(--color-primary) / 0.08);
}
.item-header {
display: flex;
align-items: center;
gap: 0.75rem;
}
.g1-icon {
font-family: var(--font-display);
font-weight: 700;
font-size: 1.1rem;
line-height: 1;
}
.item-icon {
display: flex;
align-items: center;
justify-content: center;
width: 2.25rem;
height: 2.25rem;
border-radius: 0.5rem;
background: hsl(var(--color-primary) / 0.15);
color: hsl(var(--color-primary));
box-shadow: 0 0 12px hsl(var(--color-primary) / 0.12);
flex-shrink: 0;
}
.gestation-badge {
display: inline-flex;
align-items: center;
gap: 0.25rem;
margin-left: auto;
padding: 0.125rem 0.5rem;
border-radius: 9999px;
background: hsl(var(--color-accent) / 0.12);
color: hsl(var(--color-accent));
font-size: 0.7rem;
font-weight: 500;
font-family: var(--font-mono);
}
.book-block {
padding: 1.5rem;
border-radius: 0.75rem;
border: 1px solid hsl(var(--color-text) / 0.08);
background: hsl(var(--color-surface));
}
/* Shadok illustrations */
.shadok {
position: absolute;
pointer-events: none;
width: clamp(70px, 10vw, 140px);
z-index: 0;
}
.shadok-boulangere {
top: 1%;
left: 2%;
opacity: 0.22;
color: hsl(var(--color-primary));
animation: shadok-float-1 9s ease-in-out infinite;
}
.shadok-potier {
top: 1%;
right: 2%;
opacity: 0.2;
color: hsl(var(--color-accent));
animation: shadok-float-2 11s ease-in-out infinite;
}
.shadok-apicultrice {
left: 2%;
top: 40%;
opacity: 0.2;
color: hsl(var(--color-accent));
animation: shadok-float-3 10s ease-in-out infinite;
}
.shadok-forgeron {
right: 3%;
top: 35%;
opacity: 0.24;
color: hsl(var(--color-primary));
animation: shadok-float-4 8s ease-in-out infinite;
}
.shadok-maraichere {
bottom: 14%;
left: 1%;
opacity: 0.18;
color: hsl(var(--color-primary));
animation: shadok-float-5 12s ease-in-out infinite;
}
.shadok-tisserand {
bottom: 12%;
right: 1%;
opacity: 0.22;
color: hsl(var(--color-accent));
animation: shadok-float-6 9.5s ease-in-out infinite;
}
.shadok-berger {
bottom: 2%;
left: 50%;
transform: translateX(-50%);
opacity: 0.28;
color: hsl(var(--color-primary));
animation: shadok-float-7 11s ease-in-out infinite;
}
.shadok-vigneronne {
right: 2%;
top: 55%;
opacity: 0.2;
color: hsl(var(--color-accent));
animation: shadok-float-8 7.5s ease-in-out infinite;
}
@keyframes shadok-float-1 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
@keyframes shadok-float-2 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
}
@keyframes shadok-float-3 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-12px); }
}
@keyframes shadok-float-4 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-9px); }
}
@keyframes shadok-float-5 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-11px); }
}
@keyframes shadok-float-6 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
}
@keyframes shadok-float-7 {
0%, 100% { transform: translateX(-50%) translateY(0); }
50% { transform: translateX(-50%) translateY(-10px); }
}
@keyframes shadok-float-8 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-7px); }
}
@media (max-width: 768px) {
.shadok {
display: none;
}
}
</style>

View File

@@ -14,7 +14,7 @@
<nav class="mt-16 flex items-center justify-between border-t border-white/8 pt-8">
<NuxtLink
v-if="prevChapter"
:to="`/modele-eco/${prevChapter.stem?.split('/').pop()}`"
:to="`/economique/modele-eco/${prevChapter.stem?.split('/').pop()}`"
class="btn-ghost gap-2"
>
<div class="i-lucide-arrow-left h-4 w-4" />
@@ -24,7 +24,7 @@
<NuxtLink
v-if="nextChapter"
:to="`/modele-eco/${nextChapter.stem?.split('/').pop()}`"
:to="`/economique/modele-eco/${nextChapter.stem?.split('/').pop()}`"
class="btn-ghost gap-2"
>
<span class="text-sm">{{ nextChapter.title }}</span>

View File

@@ -0,0 +1,562 @@
<template>
<div class="relative overflow-hidden section-padding">
<!-- Shadok illustrations -->
<!-- 1. Typographe placing movable type in composing stick, profile view -->
<svg class="shadok shadok-typographe" viewBox="0 0 170 210" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- body (small oval, profile facing right) -->
<ellipse cx="70" cy="72" rx="22" ry="28" fill="currentColor" opacity="0.28"/>
<!-- head -->
<circle cx="78" cy="36" r="16" fill="currentColor" opacity="0.3"/>
<!-- beak (pointy, profile right) -->
<polygon points="94,34 110,38 94,42" fill="currentColor" opacity="0.35"/>
<!-- eyes (profile one visible) -->
<circle cx="84" cy="33" r="2.5" fill="currentColor" opacity="0.6"/>
<!-- apron -->
<path d="M52 60 L88 60 L85 100 L55 100 Z" fill="currentColor" opacity="0.15"/>
<line x1="70" y1="60" x2="70" y2="100" stroke="currentColor" stroke-width="1" opacity="0.2"/>
<!-- arm reaching to composing stick -->
<line x1="88" y1="65" x2="120" y2="55" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3"/>
<!-- other arm holding type block -->
<line x1="52" y1="68" x2="35" y2="58" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3"/>
<!-- composing stick (big, detailed) -->
<rect x="110" y="40" width="50" height="14" rx="2" fill="currentColor" opacity="0.2"/>
<rect x="110" y="42" width="50" height="10" rx="1" stroke="currentColor" stroke-width="1" fill="none" opacity="0.25"/>
<!-- type blocks in stick -->
<rect x="114" y="44" width="6" height="7" rx="0.5" fill="currentColor" opacity="0.3"/>
<rect x="122" y="44" width="5" height="7" rx="0.5" fill="currentColor" opacity="0.25"/>
<rect x="129" y="44" width="7" height="7" rx="0.5" fill="currentColor" opacity="0.3"/>
<rect x="138" y="44" width="5" height="7" rx="0.5" fill="currentColor" opacity="0.22"/>
<rect x="145" y="44" width="6" height="7" rx="0.5" fill="currentColor" opacity="0.28"/>
<!-- tiny letter on held block -->
<rect x="30" y="52" width="8" height="10" rx="1" fill="currentColor" opacity="0.25"/>
<text x="32" y="60" font-size="6" fill="currentColor" opacity="0.5" font-family="serif">A</text>
<!-- long legs -->
<line x1="62" y1="98" x2="50" y2="165" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<line x1="78" y1="98" x2="90" y2="165" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<!-- big flat feet -->
<ellipse cx="45" cy="168" rx="10" ry="4" fill="currentColor" opacity="0.25"/>
<ellipse cx="95" cy="168" rx="10" ry="4" fill="currentColor" opacity="0.25"/>
</svg>
<!-- 2. Lectrice sitting in armchair, legs crossed, book on lap, reading glasses -->
<svg class="shadok shadok-lectrice" viewBox="0 0 180 210" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- armchair back -->
<path d="M30 55 Q25 50 28 30 L85 28 Q88 50 83 55" fill="currentColor" opacity="0.12"/>
<!-- armchair seat -->
<path d="M25 55 L88 55 L92 90 L20 90 Z" fill="currentColor" opacity="0.15"/>
<!-- armchair arms -->
<rect x="15" y="45" width="12" height="45" rx="5" fill="currentColor" opacity="0.15"/>
<rect x="85" y="45" width="12" height="45" rx="5" fill="currentColor" opacity="0.15"/>
<!-- body (seated, small) -->
<ellipse cx="58" cy="68" rx="20" ry="25" fill="currentColor" opacity="0.28"/>
<!-- head -->
<circle cx="58" cy="32" r="15" fill="currentColor" opacity="0.3"/>
<!-- beak (small, facing right-down toward book) -->
<polygon points="70,35 80,40 70,42" fill="currentColor" opacity="0.3"/>
<!-- reading glasses -->
<circle cx="52" cy="30" r="6" stroke="currentColor" stroke-width="1.5" fill="none" opacity="0.4"/>
<circle cx="65" cy="30" r="6" stroke="currentColor" stroke-width="1.5" fill="none" opacity="0.4"/>
<line x1="58" y1="30" x2="59" y2="30" stroke="currentColor" stroke-width="1.5" opacity="0.35"/>
<!-- eyes behind glasses (looking down) -->
<circle cx="53" cy="31" r="2" fill="currentColor" opacity="0.55"/>
<circle cx="64" cy="31" r="2" fill="currentColor" opacity="0.55"/>
<!-- arms holding open book on lap -->
<line x1="40" y1="60" x2="35" y2="82" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<line x1="76" y1="60" x2="80" y2="82" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<!-- open book on lap -->
<path d="M32 80 L58 88 L84 80 L84 95 L58 103 L32 95 Z" fill="currentColor" opacity="0.18"/>
<line x1="58" y1="88" x2="58" y2="103" stroke="currentColor" stroke-width="1" opacity="0.25"/>
<!-- text lines on pages -->
<line x1="37" y1="86" x2="54" y2="91" stroke="currentColor" stroke-width="0.7" opacity="0.2"/>
<line x1="37" y1="89" x2="54" y2="94" stroke="currentColor" stroke-width="0.7" opacity="0.2"/>
<line x1="62" y1="91" x2="79" y2="86" stroke="currentColor" stroke-width="0.7" opacity="0.2"/>
<line x1="62" y1="94" x2="79" y2="89" stroke="currentColor" stroke-width="0.7" opacity="0.2"/>
<!-- crossed legs (long!) -->
<line x1="48" y1="90" x2="30" y2="165" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<line x1="68" y1="90" x2="55" y2="150" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<!-- the crossed leg goes over -->
<line x1="55" y1="150" x2="75" y2="140" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.22"/>
<!-- big flat feet -->
<ellipse cx="25" cy="168" rx="11" ry="4" fill="currentColor" opacity="0.25"/>
<ellipse cx="79" cy="142" rx="9" ry="3.5" fill="currentColor" opacity="0.22"/>
<!-- cup of tea nearby -->
<rect x="130" y="78" width="14" height="16" rx="3" fill="currentColor" opacity="0.2"/>
<ellipse cx="137" cy="78" rx="7" ry="2.5" fill="currentColor" opacity="0.25"/>
<!-- tea handle -->
<path d="M144 83 Q152 86 144 92" stroke="currentColor" stroke-width="1.5" fill="none" opacity="0.2"/>
<!-- steam -->
<path d="M134 73 Q132 68 135 64" stroke="currentColor" stroke-width="0.8" fill="none" opacity="0.15"/>
<path d="M139 74 Q141 69 138 65" stroke="currentColor" stroke-width="0.8" fill="none" opacity="0.15"/>
</svg>
<!-- 3. Calligraphe standing at tilted drafting table, large quill, ink flourishes -->
<svg class="shadok shadok-calligraphe" viewBox="0 0 180 220" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- drafting table (tilted, big) -->
<rect x="75" y="50" width="65" height="85" rx="3" fill="currentColor" opacity="0.12" transform="rotate(-15 108 92)"/>
<!-- table legs -->
<line x1="85" y1="130" x2="78" y2="195" stroke="currentColor" stroke-width="2.5" opacity="0.18"/>
<line x1="140" y1="115" x2="150" y2="195" stroke="currentColor" stroke-width="2.5" opacity="0.18"/>
<!-- paper on table -->
<rect x="85" y="58" width="48" height="65" rx="1" fill="currentColor" opacity="0.08" transform="rotate(-15 109 90)"/>
<!-- ink flourishes on paper -->
<path d="M95 80 Q105 70 115 82 Q120 90 110 95" stroke="currentColor" stroke-width="1.2" fill="none" opacity="0.25" transform="rotate(-15 105 85)"/>
<path d="M100 95 Q108 88 118 98" stroke="currentColor" stroke-width="0.8" fill="none" opacity="0.2" transform="rotate(-15 109 93)"/>
<!-- body (3/4 view, facing table) -->
<ellipse cx="55" cy="95" rx="21" ry="27" fill="currentColor" opacity="0.28"/>
<!-- head (turned toward table) -->
<circle cx="62" cy="58" r="16" fill="currentColor" opacity="0.3"/>
<!-- beak pointing at paper -->
<polygon points="75,55 90,52 78,60" fill="currentColor" opacity="0.32"/>
<!-- eyes (looking at paper, slightly different directions) -->
<circle cx="66" cy="55" r="2.5" fill="currentColor" opacity="0.6"/>
<circle cx="58" cy="54" r="2" fill="currentColor" opacity="0.5"/>
<!-- arm holding large quill -->
<line x1="72" y1="85" x2="105" y2="65" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3"/>
<!-- large quill -->
<line x1="105" y1="65" x2="100" y2="80" stroke="currentColor" stroke-width="1.5" opacity="0.35"/>
<path d="M105 65 L115 30 Q108 45 100 40 Q105 55 105 65" fill="currentColor" opacity="0.2"/>
<!-- other arm resting on table edge -->
<line x1="40" y1="88" x2="80" y2="85" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<!-- ink trailing from quill tip -->
<path d="M100 80 Q95 90 98 100 Q102 108 96 115" stroke="currentColor" stroke-width="0.8" fill="none" opacity="0.2"/>
<!-- long legs -->
<line x1="45" y1="120" x2="35" y2="190" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<line x1="65" y1="120" x2="72" y2="190" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<!-- big flat feet -->
<ellipse cx="30" cy="193" rx="11" ry="4" fill="currentColor" opacity="0.25"/>
<ellipse cx="77" cy="193" rx="11" ry="4" fill="currentColor" opacity="0.25"/>
</svg>
<!-- 4. Relieur sewing book spine with needle and thread, stack of signatures -->
<svg class="shadok shadok-relieur" viewBox="0 0 170 210" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- body (leaning forward over work) -->
<ellipse cx="85" cy="80" rx="22" ry="26" fill="currentColor" opacity="0.28" transform="rotate(10 85 80)"/>
<!-- head (tilted down, focused) -->
<circle cx="95" cy="46" r="15" fill="currentColor" opacity="0.3"/>
<!-- beak (pointing down at work) -->
<polygon points="105,52 115,62 103,58" fill="currentColor" opacity="0.32"/>
<!-- eyes (both looking down at different angles) -->
<circle cx="92" cy="44" r="2" fill="currentColor" opacity="0.55"/>
<circle cx="100" cy="46" r="2.5" fill="currentColor" opacity="0.6"/>
<!-- arm holding needle high -->
<line x1="100" y1="70" x2="130" y2="40" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3"/>
<!-- needle -->
<line x1="130" y1="40" x2="135" y2="32" stroke="currentColor" stroke-width="2" opacity="0.45"/>
<!-- thread from needle down to book -->
<path d="M132 38 Q140 55 125 75 Q115 90 120 100" stroke="currentColor" stroke-width="1" fill="none" stroke-dasharray="4 3" opacity="0.3"/>
<!-- other arm holding book spine -->
<line x1="68" y1="75" x2="50" y2="95" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3"/>
<!-- book being bound (open spine view, big) -->
<path d="M40 90 L60 85 L60 125 L40 130 Z" fill="currentColor" opacity="0.18"/>
<path d="M60 85 L80 90 L80 130 L60 125 Z" fill="currentColor" opacity="0.14"/>
<!-- stitching holes along spine -->
<circle cx="60" cy="92" r="1.2" fill="currentColor" opacity="0.35"/>
<circle cx="60" cy="100" r="1.2" fill="currentColor" opacity="0.35"/>
<circle cx="60" cy="108" r="1.2" fill="currentColor" opacity="0.35"/>
<circle cx="60" cy="116" r="1.2" fill="currentColor" opacity="0.35"/>
<!-- stack of folded signatures nearby -->
<rect x="10" y="125" width="30" height="5" rx="1" fill="currentColor" opacity="0.18"/>
<rect x="12" y="119" width="28" height="5" rx="1" fill="currentColor" opacity="0.15"/>
<rect x="11" y="113" width="29" height="5" rx="1" fill="currentColor" opacity="0.2"/>
<rect x="13" y="107" width="27" height="5" rx="1" fill="currentColor" opacity="0.16"/>
<!-- long legs -->
<line x1="75" y1="104" x2="65" y2="172" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<line x1="95" y1="104" x2="105" y2="172" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<!-- big flat feet -->
<ellipse cx="60" cy="175" rx="10" ry="4" fill="currentColor" opacity="0.25"/>
<ellipse cx="110" cy="175" rx="10" ry="4" fill="currentColor" opacity="0.25"/>
</svg>
<!-- 5. Conteuse on small stage, arms dramatically wide, 3 tiny shadoks below -->
<svg class="shadok shadok-conteuse" viewBox="0 0 180 220" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- small stage/box -->
<rect x="55" y="110" width="60" height="20" rx="3" fill="currentColor" opacity="0.18"/>
<rect x="58" y="108" width="54" height="4" rx="1.5" fill="currentColor" opacity="0.22"/>
<!-- body (on stage, upright, dramatic) -->
<ellipse cx="85" cy="85" rx="20" ry="26" fill="currentColor" opacity="0.28"/>
<!-- head (thrown back slightly) -->
<circle cx="85" cy="50" r="16" fill="currentColor" opacity="0.3"/>
<!-- beak (open, telling story) -->
<polygon points="98,46 112,42 100,52" fill="currentColor" opacity="0.3"/>
<polygon points="100,52 112,55 98,54" fill="currentColor" opacity="0.22"/>
<!-- wide expressive eyes -->
<circle cx="82" cy="46" r="3" fill="currentColor" opacity="0.6"/>
<circle cx="92" cy="45" r="2.5" fill="currentColor" opacity="0.55"/>
<!-- arms dramatically wide -->
<line x1="65" y1="75" x2="15" y2="50" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3"/>
<line x1="105" y1="75" x2="160" y2="50" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3"/>
<!-- gesture sparkles -->
<circle cx="10" cy="45" r="2" fill="currentColor" opacity="0.15"/>
<circle cx="165" cy="45" r="2" fill="currentColor" opacity="0.15"/>
<circle cx="18" cy="38" r="1.5" fill="currentColor" opacity="0.12"/>
<circle cx="157" cy="38" r="1.5" fill="currentColor" opacity="0.12"/>
<!-- long legs (standing on stage) -->
<line x1="77" y1="108" x2="70" y2="110" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<line x1="93" y1="108" x2="100" y2="110" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<!-- big flat feet on stage -->
<ellipse cx="67" cy="112" rx="8" ry="3" fill="currentColor" opacity="0.2"/>
<ellipse cx="103" cy="112" rx="8" ry="3" fill="currentColor" opacity="0.2"/>
<!-- audience: 3 tiny shadoks below stage -->
<!-- tiny shadok 1 (left) -->
<ellipse cx="40" cy="165" rx="8" ry="10" fill="currentColor" opacity="0.18"/>
<circle cx="40" cy="152" r="6" fill="currentColor" opacity="0.22"/>
<circle cx="39" cy="151" r="1" fill="currentColor" opacity="0.45"/>
<circle cx="42" cy="151" r="1" fill="currentColor" opacity="0.45"/>
<polygon points="45,151 50,153 45,155" fill="currentColor" opacity="0.2"/>
<line x1="37" y1="175" x2="35" y2="195" stroke="currentColor" stroke-width="1.5" opacity="0.15"/>
<line x1="43" y1="175" x2="45" y2="195" stroke="currentColor" stroke-width="1.5" opacity="0.15"/>
<!-- tiny shadok 2 (center) -->
<ellipse cx="85" cy="168" rx="8" ry="10" fill="currentColor" opacity="0.18"/>
<circle cx="85" cy="155" r="6" fill="currentColor" opacity="0.22"/>
<circle cx="83" cy="154" r="1" fill="currentColor" opacity="0.45"/>
<circle cx="87" cy="154" r="1" fill="currentColor" opacity="0.45"/>
<polygon points="90,154 95,156 90,158" fill="currentColor" opacity="0.2"/>
<line x1="82" y1="178" x2="80" y2="198" stroke="currentColor" stroke-width="1.5" opacity="0.15"/>
<line x1="88" y1="178" x2="90" y2="198" stroke="currentColor" stroke-width="1.5" opacity="0.15"/>
<!-- tiny shadok 3 (right) -->
<ellipse cx="130" cy="163" rx="8" ry="10" fill="currentColor" opacity="0.18"/>
<circle cx="130" cy="150" r="6" fill="currentColor" opacity="0.22"/>
<circle cx="128" cy="149" r="1" fill="currentColor" opacity="0.45"/>
<circle cx="132" cy="149" r="1" fill="currentColor" opacity="0.45"/>
<polygon points="135,149 140,151 135,153" fill="currentColor" opacity="0.2"/>
<line x1="127" y1="173" x2="125" y2="193" stroke="currentColor" stroke-width="1.5" opacity="0.15"/>
<line x1="133" y1="173" x2="135" y2="193" stroke="currentColor" stroke-width="1.5" opacity="0.15"/>
</svg>
<!-- 6. Correcteur leaning forward, magnifying glass over manuscript, red pen -->
<svg class="shadok shadok-correcteur" viewBox="0 0 170 210" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- body (leaning forward heavily) -->
<ellipse cx="75" cy="82" rx="21" ry="28" fill="currentColor" opacity="0.28" transform="rotate(20 75 82)"/>
<!-- head (craned forward) -->
<circle cx="95" cy="48" r="15" fill="currentColor" opacity="0.3"/>
<!-- beak (pursed, critical) -->
<polygon points="108,45 118,48 108,52" fill="currentColor" opacity="0.3"/>
<!-- eyes (squinting, one bigger peering through glass) -->
<circle cx="92" cy="45" r="1.8" fill="currentColor" opacity="0.5"/>
<circle cx="101" cy="46" r="3" fill="currentColor" opacity="0.6"/>
<!-- arm holding magnifying glass -->
<line x1="90" y1="72" x2="120" y2="90" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3"/>
<!-- magnifying glass (big) -->
<circle cx="128" cy="98" r="18" stroke="currentColor" stroke-width="2.5" fill="none" opacity="0.3"/>
<circle cx="128" cy="98" r="16" fill="currentColor" opacity="0.06"/>
<!-- handle -->
<line x1="140" y1="112" x2="155" y2="135" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3"/>
<!-- manuscript under magnifying glass -->
<rect x="95" y="115" width="55" height="70" rx="2" fill="currentColor" opacity="0.1"/>
<!-- text lines on manuscript -->
<line x1="100" y1="125" x2="140" y2="125" stroke="currentColor" stroke-width="0.8" opacity="0.18"/>
<line x1="100" y1="132" x2="145" y2="132" stroke="currentColor" stroke-width="0.8" opacity="0.18"/>
<line x1="100" y1="139" x2="138" y2="139" stroke="currentColor" stroke-width="0.8" opacity="0.18"/>
<line x1="100" y1="146" x2="142" y2="146" stroke="currentColor" stroke-width="0.8" opacity="0.18"/>
<line x1="100" y1="153" x2="135" y2="153" stroke="currentColor" stroke-width="0.8" opacity="0.18"/>
<!-- crossed-out text (red corrections) -->
<line x1="100" y1="132" x2="130" y2="132" stroke="currentColor" stroke-width="1.5" opacity="0.35"/>
<line x1="105" y1="146" x2="125" y2="146" stroke="currentColor" stroke-width="1.5" opacity="0.35"/>
<!-- other arm holding red pen -->
<line x1="58" y1="78" x2="35" y2="100" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<!-- red pen -->
<line x1="35" y1="100" x2="25" y2="115" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.35"/>
<circle cx="24" cy="117" r="1.5" fill="currentColor" opacity="0.4"/>
<!-- long legs -->
<line x1="65" y1="108" x2="50" y2="178" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<line x1="82" y1="105" x2="95" y2="178" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<!-- big flat feet -->
<ellipse cx="45" cy="181" rx="10" ry="4" fill="currentColor" opacity="0.25"/>
<ellipse cx="100" cy="181" rx="10" ry="4" fill="currentColor" opacity="0.25"/>
</svg>
<!-- 7. Colporteur walking profile, books in wooden crate on back, walking stick, hat -->
<svg class="shadok shadok-colporteur" viewBox="0 0 160 210" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- body (profile, walking right, leaning forward under weight) -->
<ellipse cx="70" cy="72" rx="20" ry="25" fill="currentColor" opacity="0.28" transform="rotate(15 70 72)"/>
<!-- head -->
<circle cx="82" cy="38" r="14" fill="currentColor" opacity="0.3"/>
<!-- hat (brimmed) -->
<ellipse cx="82" cy="26" rx="18" ry="5" fill="currentColor" opacity="0.25"/>
<rect x="72" y="16" width="20" height="12" rx="3" fill="currentColor" opacity="0.2"/>
<!-- beak (profile right) -->
<polygon points="94,36 106,40 94,43" fill="currentColor" opacity="0.32"/>
<!-- eye (profile one visible, determined) -->
<circle cx="88" cy="35" r="2.5" fill="currentColor" opacity="0.6"/>
<!-- wooden crate on back (big, loaded with books) -->
<rect x="25" y="35" width="40" height="50" rx="3" stroke="currentColor" stroke-width="2" fill="currentColor" opacity="0.12"/>
<!-- strap over shoulder -->
<line x1="45" y1="35" x2="78" y2="55" stroke="currentColor" stroke-width="2" opacity="0.25"/>
<line x1="65" y1="35" x2="85" y2="60" stroke="currentColor" stroke-width="2" opacity="0.25"/>
<!-- books in crate (visible spines) -->
<rect x="28" y="38" width="6" height="44" rx="1" fill="currentColor" opacity="0.22"/>
<rect x="36" y="40" width="5" height="42" rx="1" fill="currentColor" opacity="0.18"/>
<rect x="43" y="37" width="7" height="45" rx="1" fill="currentColor" opacity="0.2"/>
<rect x="52" y="39" width="5" height="43" rx="1" fill="currentColor" opacity="0.16"/>
<rect x="58" y="38" width="4" height="44" rx="1" fill="currentColor" opacity="0.2"/>
<!-- arm forward with walking stick -->
<line x1="88" y1="65" x2="115" y2="80" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3"/>
<!-- walking stick (long) -->
<line x1="115" y1="80" x2="125" y2="195" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.3"/>
<!-- other arm back holding strap -->
<line x1="55" y1="68" x2="45" y2="55" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<!-- long legs (walking stride) front leg forward, back leg behind -->
<line x1="78" y1="95" x2="100" y2="170" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<line x1="62" y1="95" x2="40" y2="170" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<!-- big flat feet (walking) -->
<ellipse cx="105" cy="173" rx="11" ry="4" fill="currentColor" opacity="0.25"/>
<ellipse cx="35" cy="173" rx="10" ry="4" fill="currentColor" opacity="0.22"/>
</svg>
<!-- 8. Illustratrice at easel, brush in one hand, palette in other, canvas showing a shadok -->
<svg class="shadok shadok-illustratrice" viewBox="0 0 180 220" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- easel legs -->
<line x1="105" y1="30" x2="85" y2="210" stroke="currentColor" stroke-width="2" opacity="0.2"/>
<line x1="145" y1="30" x2="165" y2="210" stroke="currentColor" stroke-width="2" opacity="0.2"/>
<line x1="125" y1="60" x2="125" y2="210" stroke="currentColor" stroke-width="2" opacity="0.18"/>
<!-- canvas on easel -->
<rect x="95" y="25" width="60" height="75" rx="2" fill="currentColor" opacity="0.08"/>
<rect x="95" y="25" width="60" height="75" rx="2" stroke="currentColor" stroke-width="1.5" fill="none" opacity="0.2"/>
<!-- tiny shadok drawing on canvas! -->
<ellipse cx="125" cy="65" rx="8" ry="10" fill="currentColor" opacity="0.18"/>
<circle cx="125" cy="52" r="6" fill="currentColor" opacity="0.2"/>
<polygon points="130,51 136,53 130,55" fill="currentColor" opacity="0.18"/>
<circle cx="123" cy="51" r="1" fill="currentColor" opacity="0.3"/>
<circle cx="127" cy="51" r="1" fill="currentColor" opacity="0.3"/>
<line x1="121" y1="75" x2="118" y2="88" stroke="currentColor" stroke-width="1" opacity="0.15"/>
<line x1="129" y1="75" x2="132" y2="88" stroke="currentColor" stroke-width="1" opacity="0.15"/>
<!-- body (3/4 view, standing back from easel) -->
<ellipse cx="55" cy="90" rx="22" ry="28" fill="currentColor" opacity="0.28"/>
<!-- head (looking at canvas) -->
<circle cx="62" cy="52" r="16" fill="currentColor" opacity="0.3"/>
<!-- beak (profile right, toward canvas) -->
<polygon points="75,50 88,54 76,56" fill="currentColor" opacity="0.3"/>
<!-- eyes (artistic scrutiny, different sizes) -->
<circle cx="60" cy="49" r="2" fill="currentColor" opacity="0.55"/>
<circle cx="69" cy="50" r="2.8" fill="currentColor" opacity="0.6"/>
<!-- arm holding brush toward canvas -->
<line x1="73" y1="82" x2="100" y2="60" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3"/>
<!-- paintbrush -->
<line x1="100" y1="60" x2="108" y2="52" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.35"/>
<circle cx="110" cy="50" r="2" fill="currentColor" opacity="0.3"/>
<!-- other arm holding palette -->
<line x1="38" y1="85" x2="18" y2="95" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<!-- palette (big, with color dots) -->
<ellipse cx="12" cy="102" rx="16" ry="12" fill="currentColor" opacity="0.15"/>
<!-- thumb hole -->
<circle cx="12" cy="108" r="3" fill="currentColor" opacity="0.05"/>
<!-- paint dabs on palette -->
<circle cx="6" cy="97" r="2.5" fill="currentColor" opacity="0.3"/>
<circle cx="14" cy="94" r="2" fill="currentColor" opacity="0.25"/>
<circle cx="21" cy="98" r="2.5" fill="currentColor" opacity="0.28"/>
<circle cx="8" cy="104" r="2" fill="currentColor" opacity="0.22"/>
<circle cx="18" cy="103" r="2" fill="currentColor" opacity="0.3"/>
<!-- long legs -->
<line x1="45" y1="116" x2="35" y2="188" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<line x1="65" y1="116" x2="75" y2="188" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.25"/>
<!-- big flat feet -->
<ellipse cx="30" cy="191" rx="10" ry="4" fill="currentColor" opacity="0.25"/>
<ellipse cx="80" cy="191" rx="10" ry="4" fill="currentColor" opacity="0.25"/>
</svg>
<div class="container-content">
<!-- Page de couverture du livre -->
<HomeBookSection
class="mb-16"
:show-chapters="false"
@open-player="showBookPlayer = true"
@open-pdf="showPdfReader = true"
/>
<header class="mb-12 text-center">
<p class="mb-2 font-mono text-sm tracking-widest text-primary uppercase">{{ content?.kicker }}</p>
<h1 class="page-title font-display font-bold tracking-tight" style="color: hsl(var(--color-text))">
{{ content?.title }}
</h1>
<p class="mt-4 mx-auto max-w-2xl" style="color: hsl(var(--color-text-muted))">
{{ content?.description }}
</p>
</header>
<div class="mx-auto max-w-3xl">
<ul class="flex flex-col gap-3">
<li
v-for="chapter in chapters"
:key="chapter.path"
>
<NuxtLink
:to="`/economique/modele-eco/${chapter.stem?.split('/').pop()}`"
class="card-surface flex items-start gap-4 group"
>
<span class="font-mono text-2xl font-bold text-primary/30 leading-none mt-1 w-10 text-right flex-shrink-0">
{{ String(chapter.order).padStart(2, '0') }}
</span>
<div class="min-w-0 flex-1">
<h2 class="font-display text-lg font-semibold text-white group-hover:text-primary transition-colors">
{{ chapter.title }}
</h2>
<p v-if="chapter.description" class="mt-1 text-sm text-white/50">
{{ chapter.description }}
</p>
<div class="mt-2 flex items-center gap-3">
<span v-if="chapter.readingTime" class="text-xs text-white/30">
<span class="i-lucide-clock inline-block h-3 w-3 mr-1 align-middle" />
{{ chapter.readingTime }}
</span>
<SongBadges :chapter-slug="chapter.stem?.split('/').pop() ?? ''" />
</div>
</div>
<div class="i-lucide-chevron-right h-5 w-5 text-white/20 group-hover:text-primary/60 transition-colors flex-shrink-0 mt-2" />
</NuxtLink>
</li>
</ul>
</div>
</div>
<BookPlayer v-model="showBookPlayer" />
<BookPdfReader v-model="showPdfReader" />
</div>
</template>
<script setup lang="ts">
definePageMeta({
layout: 'default',
})
const { data: content } = await usePageContent('economique/modele-eco')
useHead({
title: content.value?.meta?.title ?? 'Table des matières',
})
const { data: chapters } = await useAsyncData('book-toc', () =>
queryCollection('book').order('order', 'ASC').all(),
)
const showBookPlayer = ref(false)
const showPdfReader = ref(false)
</script>
<style scoped>
.page-title {
font-size: clamp(2rem, 5vw, 2.75rem);
}
/* Shadok illustrations — shared */
.shadok {
position: absolute;
pointer-events: none;
width: clamp(70px, 10vw, 140px);
z-index: 0;
}
/* 1. Typographe — top left */
.shadok-typographe {
top: 1%;
left: 1%;
opacity: 0.24;
color: hsl(var(--color-primary));
animation: shadok-float-1 9s ease-in-out infinite;
}
/* 2. Lectrice — top right, sitting */
.shadok-lectrice {
top: 2%;
right: 1%;
opacity: 0.22;
color: hsl(var(--color-accent));
animation: shadok-float-2 11s ease-in-out infinite;
}
/* 3. Calligraphe — left, 40% */
.shadok-calligraphe {
top: 40%;
left: 1%;
opacity: 0.2;
color: hsl(var(--color-primary));
animation: shadok-float-3 10s ease-in-out infinite;
}
/* 4. Relieur — right, 35% */
.shadok-relieur {
top: 35%;
right: 2%;
opacity: 0.24;
color: hsl(var(--color-accent));
animation: shadok-float-4 8s ease-in-out infinite;
}
/* 5. Conteuse — bottom left */
.shadok-conteuse {
bottom: 6%;
left: 1%;
opacity: 0.22;
color: hsl(var(--color-primary));
animation: shadok-float-5 12s ease-in-out infinite;
}
/* 6. Correcteur — bottom right, leaning */
.shadok-correcteur {
bottom: 5%;
right: 1%;
opacity: 0.2;
color: hsl(var(--color-accent));
animation: shadok-float-6 9.5s ease-in-out infinite;
}
/* 7. Colporteur — center bottom, walking */
.shadok-colporteur {
bottom: 2%;
left: 50%;
transform: translateX(-50%);
opacity: 0.18;
color: hsl(var(--color-primary));
animation: shadok-float-7 7.5s ease-in-out infinite;
}
/* 8. Illustratrice — right, 58% */
.shadok-illustratrice {
top: 58%;
right: 1%;
opacity: 0.26;
color: hsl(var(--color-accent));
animation: shadok-float-8 10.5s ease-in-out infinite;
}
/* Float animations — each unique duration and offset */
@keyframes shadok-float-1 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
@keyframes shadok-float-2 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
}
@keyframes shadok-float-3 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-12px); }
}
@keyframes shadok-float-4 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-9px); }
}
@keyframes shadok-float-5 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-11px); }
}
@keyframes shadok-float-6 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-7px); }
}
@keyframes shadok-float-7 {
0%, 100% { transform: translateX(-50%) translateY(0); }
50% { transform: translateX(-50%) translateY(-10px); }
}
@keyframes shadok-float-8 {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
}
/* Hidden on mobile */
@media (max-width: 768px) {
.shadok {
display: none;
}
}
</style>

View File

@@ -0,0 +1,119 @@
<template>
<div class="section-padding">
<div class="container-content">
<div class="mx-auto max-w-2xl">
<div class="section-icon mx-auto mb-6">
<span v-if="content?.icon === 'g1'" class="g1-icon">Ğ1</span>
<div v-else :class="`i-lucide-${content?.icon ?? 'coins'}`" class="h-12 w-12" />
</div>
<p class="mb-2 font-mono text-sm tracking-widest text-primary uppercase text-center">
{{ content?.kicker }}
</p>
<h1 class="font-display text-3xl font-bold mb-4 text-center" style="color: hsl(var(--color-text))">
{{ content?.title }}
</h1>
<p class="text-lg leading-relaxed mb-8 text-center" style="color: hsl(var(--color-text-muted))">
{{ content?.description }}
</p>
<!-- Content -->
<div v-if="content?.content" class="prose-block mb-8">
<p class="leading-relaxed whitespace-pre-line" style="color: hsl(var(--color-text-muted))">
{{ content.content }}
</p>
</div>
<!-- External links -->
<div v-if="content?.links" class="flex flex-col gap-3 mb-10">
<a
v-for="link in content.links"
:key="link.href"
:href="link.href"
target="_blank"
rel="noopener"
class="link-card group"
>
<div class="link-icon">
<div :class="`i-lucide-${link.icon ?? 'external-link'} h-4 w-4`" />
</div>
<span class="text-sm font-medium" style="color: hsl(var(--color-text))">{{ link.label }}</span>
<div class="i-lucide-arrow-up-right h-3.5 w-3.5 ml-auto text-primary/40 group-hover:text-primary transition-colors" />
</a>
</div>
<div class="text-center">
<UiBaseButton variant="ghost" to="/economique">
<div class="i-lucide-arrow-left mr-2 h-4 w-4" />
Autonomie économique
</UiBaseButton>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
const { data: content } = await usePageContent('economique/monnaie-libre')
useHead({
title: content.value?.meta?.title ?? 'Monnaie libre',
})
</script>
<style scoped>
.g1-icon {
font-family: var(--font-display);
font-weight: 700;
font-size: 1.75rem;
line-height: 1;
}
.section-icon {
display: flex;
align-items: center;
justify-content: center;
width: 5rem;
height: 5rem;
border-radius: 1rem;
background: hsl(var(--color-primary) / 0.1);
border: 1px solid hsl(var(--color-primary) / 0.2);
color: hsl(var(--color-primary));
}
.prose-block {
padding: 1.5rem;
border-radius: 0.75rem;
background: hsl(var(--color-surface));
}
.link-card {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem 1rem;
border-radius: 0.5rem;
border: 1px solid hsl(var(--color-primary) / 0.1);
background: hsl(var(--color-surface));
text-decoration: none;
transition: border-color 0.2s;
}
.link-card:hover {
border-color: hsl(var(--color-primary) / 0.25);
}
.link-icon {
display: flex;
align-items: center;
justify-content: center;
width: 1.75rem;
height: 1.75rem;
border-radius: 0.375rem;
background: hsl(var(--color-primary) / 0.1);
color: hsl(var(--color-primary));
flex-shrink: 0;
}
</style>

View File

@@ -0,0 +1,85 @@
<template>
<div class="section-padding">
<div class="container-content">
<div class="mx-auto max-w-2xl">
<div class="section-icon mx-auto mb-6">
<div :class="`i-lucide-${content?.icon ?? 'users'}`" class="h-12 w-12" />
</div>
<p class="mb-2 font-mono text-sm tracking-widest text-primary uppercase text-center">
{{ content?.kicker }}
</p>
<h1 class="font-display text-3xl font-bold mb-4 text-center" style="color: hsl(var(--color-text))">
{{ content?.title }}
</h1>
<p class="text-lg leading-relaxed mb-8 text-center" style="color: hsl(var(--color-text-muted))">
{{ content?.description }}
</p>
<span v-if="content?.gestation" class="gestation-badge mx-auto mb-8">
<div class="i-lucide-flask-conical h-3 w-3" />
En gestation
</span>
<!-- Content -->
<div v-if="content?.content" class="prose-block mb-10">
<p class="leading-relaxed whitespace-pre-line" style="color: hsl(var(--color-text-muted))">
{{ content.content }}
</p>
</div>
<div class="text-center">
<UiBaseButton variant="ghost" to="/economique">
<div class="i-lucide-arrow-left mr-2 h-4 w-4" />
Autonomie économique
</UiBaseButton>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
const { data: content } = await usePageContent('economique/productions-collectives')
useHead({
title: content.value?.meta?.title ?? 'Productions collectives',
})
</script>
<style scoped>
.section-icon {
display: flex;
align-items: center;
justify-content: center;
width: 5rem;
height: 5rem;
border-radius: 1rem;
background: hsl(var(--color-primary) / 0.1);
border: 1px solid hsl(var(--color-primary) / 0.2);
color: hsl(var(--color-primary));
}
.gestation-badge {
display: flex;
align-items: center;
justify-content: center;
gap: 0.25rem;
padding: 0.25rem 0.75rem;
border-radius: 9999px;
background: hsl(var(--color-accent) / 0.12);
color: hsl(var(--color-accent));
font-size: 0.75rem;
font-weight: 500;
font-family: var(--font-mono);
width: fit-content;
}
.prose-block {
padding: 1.5rem;
border-radius: 0.75rem;
background: hsl(var(--color-surface));
}
</style>

View File

@@ -1,152 +1,340 @@
<template>
<div class="relative overflow-hidden section-padding min-h-[70vh] flex items-center justify-center">
<!-- Shadok jongleur: juggling coins (top-left) -->
<svg class="shadok-juggler" viewBox="0 0 240 300" fill="none" aria-hidden="true">
<!-- 1. Shadok funambule: walking on tightrope (top-left) -->
<svg class="shadok-funambule" viewBox="0 0 170 200" fill="none" aria-hidden="true">
<!-- Tightrope -->
<line x1="5" y1="170" x2="165" y2="170" stroke="currentColor" stroke-width="2" opacity="0.3"/>
<!-- Body (small oval, leaning forward) -->
<ellipse cx="85" cy="110" rx="20" ry="28" fill="currentColor" opacity="0.25" transform="rotate(-5 85 110)"/>
<!-- Head -->
<circle cx="88" cy="72" r="16" fill="currentColor" opacity="0.3"/>
<!-- Eyes (focused, looking down-right) -->
<circle cx="93" cy="70" r="1.8" fill="currentColor" opacity="0.5"/>
<circle cx="99" cy="71" r="1.8" fill="currentColor" opacity="0.5"/>
<!-- Beak (pointy, right side) -->
<polygon points="103,74 116,72 103,78" fill="currentColor" opacity="0.3"/>
<!-- Balancing pole (big, horizontal) -->
<line x1="10" y1="92" x2="160" y2="88" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- Arms holding pole -->
<line x1="67" y1="100" x2="45" y2="92" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="103" y1="98" x2="125" y2="90" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Left leg (forward, on rope) -->
<line x1="78" y1="136" x2="70" y2="170" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<ellipse cx="70" cy="172" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
<!-- Right leg (back, lifted) -->
<line x1="92" y1="136" x2="108" y2="165" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<ellipse cx="108" cy="167" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
</svg>
<!-- 2. Shadok accordeoniste: playing accordion (top-right, profile) -->
<svg class="shadok-accordeoniste" viewBox="0 0 180 210" fill="none" aria-hidden="true">
<!-- Body (profile, small) -->
<ellipse cx="70" cy="115" rx="22" ry="28" fill="currentColor" opacity="0.25"/>
<!-- Head (profile) -->
<circle cx="72" cy="75" r="16" fill="currentColor" opacity="0.3"/>
<!-- Beret -->
<ellipse cx="72" cy="60" rx="18" ry="6" fill="currentColor" opacity="0.3"/>
<circle cx="72" cy="56" r="4" fill="currentColor" opacity="0.25"/>
<!-- Eye (profile, one visible) -->
<circle cx="80" cy="73" r="1.8" fill="currentColor" opacity="0.5"/>
<!-- Beak (profile right) -->
<polygon points="86,76 98,74 86,80" fill="currentColor" opacity="0.3"/>
<!-- Accordion bellows (big, extended right) -->
<rect x="92" y="95" width="12" height="45" rx="2" fill="currentColor" opacity="0.3"/>
<line x1="98" y1="98" x2="98" y2="137" stroke="currentColor" stroke-width="0.8" opacity="0.2"/>
<rect x="107" y="93" width="8" height="49" rx="2" fill="currentColor" opacity="0.25"/>
<rect x="118" y="91" width="8" height="53" rx="2" fill="currentColor" opacity="0.2"/>
<rect x="129" y="89" width="8" height="57" rx="2" fill="currentColor" opacity="0.25"/>
<rect x="140" y="87" width="12" height="61" rx="2" fill="currentColor" opacity="0.3"/>
<!-- Keyboard dots on right panel -->
<circle cx="146" cy="100" r="1.5" fill="currentColor" opacity="0.2"/>
<circle cx="146" cy="110" r="1.5" fill="currentColor" opacity="0.2"/>
<circle cx="146" cy="120" r="1.5" fill="currentColor" opacity="0.2"/>
<circle cx="146" cy="130" r="1.5" fill="currentColor" opacity="0.2"/>
<!-- Left arm on bellows -->
<line x1="52" y1="105" x2="92" y2="105" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Right arm stretched to far end -->
<line x1="90" y1="108" x2="140" y2="100" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Foot tapping (right lifted) -->
<line x1="60" y1="141" x2="52" y2="195" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<ellipse cx="52" cy="197" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
<line x1="80" y1="141" x2="90" y2="188" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<ellipse cx="90" cy="190" rx="8" ry="3" fill="currentColor" opacity="0.3" transform="rotate(-15 90 190)"/>
<!-- Music notes -->
<text x="155" y="80" fill="currentColor" opacity="0.25" font-size="14">&#9834;</text>
<text x="145" y="68" fill="currentColor" opacity="0.2" font-size="11">&#9835;</text>
</svg>
<!-- 3. Shadok jongleur: 4 balls in the air (top-center) -->
<svg class="shadok-jongleur" viewBox="0 0 160 210" fill="none" aria-hidden="true">
<!-- Body -->
<ellipse cx="120" cy="160" rx="38" ry="46" fill="currentColor" opacity="0.85"/>
<ellipse cx="80" cy="120" rx="21" ry="27" fill="currentColor" opacity="0.25"/>
<!-- Head -->
<circle cx="120" cy="98" r="24" fill="currentColor" opacity="0.8"/>
<!-- Eyes (looking up at coins) -->
<circle cx="112" cy="92" r="3.5" fill="currentColor" opacity="0.2"/>
<circle cx="130" cy="92" r="3.5" fill="currentColor" opacity="0.2"/>
<circle cx="113" cy="91" r="1.5" fill="currentColor" opacity="0.5"/>
<circle cx="131" cy="91" r="1.5" fill="currentColor" opacity="0.5"/>
<!-- Smile -->
<path d="M112 108 Q120 114 128 108" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.35"/>
<!-- Arms up (juggling) -->
<line x1="85" y1="145" x2="55" y2="105" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<line x1="155" y1="145" x2="185" y2="105" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<!-- Hands -->
<circle cx="55" cy="103" r="4" fill="currentColor" opacity="0.4"/>
<circle cx="185" cy="103" r="4" fill="currentColor" opacity="0.4"/>
<!-- Juggling coins -->
<circle cx="90" cy="55" r="8" fill="currentColor" opacity="0.35"/>
<text x="86" y="59" fill="currentColor" opacity="0.5" font-size="10" font-weight="bold">$</text>
<circle cx="120" cy="40" r="8" fill="currentColor" opacity="0.3"/>
<text x="116" y="44" fill="currentColor" opacity="0.45" font-size="10" font-weight="bold">$</text>
<circle cx="150" cy="50" r="8" fill="currentColor" opacity="0.32"/>
<text x="146" y="54" fill="currentColor" opacity="0.48" font-size="10" font-weight="bold">$</text>
<!-- Legs -->
<line x1="105" y1="203" x2="95" y2="260" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<line x1="135" y1="203" x2="145" y2="260" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<circle cx="80" cy="82" r="15" fill="currentColor" opacity="0.3"/>
<!-- Eyes (looking up, wide) -->
<circle cx="74" cy="78" r="2" fill="currentColor" opacity="0.5"/>
<circle cx="86" cy="78" r="2" fill="currentColor" opacity="0.5"/>
<!-- Mouth open (concentration) -->
<ellipse cx="80" cy="92" rx="4" ry="3" fill="currentColor" opacity="0.2"/>
<!-- Beak (small, front view) -->
<polygon points="80,86 87,89 80,92" fill="currentColor" opacity="0.3"/>
<!-- Arms up wide -->
<line x1="60" y1="110" x2="30" y2="75" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="100" y1="110" x2="130" y2="75" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- 4 juggling balls in arc -->
<circle cx="40" cy="35" r="8" fill="currentColor" opacity="0.3"/>
<circle cx="70" cy="18" r="8" fill="currentColor" opacity="0.25"/>
<circle cx="100" cy="15" r="8" fill="currentColor" opacity="0.3"/>
<circle cx="128" cy="30" r="8" fill="currentColor" opacity="0.25"/>
<!-- Long legs -->
<line x1="72" y1="145" x2="60" y2="200" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<ellipse cx="60" cy="202" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
<line x1="88" y1="145" x2="100" y2="200" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<ellipse cx="100" cy="202" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
</svg>
<!-- Shadok échelle: on a wobbly ladder (top-right) -->
<svg class="shadok-ladder" viewBox="0 0 220 320" fill="none" aria-hidden="true">
<!-- Ladder (tilting) -->
<line x1="80" y1="50" x2="70" y2="300" stroke="currentColor" stroke-width="3" opacity="0.35"/>
<line x1="150" y1="50" x2="140" y2="300" stroke="currentColor" stroke-width="3" opacity="0.35"/>
<!-- Rungs -->
<line x1="82" y1="80" x2="148" y2="80" stroke="currentColor" stroke-width="2.5" opacity="0.3"/>
<line x1="83" y1="120" x2="147" y2="120" stroke="currentColor" stroke-width="2.5" opacity="0.3"/>
<line x1="84" y1="160" x2="146" y2="160" stroke="currentColor" stroke-width="2.5" opacity="0.3"/>
<line x1="85" y1="200" x2="145" y2="200" stroke="currentColor" stroke-width="2.5" opacity="0.3"/>
<line x1="86" y1="240" x2="144" y2="240" stroke="currentColor" stroke-width="2.5" opacity="0.3"/>
<!-- Shadok on top (arms out for balance) -->
<ellipse cx="115" cy="68" rx="18" ry="14" fill="currentColor" opacity="0.85"/>
<circle cx="115" cy="46" r="14" fill="currentColor" opacity="0.8"/>
<!-- Eyes (worried) -->
<circle cx="110" cy="43" r="3" fill="currentColor" opacity="0.25"/>
<circle cx="122" cy="43" r="3" fill="currentColor" opacity="0.25"/>
<circle cx="110" cy="44" r="1.2" fill="currentColor" opacity="0.5"/>
<circle cx="122" cy="44" r="1.2" fill="currentColor" opacity="0.5"/>
<!-- Worried mouth -->
<path d="M108 52 Q115 49 122 52" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.3"/>
<!-- Arms out (balancing) -->
<line x1="97" y1="62" x2="60" y2="55" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.6"/>
<line x1="133" y1="62" x2="170" y2="55" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.6"/>
</svg>
<!-- Shadok acrobate: doing a cartwheel (center) -->
<svg class="shadok-acrobat" viewBox="0 0 260 240" fill="none" aria-hidden="true">
<!-- Body (sideways, mid-cartwheel) -->
<ellipse cx="130" cy="120" rx="30" ry="38" fill="currentColor" opacity="0.85" transform="rotate(45 130 120)"/>
<!-- Head -->
<circle cx="155" cy="82" r="20" fill="currentColor" opacity="0.8"/>
<!-- Eyes (dizzy/happy) -->
<path d="M148 78 Q152 74 156 78" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none" opacity="0.4"/>
<path d="M160 78 Q164 74 168 78" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none" opacity="0.4"/>
<!-- Smile -->
<path d="M150 90 Q158 95 165 90" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.3"/>
<!-- Arms (one touching ground, one up) -->
<line x1="110" y1="100" x2="80" y2="130" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.6"/>
<line x1="150" y1="105" x2="185" y2="70" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.6"/>
<!-- Hand on ground -->
<circle cx="78" cy="132" r="4" fill="currentColor" opacity="0.4"/>
<!-- Legs (splayed in cartwheel) -->
<line x1="125" y1="155" x2="100" y2="195" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.6"/>
<line x1="140" y1="150" x2="175" y2="175" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.6"/>
<!-- Motion lines -->
<path d="M70 110 Q60 105 55 115" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.2"/>
<path d="M190 60 Q200 55 205 65" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.2"/>
</svg>
<!-- Shadok dormeur: sleeping on a cloud (bottom-left) -->
<svg class="shadok-sleeper" viewBox="0 0 260 220" fill="none" aria-hidden="true">
<!-- Cloud -->
<ellipse cx="130" cy="150" rx="80" ry="25" fill="currentColor" opacity="0.2"/>
<circle cx="80" cy="140" r="25" fill="currentColor" opacity="0.18"/>
<circle cx="120" cy="130" r="30" fill="currentColor" opacity="0.2"/>
<circle cx="165" cy="135" r="22" fill="currentColor" opacity="0.18"/>
<circle cx="190" cy="142" r="18" fill="currentColor" opacity="0.15"/>
<!-- Shadok body (lying down) -->
<ellipse cx="130" cy="125" rx="35" ry="18" fill="currentColor" opacity="0.85"/>
<!-- Head (on cloud, sideways) -->
<ellipse cx="85" cy="118" rx="18" ry="16" fill="currentColor" opacity="0.8"/>
<!-- Closed eyes (sleeping) -->
<path d="M76 115 Q80 112 84 115" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.4"/>
<path d="M88 115 Q92 112 96 115" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.4"/>
<!-- Snooze bubbles -->
<text x="70" y="100" fill="currentColor" opacity="0.3" font-size="12" font-weight="bold">z</text>
<text x="60" y="85" fill="currentColor" opacity="0.25" font-size="16" font-weight="bold">z</text>
<text x="48" y="68" fill="currentColor" opacity="0.2" font-size="20" font-weight="bold">z</text>
<!-- Legs (curled) -->
<path d="M165 125 Q180 130 175 140" stroke="currentColor" stroke-width="3" stroke-linecap="round" fill="none" opacity="0.5"/>
<path d="M160 130 Q172 138 168 148" stroke="currentColor" stroke-width="3" stroke-linecap="round" fill="none" opacity="0.5"/>
</svg>
<!-- Shadok cuisinier: cooking in a cauldron (bottom-right) -->
<svg class="shadok-cook" viewBox="0 0 240 300" fill="none" aria-hidden="true">
<!-- 4. Shadok cracheur de feu: head tilted back, flame from mouth -->
<svg class="shadok-cracheur" viewBox="0 0 170 220" fill="none" aria-hidden="true">
<!-- Body -->
<ellipse cx="120" cy="145" rx="38" ry="45" fill="currentColor" opacity="0.85"/>
<ellipse cx="75" cy="125" rx="22" ry="30" fill="currentColor" opacity="0.25"/>
<!-- Head (tilted back) -->
<circle cx="78" cy="82" r="16" fill="currentColor" opacity="0.3" />
<!-- Eyes (looking up) -->
<circle cx="73" cy="76" r="1.8" fill="currentColor" opacity="0.5"/>
<circle cx="83" cy="76" r="1.8" fill="currentColor" opacity="0.5"/>
<!-- Beak (pointing up, open) -->
<polygon points="78,66 85,52 72,66" fill="currentColor" opacity="0.3"/>
<!-- Flame stream from beak (big, upward-right) -->
<path d="M82 54 Q100 25 95 10 Q110 30 120 8 Q115 35 135 15 Q120 42 140 30 Q118 50 130 45" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="currentColor" opacity="0.2"/>
<!-- Torch in left hand -->
<line x1="55" y1="115" x2="30" y2="90" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<rect x="24" y="78" width="8" height="16" rx="2" fill="currentColor" opacity="0.35"/>
<path d="M28 78 Q28 68 32 72 Q28 65 28 78" fill="currentColor" opacity="0.25"/>
<!-- Right arm out for balance -->
<line x1="95" y1="112" x2="125" y2="100" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Long legs -->
<line x1="66" y1="153" x2="55" y2="210" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<ellipse cx="55" cy="212" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
<line x1="84" y1="153" x2="95" y2="210" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<ellipse cx="95" cy="212" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
</svg>
<!-- 5. Shadok trapeziste: hanging from trapeze, body in arc -->
<svg class="shadok-trapeziste" viewBox="0 0 150 220" fill="none" aria-hidden="true">
<!-- Trapeze ropes -->
<line x1="40" y1="0" x2="50" y2="40" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.3"/>
<line x1="110" y1="0" x2="100" y2="40" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.3"/>
<!-- Trapeze bar -->
<line x1="48" y1="40" x2="102" y2="40" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.35"/>
<!-- Arms (hanging from bar) -->
<line x1="60" y1="42" x2="65" y2="70" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="90" y1="42" x2="85" y2="70" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Body (arched, graceful) -->
<ellipse cx="75" cy="95" rx="20" ry="25" fill="currentColor" opacity="0.25" transform="rotate(10 75 95)"/>
<!-- Head (below body, looking down) -->
<circle cx="78" cy="72" r="14" fill="currentColor" opacity="0.3"/>
<!-- Eyes (excited, looking down) -->
<circle cx="74" cy="74" r="1.8" fill="currentColor" opacity="0.5"/>
<circle cx="84" cy="75" r="1.8" fill="currentColor" opacity="0.5"/>
<!-- Beak (pointing down-right) -->
<polygon points="86,78 96,84 86,82" fill="currentColor" opacity="0.3"/>
<!-- Legs (pointed, graceful, extending down-right) -->
<line x1="80" y1="118" x2="95" y2="175" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="70" y1="118" x2="82" y2="180" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Pointed feet -->
<polygon points="95,175 105,180 95,182" fill="currentColor" opacity="0.3"/>
<polygon points="82,180 92,185 82,187" fill="currentColor" opacity="0.3"/>
</svg>
<!-- 6. Shadok batteur: behind drum kit, sticks raised -->
<svg class="shadok-batteur" viewBox="0 0 180 210" fill="none" aria-hidden="true">
<!-- Snare drum (center, big) -->
<ellipse cx="90" cy="165" rx="35" ry="12" fill="currentColor" opacity="0.2"/>
<rect x="55" y="155" width="70" height="20" rx="3" fill="currentColor" opacity="0.2"/>
<ellipse cx="90" cy="155" rx="35" ry="12" fill="currentColor" opacity="0.25"/>
<!-- Hi-hat (left) -->
<ellipse cx="30" cy="140" rx="18" ry="5" fill="currentColor" opacity="0.2"/>
<line x1="30" y1="140" x2="30" y2="185" stroke="currentColor" stroke-width="2" opacity="0.2"/>
<!-- Cymbal (right) -->
<ellipse cx="155" cy="120" rx="20" ry="5" fill="currentColor" opacity="0.2"/>
<line x1="155" y1="120" x2="155" y2="185" stroke="currentColor" stroke-width="2" opacity="0.2"/>
<!-- Body (behind kit) -->
<ellipse cx="90" cy="110" rx="22" ry="28" fill="currentColor" opacity="0.25"/>
<!-- Head -->
<circle cx="120" cy="85" r="24" fill="currentColor" opacity="0.8"/>
<!-- Chef hat -->
<ellipse cx="120" cy="62" rx="22" ry="18" fill="currentColor" opacity="0.35"/>
<rect x="105" y="68" width="30" height="6" rx="1" fill="currentColor" opacity="0.4"/>
<!-- Eyes (focused on cooking) -->
<circle cx="112" cy="82" r="3.5" fill="currentColor" opacity="0.2"/>
<circle cx="130" cy="82" r="3.5" fill="currentColor" opacity="0.2"/>
<circle cx="113" cy="83" r="1.5" fill="currentColor" opacity="0.5"/>
<circle cx="131" cy="83" r="1.5" fill="currentColor" opacity="0.5"/>
<!-- Tongue out (concentrating) -->
<path d="M115 96 Q120 100 125 96" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.3"/>
<!-- Arm with ladle -->
<line x1="155" y1="135" x2="185" y2="175" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<!-- Ladle -->
<line x1="185" y1="175" x2="175" y2="200" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.5"/>
<ellipse cx="175" cy="205" rx="8" ry="5" fill="currentColor" opacity="0.35"/>
<!-- Other arm -->
<line x1="85" y1="140" x2="60" y2="175" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<!-- Legs -->
<line x1="105" y1="188" x2="95" y2="250" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<line x1="135" y1="188" x2="145" y2="250" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<!-- Cauldron -->
<path d="M55 220 Q55 260 120 260 Q185 260 185 220" fill="currentColor" opacity="0.3"/>
<ellipse cx="120" cy="220" rx="65" ry="12" fill="currentColor" opacity="0.25"/>
<ellipse cx="120" cy="220" rx="65" ry="12" stroke="currentColor" stroke-width="2" fill="none" opacity="0.35"/>
<!-- Steam -->
<path d="M95 210 Q90 195 95 185" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.2"/>
<path d="M120 208 Q118 190 122 180" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.2"/>
<path d="M145 210 Q148 195 143 185" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.2"/>
<circle cx="90" cy="70" r="16" fill="currentColor" opacity="0.3"/>
<!-- Eyes (intense, looking at drums) -->
<circle cx="84" cy="68" r="2" fill="currentColor" opacity="0.5"/>
<circle cx="96" cy="69" r="2" fill="currentColor" opacity="0.5"/>
<!-- Beak (front, small) -->
<polygon points="90,76 97,80 90,82" fill="currentColor" opacity="0.3"/>
<!-- Arms raised with drumsticks -->
<line x1="70" y1="100" x2="40" y2="65" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="40" y1="65" x2="25" y2="50" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.35"/>
<line x1="110" y1="100" x2="140" y2="60" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="140" y1="60" x2="158" y2="48" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.35"/>
<!-- Motion lines on sticks -->
<path d="M22 52 Q18 48 20 44" stroke="currentColor" stroke-width="1" stroke-linecap="round" fill="none" opacity="0.2"/>
<path d="M160 50 Q164 46 162 42" stroke="currentColor" stroke-width="1" stroke-linecap="round" fill="none" opacity="0.2"/>
<!-- Legs (tucked behind kit) -->
<line x1="80" y1="136" x2="70" y2="195" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<ellipse cx="70" cy="197" rx="7" ry="3" fill="currentColor" opacity="0.25"/>
<line x1="100" y1="136" x2="110" y2="195" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<ellipse cx="110" cy="197" rx="7" ry="3" fill="currentColor" opacity="0.25"/>
</svg>
<!-- 7. Shadok marionnettiste: holding puppet strings -->
<svg class="shadok-marionnettiste" viewBox="0 0 160 220" fill="none" aria-hidden="true">
<!-- Body -->
<ellipse cx="80" cy="75" rx="20" ry="26" fill="currentColor" opacity="0.25"/>
<!-- Head -->
<circle cx="80" cy="40" r="15" fill="currentColor" opacity="0.3"/>
<!-- Eyes (looking down at puppet) -->
<circle cx="75" cy="42" r="1.8" fill="currentColor" opacity="0.5"/>
<circle cx="86" cy="43" r="1.8" fill="currentColor" opacity="0.5"/>
<!-- Beak -->
<polygon points="89,44 100,42 89,48" fill="currentColor" opacity="0.3"/>
<!-- Arms down holding control bar -->
<line x1="62" y1="68" x2="50" y2="105" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="98" y1="68" x2="110" y2="105" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Control bar (cross) -->
<line x1="40" y1="108" x2="120" y2="108" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.35"/>
<line x1="80" y1="98" x2="80" y2="118" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.35"/>
<!-- Puppet strings -->
<line x1="45" y1="108" x2="55" y2="155" stroke="currentColor" stroke-width="1" opacity="0.25"/>
<line x1="80" y1="118" x2="70" y2="158" stroke="currentColor" stroke-width="1" opacity="0.25"/>
<line x1="115" y1="108" x2="85" y2="155" stroke="currentColor" stroke-width="1" opacity="0.25"/>
<line x1="80" y1="98" x2="70" y2="148" stroke="currentColor" stroke-width="1" opacity="0.25"/>
<!-- Mini puppet shadok -->
<circle cx="70" cy="155" r="8" fill="currentColor" opacity="0.2"/>
<ellipse cx="70" cy="172" rx="10" ry="13" fill="currentColor" opacity="0.15"/>
<!-- Puppet eyes -->
<circle cx="67" cy="154" r="1" fill="currentColor" opacity="0.4"/>
<circle cx="74" cy="154" r="1" fill="currentColor" opacity="0.4"/>
<!-- Puppet beak -->
<polygon points="76,156 82,155 76,158" fill="currentColor" opacity="0.2"/>
<!-- Puppet legs -->
<line x1="64" y1="184" x2="58" y2="208" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.25"/>
<line x1="76" y1="184" x2="82" y2="208" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.25"/>
<!-- Master shadok legs -->
<line x1="72" y1="99" x2="62" y2="155" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3"/>
<line x1="88" y1="99" x2="98" y2="155" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.3"/>
<ellipse cx="62" cy="157" rx="7" ry="3" fill="currentColor" opacity="0.25"/>
<ellipse cx="98" cy="157" rx="7" ry="3" fill="currentColor" opacity="0.25"/>
</svg>
<!-- 8. Shadok clown: oversized shoes, red nose, squirting flower -->
<svg class="shadok-clown" viewBox="0 0 160 210" fill="none" aria-hidden="true">
<!-- Body -->
<ellipse cx="80" cy="110" rx="22" ry="28" fill="currentColor" opacity="0.25"/>
<!-- Head -->
<circle cx="80" cy="70" r="16" fill="currentColor" opacity="0.3"/>
<!-- Party hat (tall cone) -->
<polygon points="80,38 68,62 92,62" fill="currentColor" opacity="0.25"/>
<circle cx="80" cy="38" r="3" fill="currentColor" opacity="0.35"/>
<!-- Big red nose (circle on beak) -->
<circle cx="92" cy="74" r="5" fill="currentColor" opacity="0.4"/>
<!-- Beak behind nose -->
<polygon points="88,72 100,74 88,78" fill="currentColor" opacity="0.2"/>
<!-- Eyes (different directions goofy) -->
<circle cx="74" cy="66" r="2" fill="currentColor" opacity="0.5"/>
<circle cx="85" cy="64" r="2" fill="currentColor" opacity="0.5"/>
<!-- Big goofy grin -->
<path d="M72 82 Q80 90 88 82" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.3"/>
<!-- Squirting flower on chest -->
<circle cx="80" cy="95" r="6" fill="currentColor" opacity="0.25"/>
<circle cx="80" cy="95" r="2.5" fill="currentColor" opacity="0.35"/>
<!-- Water squirt from flower -->
<path d="M86 93 Q100 85 105 90" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.2"/>
<circle cx="107" cy="90" r="2" fill="currentColor" opacity="0.2"/>
<circle cx="112" cy="88" r="1.5" fill="currentColor" opacity="0.15"/>
<!-- Arms -->
<line x1="60" y1="100" x2="35" y2="90" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="100" y1="100" x2="125" y2="85" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Long legs -->
<line x1="72" y1="136" x2="50" y2="185" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="88" y1="136" x2="110" y2="185" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- OVERSIZED shoes -->
<ellipse cx="42" cy="190" rx="18" ry="6" fill="currentColor" opacity="0.3"/>
<ellipse cx="118" cy="190" rx="18" ry="6" fill="currentColor" opacity="0.3"/>
</svg>
<!-- 9. Shadok acrobate: mid-cartwheel, body rotated 90deg -->
<svg class="shadok-acrobate" viewBox="0 0 160 200" fill="none" aria-hidden="true">
<!-- Body (rotated 90 degrees) -->
<ellipse cx="80" cy="100" rx="20" ry="26" fill="currentColor" opacity="0.25" transform="rotate(90 80 100)"/>
<!-- Head (at bottom-right, inverted) -->
<circle cx="112" cy="100" r="14" fill="currentColor" opacity="0.3"/>
<!-- Eyes (dizzy, spiral-ish) -->
<path d="M108 97 Q110 94 113 97" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.4"/>
<path d="M117 97 Q119 94 122 97" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.4"/>
<!-- Beak (pointing right) -->
<polygon points="124,102 136,100 124,106" fill="currentColor" opacity="0.3"/>
<!-- Limbs in pinwheel pattern -->
<!-- Arm up-right -->
<line x1="85" y1="80" x2="110" y2="35" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Arm down-left -->
<line x1="75" y1="120" x2="50" y2="165" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Leg up-left (hand on ground) -->
<line x1="65" y1="88" x2="25" y2="55" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<circle cx="23" cy="53" r="4" fill="currentColor" opacity="0.25"/>
<!-- Leg down-right -->
<line x1="95" y1="112" x2="135" y2="150" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Feet -->
<ellipse cx="110" cy="33" rx="6" ry="3" fill="currentColor" opacity="0.25" transform="rotate(-60 110 33)"/>
<ellipse cx="135" cy="152" rx="6" ry="3" fill="currentColor" opacity="0.25" transform="rotate(40 135 152)"/>
<!-- Motion arc -->
<path d="M30 40 Q20 50 25 60" stroke="currentColor" stroke-width="1" stroke-linecap="round" fill="none" opacity="0.2"/>
<path d="M140 140 Q148 148 145 158" stroke="currentColor" stroke-width="1" stroke-linecap="round" fill="none" opacity="0.2"/>
</svg>
<!-- 10. Shadok regisseur: headset, clipboard, running -->
<svg class="shadok-regisseur" viewBox="0 0 160 210" fill="none" aria-hidden="true">
<!-- Body (leaning forward, running) -->
<ellipse cx="75" cy="105" rx="20" ry="27" fill="currentColor" opacity="0.25" transform="rotate(-12 75 105)"/>
<!-- Head -->
<circle cx="80" cy="68" r="15" fill="currentColor" opacity="0.3"/>
<!-- Headset arc -->
<path d="M66 60 Q80 48 94 60" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" fill="none" opacity="0.35"/>
<!-- Headset earpiece -->
<ellipse cx="66" cy="64" rx="4" ry="6" fill="currentColor" opacity="0.3"/>
<!-- Headset mic -->
<path d="M66 70 Q62 78 70 80" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.3"/>
<!-- Eyes (stressed, one looking forward one sideways) -->
<circle cx="76" cy="65" r="2" fill="currentColor" opacity="0.5"/>
<circle cx="87" cy="64" r="2" fill="currentColor" opacity="0.5"/>
<!-- Beak -->
<polygon points="91,68 104,66 91,72" fill="currentColor" opacity="0.3"/>
<!-- Lanyard -->
<line x1="80" y1="82" x2="80" y2="100" stroke="currentColor" stroke-width="1.5" opacity="0.25"/>
<!-- Badge -->
<rect x="74" y="100" width="12" height="15" rx="2" fill="currentColor" opacity="0.25"/>
<rect x="76" y="103" width="8" height="3" rx="1" fill="currentColor" opacity="0.15"/>
<!-- Right arm pointing forward (with authority) -->
<line x1="92" y1="95" x2="135" y2="75" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Pointing finger -->
<line x1="135" y1="75" x2="145" y2="70" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.35"/>
<!-- Left arm holding clipboard -->
<line x1="58" y1="98" x2="38" y2="110" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Clipboard (big) -->
<rect x="22" y="105" width="22" height="30" rx="2" fill="currentColor" opacity="0.25"/>
<rect x="28" y="102" width="10" height="5" rx="1" fill="currentColor" opacity="0.3"/>
<!-- Clipboard lines -->
<line x1="26" y1="114" x2="40" y2="114" stroke="currentColor" stroke-width="1" opacity="0.15"/>
<line x1="26" y1="120" x2="38" y2="120" stroke="currentColor" stroke-width="1" opacity="0.15"/>
<line x1="26" y1="126" x2="40" y2="126" stroke="currentColor" stroke-width="1" opacity="0.15"/>
<!-- Legs (running stride, long) -->
<line x1="68" y1="130" x2="40" y2="195" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<ellipse cx="38" cy="197" rx="9" ry="3" fill="currentColor" opacity="0.3"/>
<line x1="82" y1="130" x2="115" y2="190" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<ellipse cx="117" cy="192" rx="9" ry="3" fill="currentColor" opacity="0.3"/>
</svg>
<div class="container-content relative z-10 text-center">
<p class="mb-3 font-mono text-sm tracking-widest text-accent uppercase">{{ content?.kicker }}</p>
<h1 class="page-title font-display font-extrabold tracking-tight text-white">
<h1 class="page-title font-display font-extrabold tracking-tight" style="color: hsl(var(--color-text))">
{{ content?.title }}
</h1>
<p class="mt-4 text-lg text-white/50">
<p class="mt-4 text-lg" style="color: hsl(var(--color-text-muted))">
{{ content?.description }}
</p>
</div>
@@ -170,98 +358,201 @@ useHead({
font-size: clamp(2.5rem, 6vw, 3.5rem);
}
.shadok-juggler {
/* 1. Funambule — top-left */
.shadok-funambule {
position: absolute;
left: 4%;
top: 5%;
width: clamp(100px, 14vw, 190px);
opacity: 0.3;
width: clamp(70px, 10vw, 140px);
opacity: 0.24;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-bounce-juggler 4s ease-in-out infinite;
animation: shadok-sway-funambule 9s ease-in-out infinite;
}
.shadok-ladder {
/* 2. Accordeoniste — top-right */
.shadok-accordeoniste {
position: absolute;
right: 4%;
top: 3%;
width: clamp(90px, 12vw, 170px);
opacity: 0.28;
right: 3%;
top: 4%;
width: clamp(70px, 10vw, 140px);
opacity: 0.22;
pointer-events: none;
color: hsl(var(--color-accent));
animation: shadok-wobble-ladder 5s ease-in-out infinite;
animation: shadok-bounce-accordeon 8s ease-in-out infinite;
}
.shadok-acrobat {
/* 3. Jongleur — top-center */
.shadok-jongleur {
position: absolute;
left: 50%;
top: 55%;
top: 2%;
transform: translateX(-50%);
width: clamp(100px, 13vw, 180px);
width: clamp(70px, 10vw, 130px);
opacity: 0.2;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-spin-acrobat 6s ease-in-out infinite;
animation: shadok-float-jongleur 7s ease-in-out infinite;
}
.shadok-sleeper {
/* 4. Cracheur de feu — left 5%, 40% */
.shadok-cracheur {
position: absolute;
left: 3%;
bottom: 5%;
width: clamp(110px, 15vw, 210px);
opacity: 0.25;
left: 5%;
top: 40%;
width: clamp(70px, 10vw, 140px);
opacity: 0.22;
pointer-events: none;
color: hsl(var(--color-accent));
animation: shadok-float-sleeper 8s ease-in-out infinite;
animation: shadok-flicker-cracheur 8s ease-in-out infinite;
}
.shadok-cook {
/* 5. Trapeziste — right 3%, 30% */
.shadok-trapeziste {
position: absolute;
right: 3%;
top: 30%;
width: clamp(70px, 10vw, 130px);
opacity: 0.2;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-swing-trapeze 10s ease-in-out infinite;
}
/* 6. Batteur — left 4%, bottom 15% */
.shadok-batteur {
position: absolute;
left: 4%;
bottom: 15%;
width: clamp(70px, 10vw, 140px);
opacity: 0.2;
pointer-events: none;
color: hsl(var(--color-accent));
animation: shadok-pulse-batteur 7s ease-in-out infinite;
}
/* 7. Marionnettiste — right 4%, bottom 20% */
.shadok-marionnettiste {
position: absolute;
right: 4%;
bottom: 20%;
width: clamp(70px, 10vw, 130px);
opacity: 0.22;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-bob-marionnette 9s ease-in-out infinite;
}
/* 8. Clown — bottom-left */
.shadok-clown {
position: absolute;
left: 6%;
bottom: 3%;
width: clamp(70px, 10vw, 135px);
opacity: 0.24;
pointer-events: none;
color: hsl(var(--color-accent));
animation: shadok-wobble-clown 8s ease-in-out infinite;
}
/* 9. Acrobate — center-bottom */
.shadok-acrobate {
position: absolute;
left: 50%;
bottom: 2%;
transform: translateX(-50%);
width: clamp(70px, 10vw, 130px);
opacity: 0.18;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-spin-acrobate 12s ease-in-out infinite;
}
/* 10. Regisseur — bottom-right */
.shadok-regisseur {
position: absolute;
right: 3%;
bottom: 4%;
width: clamp(100px, 14vw, 200px);
opacity: 0.3;
width: clamp(70px, 10vw, 140px);
opacity: 0.22;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-bounce-cook 5s ease-in-out infinite;
color: hsl(var(--color-accent));
animation: shadok-rush-regisseur 7s ease-in-out infinite;
}
@keyframes shadok-bounce-juggler {
@keyframes shadok-sway-funambule {
0%, 100% { transform: translateY(0) rotate(0deg); }
25% { transform: translateY(-5px) rotate(2deg); }
75% { transform: translateY(-3px) rotate(-2deg); }
}
@keyframes shadok-bounce-accordeon {
0%, 100% { transform: translateY(0); }
30% { transform: translateY(-12px); }
60% { transform: translateY(-6px); }
40% { transform: translateY(-8px); }
70% { transform: translateY(-3px); }
}
@keyframes shadok-wobble-ladder {
@keyframes shadok-float-jongleur {
0%, 100% { transform: translateX(-50%) translateY(0); }
50% { transform: translateX(-50%) translateY(-10px); }
}
@keyframes shadok-flicker-cracheur {
0%, 100% { transform: translateY(0) scale(1); }
30% { transform: translateY(-4px) scale(1.02); }
60% { transform: translateY(-2px) scale(0.99); }
}
@keyframes shadok-swing-trapeze {
0%, 100% { transform: rotate(0deg); }
25% { transform: rotate(3deg); }
75% { transform: rotate(-3deg); }
25% { transform: rotate(4deg); }
75% { transform: rotate(-4deg); }
}
@keyframes shadok-spin-acrobat {
@keyframes shadok-pulse-batteur {
0%, 100% { transform: translateY(0); }
15% { transform: translateY(-4px); }
30% { transform: translateY(0); }
45% { transform: translateY(-6px); }
60% { transform: translateY(0); }
}
@keyframes shadok-bob-marionnette {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-7px); }
}
@keyframes shadok-wobble-clown {
0%, 100% { transform: translateY(0) rotate(0deg); }
30% { transform: translateY(-5px) rotate(-3deg); }
70% { transform: translateY(-2px) rotate(3deg); }
}
@keyframes shadok-spin-acrobate {
0% { transform: translateX(-50%) rotate(0deg); }
25% { transform: translateX(-50%) rotate(15deg); }
50% { transform: translateX(-50%) rotate(0deg); }
75% { transform: translateX(-50%) rotate(-15deg); }
50% { transform: translateX(-50%) rotate(10deg); }
100% { transform: translateX(-50%) rotate(0deg); }
}
@keyframes shadok-float-sleeper {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-6px); }
}
@keyframes shadok-bounce-cook {
0%, 100% { transform: translateY(0); }
40% { transform: translateY(-10px); }
70% { transform: translateY(-4px); }
@keyframes shadok-rush-regisseur {
0%, 100% { transform: translateX(0) translateY(0); }
25% { transform: translateX(3px) translateY(-5px); }
50% { transform: translateX(-2px) translateY(-2px); }
75% { transform: translateX(2px) translateY(-6px); }
}
@media (max-width: 768px) {
.shadok-juggler { display: none; }
.shadok-ladder { display: none; }
.shadok-acrobat { display: none; }
.shadok-sleeper { display: none; }
.shadok-cook { display: none; }
.shadok-funambule,
.shadok-accordeoniste,
.shadok-jongleur,
.shadok-cracheur,
.shadok-trapeziste,
.shadok-batteur,
.shadok-marionnettiste,
.shadok-clown,
.shadok-acrobate,
.shadok-regisseur {
display: none;
}
}
</style>

View File

@@ -1,105 +0,0 @@
<template>
<div class="section-padding">
<div class="container-content">
<div class="mx-auto max-w-2xl">
<div class="gestation-icon mx-auto mb-6">
<div class="i-lucide-flask-conical h-12 w-12 text-accent" />
</div>
<h1 class="font-display text-3xl font-bold text-white mb-4 text-center">
{{ item?.label ?? 'En gestation' }}
</h1>
<p class="text-lg text-white/60 leading-relaxed mb-8 text-center">
{{ item?.description ?? 'Cette initiative est en cours de préparation.' }}
</p>
<!-- Présentation spécifique -->
<div v-if="item?.presentation" class="presentation-card mb-10">
<div class="presentation-icon">
<div class="i-lucide-rocket h-5 w-5" />
</div>
<h2 class="font-display text-xl font-semibold text-white mb-2">
{{ item.presentation.title }}
</h2>
<p class="text-white/60 leading-relaxed">
{{ item.presentation.text }}
</p>
<p class="mt-4 text-sm text-white/30 italic">En cours de développement.</p>
</div>
<!-- Bouton SejeteralO pour tarifs-eau -->
<div v-if="slug === 'tarifs-eau'" class="text-center mb-10">
<UiBaseButton :href="sejeteral0Url" target="_blank">
<div class="i-lucide-external-link mr-2 h-4 w-4" />
Lancer SejeteralO
</UiBaseButton>
</div>
<div class="text-center">
<UiBaseButton variant="ghost" to="/">
<div class="i-lucide-arrow-left mr-2 h-4 w-4" />
Retour à l'accueil
</UiBaseButton>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
const route = useRoute()
const slug = route.params.slug as string
const { data: content } = await usePageContent('home')
const appConfig = useAppConfig()
const sejeteral0Url = (appConfig.sejeteral0 as { url: string }).url
const item = computed(() => {
const axes = (content.value as any)?.axes
if (!axes) return null
for (const axis of Object.values(axes) as any[]) {
for (const it of axis.items ?? []) {
if (it.to === `/gestation/${slug}`) return it
}
}
return null
})
useHead({
title: item.value?.label ?? `En gestation — ${slug}`,
})
</script>
<style scoped>
.gestation-icon {
display: flex;
align-items: center;
justify-content: center;
width: 5rem;
height: 5rem;
border-radius: 1rem;
background: hsl(var(--color-accent) / 0.1);
border: 1px solid hsl(var(--color-accent) / 0.2);
}
.presentation-card {
padding: 1.5rem;
border-radius: 0.75rem;
border: 1px solid hsl(var(--color-primary) / 0.15);
background: hsl(var(--color-surface));
}
.presentation-icon {
display: flex;
align-items: center;
justify-content: center;
width: 2.5rem;
height: 2.5rem;
border-radius: 0.5rem;
background: hsl(var(--color-primary) / 0.1);
color: hsl(var(--color-primary));
margin-bottom: 1rem;
}
</style>

View File

@@ -1,212 +0,0 @@
<template>
<div class="relative overflow-hidden section-padding">
<!-- Shadok reader: character with big glasses reading a book -->
<svg class="shadok-reader" viewBox="0 0 240 300" fill="none" aria-hidden="true">
<!-- Body -->
<ellipse cx="120" cy="170" rx="45" ry="55" fill="currentColor" opacity="0.85"/>
<!-- Head -->
<circle cx="120" cy="100" r="28" fill="currentColor" opacity="0.8"/>
<!-- Big round glasses -->
<circle cx="107" cy="94" r="11" stroke="currentColor" stroke-width="2.5" fill="none" opacity="0.5"/>
<circle cx="133" cy="94" r="11" stroke="currentColor" stroke-width="2.5" fill="none" opacity="0.5"/>
<line x1="118" y1="94" x2="122" y2="94" stroke="currentColor" stroke-width="2" opacity="0.5"/>
<!-- Eyes behind glasses -->
<circle cx="108" cy="93" r="2.5" fill="currentColor" opacity="0.5"/>
<circle cx="134" cy="93" r="2.5" fill="currentColor" opacity="0.5"/>
<!-- Arms holding book -->
<line x1="78" y1="155" x2="60" y2="180" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<line x1="162" y1="155" x2="180" y2="180" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<!-- Book (open) -->
<rect x="55" y="175" width="55" height="40" rx="2" fill="currentColor" opacity="0.35"/>
<rect x="110" y="175" width="55" height="40" rx="2" fill="currentColor" opacity="0.3"/>
<line x1="110" y1="175" x2="110" y2="215" stroke="currentColor" stroke-width="2" opacity="0.5"/>
<!-- Book lines (text) -->
<line x1="65" y1="188" x2="100" y2="188" stroke="currentColor" stroke-width="1" opacity="0.2"/>
<line x1="65" y1="195" x2="95" y2="195" stroke="currentColor" stroke-width="1" opacity="0.2"/>
<line x1="65" y1="202" x2="98" y2="202" stroke="currentColor" stroke-width="1" opacity="0.2"/>
<!-- Legs -->
<line x1="105" y1="222" x2="95" y2="270" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<line x1="135" y1="222" x2="145" y2="270" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
</svg>
<!-- Shadok stack: pile of books tilting -->
<svg class="shadok-stack" viewBox="0 0 160 220" fill="none" aria-hidden="true">
<!-- Bottom book -->
<rect x="20" y="170" width="120" height="22" rx="3" fill="currentColor" opacity="0.5" transform="rotate(-2 80 181)"/>
<!-- Second book -->
<rect x="30" y="145" width="100" height="20" rx="3" fill="currentColor" opacity="0.45" transform="rotate(3 80 155)"/>
<!-- Third book -->
<rect x="25" y="120" width="110" height="18" rx="3" fill="currentColor" opacity="0.4" transform="rotate(-4 80 129)"/>
<!-- Fourth book -->
<rect x="35" y="97" width="90" height="18" rx="3" fill="currentColor" opacity="0.35" transform="rotate(5 80 106)"/>
<!-- Fifth book (tilting more) -->
<rect x="40" y="74" width="80" height="17" rx="3" fill="currentColor" opacity="0.3" transform="rotate(-7 80 82)"/>
<!-- Top book (really tilting) -->
<rect x="45" y="52" width="70" height="16" rx="3" fill="currentColor" opacity="0.25" transform="rotate(10 80 60)"/>
<!-- Tiny Shadok sitting on top -->
<ellipse cx="85" cy="42" rx="10" ry="8" fill="currentColor" opacity="0.5"/>
<circle cx="85" cy="30" r="6" fill="currentColor" opacity="0.45"/>
<circle cx="87" cy="29" r="1.5" fill="currentColor" opacity="0.3"/>
</svg>
<!-- Shadok scribe: character with quill and inkwell -->
<svg class="shadok-scribe" viewBox="0 0 240 280" fill="none" aria-hidden="true">
<ellipse cx="120" cy="155" rx="40" ry="48" fill="currentColor" opacity="0.85"/>
<circle cx="120" cy="92" r="25" fill="currentColor" opacity="0.8"/>
<ellipse cx="120" cy="72" rx="20" ry="8" fill="currentColor" opacity="0.35"/>
<circle cx="112" cy="90" r="4" fill="currentColor" opacity="0.2"/>
<circle cx="130" cy="90" r="4" fill="currentColor" opacity="0.2"/>
<circle cx="113" cy="91" r="1.8" fill="currentColor" opacity="0.5"/>
<circle cx="131" cy="91" r="1.8" fill="currentColor" opacity="0.5"/>
<path d="M118 104 Q120 108 122 104" fill="currentColor" opacity="0.3"/>
<line x1="160" y1="140" x2="190" y2="170" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<line x1="190" y1="170" x2="210" y2="145" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.45"/>
<path d="M210 145 Q215 140 212 135 Q208 138 210 145" fill="currentColor" opacity="0.3"/>
<line x1="80" y1="148" x2="55" y2="180" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<path d="M100 200 Q90 230 95 250" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" fill="none" opacity="0.6"/>
<path d="M140 200 Q150 230 145 250" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" fill="none" opacity="0.6"/>
<rect x="45" y="185" width="20" height="18" rx="3" fill="currentColor" opacity="0.35"/>
<ellipse cx="55" cy="185" rx="12" ry="4" fill="currentColor" opacity="0.3"/>
<rect x="170" y="175" width="40" height="50" rx="2" fill="currentColor" opacity="0.2"/>
<line x1="178" y1="188" x2="202" y2="188" stroke="currentColor" stroke-width="1" opacity="0.15"/>
<line x1="178" y1="195" x2="200" y2="195" stroke="currentColor" stroke-width="1" opacity="0.15"/>
<line x1="178" y1="202" x2="198" y2="202" stroke="currentColor" stroke-width="1" opacity="0.15"/>
</svg>
<div class="container-content">
<!-- Page de couverture du livre -->
<HomeBookSection
class="mb-16"
@open-player="showBookPlayer = true"
@open-pdf="showPdfReader = true"
/>
<header class="mb-12 text-center">
<p class="mb-2 font-mono text-sm tracking-widest text-primary uppercase">{{ content?.kicker }}</p>
<h1 class="page-title font-display font-bold tracking-tight text-white">
{{ content?.title }}
</h1>
<p class="mt-4 mx-auto max-w-2xl text-white/60">
{{ content?.description }}
</p>
</header>
<div class="mx-auto max-w-3xl">
<ul class="flex flex-col gap-3">
<li
v-for="chapter in chapters"
:key="chapter.path"
>
<NuxtLink
:to="`/modele-eco/${chapter.stem?.split('/').pop()}`"
class="card-surface flex items-start gap-4 group"
>
<span class="font-mono text-2xl font-bold text-primary/30 leading-none mt-1 w-10 text-right flex-shrink-0">
{{ String(chapter.order).padStart(2, '0') }}
</span>
<div class="min-w-0 flex-1">
<h2 class="font-display text-lg font-semibold text-white group-hover:text-primary transition-colors">
{{ chapter.title }}
</h2>
<p v-if="chapter.description" class="mt-1 text-sm text-white/50">
{{ chapter.description }}
</p>
<div class="mt-2 flex items-center gap-3">
<span v-if="chapter.readingTime" class="text-xs text-white/30">
<span class="i-lucide-clock inline-block h-3 w-3 mr-1 align-middle" />
{{ chapter.readingTime }}
</span>
<SongBadges :chapter-slug="chapter.stem?.split('/').pop() ?? ''" />
</div>
</div>
<div class="i-lucide-chevron-right h-5 w-5 text-white/20 group-hover:text-primary/60 transition-colors flex-shrink-0 mt-2" />
</NuxtLink>
</li>
</ul>
</div>
</div>
<BookPlayer v-model="showBookPlayer" />
<BookPdfReader v-model="showPdfReader" />
</div>
</template>
<script setup lang="ts">
definePageMeta({
layout: 'default',
})
const { data: content } = await usePageContent('modele-eco')
useHead({
title: content.value?.meta?.title ?? 'Table des matières',
})
const { data: chapters } = await useAsyncData('book-toc', () =>
queryCollection('book').order('order', 'ASC').all(),
)
const showBookPlayer = ref(false)
const showPdfReader = ref(false)
</script>
<style scoped>
.page-title {
font-size: clamp(2rem, 5vw, 2.75rem);
}
.shadok-reader {
position: absolute;
right: 2%;
top: 3%;
width: clamp(110px, 15vw, 220px);
opacity: 0.3;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-float-reader 9s ease-in-out infinite;
}
.shadok-stack {
position: absolute;
left: 2%;
bottom: 5%;
width: clamp(100px, 13vw, 180px);
opacity: 0.25;
pointer-events: none;
color: hsl(var(--color-accent));
animation: shadok-float-stack 11s ease-in-out infinite;
}
@keyframes shadok-float-reader {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
@keyframes shadok-float-stack {
0%, 100% { transform: translateY(0) rotate(0deg); }
50% { transform: translateY(-8px) rotate(-2deg); }
}
.shadok-scribe {
position: absolute;
left: 50%;
bottom: 3%;
transform: translateX(-50%);
width: clamp(100px, 13vw, 180px);
opacity: 0.25;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-float-scribe 10s ease-in-out infinite;
}
@keyframes shadok-float-scribe {
0%, 100% { transform: translateX(-50%) translateY(0); }
50% { transform: translateX(-50%) translateY(-8px); }
}
@media (max-width: 768px) {
.shadok-reader { display: none; }
.shadok-stack { display: none; }
.shadok-scribe { display: none; }
}
</style>

View File

@@ -1,232 +0,0 @@
<template>
<div class="relative overflow-hidden section-padding">
<!-- Shadok jardinier -->
<svg class="shadok-jardinier" viewBox="0 0 240 300" fill="none" aria-hidden="true">
<ellipse cx="110" cy="160" rx="40" ry="48" fill="currentColor" opacity="0.85"/>
<circle cx="110" cy="96" r="25" fill="currentColor" opacity="0.8"/>
<ellipse cx="110" cy="78" rx="35" ry="8" fill="currentColor" opacity="0.4"/>
<path d="M85 78 Q110 60 135 78" fill="currentColor" opacity="0.35"/>
<circle cx="102" cy="94" r="4" fill="currentColor" opacity="0.2"/>
<circle cx="120" cy="94" r="4" fill="currentColor" opacity="0.2"/>
<circle cx="103" cy="95" r="1.8" fill="currentColor" opacity="0.5"/>
<circle cx="121" cy="95" r="1.8" fill="currentColor" opacity="0.5"/>
<path d="M103 106 Q110 111 118 106" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.3"/>
<line x1="70" y1="150" x2="40" y2="170" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<rect x="20" y="165" width="30" height="20" rx="3" fill="currentColor" opacity="0.4"/>
<line x1="20" y1="168" x2="10" y2="160" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.4"/>
<circle cx="12" cy="165" r="1.5" fill="currentColor" opacity="0.25"/>
<circle cx="8" cy="170" r="1.5" fill="currentColor" opacity="0.2"/>
<circle cx="15" cy="172" r="1.5" fill="currentColor" opacity="0.2"/>
<line x1="150" y1="150" x2="170" y2="180" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<line x1="95" y1="205" x2="85" y2="260" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<line x1="125" y1="205" x2="135" y2="260" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<line x1="180" y1="220" x2="180" y2="180" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.4"/>
<path d="M180 195 Q195 185 190 175" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none" opacity="0.35"/>
<path d="M180 205 Q165 195 168 185" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none" opacity="0.35"/>
<path d="M180 185 Q192 172 188 165" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none" opacity="0.3"/>
<path d="M170 220 L175 240 L185 240 L190 220 Z" fill="currentColor" opacity="0.35"/>
</svg>
<!-- Shadok bâtisseur -->
<svg class="shadok-batisseur" viewBox="0 0 260 300" fill="none" aria-hidden="true">
<ellipse cx="130" cy="150" rx="40" ry="48" fill="currentColor" opacity="0.85"/>
<circle cx="130" cy="86" r="25" fill="currentColor" opacity="0.8"/>
<ellipse cx="130" cy="68" rx="28" ry="6" fill="currentColor" opacity="0.4"/>
<rect x="108" y="60" width="44" height="10" rx="3" fill="currentColor" opacity="0.35"/>
<circle cx="122" cy="84" r="4" fill="currentColor" opacity="0.2"/>
<circle cx="140" cy="84" r="4" fill="currentColor" opacity="0.2"/>
<circle cx="123" cy="83" r="1.8" fill="currentColor" opacity="0.5"/>
<circle cx="141" cy="83" r="1.8" fill="currentColor" opacity="0.5"/>
<path d="M123 96 Q130 101 138 96" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" fill="none" opacity="0.3"/>
<line x1="170" y1="140" x2="210" y2="120" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<polygon points="210,115 230,110 225,120 210,122" fill="currentColor" opacity="0.45"/>
<line x1="210" y1="118" x2="200" y2="125" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.4"/>
<line x1="90" y1="145" x2="65" y2="170" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<line x1="115" y1="195" x2="105" y2="255" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<line x1="145" y1="195" x2="155" y2="255" stroke="currentColor" stroke-width="3.5" stroke-linecap="round" opacity="0.6"/>
<rect x="40" y="200" width="50" height="16" rx="1" fill="currentColor" opacity="0.3"/>
<rect x="45" y="183" width="40" height="16" rx="1" fill="currentColor" opacity="0.28"/>
<rect x="50" y="166" width="30" height="16" rx="1" fill="currentColor" opacity="0.25"/>
<line x1="65" y1="200" x2="65" y2="216" stroke="currentColor" stroke-width="1" opacity="0.15"/>
<line x1="55" y1="183" x2="55" y2="199" stroke="currentColor" stroke-width="1" opacity="0.15"/>
</svg>
<div class="container-content">
<header class="mb-12 text-center">
<p class="mb-2 font-mono text-sm tracking-widest text-primary uppercase">{{ content?.kicker }}</p>
<h1 class="page-title font-display font-bold tracking-tight text-white">
{{ content?.title }}
</h1>
<p class="mt-4 mx-auto max-w-2xl text-white/60 leading-relaxed">
{{ content?.description }}
</p>
</header>
<div class="mx-auto max-w-3xl flex flex-col gap-6">
<div
v-for="pillar in content?.pillars"
:key="pillar.id"
class="pillar-card"
>
<div class="pillar-header">
<div class="pillar-icon">
<div :class="`i-lucide-${pillar.icon}`" class="h-5 w-5" />
</div>
<h2 class="font-display text-xl font-bold text-white">
{{ pillar.label }}
</h2>
<span v-if="pillar.gestation" class="gestation-badge">
<div class="i-lucide-flask-conical h-3 w-3" />
En gestation
</span>
</div>
<p class="text-white/65 leading-relaxed whitespace-pre-line mt-3">{{ pillar.text }}</p>
<!-- Project card -->
<div v-if="pillar.project" class="project-card mt-4">
<div class="project-icon">
<div class="i-lucide-rocket h-4 w-4" />
</div>
<div>
<span class="font-display font-semibold text-white text-sm">{{ pillar.project.name }}</span>
<span class="text-white/45 text-sm ml-2">{{ pillar.project.text }}</span>
</div>
</div>
<div v-if="pillar.to" class="mt-4">
<NuxtLink
:to="pillar.to"
class="inline-flex items-center gap-1 text-sm text-primary hover:text-primary/80 transition-colors"
>
En savoir plus
<div class="i-lucide-arrow-right h-3.5 w-3.5" />
</NuxtLink>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
definePageMeta({
layout: 'default',
})
const { data: content } = await usePageContent('numerique')
useHead({
title: content.value?.meta?.title ?? 'Autonomie numérique',
})
</script>
<style scoped>
.page-title {
font-size: clamp(2rem, 5vw, 2.75rem);
}
.pillar-card {
padding: 1.5rem;
border-radius: 0.75rem;
border: 1px solid hsl(var(--color-text) / 0.08);
background: hsl(var(--color-surface));
transition: border-color 0.2s;
}
.pillar-card:hover {
border-color: hsl(var(--color-primary) / 0.2);
}
.pillar-header {
display: flex;
align-items: center;
gap: 0.75rem;
}
.pillar-icon {
display: flex;
align-items: center;
justify-content: center;
width: 2.25rem;
height: 2.25rem;
border-radius: 0.5rem;
background: hsl(var(--color-primary) / 0.15);
color: hsl(var(--color-primary));
box-shadow: 0 0 12px hsl(var(--color-primary) / 0.12);
flex-shrink: 0;
}
.gestation-badge {
display: inline-flex;
align-items: center;
gap: 0.25rem;
margin-left: auto;
padding: 0.125rem 0.5rem;
border-radius: 9999px;
background: hsl(var(--color-accent) / 0.12);
color: hsl(var(--color-accent));
font-size: 0.7rem;
font-weight: 500;
font-family: var(--font-mono);
}
.project-card {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem 1rem;
border-radius: 0.5rem;
background: hsl(var(--color-bg) / 0.5);
border: 1px solid hsl(var(--color-primary) / 0.1);
}
.project-icon {
display: flex;
align-items: center;
justify-content: center;
width: 1.75rem;
height: 1.75rem;
border-radius: 0.375rem;
background: hsl(var(--color-primary) / 0.1);
color: hsl(var(--color-primary));
flex-shrink: 0;
}
.shadok-jardinier {
position: absolute;
left: 2%;
top: 5%;
width: clamp(100px, 14vw, 200px);
opacity: 0.28;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-float-jardinier 10s ease-in-out infinite;
}
.shadok-batisseur {
position: absolute;
right: 2%;
bottom: 5%;
width: clamp(110px, 15vw, 210px);
opacity: 0.3;
pointer-events: none;
color: hsl(var(--color-accent));
animation: shadok-float-batisseur 11s ease-in-out infinite;
}
@keyframes shadok-float-jardinier {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
@keyframes shadok-float-batisseur {
0%, 100% { transform: translateY(0) rotate(0deg); }
50% { transform: translateY(-8px) rotate(1deg); }
}
@media (max-width: 768px) {
.shadok-jardinier { display: none; }
.shadok-batisseur { display: none; }
}
</style>

View File

@@ -0,0 +1,124 @@
<template>
<div class="section-padding">
<div class="container-content">
<div class="mx-auto max-w-2xl">
<div class="section-icon mx-auto mb-6">
<div :class="`i-lucide-${content?.icon ?? 'monitor'}`" class="h-12 w-12" />
</div>
<p class="mb-2 font-mono text-sm tracking-widest text-primary uppercase text-center">
{{ content?.kicker }}
</p>
<h1 class="font-display text-3xl font-bold mb-4 text-center" style="color: hsl(var(--color-text))">
{{ content?.title ?? slug }}
</h1>
<p class="text-lg leading-relaxed mb-8 text-center" style="color: hsl(var(--color-text-muted))">
{{ content?.description }}
</p>
<!-- Project card -->
<div v-if="content?.project" class="project-card mb-8">
<div class="project-icon">
<div class="i-lucide-rocket h-5 w-5" />
</div>
<h2 class="font-display text-xl font-semibold mb-2" style="color: hsl(var(--color-text))">
{{ content.project.name }}
</h2>
<p style="color: hsl(var(--color-text-muted))" class="leading-relaxed">
{{ content.project.text }}
</p>
<span v-if="content?.gestation" class="gestation-badge mt-3">
<div class="i-lucide-flask-conical h-3 w-3" />
En gestation
</span>
</div>
<!-- Extended content -->
<div v-if="content?.content" class="prose-block mb-10">
<p class="leading-relaxed whitespace-pre-line" style="color: hsl(var(--color-text-muted))">
{{ content.content }}
</p>
</div>
<div class="text-center flex flex-col items-center gap-3 sm:flex-row sm:justify-center">
<UiBaseButton v-if="slug === 'tarifs-eau'" :href="sejeteral0Url" target="_blank">
<div class="i-lucide-external-link mr-2 h-4 w-4" />
Lancer SejeteralO
</UiBaseButton>
<UiBaseButton variant="ghost" to="/numerique">
<div class="i-lucide-arrow-left mr-2 h-4 w-4" />
Autonomie numérique
</UiBaseButton>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
const route = useRoute()
const slug = route.params.slug as string
const { data: content } = await usePageContent(`numerique/${slug}`)
const appConfig = useAppConfig()
const sejeteral0Url = (appConfig.sejeteral0 as { url: string })?.url ?? '#'
useHead({
title: content.value?.meta?.title ?? slug,
})
</script>
<style scoped>
.section-icon {
display: flex;
align-items: center;
justify-content: center;
width: 5rem;
height: 5rem;
border-radius: 1rem;
background: hsl(var(--color-primary) / 0.1);
border: 1px solid hsl(var(--color-primary) / 0.2);
color: hsl(var(--color-primary));
}
.project-card {
padding: 1.5rem;
border-radius: 0.75rem;
border: 1px solid hsl(var(--color-primary) / 0.15);
background: hsl(var(--color-surface));
}
.project-icon {
display: flex;
align-items: center;
justify-content: center;
width: 2.5rem;
height: 2.5rem;
border-radius: 0.5rem;
background: hsl(var(--color-primary) / 0.1);
color: hsl(var(--color-primary));
margin-bottom: 1rem;
}
.gestation-badge {
display: inline-flex;
align-items: center;
gap: 0.25rem;
padding: 0.125rem 0.5rem;
border-radius: 9999px;
background: hsl(var(--color-accent) / 0.12);
color: hsl(var(--color-accent));
font-size: 0.7rem;
font-weight: 500;
font-family: var(--font-mono);
}
.prose-block {
padding: 1.5rem;
border-radius: 0.75rem;
background: hsl(var(--color-surface));
}
</style>

View File

@@ -0,0 +1,586 @@
<template>
<div class="relative overflow-hidden section-padding">
<!-- Shadok codeuse sitting at desk, typing on laptop, glasses -->
<svg class="shadok-codeuse" viewBox="0 0 170 200" fill="none" aria-hidden="true">
<!-- Desk -->
<rect x="15" y="120" width="80" height="5" rx="2" fill="currentColor" opacity="0.3"/>
<line x1="25" y1="125" x2="25" y2="165" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.25"/>
<line x1="85" y1="125" x2="85" y2="165" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.25"/>
<!-- Laptop on desk -->
<rect x="30" y="108" width="50" height="12" rx="2" fill="currentColor" opacity="0.35"/>
<path d="M35 108 L40 80 L70 80 L75 108" fill="currentColor" opacity="0.28"/>
<rect x="42" y="84" width="26" height="18" rx="1" fill="currentColor" opacity="0.15"/>
<!-- Code on screen < /> -->
<text x="48" y="96" font-size="8" fill="currentColor" opacity="0.4" font-family="monospace">&lt;/&gt;</text>
<!-- Body seated, tilted forward -->
<ellipse cx="110" cy="105" rx="20" ry="26" fill="currentColor" opacity="0.25" transform="rotate(-10 110 105)"/>
<!-- Head looking at screen -->
<circle cx="105" cy="68" r="15" fill="currentColor" opacity="0.3"/>
<!-- Glasses -->
<circle cx="100" cy="66" r="5" stroke="currentColor" stroke-width="1.2" fill="none" opacity="0.4"/>
<circle cx="111" cy="66" r="5" stroke="currentColor" stroke-width="1.2" fill="none" opacity="0.4"/>
<line x1="105" y1="66" x2="106" y2="66" stroke="currentColor" stroke-width="1" opacity="0.35"/>
<!-- Eyes behind glasses -->
<circle cx="101" cy="66" r="1.5" fill="currentColor" opacity="0.5"/>
<circle cx="110" cy="65" r="1.5" fill="currentColor" opacity="0.5"/>
<!-- Beak pointy, looking left -->
<polygon points="88,68 82,65 88,72" fill="currentColor" opacity="0.35"/>
<!-- Arms reaching to laptop -->
<line x1="95" y1="95" x2="78" y2="110" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="125" y1="98" x2="80" y2="115" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- Legs bent, seated -->
<line x1="100" y1="128" x2="90" y2="180" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="118" y1="128" x2="125" y2="180" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Feet -->
<ellipse cx="88" cy="183" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
<ellipse cx="127" cy="183" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
</svg>
<!-- Shadok electricien profile view, climbing utility pole, tool belt -->
<svg class="shadok-electricien" viewBox="0 0 150 210" fill="none" aria-hidden="true">
<!-- Utility pole -->
<rect x="68" y="5" width="8" height="200" rx="2" fill="currentColor" opacity="0.2"/>
<line x1="50" y1="30" x2="94" y2="30" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.25"/>
<line x1="45" y1="55" x2="99" y2="55" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" opacity="0.22"/>
<!-- Cables hanging -->
<path d="M50 30 Q35 45 30 35" stroke="currentColor" stroke-width="1.5" fill="none" opacity="0.2"/>
<path d="M94 30 Q110 45 115 35" stroke="currentColor" stroke-width="1.5" fill="none" opacity="0.2"/>
<path d="M45 55 Q30 68 25 60" stroke="currentColor" stroke-width="1.5" fill="none" opacity="0.18"/>
<!-- Body climbing, profile, tilted -->
<ellipse cx="95" cy="100" rx="20" ry="25" fill="currentColor" opacity="0.25" transform="rotate(15 95 100)"/>
<!-- Head looking up at cable -->
<circle cx="100" cy="65" r="14" fill="currentColor" opacity="0.3"/>
<!-- Eyes looking up -->
<circle cx="96" cy="61" r="1.5" fill="currentColor" opacity="0.5"/>
<circle cx="105" cy="60" r="1.5" fill="currentColor" opacity="0.45"/>
<!-- Beak profile right -->
<polygon points="114,63 122,60 114,67" fill="currentColor" opacity="0.35"/>
<!-- Hard hat -->
<ellipse cx="100" cy="53" rx="16" ry="5" fill="currentColor" opacity="0.3"/>
<path d="M88 53 Q100 42 112 53" fill="currentColor" opacity="0.25"/>
<!-- Arms one gripping pole, one holding cable -->
<line x1="82" y1="90" x2="74" y2="75" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="108" y1="88" x2="118" y2="60" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Tool belt -->
<ellipse cx="95" cy="118" rx="22" ry="4" fill="currentColor" opacity="0.25"/>
<rect x="82" y="118" width="6" height="8" rx="1" fill="currentColor" opacity="0.2"/>
<rect x="105" y="118" width="5" height="10" rx="1" fill="currentColor" opacity="0.2"/>
<!-- Legs climbing, spread on pole -->
<line x1="85" y1="122" x2="72" y2="185" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="105" y1="122" x2="76" y2="175" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Feet gripping pole -->
<ellipse cx="70" cy="188" rx="9" ry="3" fill="currentColor" opacity="0.3"/>
<ellipse cx="75" cy="178" rx="8" ry="3" fill="currentColor" opacity="0.28"/>
</svg>
<!-- Shadok soudeuse welding mask flipped up, torch with sparks, apron -->
<svg class="shadok-soudeuse" viewBox="0 0 160 210" fill="none" aria-hidden="true">
<!-- Body upright, slight lean forward -->
<ellipse cx="80" cy="110" rx="22" ry="28" fill="currentColor" opacity="0.25"/>
<!-- Apron -->
<path d="M62 95 L60 140 L100 140 L98 95" fill="currentColor" opacity="0.18"/>
<line x1="80" y1="95" x2="80" y2="140" stroke="currentColor" stroke-width="1" opacity="0.15"/>
<!-- Head -->
<circle cx="80" cy="65" r="16" fill="currentColor" opacity="0.3"/>
<!-- Welding mask flipped up on head -->
<rect x="65" y="42" width="30" height="18" rx="4" fill="currentColor" opacity="0.2"/>
<rect x="70" y="46" width="20" height="10" rx="2" fill="currentColor" opacity="0.12"/>
<!-- Eyes squinting from bright light -->
<line x1="73" y1="64" x2="77" y2="64" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" opacity="0.5"/>
<line x1="84" y1="63" x2="88" y2="63" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" opacity="0.45"/>
<!-- Beak small, front-facing -->
<polygon points="78,72 80,78 82,72" fill="currentColor" opacity="0.35"/>
<!-- Right arm holding torch -->
<line x1="100" y1="100" x2="135" y2="85" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Welding torch -->
<rect x="132" y="78" width="22" height="6" rx="2" fill="currentColor" opacity="0.35"/>
<line x1="154" y1="81" x2="160" y2="78" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.4"/>
<!-- Sparks from torch -->
<circle cx="158" cy="75" r="1.5" fill="currentColor" opacity="0.45"/>
<circle cx="155" cy="70" r="1" fill="currentColor" opacity="0.35"/>
<circle cx="160" cy="72" r="1.2" fill="currentColor" opacity="0.4"/>
<line x1="157" y1="76" x2="160" y2="68" stroke="currentColor" stroke-width="0.8" opacity="0.3"/>
<line x1="155" y1="78" x2="152" y2="71" stroke="currentColor" stroke-width="0.8" opacity="0.25"/>
<!-- Left arm down -->
<line x1="60" y1="100" x2="45" y2="125" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Legs standing, spread -->
<line x1="70" y1="136" x2="58" y2="195" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="90" y1="136" x2="102" y2="195" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Big flat feet -->
<ellipse cx="55" cy="198" rx="9" ry="3" fill="currentColor" opacity="0.3"/>
<ellipse cx="105" cy="198" rx="9" ry="3" fill="currentColor" opacity="0.3"/>
</svg>
<!-- Shadok admin réseau tangled in cables, router at feet, frustrated -->
<svg class="shadok-admin-reseau" viewBox="0 0 160 200" fill="none" aria-hidden="true">
<!-- Body upright but struggling -->
<ellipse cx="80" cy="95" rx="21" ry="27" fill="currentColor" opacity="0.25"/>
<!-- Head tilted, frustrated -->
<circle cx="82" cy="52" r="15" fill="currentColor" opacity="0.3" />
<!-- Eyes looking in different directions (frustrated) -->
<circle cx="77" cy="50" r="1.8" fill="currentColor" opacity="0.5"/>
<circle cx="88" cy="48" r="1.8" fill="currentColor" opacity="0.45"/>
<!-- Angry eyebrows -->
<line x1="74" y1="46" x2="79" y2="47" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" opacity="0.4"/>
<line x1="91" y1="44" x2="86" y2="46" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" opacity="0.4"/>
<!-- Beak open, yelling -->
<polygon points="73,56 65,55 73,60" fill="currentColor" opacity="0.35"/>
<line x1="67" y1="56" x2="66" y2="58" stroke="currentColor" stroke-width="1" opacity="0.3"/>
<!-- Cables tangling around body -->
<path d="M50 40 Q30 60 55 80 Q80 95 60 115 Q40 130 70 140" stroke="currentColor" stroke-width="2" fill="none" opacity="0.3"/>
<path d="M110 45 Q130 65 105 85 Q85 100 110 120 Q125 130 95 145" stroke="currentColor" stroke-width="2" fill="none" opacity="0.28"/>
<path d="M75 38 Q95 50 75 70" stroke="currentColor" stroke-width="1.5" fill="none" opacity="0.22"/>
<!-- Arms trying to untangle -->
<line x1="60" y1="85" x2="40" y2="70" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="100" y1="85" x2="120" y2="68" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Legs -->
<line x1="70" y1="120" x2="60" y2="175" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="90" y1="120" x2="100" y2="175" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Feet -->
<ellipse cx="57" cy="178" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
<ellipse cx="103" cy="178" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
<!-- Router box at feet -->
<rect x="60" y="168" width="40" height="14" rx="3" fill="currentColor" opacity="0.25"/>
<circle cx="70" cy="175" r="1.5" fill="currentColor" opacity="0.35"/>
<circle cx="78" cy="175" r="1.5" fill="currentColor" opacity="0.3"/>
<circle cx="86" cy="175" r="1.5" fill="currentColor" opacity="0.35"/>
<!-- Antenna on router -->
<line x1="92" y1="168" x2="96" y2="155" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" opacity="0.25"/>
</svg>
<!-- Shadok imprimeuse 3D watching printer build object layer by layer -->
<svg class="shadok-imprimeuse3d" viewBox="0 0 170 210" fill="none" aria-hidden="true">
<!-- 3D printer frame -->
<rect x="10" y="90" width="65" height="60" rx="3" fill="currentColor" opacity="0.2"/>
<!-- Printer rails -->
<line x1="15" y1="95" x2="15" y2="145" stroke="currentColor" stroke-width="1.5" opacity="0.25"/>
<line x1="70" y1="95" x2="70" y2="145" stroke="currentColor" stroke-width="1.5" opacity="0.25"/>
<!-- Print bed -->
<rect x="18" y="135" width="49" height="4" rx="1" fill="currentColor" opacity="0.25"/>
<!-- Object being printed (layered) -->
<rect x="32" y="128" width="20" height="7" rx="1" fill="currentColor" opacity="0.3"/>
<rect x="34" y="122" width="16" height="6" rx="1" fill="currentColor" opacity="0.25"/>
<rect x="36" y="117" width="12" height="5" rx="1" fill="currentColor" opacity="0.2"/>
<!-- Extruder head -->
<rect x="34" y="110" width="16" height="6" rx="2" fill="currentColor" opacity="0.35"/>
<line x1="42" y1="116" x2="42" y2="118" stroke="currentColor" stroke-width="1.5" opacity="0.4"/>
<!-- Body leaning forward, watching intently -->
<ellipse cx="120" cy="105" rx="20" ry="25" fill="currentColor" opacity="0.25" transform="rotate(-15 120 105)"/>
<!-- Head looking down at printer -->
<circle cx="108" cy="70" r="15" fill="currentColor" opacity="0.3"/>
<!-- Eyes both staring down at printer, fascinated -->
<circle cx="103" cy="72" r="1.8" fill="currentColor" opacity="0.5"/>
<circle cx="112" cy="73" r="1.8" fill="currentColor" opacity="0.5"/>
<!-- Beak pointing down -->
<polygon points="100,78 96,82 104,82" fill="currentColor" opacity="0.35"/>
<!-- Arms one pointing at printer -->
<line x1="105" y1="95" x2="75" y2="105" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="135" y1="98" x2="150" y2="115" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<!-- Legs standing, leaning -->
<line x1="112" y1="128" x2="105" y2="192" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="128" y1="128" x2="138" y2="192" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Feet -->
<ellipse cx="103" cy="195" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
<ellipse cx="140" cy="195" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
</svg>
<!-- Shadok cryptographe 3/4 view, cloak, giant key + padlock -->
<svg class="shadok-cryptographe" viewBox="0 0 170 210" fill="none" aria-hidden="true">
<!-- Mysterious cloak -->
<path d="M55 70 Q50 110 45 160 L125 160 Q120 110 115 70" fill="currentColor" opacity="0.15"/>
<path d="M45 160 Q40 170 38 180 L132 180 Q130 170 125 160" fill="currentColor" opacity="0.12"/>
<!-- Body under cloak -->
<ellipse cx="85" cy="105" rx="22" ry="28" fill="currentColor" opacity="0.25"/>
<!-- Head 3/4 view, slightly turned -->
<circle cx="85" cy="55" r="16" fill="currentColor" opacity="0.3"/>
<!-- Hood suggestion -->
<path d="M68 50 Q85 35 102 50" fill="currentColor" opacity="0.18"/>
<!-- Eyes mysterious, one slightly larger -->
<circle cx="80" cy="53" r="2" fill="currentColor" opacity="0.5"/>
<circle cx="91" cy="52" r="1.5" fill="currentColor" opacity="0.4"/>
<!-- Beak 3/4 profile -->
<polygon points="75,58 67,55 74,62" fill="currentColor" opacity="0.35"/>
<!-- Left arm holding giant key -->
<line x1="63" y1="95" x2="30" y2="110" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Giant key -->
<circle cx="18" cy="108" r="12" stroke="currentColor" stroke-width="2.5" fill="none" opacity="0.4"/>
<line x1="30" y1="108" x2="55" y2="108" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.35"/>
<line x1="48" y1="108" x2="48" y2="118" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.3"/>
<line x1="53" y1="108" x2="53" y2="115" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.3"/>
<!-- Right arm holding padlock -->
<line x1="107" y1="95" x2="140" y2="85" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Padlock big -->
<rect x="135" y="82" width="28" height="24" rx="4" fill="currentColor" opacity="0.3"/>
<path d="M141 82 L141 70 Q149 58 157 70 L157 82" stroke="currentColor" stroke-width="2.5" fill="none" opacity="0.35"/>
<circle cx="149" cy="95" r="3" fill="currentColor" opacity="0.2"/>
<line x1="149" y1="98" x2="149" y2="103" stroke="currentColor" stroke-width="1.5" opacity="0.2"/>
<!-- Legs long, cloak partly covering -->
<line x1="75" y1="130" x2="65" y2="195" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="95" y1="130" x2="108" y2="195" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Feet -->
<ellipse cx="63" cy="198" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
<ellipse cx="110" cy="198" rx="8" ry="3" fill="currentColor" opacity="0.3"/>
</svg>
<!-- Shadok droneuse looking up at flying drone, remote in hands -->
<svg class="shadok-droneuse" viewBox="0 0 160 210" fill="none" aria-hidden="true">
<!-- Drone above -->
<rect x="60" y="12" width="30" height="8" rx="3" fill="currentColor" opacity="0.3"/>
<!-- Drone arms -->
<line x1="55" y1="16" x2="35" y2="16" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.25"/>
<line x1="95" y1="16" x2="115" y2="16" stroke="currentColor" stroke-width="2" stroke-linecap="round" opacity="0.25"/>
<!-- Propellers spinning -->
<ellipse cx="35" cy="14" rx="12" ry="3" fill="currentColor" opacity="0.2"/>
<ellipse cx="115" cy="14" rx="12" ry="3" fill="currentColor" opacity="0.2"/>
<!-- Propeller blur lines -->
<line x1="25" y1="12" x2="45" y2="12" stroke="currentColor" stroke-width="0.8" opacity="0.15"/>
<line x1="105" y1="12" x2="125" y2="12" stroke="currentColor" stroke-width="0.8" opacity="0.15"/>
<!-- Drone camera -->
<circle cx="75" cy="22" r="3" fill="currentColor" opacity="0.25"/>
<!-- Drone legs -->
<line x1="62" y1="20" x2="58" y2="28" stroke="currentColor" stroke-width="1.5" opacity="0.2"/>
<line x1="88" y1="20" x2="92" y2="28" stroke="currentColor" stroke-width="1.5" opacity="0.2"/>
<!-- Body upright, looking up -->
<ellipse cx="78" cy="115" rx="20" ry="26" fill="currentColor" opacity="0.25"/>
<!-- Head tilted back looking up -->
<circle cx="78" cy="72" r="15" fill="currentColor" opacity="0.3"/>
<!-- Eyes looking up at drone -->
<circle cx="74" cy="68" r="1.8" fill="currentColor" opacity="0.5"/>
<circle cx="83" cy="67" r="1.8" fill="currentColor" opacity="0.45"/>
<!-- Beak pointing up -->
<polygon points="76,56 80,50 82,57" fill="currentColor" opacity="0.35"/>
<!-- Arms holding remote control -->
<line x1="60" y1="108" x2="50" y2="128" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="96" y1="108" x2="106" y2="128" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Remote control in hands -->
<rect x="42" y="126" width="70" height="14" rx="4" fill="currentColor" opacity="0.3"/>
<circle cx="55" cy="133" r="3" fill="currentColor" opacity="0.2"/>
<circle cx="100" cy="133" r="3" fill="currentColor" opacity="0.2"/>
<!-- Joysticks -->
<line x1="55" y1="130" x2="55" y2="127" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" opacity="0.3"/>
<line x1="100" y1="131" x2="102" y2="128" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" opacity="0.3"/>
<!-- Legs standing -->
<line x1="68" y1="138" x2="58" y2="195" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="88" y1="138" x2="100" y2="195" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Feet -->
<ellipse cx="55" cy="198" rx="9" ry="3" fill="currentColor" opacity="0.3"/>
<ellipse cx="103" cy="198" rx="9" ry="3" fill="currentColor" opacity="0.3"/>
</svg>
<!-- Shadok mécanicienne lying under machine, legs sticking out, wrench, oil drops -->
<svg class="shadok-mecanicienne" viewBox="0 0 180 200" fill="none" aria-hidden="true">
<!-- Machine/server box above -->
<rect x="5" y="55" width="100" height="50" rx="5" fill="currentColor" opacity="0.2"/>
<rect x="12" y="62" width="35" height="12" rx="2" fill="currentColor" opacity="0.15"/>
<rect x="12" y="80" width="35" height="12" rx="2" fill="currentColor" opacity="0.15"/>
<!-- Machine details -->
<circle cx="20" cy="68" r="2" fill="currentColor" opacity="0.3"/>
<circle cx="20" cy="86" r="2" fill="currentColor" opacity="0.25"/>
<line x1="60" y1="65" x2="90" y2="65" stroke="currentColor" stroke-width="1.5" opacity="0.15"/>
<line x1="60" y1="72" x2="85" y2="72" stroke="currentColor" stroke-width="1.5" opacity="0.15"/>
<!-- Body lying flat under machine, only partial visible -->
<ellipse cx="80" cy="118" rx="25" ry="18" fill="currentColor" opacity="0.22" transform="rotate(90 80 118)"/>
<!-- Head under machine (barely visible) -->
<circle cx="55" cy="115" r="12" fill="currentColor" opacity="0.2"/>
<!-- Arm sticking out with wrench -->
<line x1="42" y1="115" x2="15" y2="105" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Wrench -->
<path d="M8 100 L15 105 L12 108 L5 103 Z" fill="currentColor" opacity="0.35"/>
<circle cx="5" cy="100" r="5" stroke="currentColor" stroke-width="1.5" fill="none" opacity="0.3"/>
<!-- Oil drops falling -->
<ellipse cx="70" cy="108" rx="2" ry="3" fill="currentColor" opacity="0.3"/>
<ellipse cx="85" cy="112" rx="1.5" ry="2.5" fill="currentColor" opacity="0.25"/>
<ellipse cx="62" cy="105" rx="1" ry="2" fill="currentColor" opacity="0.2"/>
<!-- Legs sticking out from under machine the signature view -->
<line x1="90" y1="125" x2="130" y2="175" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<line x1="95" y1="120" x2="145" y2="165" stroke="currentColor" stroke-width="3" stroke-linecap="round" opacity="0.4"/>
<!-- Big feet sticking up -->
<ellipse cx="133" cy="178" rx="10" ry="4" fill="currentColor" opacity="0.35" transform="rotate(-25 133 178)"/>
<ellipse cx="148" cy="168" rx="10" ry="4" fill="currentColor" opacity="0.35" transform="rotate(-25 148 168)"/>
<!-- Beak visible from side -->
<polygon points="42,118 35,116 42,122" fill="currentColor" opacity="0.3"/>
<!-- Eye visible -->
<circle cx="50" cy="113" r="1.5" fill="currentColor" opacity="0.4"/>
</svg>
<div class="container-content">
<header class="mb-12 text-center">
<p class="mb-2 font-mono text-sm tracking-widest text-primary uppercase">{{ content?.kicker }}</p>
<h1 class="page-title font-display font-bold tracking-tight" style="color: hsl(var(--color-text))">
{{ content?.title }}
</h1>
<p class="mt-4 mx-auto max-w-2xl leading-relaxed" style="color: hsl(var(--color-text-muted))">
{{ content?.description }}
</p>
</header>
<div class="mx-auto max-w-3xl flex flex-col gap-6">
<div
v-for="pillar in content?.pillars"
:key="pillar.id"
class="pillar-card"
>
<div class="pillar-header">
<div class="pillar-icon">
<div :class="`i-lucide-${pillar.icon}`" class="h-5 w-5" />
</div>
<h2 class="font-display text-xl font-bold" style="color: hsl(var(--color-text))">
{{ pillar.label }}
</h2>
<span v-if="pillar.gestation" class="gestation-badge">
<div class="i-lucide-flask-conical h-3 w-3" />
En gestation
</span>
</div>
<p class="leading-relaxed whitespace-pre-line mt-3" style="color: hsl(var(--color-text-muted))">{{ pillar.text }}</p>
<!-- Project card -->
<div v-if="pillar.project" class="project-card mt-4">
<div class="project-icon">
<div class="i-lucide-rocket h-4 w-4" />
</div>
<div>
<span class="font-display font-semibold text-sm" style="color: hsl(var(--color-text))">{{ pillar.project.name }}</span>
<span class="text-sm ml-2" style="color: hsl(var(--color-text-muted))">{{ pillar.project.text }}</span>
</div>
</div>
<div v-if="pillar.to" class="mt-4">
<NuxtLink
:to="pillar.to"
class="inline-flex items-center gap-1 text-sm text-primary hover:text-primary/80 transition-colors"
>
En savoir plus
<div class="i-lucide-arrow-right h-3.5 w-3.5" />
</NuxtLink>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
definePageMeta({
layout: 'default',
})
const { data: content } = await usePageContent('numerique')
useHead({
title: content.value?.meta?.title ?? 'Autonomie numérique',
})
</script>
<style scoped>
.page-title {
font-size: clamp(2rem, 5vw, 2.75rem);
}
.pillar-card {
padding: 1.5rem;
border-radius: 0.75rem;
border: 1px solid hsl(var(--color-text) / 0.08);
background: hsl(var(--color-surface));
transition: border-color 0.2s;
}
.pillar-card:hover {
border-color: hsl(var(--color-primary) / 0.2);
}
.pillar-header {
display: flex;
align-items: center;
gap: 0.75rem;
}
.pillar-icon {
display: flex;
align-items: center;
justify-content: center;
width: 2.25rem;
height: 2.25rem;
border-radius: 0.5rem;
background: hsl(var(--color-primary) / 0.15);
color: hsl(var(--color-primary));
box-shadow: 0 0 12px hsl(var(--color-primary) / 0.12);
flex-shrink: 0;
}
.gestation-badge {
display: inline-flex;
align-items: center;
gap: 0.25rem;
margin-left: auto;
padding: 0.125rem 0.5rem;
border-radius: 9999px;
background: hsl(var(--color-accent) / 0.12);
color: hsl(var(--color-accent));
font-size: 0.7rem;
font-weight: 500;
font-family: var(--font-mono);
}
.project-card {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem 1rem;
border-radius: 0.5rem;
background: hsl(var(--color-bg) / 0.5);
border: 1px solid hsl(var(--color-primary) / 0.1);
}
.project-icon {
display: flex;
align-items: center;
justify-content: center;
width: 1.75rem;
height: 1.75rem;
border-radius: 0.375rem;
background: hsl(var(--color-primary) / 0.1);
color: hsl(var(--color-primary));
flex-shrink: 0;
}
.shadok-codeuse {
position: absolute;
left: 1%;
top: 4%;
width: clamp(70px, 10vw, 140px);
opacity: 0.24;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-float-codeuse 9s ease-in-out infinite;
}
.shadok-electricien {
position: absolute;
right: 1%;
top: 3%;
width: clamp(70px, 10vw, 130px);
opacity: 0.22;
pointer-events: none;
color: hsl(var(--color-accent));
animation: shadok-float-electricien 11s ease-in-out infinite;
}
.shadok-soudeuse {
position: absolute;
left: 3%;
top: 40%;
width: clamp(70px, 10vw, 130px);
opacity: 0.2;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-float-soudeuse 8s ease-in-out infinite;
}
.shadok-admin-reseau {
position: absolute;
right: 2%;
top: 35%;
width: clamp(70px, 10vw, 130px);
opacity: 0.22;
pointer-events: none;
color: hsl(var(--color-accent));
animation: shadok-float-admin-reseau 10s ease-in-out infinite;
}
.shadok-imprimeuse3d {
position: absolute;
left: 2%;
bottom: 8%;
width: clamp(70px, 10vw, 135px);
opacity: 0.2;
pointer-events: none;
color: hsl(var(--color-accent));
animation: shadok-float-imprimeuse3d 12s ease-in-out infinite;
}
.shadok-cryptographe {
position: absolute;
right: 1%;
bottom: 6%;
width: clamp(70px, 10vw, 130px);
opacity: 0.18;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-float-cryptographe 11s ease-in-out infinite;
}
.shadok-droneuse {
position: absolute;
left: 40%;
bottom: 2%;
width: clamp(70px, 10vw, 130px);
opacity: 0.2;
pointer-events: none;
color: hsl(var(--color-primary));
animation: shadok-float-droneuse 7s ease-in-out infinite;
}
.shadok-mecanicienne {
position: absolute;
right: 2%;
top: 60%;
width: clamp(70px, 10vw, 140px);
opacity: 0.22;
pointer-events: none;
color: hsl(var(--color-accent));
animation: shadok-float-mecanicienne 9s ease-in-out infinite;
}
@keyframes shadok-float-codeuse {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
}
@keyframes shadok-float-electricien {
0%, 100% { transform: translateY(0) rotate(0deg); }
50% { transform: translateY(-10px) rotate(1deg); }
}
@keyframes shadok-float-soudeuse {
0%, 100% { transform: translateY(0) rotate(0deg); }
50% { transform: translateY(-7px) rotate(-0.8deg); }
}
@keyframes shadok-float-admin-reseau {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-9px); }
}
@keyframes shadok-float-imprimeuse3d {
0%, 100% { transform: translateY(0) rotate(0deg); }
50% { transform: translateY(-11px) rotate(0.5deg); }
}
@keyframes shadok-float-cryptographe {
0%, 100% { transform: translateY(0) rotate(0deg); }
50% { transform: translateY(-8px) rotate(-0.6deg); }
}
@keyframes shadok-float-droneuse {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-12px); }
}
@keyframes shadok-float-mecanicienne {
0%, 100% { transform: translateY(0) rotate(0deg); }
50% { transform: translateY(-7px) rotate(1.2deg); }
}
@media (max-width: 768px) {
.shadok-codeuse { display: none; }
.shadok-electricien { display: none; }
.shadok-soudeuse { display: none; }
.shadok-admin-reseau { display: none; }
.shadok-imprimeuse3d { display: none; }
.shadok-cryptographe { display: none; }
.shadok-droneuse { display: none; }
.shadok-mecanicienne { display: none; }
}
</style>

View File

@@ -77,7 +77,7 @@ const palettes: Record<PaletteName, PaletteColors> = {
export const usePaletteStore = defineStore('palette', () => {
const currentPalette = ref<PaletteName>(
(import.meta.client && localStorage.getItem('palette') as PaletteName) || 'automne',
(import.meta.client && localStorage.getItem('palette') as PaletteName) || 'ete',
)
const colors = computed(() => palettes[currentPalette.value])

View File

@@ -0,0 +1,39 @@
import { readdir, stat } from 'node:fs/promises'
import { join } from 'node:path'
interface PageEntry {
path: string
label: string
section?: string
}
async function listYamlFiles(dir: string, prefix = ''): Promise<PageEntry[]> {
const entries: PageEntry[] = []
const items = await readdir(dir)
for (const item of items) {
const fullPath = join(dir, item)
const s = await stat(fullPath)
if (s.isDirectory()) {
const subEntries = await listYamlFiles(fullPath, prefix ? `${prefix}/${item}` : item)
entries.push(...subEntries)
}
else if (item.endsWith('.yml')) {
const name = item.replace('.yml', '')
const path = prefix ? `${prefix}/${name}` : name
entries.push({
path,
label: name,
section: prefix || undefined,
})
}
}
return entries
}
export default defineEventHandler(async () => {
const pagesDir = join(process.cwd(), 'site', 'pages')
return await listYamlFiles(pagesDir)
})

View File

@@ -0,0 +1,21 @@
import { mkdir } from 'node:fs/promises'
import { join, dirname } from 'node:path'
export default defineEventHandler(async (event) => {
const path = getRouterParam(event, 'path')
if (!path || !/^[a-z0-9-/]+$/.test(path)) {
throw createError({ statusCode: 400, statusMessage: 'Invalid page path' })
}
const body = await readBody(event)
const relativePath = `pages/${path}.yml`
// Ensure subdirectory exists
const fullPath = join(process.cwd(), 'site', relativePath)
await mkdir(dirname(fullPath), { recursive: true })
await writeYaml(relativePath, body)
gitSyncContent(`Mise à jour page ${path}`, [`site/${relativePath}`])
return { ok: true }
})

View File

@@ -1,12 +0,0 @@
export default defineEventHandler(async (event) => {
const name = getRouterParam(event, 'name')
if (!name || !/^[a-z0-9-]+$/.test(name)) {
throw createError({ statusCode: 400, statusMessage: 'Invalid page name' })
}
const body = await readBody(event)
await writeYaml(`pages/${name}.yml`, body)
gitSyncContent(`Mise à jour page ${name}`, [`site/pages/${name}.yml`])
return { ok: true }
})

View File

@@ -1,14 +1,14 @@
export default defineEventHandler(async (event) => {
const name = getRouterParam(event, 'name')
const path = getRouterParam(event, 'path')
if (!name || !/^[a-z0-9-]+$/.test(name)) {
throw createError({ statusCode: 400, statusMessage: 'Invalid page name' })
if (!path || !/^[a-z0-9-/]+$/.test(path)) {
throw createError({ statusCode: 400, statusMessage: 'Invalid page path' })
}
try {
return await readYaml(`pages/${name}.yml`)
return await readYaml(`pages/${path}.yml`)
}
catch {
throw createError({ statusCode: 404, statusMessage: `Page "${name}" not found` })
throw createError({ statusCode: 404, statusMessage: `Page "${path}" not found` })
}
})

View File

@@ -1,9 +1,10 @@
export default defineEventHandler((event) => {
const path = getRequestURL(event).pathname
// /lire → /economique/modele-eco
if (path.startsWith('/lire')) {
const rest = path.slice(5) // remove '/lire'
return sendRedirect(event, `/modele-eco${rest || '/'}`, 301)
return sendRedirect(event, `/economique/modele-eco${rest || '/'}`, 301)
}
if (path.startsWith('/ecouter')) {
@@ -14,4 +15,31 @@ export default defineEventHandler((event) => {
if (path === '/autonomie' || path === '/autonomie/') {
return sendRedirect(event, '/numerique', 301)
}
if (path === '/decision' || path === '/decision/') {
return sendRedirect(event, '/citoyenne/decision', 301)
}
// /modele-eco → /economique/modele-eco
if (path.startsWith('/modele-eco')) {
const rest = path.slice(11) // remove '/modele-eco'
return sendRedirect(event, `/economique/modele-eco${rest || '/'}`, 301)
}
// Redirect old /gestation/* routes to proper sections
if (path.startsWith('/gestation/')) {
const slug = path.slice(11).replace(/\/$/, '')
const numeriquePages = ['logiciel-libre', 'authentification-wot', 'cloud-libre']
if (numeriquePages.includes(slug)) {
return sendRedirect(event, `/numerique/${slug}`, 301)
}
if (slug === 'productions-collectives') {
return sendRedirect(event, '/economique/productions-collectives', 301)
}
if (slug === 'tarifs-eau') {
return sendRedirect(event, '/citoyenne/tarifs-eau', 301)
}
// Fallback
return sendRedirect(event, '/', 301)
}
})

22
site/pages/citoyenne.yml Normal file
View File

@@ -0,0 +1,22 @@
meta:
title: Autonomie citoyenne
kicker: Autonomie citoyenne
title: La décision
description: >
Se donner les moyens de la décision collective. Reprendre la main
sur les processus qui structurent notre vie commune — à l'échelle
des bassins de vie.
items:
- id: decision
label: Décision collective
icon: gavel
description: Se donner les moyens de la décision collective.
to: /citoyenne/decision
- id: tarifs-eau
label: Tarifs de l'eau
icon: droplets
description: Application pour obtenir justice sociale et incitation dynamique à la réduction. Permet de confier la décision à la population des communes.
to: /citoyenne/tarifs-eau
gestation: true

View File

@@ -0,0 +1,21 @@
meta:
title: Décision collective — Autonomie citoyenne
kicker: Autonomie citoyenne
title: Plateforme Décision
icon: gavel
description: Se donner les moyens de la décision collective.
features:
- icon: vote
title: Décisions on-chain
text: Des décisions transparentes et vérifiables, inscrites sur la blockchain.
- icon: scroll-text
title: Les Mandats
text: Formaliser et suivre les mandats confiés aux personnes désignées.
- icon: scroll-text
title: Documents de référence
text: Les textes fondateurs et documents qui encadrent la prise de décision.
- icon: git-branch
title: Les Protocoles
text: Les règles et processus qui structurent la décision collective.

View File

@@ -0,0 +1,20 @@
meta:
title: Tarifs de l'eau — Autonomie citoyenne
kicker: Autonomie citoyenne
title: Tarifs de l'eau
icon: droplets
gestation: true
description: >
Application pour obtenir justice sociale et incitation dynamique
à la réduction. Permet de confier la décision à la population des communes.
project:
name: SejeteralO
text: Simulateur de tarification de l'eau — justice sociale et écologie.
content: >
La tarification de l'eau est un levier essentiel de justice sociale
et d'incitation à la réduction de la consommation. SejeteralO permet
aux communes de simuler et comparer différentes grilles tarifaires.

29
site/pages/economique.yml Normal file
View File

@@ -0,0 +1,29 @@
meta:
title: Autonomie économique
kicker: Autonomie économique
title: La création monétaire
description: >
Pour fonctionner autrement, il faut créer une économie qui le permette.
Au fondement de toute économie se trouve la création monétaire — son code,
ses règles, ses bénéficiaires. Tant que ce code est écrit par d'autres,
pour d'autres, aucune autonomie réelle n'est possible.
La monnaie libre propose un autre code : symétrique, transparent, co-créé.
items:
- id: monnaie-libre
label: Monnaie libre
icon: g1
description: "La Ğ1 (June) : une monnaie co-créée par ses membres, sans dette ni intérêt. Le dividende universel comme base."
to: /economique/monnaie-libre
- id: modele-eco
label: Économie du don
icon: scale
description: Un livre et des chansons pour une proposition de modèle économique fondé sur le don.
to: /economique/modele-eco
- id: productions-collectives
label: Productions collectives
icon: users
description: Une plateforme pour faciliter la création d'équipes et la réalisation de productions à l'échelle des bassins de vie.
to: /economique/productions-collectives
gestation: true

View File

@@ -0,0 +1,23 @@
meta:
title: Commandez le livre papier
kicker: Le livre
title: Commandez le livre papier
icon: shopping-bag
description: >
« Une économie du don — enfin concevable » est disponible en version papier.
Vous pouvez le commander en ligne ou le demander en librairie.
bookelis:
label: Commander sur Bookelis
url: https://www.bookelis.com/economie/56818-Une-economie-du-don-enfin-concevable.html
librairie:
title: En librairie
text: >
Le livre est disponible à la commande dans toute librairie jusqu'au printemps 2027.
Cette disponibilité dépend d'un abonnement de référencement Hachette,
qui permet aux libraires de le trouver dans leur catalogue et de le commander
auprès de leur distributeur. Au-delà de cette date, la commande en ligne
sur Bookelis reste disponible.

View File

@@ -0,0 +1,33 @@
meta:
title: Monnaie libre — Autonomie économique
kicker: Autonomie économique
title: Monnaie libre
icon: g1
description: >
La Ğ1 (June) est une monnaie co-créée par ses membres, sans dette ni intérêt.
Chaque être humain qui y participe co-crée la même part de monnaie —
c'est le dividende universel. Un code monétaire symétrique dans le temps
et dans l'espace.
content: >
La monnaie libre repose sur la Théorie Relative de la Monnaie (TRM),
formulée par Stéphane Laborde. Elle définit les conditions d'une monnaie
qui ne privilégie aucune génération ni aucun individu dans sa création.
La Ğ1 est la première implémentation de cette théorie. Chaque membre
certifié par la toile de confiance co-crée quotidiennement un dividende
universel — la même quantité relative de monnaie pour tous.
Ce n'est pas une monnaie complémentaire ni une monnaie locale.
C'est une monnaie libre : libre dans son code, libre dans sa création,
libre dans son usage.
links:
- label: monnaie-libre.fr
href: https://monnaie-libre.fr
icon: external-link
- label: Théorie Relative de la Monnaie
href: https://trm.creationmonetaire.info
icon: book-open

View File

@@ -0,0 +1,16 @@
meta:
title: Productions collectives — Autonomie citoyenne
kicker: Autonomie citoyenne
title: Productions collectives
icon: users
gestation: true
description: >
Une plateforme pour faciliter la création d'équipes et la réalisation
de productions à l'échelle des bassins de vie.
content: >
Les productions collectives permettent de mutualiser les compétences
et les ressources pour réaliser des projets concrets au service
du territoire.

View File

@@ -1,16 +1,16 @@
hero:
heading:
- "Construire une autonomie collective."
- "à l'échelle des bassins de vie"
- "Pousser les curseurs"
- "Autonomie numérique, économique, citoyenne."
- "— s'en donner les moyens —"
- Construire une autonomie collective.
- à l'échelle des bassins de vie
- Pousser les curseurs
- Autonomie numérique, économique, citoyenne.
- — s'en donner les moyens —
citations:
- "Il s'agit d'émancipation."
- "Les trois dimensions qui nous émancipent sont le numérique, l'économie et le politique."
- "Elles peuvent nous asservir tout autant."
- "Ce sont les 3 axes de l'espace dans lequel nous naviguons."
approach: "Dans chaque dimension, nous adressons ce qui est le plus en amont"
- Il s'agit d'émancipation.
- Les trois dimensions qui nous émancipent sont le numérique, l'économie et le politique.
- Elles peuvent nous asservir tout autant.
- Ce sont les 3 axes de l'espace dans lequel nous naviguons.
approach: Dans chaque dimension, nous adressons ce qui est le plus en amont
axes:
- label: numérique
value: le code source
@@ -18,7 +18,6 @@ hero:
value: la création monétaire
- label: citoyenne
value: la décision
book:
kicker: Modèle économique
title: Une économie du don — enfin concevable
@@ -29,7 +28,6 @@ book:
cta:
player: Présentation musicale
pdf: Lecture du livre
axes:
numerique:
title: Autonomie numérique
@@ -37,7 +35,7 @@ axes:
items:
- label: Logiciel libre
description: Maîtriser le code source, c'est maîtriser l'outil. Le logiciel libre est la base de l'autonomie numérique.
to: /gestation/logiciel-libre
to: /numerique/logiciel-libre
gestation: true
icon: code-2
presentation:
@@ -45,7 +43,7 @@ axes:
text: Application pour le financement fléché des développements.
- label: Authentification — WoT
description: Une toile de confiance décentralisée, sans autorité centrale. Chaque identité est certifiée par ses pairs.
to: /gestation/authentification-wot
to: /numerique/authentification-wot
gestation: true
icon: share-2
presentation:
@@ -53,7 +51,7 @@ axes:
text: Gestionnaire de confiances.
- label: Cloud libre
description: Héberger ses propres services pour ne dépendre de personne. Serveurs, noms de domaine, infrastructure.
to: /gestation/cloud-libre
to: /numerique/cloud-libre
gestation: true
icon: cloud
presentation:
@@ -64,12 +62,13 @@ axes:
icon: coins
items:
- label: Monnaie libre
description: "La Ğ1 (June) : une monnaie co-créée par ses membres, sans dette ni intérêt. Le dividende universel comme base."
href: https://monnaie-libre.fr
description: "La Ğ1 (June) : une monnaie co-créée par ses membres, sans dette ni intérêt. Le dividende universel comme
base."
to: /economique/monnaie-libre
icon: g1
- label: Économie du don
description: Un livre et des chansons pour une proposition de modèle économique fondé sur le don.
to: /modele-eco
to: /economique/modele-eco
icon: scale
actions:
- id: open-player
@@ -77,11 +76,22 @@ axes:
icon: play
highlight: true
- id: open-pdf
label: Lecture du livre
label: Lire le livre
icon: book-open
- id: link
label: Présentation des chapitres
icon: list
to: /economique/modele-eco
secondary: true
- id: link
label: Commandez le livre
icon: shopping-bag
to: /economique/commande
secondary: true
- label: Productions collectives
description: Une plateforme pour faciliter la création d'équipes et la réalisation de productions à l'échelle des bassins de vie.
to: /gestation/productions-collectives
description: Une plateforme pour faciliter la création d'équipes et la réalisation de productions à l'échelle des
bassins de vie.
to: /economique/productions-collectives
gestation: true
icon: users
politique:
@@ -90,20 +100,19 @@ axes:
items:
- label: Décision collective
description: Se donner les moyens de la décision collective.
to: /decision
to: /citoyenne/decision
icon: gavel
- label: Tarifs de l'eau
description: Application pour obtenir justice sociale et incitation dynamique à la réduction. Permet de confier la décision à la population des communes.
to: /gestation/tarifs-eau
description: Application pour obtenir justice sociale et incitation dynamique à la réduction. Permet de confier la
décision à la population des communes.
to: /citoyenne/tarifs-eau
gestation: true
icon: droplets
gratewizard:
title: grateWizard
subtitle: Le compagnon interactif du livre et du projet
subtitle: Un utilitaire pratique pour estimer les valeurs de façon relative
description: Explorez le modèle économique, posez vos questions, suivez le fil du raisonnement.
icon: sparkles
evenement:
title: Le librodrome,
subtitle: c'est également un événement.

View File

@@ -17,7 +17,7 @@ pillars:
name: wishBounty
text: Application pour le financement fléché des développements libres.
gestation: true
to: /gestation/logiciel-libre
to: /numerique/logiciel-libre
- id: authentification-wot
label: "Authentification — WoT"
@@ -31,7 +31,7 @@ pillars:
name: trustWallet
text: Gestionnaire de confiances.
gestation: true
to: /gestation/authentification-wot
to: /numerique/authentification-wot
- id: cloud-libre
label: Cloud libre
@@ -45,4 +45,4 @@ pillars:
name: Bouquet de services
text: "Drive, Visio, Forum, Wiki, CMS. IA frugale localisée."
gestation: true
to: /gestation/cloud-libre
to: /numerique/cloud-libre

View File

@@ -0,0 +1,22 @@
meta:
title: Authentification WoT — Autonomie numérique
kicker: Autonomie numérique
title: "Authentification — WoT"
icon: share-2
gestation: true
description: >
Une toile de confiance décentralisée, sans autorité centrale.
Chaque identité est certifiée par ses pairs — pas par un serveur,
pas par une entreprise. C'est le fondement de la monnaie libre Ğ1
et de toute gouvernance entre égaux.
project:
name: trustWallet
text: Gestionnaire de confiances.
content: >
La Web of Trust (toile de confiance) est un mécanisme d'authentification
décentralisé où chaque participant certifie l'identité des autres.
Aucune autorité centrale n'est nécessaire — la confiance émerge du réseau.

View File

@@ -0,0 +1,22 @@
meta:
title: Cloud libre — Autonomie numérique
kicker: Autonomie numérique
title: Cloud libre
icon: cloud
gestation: true
description: >
Héberger ses propres services pour ne dépendre de personne.
Serveurs, noms de domaine, infrastructure.
Un bouquet de services complet — Drive, Visio, Forum, Wiki, CMS —
et demain, une IA frugale localisée.
project:
name: Bouquet de services
text: "Drive, Visio, Forum, Wiki, CMS. IA frugale localisée."
content: >
L'auto-hébergement est la clé de voûte de l'autonomie numérique.
Il s'agit de maîtriser l'infrastructure sur laquelle reposent nos outils
de communication, de stockage et de collaboration.

View File

@@ -0,0 +1,23 @@
meta:
title: Logiciel libre — Autonomie numérique
kicker: Autonomie numérique
title: Logiciel libre
icon: code-2
gestation: true
description: >
Le logiciel libre n'est pas qu'une question technique.
C'est la condition d'existence d'outils qui nous appartiennent —
que l'on peut auditer, modifier, partager.
Sans logiciel libre, toute promesse de souveraineté numérique est creuse.
project:
name: wishBounty
text: Application pour le financement fléché des développements libres.
content: >
Le logiciel libre garantit quatre libertés fondamentales : utiliser, étudier,
modifier et redistribuer. Ces libertés sont le socle de toute autonomie numérique.
Sans elles, nous sommes dépendants d'éditeurs qui peuvent à tout moment modifier
les règles du jeu.

View File

@@ -8,9 +8,9 @@ navigation:
- label: numérique
to: /numerique
- label: économique
to: /modele-eco
to: /economique
- label: citoyenne
to: /decision
to: /citoyenne
extra:
- label: Événement
to: /evenement