# Lætitia Bica — Site portfolio

Site portfolio de **Lætitia Bica**, photographe & artiste visuelle basée à Bruxelles. Construit sur Kirby 5, entièrement bilingue FR/EN, avec un CMS administrable par la cliente.

---

## Stack technique

| Élément | Détail |
|---|---|
| CMS | [Kirby 5](https://getkirby.com) (flat-file, PHP) |
| PHP | 8.2+ |
| Langues | FR (défaut) + EN |
| Polices | BBB DM Sans (Bye Bye Binary) — self-hosted, Instrument Serif + Kavivanar (Google Fonts) |
| Masonry | [FlexMasonry](https://github.com/gilbitron/flexmasonry) |
| Build | Aucun bundler — CSS/JS vanilla, pas de dépendances npm |
| Hébergement | À définir |

---

## Installation locale

### Prérequis

- PHP 8.2+
- Un serveur local (MAMP, Laravel Herd, Valet…)
- Composer

### Setup

```bash
git clone https://github.com/paulmarique/laetitiabica.be.git
cd laetitiabica.be
composer install
```

Pointer le serveur local sur le dossier `www/`. Le panneau Kirby est accessible sur `/panel`.

### Config locale

Le fichier `site/config/config.localhost.php` active le mode debug automatiquement sur `localhost` :

```php
return ['debug' => true];
```

---

## Architecture

```
www/
├── assets/
│   ├── bbbdmsans/          # Police BBB DM Sans (woff/woff2)
│   ├── css/
│   │   ├── components/     # Un fichier CSS par composant
│   │   ├── main.css        # Point d'entrée — @import de tous les composants
│   │   ├── tokens.css      # Variables CSS (couleurs, typo, layout)
│   │   ├── reset.css       # Reset + font-variant-ligatures global
│   │   ├── typography.css  # Utilitaires de classes typo (.t-nav, .t-h3…)
│   │   └── layout.css      # Classes de mise en page (.l-container, .l-section)
│   ├── js/                 # Scripts vanilla, un fichier par fonctionnalité
│   └── vendor/             # FlexMasonry (css + js)
├── content/                # Contenu flat-file Kirby
│   ├── 1_home/
│   ├── 2_projets/          # Un dossier par projet
│   ├── parametres/         # Catégories, réglages globaux
│   └── ...
└── site/
    ├── blueprints/         # Définition des champs CMS
    │   ├── blocks/         # Blocs de contenu (gallery, text, video…)
    │   ├── files/          # Templates de fichiers (cover, masonry-image…)
    │   └── pages/          # Blueprints de pages
    ├── config/             # Config Kirby (thumbs WebP, routes, langues)
    ├── controllers/        # Logique PHP des pages (filtres projets)
    ├── languages/          # Traductions UI (fr.php, en.php)
    ├── models/             # Modèle ProjectPage (coverImage helper)
    ├── snippets/           # Composants PHP réutilisables
    │   └── blocks/         # Rendu des blocs de contenu
    └── templates/          # Templates de pages
```

---

## Pages

| URL | Template | Description |
|---|---|---|
| `/` | `home.php` | Homepage — diptyque, annonce, grille projets |
| `/projets` | `projects.php` | Liste filtrée par catégorie |
| `/projets/[slug]` | `project.php` | Page détail projet |
| `/bio` | `bio.php` | Biographie, CV, publications |
| `/presse` | `press.php` | Revue de presse globale |
| `/contact` | `contact.php` | Formulaire de contact |

Les URLs legacy (`/project-detail`, `/project-list`, `/press`) redirigent automatiquement via des routes Kirby.

---

## CMS — Structure d'un projet

Un projet comporte trois onglets dans le panel :

### Onglet Principal
- **Titre** (traduit FR/EN)
- **Couverture** — image template `project-cover`
- **Catégories** — checkboxes liées aux pages enfants de `parametres/`
- **Tags / Techniques** — tags libres (traduits)
- **Chapeau** — citation courte (traduit)

### Onglet Blocs
Champ `modules` de type `blocks`, traduit. Blocs disponibles :

| Bloc | Champs | Notes |
|---|---|---|
| `gallery` | images (non traduit) | Slider horizontal pleine largeur |
| `text` | subtitle, body (writer), photos latérales | Layout texte + photos sticky |
| `video` | url YouTube, title, caption (writer+lien) | Iframe directe avec légende |
| `image` | image, caption (writer+lien) | Image simple avec légende |
| `masonry` | images (non traduit), caption (writer+lien) | Grille FlexMasonry |
| `quote` | text | Citation avec trait vertical gauche |

### Onglet Crédits & Presse
- **Crédits** — structure role/nom/url
- **Note de remerciements** — textarea libre
- **Articles de presse liés** — structure source/titre/url (non traduit)

---

## Système de blocs — Fallback langue

Le champ `modules` est `translate: true`, ce qui permet des structures de blocs différentes par langue. Deux mécanismes de fallback sont en place :

1. **Modules vides** (`project.php`) — si la version EN est vide, on charge les blocs FR :
   ```php
   $blocks = $page->modules()->toBlocks();
   if ($blocks->count() === 0) {
       $blocks = $page->content('fr')->modules()->toBlocks();
   }
   ```

2. **Galerie/Masonry sans images** (`blocks/gallery.php`, `blocks/masonry.php`) — fallback positionnel vers le bloc FR correspondant si les images sont vides en EN.

> **Important** : pour éviter ce fallback, les blocs EN doivent être créés via le bouton "traduire depuis FR" dans le panel (préservation des UUIDs), pas recréés from scratch.

---

## Header — Comportement compact

Le header est en `mix-blend-mode: difference` (blanc sur tout fond).

| Page | Comportement |
|---|---|
| Homepage | Démarré étendu, se collapse au scroll (≥ 80px) |
| Autres pages | Logo + lang toggle toujours compacts (via CSS `body.page-detail`), nav étendue qui se collapse au scroll |

Le logo et le switch de langue ne s'animent **jamais** sur les pages non-home (`transition: none !important`).

---

## Page Projets — Filtrage

- La navigation principale filtre par catégorie via `?category=[uid]`
- Quand une catégorie est sélectionnée :
  - Le titre de la page = nom de la catégorie
  - Une description éditoriale s'affiche (champ `description` de la catégorie)
  - Une section **"Tous mes projets"** apparaît en bas avec les projets des autres catégories (`->not($projects)`)
- Le switch de langue préserve les query params (`?category=`, `?tag=`)

---

## Related projects

Logique dans `snippets/project-related.php` :

1. Lire `related_projects_count` depuis `parametres` (défaut : 3)
2. Prendre les `featured_projects` du `site.yml` en priorité (hors page courante)
3. Compléter avec des projets aléatoires (`->shuffle()`) hors page courante et hors featured

---

## Typographie

| Variable | Valeur | Usage |
|---|---|---|
| `--font-sans` | BBB DM Sans | Corps de texte, UI |
| `--font-ui` | BBB DM Sans | Titres, navigation |
| `--font-serif` | Instrument Serif | Logo |
| `--font-quote` | Kavivanar | Chapeau, citations |

Les **ligatures discrétionnaires** sont activées globalement via :
```css
font-variant-ligatures: common-ligatures discretionary-ligatures contextual;
```
Ce qui active notamment le `æ` dans *Lætitia* (BBB DM Sans étant une police de Bye Bye Binary, spécialisée dans l'écriture inclusive).

---

## Règles globales front

- **Liens externes** — tous les liens hors domaine reçoivent `target="_blank" rel="noopener noreferrer"` via `main.js`
- **Fallback langue** — si un champ traduit est vide en EN, afficher le contenu FR (à appliquer champ par champ dans les templates)
- **Images** — thumbs générés en WebP via Kirby (qualité 85)

---

## Scripts JS

| Fichier | Rôle |
|---|---|
| `intro.js` | Animation d'intro au chargement de page |
| `main.js` | Menu mobile, switch langue (i18n), liens externes |
| `i18n.js` | Traductions client-side via `data-i18n` attributes |
| `header-compact.js` | Compact/expand du header au scroll |
| `project-gallery.js` | Slider horizontal infini avec clonage (infinite loop) |
| `masonry.js` | Init FlexMasonry sur `.project-masonry__grid` |
| `cursor.js` | Curseur custom (blend mode) — diptyque, grille, slider |
| `diptyque.js` | Interactions du bloc diptyque (homepage) |
| `project-filter.js` | Filtrage client-side de la grille projets |
| `hero.js` | Animation du hero (homepage) |

---

## Panel — Accès

URL : `/panel`  
Langue de l'interface : **Français**  
Thème : **Dark**

L'administration est organisée en trois colonnes :
- **Projets** — liste draggable des projets (site.yml)
- **Pages** — pages fixes (home, bio, presse, contact…)
- **Catégories + Paramètres** — catégories, featured projects, footer, SEO

---

## Déploiement

```bash
git push origin main
```

Les fichiers `content/` sont versionnés (flat-file Kirby). Les médias uploadés via le panel (`content/*/` — images, PDF) ne sont pas dans le `.gitignore` par défaut — à ajuster selon la stratégie d'hébergement.

---

## Crédits

- **Design & développement** — [Paul Marique](https://paulmarique.com)
- **Police** — [BBB DM Sans](https://beyondbinarybold.com) par Bye Bye Binary
- **CMS** — [Kirby](https://getkirby.com)
