@charset "utf-8";
/* ─────────────────────────────────────────────────────────────────────────
   pika — langage visuel « crayonné » (page de présentation et écrans produit)
   ─────────────────────────────────────────────────────────────────────────

   Contrat de formes DICTÉ PAR SIMON, pas déduit de mes réflexes :
     · bordures  → trait tremblé, main levée (SVG, jamais border-radius)
     · profondeur→ À PLAT. Aucune box-shadow, nulle part.
     · géométrie → légère rotation aléatoire des blocs (0,3° à 1°)
     · fond      → papier crème uni, grain léger

   Ancre : design-system Open Design « doodle ». Deux écarts assumés :
     1. Sa police (Comic Sans dans les tokens, Delius Swash Caps dans son
        DESIGN.md — le paquet se contredit) est écartée : Delius n'a PAS le
        latin étendu, donc pas de č/š/ž. Sur un site slovène d'abord, les
        titres casseraient en plein mot. → Caveat, auto-hébergée, latin-ext.
     2. Son accent bleu #49B6E5 est remplacé par le rose de pika : les pages
        de vote gardent leur identité rose, un bleu ici couperait le produit
        en deux à chaque clic. On prend les FORMES de doodle, pas sa palette.

   ⚠️ Ne pas « assainir » ce fichier en y remettant des border-radius uniformes
   ou des ombres portées : c'est exactement ce qu'il existe pour empêcher.
   ───────────────────────────────────────────────────────────────────────── */

/* La police Caveat est déclarée dans fonts.css, partagé avec style.css.
   Toute page qui charge sketch.css DOIT aussi charger fonts.css. */

:root {
  --paper:   #fbf7f2;   /* crème, jamais blanc pur */
  --ink:     #2e2a28;   /* encre chaude, jamais noir pur */
  --pencil:  #6b625d;   /* gris crayon : texte secondaire */
  --accent:  #e07a92;   /* rose pika — continuité avec les pages de vote */
  --accent-d:#b84e6a;
  --line:    #3a3330;   /* couleur du trait dessiné */
}

* { box-sizing: border-box; }

/* ⚠️ `100vw` COMPTE LA BARRE DE DEFILEMENT, `100cqw` non. Les blocs pleine largeur de
   cette feuille (`.hero-sk`, le trait de `.topbar::after`, le calage du texte du heros)
   sont construits en `50% - 50vw` : sur un navigateur de bureau, dont la barre est
   classique et non en surimpression, ils depassaient de la moitie de sa largeur DE CHAQUE
   COTE (mesure a 390px : heros [-7,5 ; 382,5] pour une largeur utile de 375). D'ou un
   defilement horizontal et un heros decale du reste de la page.
   `body` est donc declare CONTENEUR : `100cqw` vaut sa largeur de contenu, barre exclue.
   Mesure apres correction : heros [0 ; 375], defilement horizontal 0.
   - ⚠️ Ni `overflow-x: hidden` ni `overflow-x: clip` sur `html` n'y changent quoi que ce
     soit (les deux mesures, 8px de defilement residuel dans les trois cas). Ne pas y
     revenir en croyant a un oubli.
   - Le confinement de `body` ne casse PAS la visionneuse : verifie sur `/why`, elle
     couvre toujours l'ecran (top 0, hauteur = viewport) une fois `body` conteneur.
   - Chaque regle garde sa version `vw` AVANT sa version `cqw` : sur un navigateur sans
     requetes de conteneur, la seconde est ignoree et l'ancien rendu subsiste.
   - ⚠️ INVISIBLE EN CAPTURE HEADLESS : la barre y est en surimpression, largeur 0. Ce
     defaut ne se reproduit qu'avec `scrollbar-gutter: stable` (ou un vrai navigateur de
     bureau). Une capture Playwright propre ne prouve rien ici. */
body { container-type: inline-size; }

body {
  margin: 0;
  font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
  color: var(--ink);
  line-height: 1.6;
  background-color: var(--paper);
  /* Grain : deux trames de points décalées, très pâles. Pas d'image à charger. */
  background-image:
    radial-gradient(circle at 1px 1px, rgba(58,51,48,.055) 1px, transparent 0),
    radial-gradient(circle at 1px 1px, rgba(58,51,48,.035) 1px, transparent 0);
  background-size: 13px 13px, 29px 29px;
  background-position: 0 0, 7px 11px;
}

/* ── Typographie ────────────────────────────────────────────────────────── */
/* Caveat en TITRAGE seulement : une manuscrite en corps de texte se paie en
   lisibilité, surtout sur les diacritiques slovènes et pour des lecteurs âgés. */
.hand { font-family: 'Caveat', 'Segoe UI', cursive; font-weight: 700; }

h1, h2, h3 { font-family: 'Caveat', 'Segoe UI', cursive; font-weight: 700; line-height: 1.15; margin: 0 0 .35em; }
h1 { font-size: clamp(2.6rem, 9vw, 4.2rem); }
h2 { font-size: clamp(1.8rem, 5vw, 2.4rem); }
h3 { font-size: 1.5rem; }

.lede  { font-size: 1.12rem; color: var(--pencil); max-width: 46ch; }
.small { font-size: .88rem; color: var(--pencil); }

/* ── Le trait tremblé ───────────────────────────────────────────────────────
   Un vrai contour irrégulier, en SVG inline (data URI) étiré sur la boîte.
   `border-image` porte le tracé : aucune règle border-radius n'intervient,
   donc aucun risque de retomber sur le bloc arrondi générique.
   Le filtre feTurbulence ondule le trait — c'est lui qui fait la main levée. */
.sketch {
  border: 3px solid transparent;
  border-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'>\
<filter id='w'><feTurbulence type='fractalNoise' baseFrequency='0.028' numOctaves='2' seed='7'/>\
<feDisplacementMap in='SourceGraphic' scale='3.6'/></filter>\
<rect x='5' y='5' width='110' height='110' fill='none' stroke='%233a3330' stroke-width='2.4'\
 stroke-linejoin='round' filter='url(%23w)'/></svg>") 14 / 14px / 0 round;
  background: #fffdfa;
  padding: 22px 24px;
}

/* Variantes de graine : deux blocs voisins ne doivent pas avoir le MÊME tremblé,
   sinon l'irrégularité devient un motif — et trahit la génération. */
.sketch.s2 {
  border-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'>\
<filter id='w'><feTurbulence type='fractalNoise' baseFrequency='0.035' numOctaves='2' seed='23'/>\
<feDisplacementMap in='SourceGraphic' scale='4.2'/></filter>\
<rect x='5' y='5' width='110' height='110' fill='none' stroke='%233a3330' stroke-width='2.2'\
 stroke-linejoin='round' filter='url(%23w)'/></svg>") 14 / 14px / 0 round;
}
.sketch.s3 {
  border-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'>\
<filter id='w'><feTurbulence type='fractalNoise' baseFrequency='0.022' numOctaves='3' seed='41'/>\
<feDisplacementMap in='SourceGraphic' scale='3.1'/></filter>\
<rect x='5' y='5' width='110' height='110' fill='none' stroke='%233a3330' stroke-width='2.6'\
 stroke-linejoin='round' filter='url(%23w)'/></svg>") 14 / 14px / 0 round;
}

/* ── Rotation légère ────────────────────────────────────────────────────────
   0,3° à 1°, alternée. Redressée au survol/focus pour ne pas gêner la lecture
   d'un champ, et annulée si l'utilisateur demande moins d'animations. */
.tilt-a { transform: rotate(-0.7deg); }
.tilt-b { transform: rotate( 0.5deg); }
.tilt-c { transform: rotate(-0.35deg); }
.tilt-d { transform: rotate( 0.9deg); }
.sketch { transition: transform .18s ease; }
.sketch:focus-within { transform: rotate(0deg); }

@media (prefers-reduced-motion: reduce) {
  .tilt-a, .tilt-b, .tilt-c, .tilt-d { transform: none; }
  .sketch { transition: none; }
}

/* ── Mise en page ───────────────────────────────────────────────────────── */
.sheet { max-width: 760px; margin: 0 auto; padding: 28px 20px 72px; }

.topbar { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 0; padding-bottom: 22px; position: relative; }
.topbar::after { content: ''; position: absolute; left: calc(50% - 50vw); bottom: 0; width: 100vw; border-bottom: 1px solid var(--ink);
                 left: calc(50% - 50cqw); width: 100cqw; }
.brand { font-family: 'Caveat', cursive; font-weight: 700; font-size: 2rem; color: var(--ink); text-decoration: none; }
/* L'icone patte-coeur, devant le mot. Dimensionnee en `em` : elle suit la taille du
   wordmark, y compris la reduction sous 480px — une hauteur en pixels s'en detacherait.
   ⚠️ `.brand` reste EN LIGNE, pas `inline-flex` : la barre du haut aligne ses elements
   sur la LIGNE DE BASE, et un conteneur flex prend pour ligne de base celle de son
   premier element — l'image — ce qui decale le mot par rapport aux liens de nav. D'ou
   un simple `vertical-align` negatif, qui pose l'icone sur la ligne de base du mot. */
/* 1,40em : l'icone depasse le mot en haut ET en bas, comme sur le logo de reference —
   elle est son egale, pas un accessoire pose devant. Choisi en comparant quatre tailles
   rendues cote a cote (1,15 / 1,30 / 1,40 / 1,55) : en dessous elle fait vignette, au
   dessus elle ecrase le mot. Le calage negatif suit la hauteur, les deux vont ensemble. */
.brand-icon { height: 1.4em; width: auto; vertical-align: -.42em; margin-right: .22em; }
.topbar nav { display: flex; gap: 16px; align-items: baseline; }
.topbar nav a { color: var(--pencil); text-decoration: none; font-size: .92rem; border-bottom: 1.5px solid transparent; }
.topbar nav a:hover { color: var(--ink); border-bottom-color: var(--accent); }

/* Héros : un seul par page. Le titre porte, rien d'autre ne doit concurrencer.
   ⚠️ `.hero-sk` est l'en-tête de HUIT gabarits (accueil, palmarès, pourquoi, connexion,
   création x2, réglages, page introuvable) et un SEUL porte le bandeau. Il reste donc un
   bloc ordinaire, dans la colonne : la pleine largeur est posée plus bas sur
   `.hero-content`, qui n'existe que là où il y a une image à étendre. Les deux ont été
   confondus un temps — les sept autres écrans ont alors sorti leur titre et leur chapô
   à x=0, contre x=340 pour tout le reste de la page, sans aucun retrait pour les
   rattraper (`.hero-content` porte le retrait, `.hero-sk` n'en a jamais eu). */
.hero-sk { margin: 0 0 52px; }
.hero-sk h1 { margin-bottom: .25em; }
.hero-sk .lede { font-size: 1.22rem; }
.hero-content {
  /* La pleine largeur vit ICI, pas sur `.hero-sk` : c'est le bandeau qui s'etend, et
     `.hero-content` n'existe que sur l'accueil. Meme unite `cqw` que partout ailleurs,
     avec son repli `vw` — voir la note en tete de feuille. */
  width: 100vw; margin-left: calc(50% - 50vw);
  width: 100cqw; margin-left: calc(50% - 50cqw);
  /* 30.125 = 482/1600, le ratio du bandeau : la boite part a sa hauteur naturelle.
     En `vw` elle depassait l'image de quelques pixels (barre de defilement comptee),
     ce qui laissait un liseré de papier sous elle. */
  min-height: min(482px, 30.125vw);
  min-height: min(482px, 30.125cqw);
  /* Cale le texte du heros sur la colonne de `.sheet` : meme unite que la largeur du
     bloc, sinon le calage se decale de la moitie de la barre de defilement. */
  padding: 38px max(20px, calc((100vw - 760px) / 2 + 20px));
  padding: 38px max(20px, calc((100cqw - 760px) / 2 + 20px));
  background-image: var(--hero-image);
  /* ⚠️ `100% auto`, JAMAIS `100% 100%` : la hauteur de ce bloc est un MINIMUM, et
     l'accroche la depasse des que la fenetre se resserre (ou dans une langue plus
     verbeuse). En `100% 100%` l'image (1600x482) suivait la boite et se contractait
     horizontalement. Largeur imposee + hauteur libre = proportions conservees, sans
     recadrage. Ancree en HAUT (`50% 0`) : le debord se fait donc vers le bas, la ou
     le voile du texte le couvre. */
  background-position: 50% 0;
  background-repeat: no-repeat; background-size: 100% auto;
}
.hero-copy { width: min(590px, 100%); padding: 18px 24px 22px; background: rgba(255, 252, 248, .88); }
.hero-copy > :first-child { margin-top: 0; }
.hero-copy > :last-child { margin-bottom: 0; }

/* Bloc qui doit rester RATTACHÉ à l'accroche, et non flotter au milieu de la page.
   ⚠️ Marge NÉGATIVE, et c'est le seul levier : les marges verticales adjacentes
   fusionnent (max des positives + somme des négatives), donc le `margin-top` positif
   d'un <p> qui suit le hero est purement et simplement avalé par les 52 px de celui-ci.
   On rabote la marge du hero, on n'en ajoute pas une. */
.after-lede { margin-top: -30px; margin-bottom: 30px; }

/* ── Écran large : le bloc « page d'exemple » occupe la place du bandeau ──────
   Le bandeau y était décoratif — il montrait des conversations, il ne menait nulle part.
   À sa place, le seul bloc de la page qui donne à VOIR le produit : une vraie page de vote.
   L'accroche garde sa colonne à gauche, le bloc prend la droite.

   ⚠️ C'est une PLACE DE GRILLE, pas un déplacement du balisage : le bloc reste écrit une
   seule fois, à sa place de téléphone (en bas), et `grid-row`/`grid-column` le remontent
   ici. Ne jamais « simplifier » en dupliquant le bloc pour en masquer un des deux par
   requête média : deux versions à corriger, et un lien fantôme pour les lecteurs d'écran.

   ⚠️ Le héros perd sa pleine largeur ICI SEULEMENT (`.hero-content`, jamais `.hero-sk` —
   sept autres gabarits partagent cette classe). Sans bandeau il n'y a plus rien à étendre,
   et le voile de papier disparaît avec lui : sur du papier crème, un rectangle crème ne
   fait que décaler le titre.

   ⚠️ Les marges NE FUSIONNENT PLUS entre éléments de grille. Vérifié que les écarts ne
   bougent pas : `.after-lede` (-30px) et le chapô sous les trois temps (-22px) rabotent une
   marge de bloc adjacente, dont ils font la somme dans les deux modes (52-30, 52-22).

   ⚠️⚠️ TOUT EST PORTÉ PAR `.sheet:has(.lp-example)`, jamais par `.sheet` ni `.hero-sk` nus.
   `.sheet` est le socle des HUIT gabarits et `.hero-sk` leur en-tête commun : une première
   version qui mettait `.hero-sk` en colonne 1 a rétréci l'en-tête de `why`, `login`,
   `names`, `new` et « page introuvable » à 444px, colonne de droite vide à côté — +184px de
   hauteur sur `/why`, +129px sur la page introuvable. Mesuré en comparant les six gabarits
   avant/après, pas vu à l'œil : chaque page rendait « correctement », simplement plus
   étroite. C'est le même piège que la pleine largeur du bandeau, sous une autre forme.
   `:has()` est le bon outil ici : la mise en page suit la PRÉSENCE du bloc, et un navigateur
   qui ne le connaît pas retombe sur la colonne unique — soit exactement l'état d'avant. */
@media (min-width: 561px) {
  .sheet:has(.lp-example) {
    /* La colonne de gauche ne descend pas sous ~450px : c'est ce qu'il faut aux DEUX
       boutons du héros pour rester côte à côte (mesuré à 432px de contenu). En dessous ils
       s'empilent, et l'accroche perd la compacité qu'on vient de lui gagner. */
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(228px, .45fr);
    column-gap: 22px; align-items: start;
  }
  /* Tout occupe les deux colonnes ; seules l'accroche et le bloc d'exemple se partagent
     la ligne 2. Déclaré AVANT les deux exceptions : le dernier gagne à spécificité égale. */
  .sheet:has(.lp-example) > * { grid-column: 1 / -1; }
  .sheet:has(.lp-example) .hero-sk { grid-column: 1; grid-row: 2; }
  /* ⚠️ CE SÉLECTEUR DOIT PORTER LE `:has()` LUI AUSSI, pas seulement le conteneur.
     `.sheet:has(.lp-example) > *` pèse (0,2,0) — `:has()` prend la spécificité de son
     argument — contre (0,1,0) pour un `.lp-example` nu : la règle générique gagnait, le
     bloc restait sur les deux colonnes ET sur la ligne du héros, qu'il RECOUVRAIT. Le titre
     disparaissait derrière lui. Vu seulement en regardant la capture : le comparateur de
     positions disait « des blocs ont bougé », ce qui était vrai — dans la mauvaise case.
     Padding resserré : dans 760px de colonne partagée, les 24px des blocs `sketch` se
     paient sur le seul élément qui ne peut pas se replier, le bouton. */
  .sheet:has(.lp-example) .lp-example {
    grid-column: 2; grid-row: 2; margin: 0; padding: 18px 18px 20px;
  }
  /* Bouton resserré dans cette place, et seulement là : à 208px de contenu, « Open the
     example » / « Példa megnyitása » se cassaient en deux. Il est SECONDAIRE — le bouton
     qui doit rester gros est « Créer ma page », à gauche. Mesuré dans les huit langues. */
  .sheet:has(.lp-example) .lp-example .btn { padding: 9px 15px; font-size: .88rem; }

  /* ── Le bandeau, DERRIÈRE les deux blocs ──────────────────────────────────
     Il ne peut plus être le fond de `.hero-content` : celui-ci n'occupe que la colonne de
     gauche, l'image s'arrêterait au milieu de la page. C'est donc un ÉLÉMENT DE GRILLE à
     part entière — le `::before` du conteneur — posé sur la ligne du héros et sur les deux
     colonnes, avec le débord pleine largeur habituel (`100cqw` + son repli `vw`). Le calcul
     tient parce qu'il s'étale sur toute la sheet : `50%` y vaut la moitié de la colonne de
     texte, comme pour `.topbar::after`. Sur un seul des deux blocs, il serait faux.
     ⚠️ `align-self: stretch` : la grille est en `align-items: start`, sans quoi le fond
     ferait la hauteur d'une boîte vide (zéro).
     ⚠️ `100% auto` + `min-height` au ratio de l'image (30.125cqw = 482/1600), EXACTEMENT
     comme la version pleine largeur — et surtout pas `cover`. Essayé : la ligne étant dictée
     par le texte (~300px), `cover` agrandit l'image jusqu'à 525px de haut pour la remplir et
     recadre de 250px de chaque côté. Le bandeau devient un gros plan illisible. Le
     `min-height` règle le problème par l'autre bout : c'est la LIGNE qui prend la hauteur de
     l'image, donc rien à recadrer et pas de bande de papier vide en dessous.
     Ancré en haut : le débord se fait vers le bas, comme avant.
     ⚠️ Les deux blocs REPRENNENT un contexte d'empilement au-dessus (`z-index: 1`) : les
     blocs `sketch` sont inclinés par `transform`, donc chacun ouvre le sien, et sans ordre
     explicite le fond passait devant l'un ou l'autre selon la page. */
  .sheet:has(.lp-example)::before {
    content: ''; grid-column: 1 / -1; grid-row: 2; align-self: stretch; z-index: 0;
    margin-left: calc(50% - 50vw);  width: 100vw;  min-height: min(482px, 30.125vw);
    margin-left: calc(50% - 50cqw); width: 100cqw; min-height: min(482px, 30.125cqw);
    /* ⚠️ Un FONDU vers le papier par-dessus l'image, et il n'est pas décoratif : la bande
       prend la hauteur du texte, l'image celle de son ratio (30,125 % de la largeur). Dès
       que la première dépasse la seconde — ce qui arrive sous ~1000px, ou dans une langue
       plus verbeuse — l'image s'arrêtait NET au milieu de la bande, un trait horizontal en
       travers de la page. Le fondu rend cette limite au papier au lieu de la trancher, et
       il ne se voit pas quand l'image couvre toute la bande. */
    background:
      linear-gradient(180deg, rgba(250, 247, 242, 0) 55%, var(--paper) 92%),
      var(--hero-image) 50% 0 / 100% auto no-repeat;
  }
  .sheet:has(.lp-example) .hero-sk,
  .sheet:has(.lp-example) .lp-example { position: relative; z-index: 1; }
  /* Le voile de papier RESTE, lui : c'est ce qui garde le titre lisible sur la photo.
     Seule la pleine largeur quitte `.hero-content` — elle est passée au fond ci-dessus. */
  .hero-content {
    width: auto; margin-left: 0; min-height: 0; padding: 26px 0; background-image: none;
  }
  .hero-copy { width: 100%; padding: 14px 16px 16px; background: rgba(255, 252, 248, .88); }
  /* Le bloc d'exemple s'aligne sur le voile, pas sur le bord de la bande : les deux doivent
     partir de la même ligne, sinon la colonne de droite a l'air de flotter. */
  .sheet:has(.lp-example) .lp-example { margin-top: 26px; }
}

/* Souligné tracé à la main sous un mot-clé du titre */
.underline {
  position: relative; white-space: nowrap; color: var(--accent-d);
}
.underline::after {
  content: ''; position: absolute; left: -2%; right: -2%; bottom: -.07em; height: .28em;
  background: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='200' height='16' viewBox='0 0 200 16' preserveAspectRatio='none'>\
<path d='M3 11 C 40 4, 78 14, 116 7 S 176 5, 197 10' fill='none' stroke='%23e07a92' stroke-width='4'\
 stroke-linecap='round'/></svg>") no-repeat center/100% 100%;
}

/* Étapes : numérotées à la main, en colonne. Volontairement PAS une grille de
   cartes auto-fit — c'est le réflexe que ce fichier existe pour éviter. */
.steps { display: flex; flex-direction: column; gap: 26px; margin: 0 0 52px; padding: 0; list-style: none; }
.step { display: flex; gap: 18px; align-items: flex-start; }
.step-n {
  flex: none; width: 52px; height: 52px; display: grid; place-items: center;
  font-family: 'Caveat', cursive; font-weight: 700; font-size: 1.9rem; color: var(--accent-d);
  background: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='60' height='60' viewBox='0 0 60 60'>\
<filter id='w'><feTurbulence type='fractalNoise' baseFrequency='0.05' numOctaves='2' seed='13'/>\
<feDisplacementMap in='SourceGraphic' scale='2.4'/></filter>\
<circle cx='30' cy='30' r='25' fill='none' stroke='%23e07a92' stroke-width='2.4' filter='url(%23w)'/></svg>")
  no-repeat center/contain;
}
.step h3 { margin-bottom: .1em; }
.step p { margin: 0; color: var(--pencil); }

/* Boutons : remplis, coins à peine cassés, sans la moindre ombre. */
/* Boutons : forme tracee a la main (SVG de fond), pas un rectangle arrondi.
   C'etait l'element le plus generique de la page — donc celui qui trahissait le plus. */
.btn {
  display: inline-block; font: inherit; font-weight: 700; cursor: pointer;
  padding: 14px 28px; border: none; color: #fff; text-decoration: none; background: none;
  background-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='260' height='64' viewBox='0 0 260 64' preserveAspectRatio='none'>\
<filter id='b'><feTurbulence type='fractalNoise' baseFrequency='0.04' numOctaves='2' seed='11'/>\
<feDisplacementMap in='SourceGraphic' scale='3'/></filter>\
<rect x='4' y='4' width='252' height='56' fill='%23b84e6a' filter='url(%23b)'/></svg>");
  background-repeat: no-repeat; background-size: 100% 100%;
}
.btn:hover {
  background-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='260' height='64' viewBox='0 0 260 64' preserveAspectRatio='none'>\
<filter id='b'><feTurbulence type='fractalNoise' baseFrequency='0.04' numOctaves='2' seed='11'/>\
<feDisplacementMap in='SourceGraphic' scale='3'/></filter>\
<rect x='4' y='4' width='252' height='56' fill='%23e07a92' filter='url(%23b)'/></svg>");
}
.btn-ghost {
  color: var(--accent-d);
  background-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='260' height='64' viewBox='0 0 260 64' preserveAspectRatio='none'>\
<filter id='b'><feTurbulence type='fractalNoise' baseFrequency='0.045' numOctaves='2' seed='29'/>\
<feDisplacementMap in='SourceGraphic' scale='2.6'/></filter>\
<rect x='4' y='4' width='252' height='56' fill='none' stroke='%23b84e6a' stroke-width='2.6' filter='url(%23b)'/></svg>");
}
.btn-ghost:hover {
  background-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='260' height='64' viewBox='0 0 260 64' preserveAspectRatio='none'>\
<filter id='b'><feTurbulence type='fractalNoise' baseFrequency='0.045' numOctaves='2' seed='29'/>\
<feDisplacementMap in='SourceGraphic' scale='2.6'/></filter>\
<rect x='4' y='4' width='252' height='56' fill='%23fdeef2' stroke='%23b84e6a' stroke-width='2.6' filter='url(%23b)'/></svg>");
}
.btn-lg { font-size: 1.08rem; padding: 15px 32px; }

/* Liens dans le corps du texte. Sans cette règle ils restent au bleu souligné par
   défaut du navigateur — ce qui saute aux yeux au milieu d'une page tracée à la main.
   Ciblé sur `p`/`li` pour ne pas écraser la barre de navigation ni les boutons. */
/* ⚠️ `:not(.btn)` est INDISPENSABLE : les boutons sont des <a class="btn"> souvent
   posés dans un <p>. Sans l'exclusion, cette règle (plus spécifique que `.btn`)
   repeint leur libellé en rose sur un fond rose — bouton illisible. */
.sheet p a:not(.btn), .sheet li a:not(.btn) {
  color: var(--accent-d);
  text-decoration-color: var(--accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}
.sheet p a:not(.btn):hover, .sheet li a:not(.btn):hover { color: var(--ink); text-decoration-color: var(--ink); }

/* Ceinture et bretelles : un bouton garde son libellé quel que soit l'état du lien.
   Sans `:visited` explicite, le style par défaut du navigateur pour un lien déjà
   visité peut le repeindre — et un bouton illisible ne se voit qu'après coup. */
.btn, .btn:link, .btn:visited, .btn:active { color: #fff; text-decoration: none; }
.btn-ghost, .btn-ghost:link, .btn-ghost:visited, .btn-ghost:active { color: var(--accent-d); }

/* Formulaires */
.field { display: block; margin-bottom: 18px; }
.field > span { display: block; font-size: .84rem; font-weight: 700; color: var(--pencil); margin-bottom: 6px; }
.field input, .field textarea, .field select {
  width: 100%; min-width: 0; padding: 12px 14px; font: inherit; color: var(--ink);
  background: #fffdfa; border: 2px solid var(--line); border-radius: 4px 10px 5px 9px;
}
.field input:focus, .field textarea:focus { outline: 2px solid var(--accent); border-color: var(--accent); }
.public-check { display: flex; align-items: flex-start; gap: 10px; font-weight: 700; }
.public-check input { width: 18px; height: 18px; margin-top: 3px; accent-color: var(--accent-d); flex: none; }
.public-check + .hint { margin-top: .65em; }
.public-pages { display: grid; gap: 10px; margin-left: 0; padding-left: 0; }
.public-pages li {
  display: grid; grid-template-columns: 52px 1fr auto; gap: 14px; align-items: center;
  padding: 10px 12px;
}
.public-pages .btn { grid-column: 3; grid-row: 1; }
.public-page-thumb {
  display: grid; place-items: center; width: 52px; height: 52px;
  border: 1px solid rgba(58, 51, 48, .35); background-size: 30px 30px;
  font-size: 1.35rem; line-height: 1; letter-spacing: -.18em;
}
@media (max-width: 560px) {
  .public-pages li { grid-template-columns: 44px 1fr; gap: 10px 12px; }
  .public-page-thumb { width: 44px; height: 44px; background-size: 26px 26px; font-size: 1.1rem; }
  .public-pages .btn { grid-column: 2; grid-row: 2; justify-self: start; }
}
.hint { font-size: .82rem; color: var(--pencil); margin: -10px 0 16px; }

/* Accroche + action secondaire sur la même ligne (« Bienvenue Simon · Se déconnecter »).
   `baseline` et non `center` : les deux textes n'ont pas la même taille, un alignement
   centré ferait flotter le lien au-dessus de la ligne d'écriture. */
.lede-row { display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap; }
.logout-inline { margin: 0; }

/* Bouton déguisé en lien. Il RESTE un <button> dans un formulaire POST : /logout ne peut
   pas devenir un <a href>, sinon une image distante déconnecterait les gens (cf. auth).
   D'où la remise à zéro des styles de bouton — sans elle, le navigateur lui redonne son
   fond gris et son cadre. */
.link-btn {
  background: none; border: none; padding: 0; margin: 0;
  font: inherit; font-size: .92rem; color: var(--pencil);
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-thickness: 1px; cursor: pointer;
}
.link-btn:hover { color: var(--ink); text-decoration-color: var(--ink); }
.link-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.note {
  background: #fdeef2; border: 2px solid var(--accent);
  border-radius: 4px 12px 6px 10px; padding: 12px 16px; margin-bottom: 22px; font-size: .93rem;
}
.note.warn { background: #fff6e5; border-color: #e0a34a; }

/* Note précédée d'un pictogramme (le sablier du compte à rebours). Variante LÉGÈRE de
   `.note-lead` : celle-ci a un titre, un gros pictogramme et de l'air, parce qu'elle
   conditionne la suite ; ici il s'agit d'une phrase, l'icône ne doit pas la dominer.
   Alignée en haut et non centrée : sur deux lignes (mobile), un sablier centré flotte
   au milieu du paragraphe. */
.note-with-ico { display: flex; gap: 10px; align-items: flex-start; }
.note-ico { flex: none; width: 19px; height: 19px; margin-top: .15em; color: var(--accent-d); }
/* En avertissement, le pictogramme prend l'ambre du cadre — comme le triangle de
   `.note-lead`. Sinon un sablier rose dans un encart ambre jure. */
.note.warn .note-ico { color: #a2600c; }

/* Encart d'alerte « de tête » : une note ordinaire ne suffit pas quand le message
   conditionne la suite (ici : la page reste invisible tant que l'adresse n'est pas
   confirmée). Plus d'air, un titre, un pictogramme.
   ⚠️ Triangle en SVG `currentColor`, JAMAIS en emoji : le serveur n'a aucune police
   emoji (les captures headless les rendent en carrés vides) et rien ne garantit
   celle du visiteur. Les autres pictogrammes du site suivent déjà cette règle. */
.note-lead { display: flex; gap: 13px; align-items: flex-start; padding: 16px 18px; font-size: .97rem; }
.note-lead > svg { flex: none; width: 26px; height: 26px; margin-top: 2px; color: #a2600c; }
.note-lead strong { display: block; font-size: 1.06rem; margin-bottom: .35em; }
.note-lead p { margin: .5em 0 0; }
.note-lead p:first-of-type { margin-top: 0; }

/* Lien copiable (liens de partage) */
.copyline {
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  background: #fffdfa; border: 2px dashed var(--line);
  border-radius: 4px 10px 5px 9px; padding: 10px 14px; margin-bottom: 10px;
}
.copyline code { font-size: .86rem; word-break: break-all; flex: 1; min-width: 0; }

.foot-sk { margin-top: 64px; padding-top: 20px; border-top: 2px dashed rgba(58,51,48,.25); color: var(--pencil); font-size: .86rem; display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.foot-sk a { color: var(--pencil); }

.langs-sk { display: flex; flex-wrap: wrap; gap: 2px 4px; }
.langs-sk a { font-size: .82rem; text-decoration: none; color: var(--pencil); padding: 2px 7px; border-bottom: 2px solid transparent; }
.langs-sk a.on { color: var(--accent-d); border-bottom-color: var(--accent); font-weight: 700; }

/* Dépliant de langue — le MEME choix que `.langs-sk`, dans l'autre rendu. Les deux sont
   toujours dans le HTML, la largeur decide lequel s'affiche : c'est ce qui permet de
   n'avoir qu'un seul balisage a maintenir (`langs.php`) et de ne rien retirer du DOM.
   Cache par defaut, montre sous 560px (voir plus bas), la ou la liste a plat prenait
   deux lignes de codes ISO dans la barre d'un telephone.
   ⚠️ `<details>` natif, aucun JavaScript — comme la palette des prix. Contrepartie
   assumee : il ne se referme pas au clic a cote. Choisir une langue navigue, donc il se
   referme de lui-meme dans le seul geste qui compte ; ajouter un fichier de script sur
   toutes les pages pour le reste ne vaut pas le cout. */
.langpick { display: none; }
.langpick > summary {
  display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  padding: 3px 7px; color: var(--pencil); font-size: .82rem;
  border: 1.5px solid var(--line);
  /* Le marqueur natif du <summary> : un triangle en plus du chevron dessine. */
  list-style: none;
}
.langpick > summary::-webkit-details-marker { display: none; }
.langpick > summary::marker { content: ''; }
.langpick > summary:hover { color: var(--ink); }
.langpick-icon, .langpick-caret { fill: none; stroke: currentColor; stroke-width: 1.6; }
.langpick-caret { stroke-linecap: round; stroke-linejoin: round; }
.langpick[open] .langpick-caret { transform: rotate(180deg); }
.langpick-now { font-weight: 700; color: var(--accent-d); letter-spacing: .02em; }
/* Le menu est en position absolue : il RECOUVRE le heros au lieu de pousser la page.
   ⚠️ Ancre a DROITE (`right: 0`) : le declencheur est groupe avec les liens de la nav, au
   bord droit de la barre — exactement la raison qui ancre la palette des prix a droite,
   rester dans le cadre. Il etait ancre a gauche quand la nav occupait toute la largeur et
   ouvrait la barre a gauche ; ancre du mauvais cote il DEPASSE, mesure en slovene (menu de
   172px sous un declencheur pousse a droite par un « Prijava » court : debordement sur les
   cinq largeurs testees, donc defilement horizontal). Verifier les DEUX bords a chaque fois
   que le declencheur change de cote. Et `--paper` est indispensable : sans fond opaque, le
   bandeau du heros se lit au travers. */
.langpick-menu {
  position: absolute; z-index: 3; top: calc(100% + 6px); right: 0;
  min-width: 172px; padding: 4px 0;
  background: var(--paper); border: 2px solid var(--line);
}
.langpick-menu a {
  display: flex; align-items: baseline; gap: 9px; padding: 7px 13px;
  text-decoration: none; color: var(--ink); font-size: .92rem; line-height: 1.3;
}
.langpick-menu a:hover { background: rgba(184, 78, 106, .09); }
.langpick-menu a.on { color: var(--accent-d); font-weight: 700; }
.langpick-code { color: var(--pencil); font-size: .74rem; font-weight: 400; width: 1.7em; flex: none; }
.langpick-menu a.on .langpick-code { color: var(--accent-d); }

/* ── Mobile ─────────────────────────────────────────────────────────────────
   Sous 420px la rotation est retirée : penchée, une boîte pleine largeur
   déborde et déclenche un défilement horizontal. */
/* À huit langues, la LISTE À PLAT ne tenait plus à côté du wordmark et du lien de connexion
   sur un téléphone : « ES » se retrouvait seul sur une ligne et « Sign in » coupé en deux.
   D'où le dépliant (`.langpick`) sous 560px — et une fois qu'il a remplacé la liste, la
   barre tient à nouveau sur UNE seule ligne : globe + code font ~70px, pas 415.
   ⚠️ Le retour à la ligne n'est donc plus IMPOSÉ (`width: 100%` sur la nav, hérité de la
   liste à plat), il est LAISSÉ AU FLUX : `flex: 1 1 auto` sur une barre en `flex-wrap`.
   La nav monte à côté du wordmark quand elle y tient, et bascule d'elle-même sur sa propre
   ligne pleine largeur quand une langue plus verbeuse ou un lien de plus l'en empêche.
   Rien à re-régler par langue — et surtout aucune largeur en dur à deviner. */
@media (max-width: 560px) {
  .topbar { align-items: center; gap: 8px 12px; padding-bottom: 20px; }
  /* `flex-wrap` sur la nav elle-même : avec le lien du palmarès EN PLUS (il revient dès que
     le classement franchit NAMES_MIN_INDEX), les trois éléments débordaient à 320px — défaut
     ANTÉRIEUR, la nav ne pouvant alors que grandir hors de l'écran. Elle passe désormais à la
     ligne plutôt que de pousser la page en défilement horizontal. */
  /* Nav groupée À DROITE (`flex-end`), comme au-dessus de 560px : le sélecteur appartient
     aux commandes de la barre, pas au wordmark. Collé à lui par un `space-between`, il se
     lisait comme un attribut du logo — « pika FR » — au lieu d'un choix qu'on vient faire. */
  /* ⚠️ C'est la NAV qui sert d'ancre au menu de langue, pas le déclencheur (`position` est
     donc ici, et surtout PAS sur `.langpick`). Ancré au déclencheur, un menu ouvert vers la
     gauche sortait du cadre par la gauche dès que le déclencheur n'était plus au bord droit
     — mesuré sur `/login` à 320px, où le lien « Meine Seite erstellen » repousse le globe.
     Ancré au bord droit de la nav, le menu est dans le cadre dans les deux dispositions,
     et reste sous la ligne qui porte le déclencheur. */
  .topbar nav { flex: 1 1 auto; flex-wrap: wrap; justify-content: flex-end; align-items: center;
                position: relative; }
  .langs-sk a { padding: 2px 5px; }
  .topbar nav > a { white-space: nowrap; }
  /* La liste a plat cede la place au depliant. ⚠️ `z-index` sur la barre : le menu est
     en position absolue DANS elle, et le heros qui suit porte une image de fond — sans
     contexte d'empilement au-dessus, le menu ouvert passait dessous. */
  .langs-sk { display: none; }
  .langpick { display: block; }
  .topbar { z-index: 2; }

  /* ── Le bandeau cède la place à la photo du panier ────────────────────────
     Le bandeau (1600x482) est une FRISE : il ne dit ce qu'il montre qu'étalé. Ici le voile
     de l'accroche prend toute la largeur et le recouvre — il n'en restait qu'une bande de
     40px en haut, illisible, pour 124 Ko. On le retire donc du fond (donc plus téléchargé)
     et la photo du panier prend le relais SOUS l'accroche, où elle a la place d'être vue.
     ⚠️ Les deux ne coexistent jamais : c'est un remplacement, pas un ajout — la page mobile
     s'allège (59 Ko contre 124). Le voile et son fond disparaissent avec le bandeau : sans
     image derrière, un rectangle crème sur du papier crème ne fait que décaler le titre. */
  .hero-content { background-image: none; min-height: 0; padding: 16px 20px 0; }
  .hero-copy { width: 100%; padding: 0; background: none; }
}

@media (max-width: 480px) {
  .sheet { padding: 20px 15px 56px; }
  .tilt-a, .tilt-b, .tilt-c, .tilt-d { transform: none; }
  .step { gap: 13px; }
  .step-n { width: 42px; height: 42px; font-size: 1.5rem; }
  .hero-sk { margin-bottom: 38px; }
  /* Pas de `background-size` ici : il ecrasait le `100% auto` de la regle de base et
     ramenait le recadrage — donc la deformation — sur la seule largeur ou l'ecart entre
     la boite et le ratio de l'image est le plus grand.
     ⚠️ Ce bloc passe APRÈS celui de 560px et écrase donc ses paddings : il doit reprendre
     lui aussi le calage sans bandeau (bas à 0, la photo ferme le héros), sinon le voile
     revient en creux sous elle. Seul le retrait horizontal change (15px, celui de `.sheet`
     à cette largeur). */
  .hero-content { min-height: 0; padding: 16px 15px 0; }
  .hero-copy { width: 100%; padding: 0; background: none; }
  /* Le hero se resserre ici (38px) : le même -30px collerait le bloc à l'accroche. */
  .after-lede { margin-top: -20px; }
  .btn-lg { width: 100%; text-align: center; }
}

/* Vignettes de photos dans les réglages */
.thumbs { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 6px; }
.thumb { position: relative; }
.thumb img { width: 104px; height: 78px; object-fit: cover; border: 2px solid var(--line); }
.thumb form { position: absolute; top: -8px; right: -8px; margin: 0; }
.thumb-x {
  width: 24px; height: 24px; line-height: 1; font-size: 1rem; font-weight: 700;
  cursor: pointer; color: #fff; background: var(--accent-d);
  border: 2px solid var(--paper); border-radius: 50%; padding: 0;
}
.thumb-x:hover { background: var(--ink); }

/* ── Page « Pourquoi ce site » ───────────────────────────────────────────────
   Récit en temps successifs : texte et photo côte à côte, l'ordre s'inverse une
   fois sur deux pour que l'œil zigzague au lieu de descendre une colonne. */
.beat {
  display: grid; grid-template-columns: 1fr 150px; gap: 26px;
  align-items: center; margin-bottom: 30px;
}
/* ⚠️ En inversant l'ordre, il faut AUSSI inverser les colonnes : sinon le texte
   atterrit dans la colonne étroite (150 px) et la photo prend tout le reste. */
/* Une section sans photo n'a pas de raison d'etre une grille : sinon son texte reste
   coince dans la colonne etroite avec un grand vide a cote. */
.beat-solo, .beat-solo:nth-child(even) { display: block; }
.beat-solo p { max-width: 62ch; }
.beat:nth-child(even) { grid-template-columns: 150px 1fr; }
.beat:nth-child(even) > .beat-text { order: 2; }
.beat h2 { font-size: clamp(1.5rem, 4vw, 2rem); margin-bottom: .15em; }
.beat p { margin: 0; color: var(--pencil); }

/* Photo façon tirage papier : cadre blanc épais, aucune ombre (le relief vient
   de l'inclinaison et du liseré, pas d'un flou porté). */
/* Vignette cliquable : c'est un <a>, donc display:block et pas de soulignement. */
.snap {
  display: block; margin: 0; background: #fffdfa;
  border: 1px solid rgba(58,51,48,.3); padding: 7px 7px 16px;
  text-decoration: none; transition: transform .15s ease;
}
.snap[href]:hover, .snap[href]:focus-visible { transform: scale(1.06) rotate(0deg); }
.snap[href]:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.snap img { display: block; width: 100%; aspect-ratio: 3 / 2; height: auto; object-fit: cover; }

/* Les chiffres, juste au-dessus du temps du récit qui les cite. Plus de filet
   au-dessus : ce n'était utile que quand la ligne fermait la page. */
.stats-line {
  text-align: center; font-size: 1.3rem; color: var(--accent-d);
  margin: 0 0 10px;
}

@media (max-width: 620px) {
  /* Sur mobile, une seule disposition : texte à gauche, vignette à droite,
     sans inversion — l'alternance n'apporte rien sur une largeur si étroite. */
  .beat, .beat:nth-child(even) { grid-template-columns: 1fr 110px; gap: 14px; margin-bottom: 24px; }
  .beat:nth-child(even) > .beat-text { order: 0; }
}

/* Deux boutons côte à côte sous le héros ; empilés et pleine largeur sur mobile. */
.cta-row { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 28px; }
@media (max-width: 480px) { .cta-row { flex-direction: column; } }

/* Photos au-delà des cinq temps du récit */
.story-extra { display: flex; flex-wrap: wrap; gap: 16px; margin: 8px 0 30px; }
.story-extra { justify-content: center; }
.story-extra .snap { flex: 0 1 150px; }
.story-extra .snap img { aspect-ratio: 3 / 2; height: auto; }


@media (prefers-reduced-motion: reduce) { .snap { transition: none; } }

/* Photo d'ouverture du récit : plus grande, centrée. Pas de `loading="lazy"` ici —
   elle est visible d'emblée, la différer ne ferait que la faire apparaître en retard. */
.snap-hero { width: min(520px, 100%); margin: 0 auto 46px; }
@media (max-width: 620px) { .snap-hero { width: 100%; margin-bottom: 32px; } }

/* Liens de partage : cliquables et copiables */
.copyline a { flex: 1; min-width: 0; text-decoration: none; }
.copyline a code { color: var(--accent-d); }
.copyline a:hover code { color: var(--ink); text-decoration: underline; }
.copy-btn {
  flex: none; cursor: pointer; display: inline-grid; place-items: center;
  width: 34px; height: 34px; padding: 0;
  color: var(--accent-d); background: none; border: 2px solid var(--accent-d);
  border-radius: 3px 8px 4px 7px;
}
.copy-btn .ico { width: 17px; height: 17px; }
.copy-btn .ico-done { display: none; }
.copy-btn:hover { background: #fdeef2; }
.copy-btn.copied { color: #fff; background: var(--accent-d); border-color: var(--accent-d); }
.copy-btn.copied .ico-copy { display: none; }
.copy-btn.copied .ico-done { display: block; }
.copy-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Ligne « animal » : type + nom côte à côte */
.pet-row { display: flex; gap: 10px; margin-bottom: 12px; }
.pet-row select { flex: 0 0 auto; width: auto; }
.pet-row input { flex: 1; min-width: 0; }
.field select, .pet-row select {
  padding: 12px 10px; font: inherit; color: var(--ink);
  background: #fffdfa; border: 2px solid var(--line); border-radius: 4px 10px 5px 9px;
}

/* Suppression d'une page : repliée par défaut, deux temps avant l'irréversible */
/* Zone de suppression : toujours visible, séparée par un filet. Le repli n'apportait
   qu'un clic de plus — le décompte et le libellé du bouton disent déjà ce qui se passe. */
.danger { margin-top: 40px; background: var(--paper); }
.danger h3 { color: #a2342c; margin-bottom: .2em; }
.btn-danger, .btn-danger:link, .btn-danger:visited {
  background: none; border: 2px solid #a2342c; color: #a2342c;
  border-radius: 3px 9px 4px 8px; padding: 11px 22px;
}
.btn-danger:hover { background: #a2342c; color: #fff; }

/* Retrait d'une ligne « animal » */
.pet-del {
  flex: none; cursor: pointer; width: 28px; height: 28px; align-self: center; padding: 0;
  color: var(--pencil); background: none; border: none;
  font-size: 1.4rem; line-height: 1; font-weight: 700;
}
.pet-del:hover { color: #a2342c; }
.pet-del:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Bouton avec icône : l'alignement doit tenir même si le libellé passe sur deux lignes */
.btn-ico { display: inline-flex; align-items: center; gap: 8px; }
.btn-ico .ico { flex: none; width: 16px; height: 16px; }

/* Choix du fond : on choisit avec les yeux, chaque vignette montre le rendu réel */
.bg-choices { display: flex; flex-wrap: wrap; gap: 12px; margin: 4px 0 18px; }
.bg-choice { display: block; margin: 0; cursor: pointer; text-align: center; width: 82px; }
.bg-choice input { position: absolute; opacity: 0; width: 0; height: 0; }
.bg-sample {
  display: block; width: 82px; height: 60px;
  border: 2px solid var(--line); background-size: 60px 60px;
}
.bg-sample-none { background: repeating-linear-gradient(45deg, #fffdfa, #fffdfa 7px, #efe9e2 7px, #efe9e2 14px); }
.bg-choice small { display: block; font-size: .76rem; color: var(--pencil); margin-top: 4px; }
/* L'état sélectionné doit se voir sans couleur seule : un liseré épais le porte. */
.bg-choice input:checked + .bg-sample { border-color: var(--accent-d); border-width: 4px; }
.bg-choice input:focus-visible + .bg-sample { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Palette fermée plutôt qu'un <input type="color"> : son panneau natif ne se ferme pas
   au clic à côté, et la page ne peut rien y faire. */
.bg-colors { display: flex; flex-wrap: wrap; gap: 10px; margin: 4px 0 18px; }
.bg-swatch { display: block; margin: 0; cursor: pointer; }
.bg-swatch input { position: absolute; opacity: 0; width: 0; height: 0; }
.bg-swatch span { display: block; width: 38px; height: 38px; border: 2px solid var(--line); }
.bg-swatch input:checked + span { border-color: var(--accent-d); border-width: 4px; }
.bg-swatch input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }
.field-label { font-weight: 700; color: var(--pencil); margin: 0 0 2px; }

/* Panneau de couleur personnalisée — le nôtre, pas celui du navigateur : lui seul peut
   porter un bouton de validation et se fermer quand on clique à côté. */
.bg-custom { display: contents; }
.bg-swatch-custom span {
  position: relative;
  background: conic-gradient(#f5a3b6, #f7d9a0, #cfe6a8, #a8e0d6, #a9c8ee, #cfb8e8, #f5a3b6);
}
/* La couleur choisie se pose DANS l'arc-en-ciel au lieu de le remplacer : sans lui, la
   pastille devient une pastille de couleur comme les autres et ne dit plus « choix libre ».
   Sans couleur choisie, --c est absent : l'arc-en-ciel reste seul. */
.bg-swatch-custom span::after {
  content: ''; position: absolute; inset: 6px;
  background: var(--c, transparent);
}
.bg-panel {
  max-width: 260px; margin: 0 0 18px; padding: 12px;
  background: var(--paper); border: 2px solid var(--line);
}
.bg-panel label { display: block; font-size: .82rem; color: var(--pencil); margin-bottom: 8px; }
.bg-panel input[type=range] { display: block; width: 100%; margin-top: 3px; }
.bg-panel-preview { height: 46px; border: 2px solid var(--line); margin-bottom: 10px; }
/* Le curseur de teinte porte l'échelle qu'il parcourt : on vise une couleur, pas un nombre. */
.bg-range-hue {
  -webkit-appearance: none; appearance: none; height: 12px; border: 1px solid var(--line);
  background: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00);
}
.btn-mini { padding: 5px 14px; font-size: .88rem; }


/* Photo du héros — encadrée comme les autres blocs (trait tremblé), jamais arrondie.
   ⚠️ TÉLÉPHONE SEULEMENT, et en remplacement du bandeau, jamais en plus (voir la requête
   média de 560px, qui retire `--hero-image` du fond). Sur écran large c'est le bandeau qui
   met les animaux en scène, en pleine largeur ; ici il ne restait qu'une bande de 40px sous
   le voile de l'accroche.
   ⚠️ Un FOND, pas une balise `<img>` — et ce n'est pas un détail de style : une image de
   contenu masquée en CSS est téléchargée quand même, l'écran large aurait donc payé les
   deux. Un `background-image` déclaré dans la seule requête média n'est chargé que là où
   elle s'applique (vérifié : mobile = corbeille.webp seule, large = bandeau.webp seule).
   Le texte de remplacement reste dû : il est porté par `role="img"` + `aria-label` sur le
   div, avec `lp_photo_alt`, traduit dans les huit langues.
   Le fond est en DEUX couches : la photo cadrée sur la boîte de contenu, le papier sous le
   padding — c'est ce qui laisse la marge crème entre le trait tremblé et la photo, comme
   une image posée sur une page. `cover` sur un cadrage déjà fait (820x656, panier centré)
   ne peut mordre que sur cette marge, jamais sur un animal. */
.hero-photo { display: none; }
@media (max-width: 560px) {
  .hero-photo {
    display: block; margin-top: 20px; aspect-ratio: 5 / 4;
    border: 3px solid transparent;
    border-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'>\
<filter id='w'><feTurbulence type='fractalNoise' baseFrequency='0.031' numOctaves='2' seed='13'/>\
<feDisplacementMap in='SourceGraphic' scale='3.9'/></filter>\
<rect x='5' y='5' width='110' height='110' fill='none' stroke='%233a3330' stroke-width='2.4'\
 stroke-linejoin='round' filter='url(%23w)'/></svg>") 14 / 14px / 0 round;
    padding: 9px;
    background: var(--hero-photo) 50% 50% / cover no-repeat content-box, var(--paper) padding-box;
  }
}


/* ── Carte d'une page dans « Mes pages » ─────────────────────────────────────
   Vignette à gauche, identité à droite. La vignette n'est PAS le repère principal :
   la photo est facultative, ce sont les animaux et le signe de vie qui identifient
   une page. Elle donne juste à l'œil un point d'accroche dans la liste.

   Filet d'encre 2 px et angles VIFS, comme les vignettes des réglages : ni cercle,
   ni coin arrondi — ce n'est pas un avatar. */
.pcard { display: flex; gap: 16px; align-items: flex-start; margin-bottom: 16px; }
.pcard-body { flex: 1; min-width: 0; }
.pcard-thumb {
  flex: none; display: block; width: 104px; height: 78px;
  object-fit: cover; border: 2px solid var(--line);
}
/* Repli sans photo : la tuile du fond choisi par le propriétaire, à demi-échelle pour
   qu'on voie la RÉPÉTITION du motif (à taille réelle, 104 px ne montrent pas même une
   tuile entière), et l'emoji de l'animal par-dessus — sans lui, trois pages au fond par
   défaut donneraient trois vignettes identiques. */
.pcard-thumb-bg {
  display: flex; align-items: center; justify-content: center;
  background-size: 60px; font-size: 1.7rem; line-height: 1;
}
.pcard-pets { margin: 0 0 2px; font-size: .95rem; }
/* Même ligne d'état sur la carte et en tête des réglages : une seule déclaration, sinon
   les deux dérivent et le même renseignement n'a plus la même allure d'un écran à l'autre. */
.pcard-life, .page-life { margin: 0 0 2px; font-size: .88rem; color: var(--pencil); }
.page-life { margin-top: 6px; }

@media (max-width: 480px) {
  .pcard { gap: 12px; }
  .pcard-thumb { width: 76px; height: 57px; }
  .pcard-thumb-bg { background-size: 44px; font-size: 1.3rem; }
}

/* ── Dépôt d'une photo (création d'une page) ─────────────────────────────────
   Glisser-déposer, collage (Ctrl+V) et aperçu — cf. photo-drop.js. Le contour est
   le trait tremblé du contrat de formes, mais en POINTILLÉ : un cadre en tirets se
   lit comme « pose quelque chose ici », là où le trait plein se lirait comme un
   bloc de plus au milieu du formulaire. Aucun border-radius (sauf le « × », qui est
   rond comme celui des vignettes), aucune ombre.

   ⚠️ Tout l'habillage est sous `.photo-pick.js` : la classe est posée par le script.
   Sans JavaScript, l'input natif reste visible et la zone n'est qu'un cadre autour
   de lui — jamais un « déposez ici » qui ne saurait rien recevoir. */
.photo-pick { position: relative; margin-bottom: 18px; }

.photo-drop {
  display: block; text-align: center; padding: 20px 18px;
  background: #fffdfa;
  border: 3px solid transparent;
  border-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'>\
<filter id='w'><feTurbulence type='fractalNoise' baseFrequency='0.045' numOctaves='2' seed='11'/>\
<feDisplacementMap in='SourceGraphic' scale='5.5'/></filter>\
<rect x='5' y='5' width='110' height='110' fill='none' stroke='%233a3330' stroke-width='2.4'\
 stroke-dasharray='10 7' stroke-linejoin='round' filter='url(%23w)'/></svg>") 14 / 14px / 0 round;
  transition: background .15s;
}
.photo-pick.js .photo-drop { cursor: pointer; }
/* Le survol et le glisser-au-dessus disent la même chose : « ça tombe ici ». Même
   traitement, donc — fond rosé et trait à l'accent (le pointillé reste : la zone
   attend toujours quelque chose). */
.photo-pick.js .photo-drop:hover,
.photo-pick.over .photo-drop {
  background: #fdeef2;
  border-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'>\
<filter id='w'><feTurbulence type='fractalNoise' baseFrequency='0.045' numOctaves='2' seed='11'/>\
<feDisplacementMap in='SourceGraphic' scale='5.5'/></filter>\
<rect x='5' y='5' width='110' height='110' fill='none' stroke='%23b84e6a' stroke-width='2.6'\
 stroke-dasharray='10 7' stroke-linejoin='round' filter='url(%23w)'/></svg>") 14 / 14px / 0 round;
}
/* Une fois la photo choisie, le trait se REFERME (plein) : le pointillé dit « il manque
   quelque chose ici », et le laisser après coup ferait douter que le fichier soit pris.
   C'est le même tracé que les blocs .sketch, à l'identique. */
.photo-pick.has-file .photo-drop {
  border-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'>\
<filter id='w'><feTurbulence type='fractalNoise' baseFrequency='0.028' numOctaves='2' seed='7'/>\
<feDisplacementMap in='SourceGraphic' scale='3.6'/></filter>\
<rect x='5' y='5' width='110' height='110' fill='none' stroke='%233a3330' stroke-width='2.4'\
 stroke-linejoin='round' filter='url(%23w)'/></svg>") 14 / 14px / 0 round;
}

/* Sans JavaScript, l'input natif est visible sous son intitulé : c'est le seul chemin,
   il doit respirer. Avec, il est escamoté mais garde le focus clavier — c'est lui qui le
   reçoit, donc c'est la zone qui doit le montrer, sinon la tabulation passe en aveugle. */
.photo-pick input[type=file] { margin-top: 10px; }
.photo-pick.js input[type=file] {
  position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; padding: 0;
}
.photo-pick.js .photo-drop:focus-within { outline: 2px solid var(--accent); outline-offset: 3px; }

.pd-ico { display: block; width: 32px; height: 32px; margin: 0 auto 4px; color: var(--pencil); }
.pd-main { display: block; font-weight: 700; }
/* Glisser et coller n'existent ni sans script, ni au doigt : la ligne qui les annonce
   n'apparaît que là où ils marchent. Sur mobile il reste « Ajouter une photo », qui
   décrit exactement ce qu'un appui fait. */
.pd-sub { display: none; font-size: .84rem; color: var(--pencil); margin-top: 2px; }
.photo-pick.js .pd-sub { display: block; }
@media (hover: none) {
  .photo-pick.js .pd-sub { display: none; }
}

/* État « une photo est choisie » : la vignette PREND LA PLACE de l'invitation, dans le
   même cadre. Deux zones (l'invitation + l'aperçu ailleurs) laisseraient croire qu'on
   peut en déposer une seconde ici, alors que le formulaire n'en accepte qu'une. */
.pd-shot { display: none; }
.photo-pick.has-file .pd-empty { display: none; }
.photo-pick.has-file .pd-shot { display: flex; gap: 14px; align-items: center; text-align: left; }
.pd-shot img { flex: none; width: 104px; height: 78px; object-fit: cover; border: 2px solid var(--line); }
.pd-meta { flex: 1; min-width: 0; }
/* Nom coupé sur UNE ligne, jamais césuré : un « IMG_20260730_184512.jpg » d'appareil
   photo se scindait en deux lignes et faisait grandir la zone à chaque photo choisie.
   Le nom n'est qu'un accusé de réception — la vignette dit déjà de quelle photo il s'agit. */
.pd-name { display: block; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pd-size { display: block; font-size: .84rem; color: var(--pencil); }
.pd-again { display: block; font-size: .84rem; color: var(--accent-d); margin-top: 2px; }

/* Le « × » vit hors du <label> (dedans, il rouvrirait le sélecteur de fichiers) et se
   pose sur l'angle, comme celui des vignettes des réglages. */
.pd-clear {
  display: none; position: absolute; top: -10px; right: -10px;
  width: 24px; height: 24px; line-height: 1; font-size: 1rem; font-weight: 700;
  cursor: pointer; color: #fff; background: var(--accent-d);
  border: 2px solid var(--paper); border-radius: 50%; padding: 0;
}
.photo-pick.has-file .pd-clear { display: block; }
.pd-clear:hover { background: var(--ink); }
.pd-clear:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.pd-err { display: none; margin: 8px 0 0; font-size: .86rem; color: #a2342c; }
.photo-pick.has-err .pd-err { display: block; }

/* Bouton d'envoi (réglages : la photo part sur validation, pas au dépôt). Il n'apparaît
   qu'une fois la photo choisie — sous une zone vide il ne peut rien faire, l'input étant
   `required`, et il répétait l'intitulé de la zone juste au-dessus. Sans JavaScript la
   classe `js` est absente et il reste visible : c'est alors le seul moyen d'envoyer. */
.pd-send { margin-top: 14px; }
.photo-pick.js .pd-send { display: none; }
.photo-pick.js.has-file .pd-send { display: inline-block; }

@media (max-width: 480px) {
  .photo-pick.has-file .pd-shot { gap: 11px; }
  .pd-shot img { width: 84px; height: 63px; }
}

/* ── Palmarès des noms (names.php) ──────────────────────────────────────────
   Une liste ordonnée, pas un tableau ni une grille de cartes : le classement
   EST l'information, et une <ol> le dit déjà. Les séparateurs sont des filets
   pointillés, comme le pied de page — aucun cadre, aucun coin arrondi. */
.kind-tabs { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: 0 0 30px; }
.kind-tab {
  font-size: .92rem; color: var(--pencil); text-decoration: none;
  padding: 3px 2px; border-bottom: 2px solid transparent;
}
.kind-tab:hover { color: var(--ink); border-bottom-color: var(--line); }
.kind-tab.on { color: var(--accent-d); border-bottom-color: var(--accent); font-weight: 700; }
/* ⚠️ `inline-block` obligatoire : ::first-letter ne s'applique pas à une boîte inline,
   la règle était simplement ignorée sur un <span> ordinaire. */
.kt-label { display: inline-block; }
.kt-label::first-letter { text-transform: uppercase; }

.rank-list { list-style: none; margin: 0 0 18px; padding: 0; counter-reset: none; }
.rank {
  display: flex; align-items: baseline; gap: 14px;
  padding: 9px 2px; border-bottom: 1.5px dashed rgba(58,51,48,.22);
}
.rank:last-child { border-bottom: 0; }

/* Le rang en manuscrite : c'est le seul endroit du site où un nombre est un titre. */
.rank-n {
  font-family: 'Caveat', 'Segoe UI', cursive; font-weight: 700;
  font-size: 1.5rem; line-height: 1; color: var(--accent-d);
  flex: none; min-width: 2.1ch; text-align: right;
}
.rank-name { flex: 1; min-width: 0; font-size: 1.08rem; overflow-wrap: anywhere; }
.rank-meta { flex: none; display: flex; gap: 12px; font-size: .86rem; color: var(--pencil); white-space: nowrap; }

/* Les trois premiers, un peu plus haut : le podium se lit avant de se compter. */
.rank:nth-child(-n+3) .rank-n { font-size: 1.95rem; }
.rank:nth-child(-n+3) .rank-name { font-size: 1.22rem; }

.nm-basis { margin: 0 0 6px; }
.nm-cta { margin: 40px 0 0; }
.nm-cta p { color: var(--pencil); }

@media (max-width: 480px) {
  .rank { gap: 10px; }
  .rank-meta { gap: 9px; font-size: .8rem; }
  .rank:nth-child(-n+3) .rank-name { font-size: 1.12rem; }
}
