/* ══════════════════════════════════════════════════════════════════════════
   Le Cahier · feuille unique (accueil + application)
   --------------------------------------------------------------------------
   Refonte visuelle d'août 2026 (handoff Claude Design « Tonalité · Cahier
   moins IA »). La version précédente portait les codes génériques d'une
   interface générée : onglets pastel multicolores, gros rayons, icône d'app
   dans un carré arrondi. On les remplace par une identité éditoriale bâtie
   sur une seule métaphore, tenue sur les trois écrans : la PAGE RÉGLÉE.

   Trois règles qui expliquent tout le reste :
   1. un seul motif de fond, `.sheet` : lignes tous les 32 px, filet de marge
      rouge vertical, lettre ou chiffre fantôme en haut à droite. Répertoire,
      pages libres et agenda sont la même page, avec un contenu différent ;
   2. une seule couleur d'accent, le rouge du filet de marge, reprise par le
      jour courant et la page sélectionnée (et par le trait sous le nom du
      logo, qui est le même rouge). Les trois
      couleurs par section (terracotta / bleu / vert) ont disparu : elles
      faisaient « tableau de bord », pas « cahier » ;
   3. trois rôles typographiques stricts : Petrona (serif) pour les titres,
      Inter Tight pour le texte, JetBrains Mono pour tout ce qui
      est système (dates, lettres d'onglets, badges).

   Polices auto-hébergées : /static/fonts.css (charte) + /static/cahier-fonts.css
   (Petrona). Aucune requête tierce, la CSP `font-src 'self'` l'interdit.

   Clair/sombre : piloté par `data-theme` sur <html>, que `theme-init.js` pose
   avant le premier rendu. Trois états, comme partout dans le dépôt : clair,
   sombre, et l'absence de choix qui veut dire « suivre le système » (le script
   le résout lui-même). D'où un SEUL bloc sombre ici : dupliquer les jetons
   entre l'attribut et une media query donnerait deux listes qui divergent, et
   la préférence de l'appareil battrait le choix explicite de l'utilisateur.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  --bg: #f4f2ec;            /* le bureau */
  /* La page : un ivoire, pas un blanc d'écran. Le blanc pur donnait une carte
     d'interface posée sur un fond crème ; c'est le grain et la chaleur du
     papier qui font l'objet, et le contraste avec le bureau reste lisible. */
  --sheet: #fdfbf5;
  --sheet-edge: #efeade;    /* la tranche des pages du dessous */
  --tab-off: #ebe8df;       /* onglet inactif, champs posés sur le bureau */
  /* Une languette A-Z sans notes. Jeton à part, et non `--tab-off` réutilisé :
     en thème sombre, ce gris à 4 % d'opacité tombait à 2 niveaux de la page,
     et une lettre vide devenait indiscernable d'une lettre pleine. */
  --tab-empty: #e7e3d8;
  --ink: #0a0a0a;
  --muted: #6f6a60;
  --faint: #a39d90;
  --line: rgba(0, 0, 0, .05);       /* lignes réglées */
  --edge: rgba(0, 0, 0, .12);
  --edge-soft: rgba(0, 0, 0, .08);
  --accent: oklch(0.62 0.18 25);    /* le rouge du filet de marge */
  --accent-ink: oklch(0.55 0.18 25);
  --rule-red: oklch(0.62 0.18 25 / .35);
  --ok: oklch(0.62 0.16 155);
  --ghost: rgba(0, 0, 0, .05);      /* la lettre fantôme */
  --on-ink: #fbfaf7;                /* texte sur aplat d'encre */

  --shadow-sheet: 0 30px 80px -20px rgba(0, 0, 0, .18);
  --shadow-pop: 0 20px 60px -25px rgba(0, 0, 0, .25);

  /* La couverture du cahier de l'accueil : un objet sombre sur le bureau
     clair, avec sa reliure et son étiquette blanche collée dessus. */
  --cover: #272320;
  --cover-edge: #14110f;
  --cover-ink: rgba(255, 255, 255, .58);
  --cover-rim: rgba(0, 0, 0, .3);      /* l'arête de la couverture */
  --label-rim: rgba(0, 0, 0, .06);     /* le bord de l'étiquette collée */

  --lh: 32px;               /* le pas des lignes réglées */
  --margin-x: 64px;         /* le filet de marge */
  --text-x: 84px;           /* le texte commence après le filet */
  /* Taille du texte écrit (pages libres, corps des notes), réglable depuis
     « Mon compte ». Le pas des lignes ne bouge PAS avec elle : le motif est
     l'identité du produit, et une ligne qui grandit avec le texte donnerait
     un interligne de brouillon. */
  --read: 15px;
}

/* Réglé depuis « Mon compte » (data-size sur <html>). */
:root[data-size="small"] { --read: 13.5px; }
:root[data-size="large"] { --read: 17px; }

/* Un seul bloc sombre, piloté par `data-theme` que `theme-init.js` pose
   toujours (il résout lui-même « suivre le système »). Dupliquer ces jetons
   entre `[data-theme]` et `prefers-color-scheme` donnerait deux listes qui
   finiraient par diverger ; le choix explicite de l'utilisateur, lui, ne
   pourrait pas battre la préférence de l'OS sans un `!important` par ligne. */
:root[data-theme="dark"] {
  --bg: #15130f;
  --sheet: #1c1a15;
  --tab-off: rgba(255, 255, 255, .04);
  --ink: #f4efe6;
  --muted: rgba(244, 239, 230, .55);
  --faint: rgba(244, 239, 230, .38);
  --line: rgba(255, 255, 255, .05);
  --sheet-edge: #131110;
  --tab-empty: #100e0b;     /* en creux vers le bureau, cf. le jeton clair */
  --edge: rgba(255, 255, 255, .12);
  --edge-soft: rgba(255, 255, 255, .08);
  --accent-ink: oklch(0.72 0.16 25);
  --ghost: rgba(255, 255, 255, .045);
  --on-ink: #15130f;

  --shadow-sheet: 0 30px 80px -20px rgba(0, 0, 0, .4);
  --shadow-pop: 0 20px 60px -25px rgba(0, 0, 0, .6);

  /* Ce qui porte l'image, c'est le RAPPORT entre la couverture et l'étiquette
     (du papier clair collé sur une couverture sombre), pas des valeurs
     absolues. Une couverture éclaircie pour « se voir » sur un bureau sombre
     passait au-dessus de `--sheet` : l'étiquette devenait le plus sombre des
     deux, et l'objet se lisait comme un panneau plat. La couverture reste
     donc l'élément le plus sombre de l'écran ; ce sont son arête claire, son
     ombre portée et le filet rouge de l'étiquette qui la détachent du bureau. */
  --cover: #100e0c;
  --cover-edge: #050404;
  --cover-ink: rgba(244, 239, 230, .62);
  --cover-rim: rgba(255, 255, 255, .1);
  --label-rim: rgba(255, 255, 255, .08);
}

/* ── Socle ────────────────────────────────────────────────────────────────── */
* { box-sizing: border-box; }
html { height: 100%; }
body {
  margin: 0;
  min-height: 100%;
  color: var(--ink);
  background: var(--bg);
  font: 400 15px/1.55 'Inter Tight', system-ui, -apple-system, 'Segoe UI', sans-serif;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3 { font-family: 'Petrona', Georgia, 'Times New Roman', serif; font-weight: 700; }
button { font: inherit; color: inherit; cursor: pointer; }
input, textarea { font: inherit; color: inherit; }
a { color: var(--ink); }
svg { display: block; }

/* Un élément masqué par attribut DOIT disparaître, quelles que soient les
   classes d'affichage qu'il porte (piège [hidden] documenté dans CLAUDE.md). */
[hidden] { display: none !important; }
/* Libellé lu par les lecteurs d'écran, invisible à l'oeil : la ligne de
   l'étiquette (« Cahier de ____ ») est un champ, pas une décoration. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

/* Marque : le logo du Cahier, une étiquette de papier au nom écrit à la main
   et soulignée du rouge du filet de marge (septembre 2026). Posé en FOND et
   non en <img> : seule la variante du thème affiché est téléchargée, et la
   bascule de thème la remplace sans script. Le nom accessible est porté par
   role="img" et aria-label dans les gabarits. Il peut rétrécir (min-width: 0,
   contain) plutôt que pousser le bouton du compte hors de la barre. */
.wordmark {
  display: inline-block; flex: 0 1 auto; min-width: 0;
  height: 38px; aspect-ratio: 996 / 256;
  background: url("brand/logo.png") left center / contain no-repeat;
}
:root[data-theme="dark"] .wordmark { background-image: url("brand/logo-dark.png"); }
.kicker {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--muted);
}

/* ── Boutons ──────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 11px 20px; min-height: 42px;
  border: 1px solid var(--edge); border-radius: 8px;
  background: var(--sheet); color: var(--ink);
  font-weight: 600; font-size: 14px; line-height: 1.2;
  transition: background .14s ease, border-color .14s ease, opacity .14s ease;
}
.btn:hover { border-color: var(--ink); }
.btn-primary {
  background: var(--ink); color: var(--on-ink); border-color: var(--ink);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .08), 0 1px 2px rgba(0, 0, 0, .15);
}
.btn-primary:hover { opacity: .88; }
.btn-danger { background: transparent; border-color: var(--accent); color: var(--accent-ink); }
.btn-danger:hover { background: var(--accent); color: #fff; border-color: var(--accent); }
.btn-small { padding: 6px 14px; min-height: 34px; font-size: 13px; }
.btn-block { width: 100%; }
.btn-pill { border-radius: 999px; padding: 9px 18px; min-height: 38px; }
.btn-round {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0;
  border: 1px solid var(--edge); border-radius: 999px;
  background: transparent; color: var(--muted);
}
.btn-round:hover { color: var(--ink); border-color: var(--ink); }
.btn-round svg { width: 14px; height: 14px; }
.btn-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0;
  border: none; border-radius: 8px;
  background: transparent; color: var(--faint);
  transition: color .14s ease, background .14s ease;
}
.btn-icon:hover { color: var(--ink); background: var(--tab-off); }
.btn-icon svg { width: 17px; height: 17px; }
.linkish {
  border: none; background: none; padding: 0;
  color: var(--accent-ink); font-size: 13px; font-weight: 600;
  text-decoration: underline; text-underline-offset: 3px;
}

/* ── Champs ───────────────────────────────────────────────────────────────── */
.field { display: block; margin: 0 0 14px; }
.field > span {
  display: block; margin-bottom: 6px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
}
.field-soft { font-style: normal; letter-spacing: .06em; text-transform: none; }
.field input, .field textarea {
  width: 100%; padding: 11px 14px;
  border: 1px solid var(--edge-soft); border-radius: 10px;
  background: var(--bg); color: var(--ink);
  font-size: 15px;
}
.field textarea { resize: vertical; min-height: 120px; line-height: 1.6; }
.field input:focus, .field textarea:focus {
  outline: none; border-color: var(--ink); background: var(--sheet);
}
.field-hint { margin: -6px 0 14px; font-size: 12.5px; color: var(--muted); }
.form-error {
  margin: 4px 0 10px; padding: 9px 12px;
  border-radius: 8px; border: 1px solid var(--accent);
  color: var(--accent-ink); font-size: 13.5px;
}

/* ══ Accueil ═══════════════════════════════════════════════════════════════
   Refonte d'août 2026 : « moins IA ». L'écran précédent avait la silhouette
   de n'importe quelle page de vente générée : sur-titre en capitales, gros
   titre-slogan, sous-titre de trois lignes, trois blocs de fonctionnalités
   numérotés, carte de connexion flottante à droite. Chaque élément était
   correct, l'ensemble ne disait rien de CE cahier-là.

   Ce qui le remplace tient en une image : **le cahier posé sur le bureau**.
   Une couverture sombre et grenue, une reliure cousue sur le bord gauche,
   des intercalaires qui dépassent à droite, et une étiquette blanche collée
   dessus, légèrement de travers, qui porte le formulaire. L'identifiant
   s'écrit sur la ligne de l'étiquette, sous « Cahier de » : c'est le geste
   de la rentrée, et c'est aussi, littéralement, le champ de connexion.
   En vis-à-vis, un sommaire à points de conduite plutôt qu'une grille de
   fonctionnalités : quatre lignes, ce que fait chaque partie, rien de plus.

   Aucune image binaire : la couverture est un dégradé, le grain un
   `feTurbulence` en data-URI (CSP `img-src 'self' data:`), la reliure deux
   pseudo-éléments. Rien à télécharger, rien à optimiser. */
.landing { min-height: 100dvh; display: flex; flex-direction: column; }
.landing-top { padding: 26px clamp(20px, 4vw, 52px) 0; }
.landing-main {
  flex: 1;
  display: grid; grid-template-columns: minmax(0, 1.04fr) minmax(330px, .96fr);
  gap: clamp(30px, 5vw, 72px); align-items: center;
  padding: clamp(24px, 4vh, 54px) clamp(20px, 4vw, 52px);
  max-width: 1180px; margin: 0 auto; width: 100%;
}

.pitch-title {
  margin: 0 0 18px;
  font-size: clamp(32px, 4vw, 46px); line-height: 1.04; letter-spacing: -.03em;
}
.pitch-sub { margin: 0 0 30px; max-width: 46ch; font-size: 16px; color: var(--muted); }

/* Le sommaire, avec ses points de conduite. Un vrai composant de papier :
   le chiffre romain dans la marge, le nom, les points, ce que ça fait. */
.sommaire { list-style: none; margin: 0 0 28px; padding: 0; }
.som-line {
  display: flex; align-items: baseline; flex-wrap: wrap;
  padding: 9px 0;
  border-top: 1px solid var(--edge-soft);
}
.som-line:last-child { border-bottom: 1px solid var(--edge-soft); }
.som-num {
  flex: none; width: 34px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px; letter-spacing: .16em; color: var(--accent-ink);
}
.som-name {
  flex: none;
  font-family: 'Petrona', Georgia, serif; font-weight: 700; font-size: 17px;
  letter-spacing: -.01em;
}
/* Les points s'étirent entre le nom et sa définition. `flex: 1` sur une
   bordure pointillée : c'est tout ce que demande un point de conduite. */
.som-dots {
  flex: 1 1 24px; min-width: 24px; align-self: center;
  margin: 0 10px; height: 0;
  border-bottom: 1px dotted var(--edge);
}
.som-what { flex: none; max-width: 42ch; font-size: 13.5px; color: var(--muted); }

.pitch-note { margin: 0 0 6px; font-size: 13.5px; color: var(--muted); }
.pitch-fine {
  margin: 0;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--faint);
}

/* ── Le cahier lui-même ──────────────────────────────────────────────────── */
/* Le padding droit réserve la place des intercalaires, qui dépassent de la
   couverture : sans lui ils sortiraient de la colonne (et de l'écran). */
.auth-side { padding-right: 58px; max-width: 410px; margin-left: auto; }
.book {
  position: relative;
  /* Le format compte : un cahier est plus haut que large. Le rembourrage
     généreux (et dissymétrique, la reliure prend à gauche) laisse voir la
     couverture autour de l'étiquette, sans quoi l'étiquette EST la carte et
     l'objet disparaît. */
  padding: 44px 34px 52px 46px;
  background: linear-gradient(158deg, var(--cover), var(--cover-edge));
  border: 1px solid var(--cover-rim);
  border-radius: 3px 14px 14px 3px;
  box-shadow: var(--shadow-sheet), 0 1px 0 rgba(255, 255, 255, .07) inset;
  transform: rotate(-.5deg);
}
/* Le grain de la couverture : un bruit fractal en data-URI, en fondu
   « overlay » pour qu'il suive la couleur du dégradé au lieu de la salir. */
.book-grain {
  position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23g)'/%3E%3C/svg%3E");
  opacity: .17; mix-blend-mode: overlay;
}
/* La reliure : une bande plus sombre sur le bord gauche, et la couture. */
.book-stitch {
  position: absolute; left: 0; top: 0; bottom: 0; width: 30px;
  border-radius: 3px 0 0 3px; pointer-events: none;
  background: linear-gradient(90deg, rgba(0, 0, 0, .38), rgba(0, 0, 0, 0));
}
.book-stitch::after {
  content: ""; position: absolute; left: 15px; top: 22px; bottom: 22px;
  border-left: 1px dashed rgba(255, 255, 255, .2);
}
/* Les intercalaires, qui dépassent du bord droit. Décoratifs (aria-hidden) :
   le sommaire d'en face nomme déjà les quatre parties. */
.book-tabs {
  position: absolute; right: 0; top: 46px;
  transform: translateX(100%);
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 7px;
}
.book-tabs li {
  padding: 5px 10px 5px 9px;
  border: 1px solid var(--edge-soft); border-left: none;
  border-radius: 0 5px 5px 0;
  background: var(--tab-off); color: var(--muted);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9px; letter-spacing: .12em; text-transform: uppercase;
  white-space: nowrap;
  box-shadow: 3px 3px 12px -6px rgba(0, 0, 0, .5);
}
/* Le premier intercalaire porte l'accent : c'est la partie où l'on arrive. */
.book-tabs li:first-child { color: var(--accent-ink); background: var(--sheet); }

/* L'étiquette collée sur la couverture. La rotation inverse de celle du
   cahier : collée à la main, jamais d'équerre. */
.book-label {
  position: relative; z-index: 1;
  padding: 22px 24px 20px;
  background: var(--sheet);
  border-radius: 2px;
  box-shadow: 0 0 0 1px var(--label-rim),
              0 1px 0 rgba(0, 0, 0, .3), 0 16px 34px -18px rgba(0, 0, 0, .7);
  transform: rotate(.65deg);
}
/* Le filet rouge en tête de l'étiquette, comme sur celles d'écolier. */
.book-label::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 3px;
  background: var(--accent); border-radius: 2px 2px 0 0;
}
.auth-owner {
  margin: 0 0 10px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; letter-spacing: .18em; text-transform: uppercase; color: var(--faint);
}

/* Sur l'étiquette, TOUS les champs sont des lignes à remplir : une boîte à
   coins arrondis sur fond gris à côté d'une ligne d'écriture, ce sont deux
   vocabulaires dans le même cadre. Deux classes battent le `.field input` du
   socle (une classe + un élément), et le `:focus` suit la même arithmétique. */
.book-label .field input {
  padding: 7px 2px 8px;
  border: none; border-bottom: 1px solid var(--edge); border-radius: 0;
  background: transparent;
}
.book-label .field input:focus {
  border-bottom-color: var(--accent); background: transparent;
}
.book-label .field { margin-bottom: 16px; }

/* La ligne du nom, elle, s'écrit en gros : c'est le titre du cahier avant
   d'être un identifiant. Déclarée APRÈS la règle ci-dessus, à spécificité
   égale, donc c'est l'ordre du fichier qui tranche (le focus compris). */
.book-label .field-name { margin-bottom: 20px; }
.book-label .field-name input {
  padding: 2px 2px 7px;
  font-family: 'Petrona', Georgia, serif; font-weight: 700; font-size: 23px;
  letter-spacing: -.02em;
}
.book-label .field-name input::placeholder {
  font-family: 'Inter Tight', system-ui, sans-serif; font-weight: 400;
  font-size: 15px; letter-spacing: 0; color: var(--faint);
}
.auth-form .btn-block { margin-top: 20px; }

/* Le bascule connexion / inscription passe SOUS le formulaire : la porte
   normale est la connexion, et quand l'inscription est fermée (le cas
   courant) le JS masque la rangée entière, une rangée d'un seul onglet
   n'étant qu'un titre déguisé. */
.auth-tabs {
  display: flex; gap: 16px; justify-content: center;
  margin: 16px -4px 0; padding-top: 13px;
  border-top: 1px dotted var(--edge);
}
.auth-tab {
  padding: 2px 0 3px;
  background: none; border: none; border-bottom: 2px solid transparent;
  font-size: 13px; font-weight: 600; color: var(--faint);
}
.auth-tab.is-active { color: var(--ink); border-bottom-color: var(--accent); }
.auth-hint {
  margin: 16px 0 0; text-align: center; font-size: 12.5px; color: var(--faint);
}

.landing-foot {
  display: flex; flex-wrap: wrap; gap: 8px 20px;
  align-items: center; justify-content: space-between;
  padding: 18px clamp(20px, 4vw, 52px) calc(18px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--edge-soft);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--faint);
}
.landing-foot nav { display: flex; gap: 18px; }
.landing-foot a { color: var(--faint); text-decoration: none; }
.landing-foot a:hover { color: var(--ink); }

/* ══ Application ═══════════════════════════════════════════════════════════ */
.app {
  min-height: 100dvh; display: flex; flex-direction: column;
  max-width: 1240px; margin: 0 auto; width: 100%;
}

.topbar {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  /* Installée sur l'écran d'accueil, la page occupe TOUT l'écran (viewport-fit
     = cover) : sans zone sûre en haut, la barre passe sous l'encoche et sous
     l'heure. `env()` vaut 0 dans un navigateur classique : coût nul ailleurs. */
  padding: calc(18px + env(safe-area-inset-top)) clamp(18px, 3vw, 36px) 0;
}

.user-zone { position: relative; }
.user-btn {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 5px 14px 5px 5px; min-height: 38px;
  border: 1px solid var(--edge); border-radius: 999px;
  background: transparent;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; letter-spacing: .2em; text-transform: uppercase; color: var(--muted);
}
.user-btn:hover { color: var(--ink); border-color: var(--ink); }
.user-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: 999px; flex: none;
  background: var(--ink); color: var(--on-ink);
  font-size: 11px; letter-spacing: 0;
}
.user-name { max-width: 12ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-pop {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 40;
  min-width: 210px; padding: 6px;
  background: var(--sheet); border: 1px solid var(--edge); border-radius: 12px;
  box-shadow: var(--shadow-pop);
}
.user-pop button {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 10px 12px;
  border: none; border-radius: 8px; background: transparent;
  font-size: 14px; text-align: left;
}
.user-pop button:hover { background: var(--tab-off); }
.user-pop svg { width: 17px; height: 17px; color: var(--faint); }

/* Onglets en languettes : l'actif est plein et plat en bas, soudé à la page
   qui commence dessous. C'est ce qui donne l'intercalaire de cahier. */
.section-tabs {
  display: flex; gap: 6px;
  padding: 22px clamp(18px, 3vw, 36px) 0 clamp(18px, 3vw, 36px);
  position: relative; z-index: 2;
}
/* Le filet qui ferme la rangée : il court sur toute la largeur, sous les
   languettes, et s'arrête au ras de l'onglet actif (dont le fond, plein et
   posé au-dessus, l'interrompt). Sans lui les onglets flottaient au-dessus du
   vide dès que la page ne commençait pas juste dessous, comme sur l'écran des
   pages libres où la feuille est décalée par le rail de gauche. */
.section-tabs::after {
  content: ""; position: absolute; z-index: -1;
  left: 0; right: 0; bottom: 0;
  border-bottom: 1px solid var(--edge);
}
.stab {
  padding: 10px 22px 13px;
  border: 1px solid var(--edge-soft); border-bottom: none;
  border-radius: 10px 10px 0 0;
  background: var(--tab-off); color: var(--muted);
  font-size: 14px; font-weight: 500; white-space: nowrap;
  position: relative; top: 1px;
  transition: background .14s ease, color .14s ease;
}
.stab-short { display: none; }
.stab:hover { color: var(--ink); }
.stab.is-active {
  background: var(--sheet); color: var(--ink); font-weight: 600;
  border-color: var(--edge);
}

.pw-banner {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 16px clamp(18px, 3vw, 36px) 0;
  padding: 12px 16px;
  background: var(--sheet);
  border: 1px solid var(--edge); border-left: 3px solid var(--accent);
  border-radius: 10px; font-size: 14px; color: var(--ink);
}
.pw-ico { display: inline-flex; flex: none; color: var(--accent-ink); }
.pw-ico svg { width: 18px; height: 18px; }
.pw-banner .btn { margin-left: auto; }

.board {
  flex: 1; width: 100%;
  padding: 0 clamp(18px, 3vw, 36px) calc(40px + env(safe-area-inset-bottom));
  display: flex; flex-direction: column;
}
.view { flex: 1; display: flex; flex-direction: column; min-height: 0; }
/* `stretch` (le défaut) et non `start` : la page réglée doit descendre jusqu'au
   bas de l'écran comme sur les deux autres écrans, pas s'arrêter à la hauteur
   de son texte. Le rail, lui, empile ses items en haut de sa colonne. */
.view-pages { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 20px; }

.toolrow { display: flex; align-items: center; gap: 12px; padding: 20px 0 0; flex-wrap: wrap; }
.search {
  flex: 1; min-width: 200px;
  display: flex; align-items: center; gap: 10px;
  padding: 0 16px;
  background: var(--sheet); border: 1px solid var(--edge-soft); border-radius: 14px;
}
.search-ico { display: inline-flex; color: var(--faint); flex: none; }
.search-ico svg { width: 14px; height: 14px; }
.search input {
  flex: 1; min-width: 0; padding: 11px 0; min-height: 42px;
  border: none; background: transparent; font-size: 14px;
}
.search input:focus { outline: none; }
.search:focus-within { border-color: var(--ink); }
.btn-new-short { display: none; }
.btn-new-short svg { width: 16px; height: 16px; }

.empty { margin: 0; color: var(--faint); font-size: 14px; }

/* ── La page réglée : le motif unique des trois écrans ───────────────────── */
.sheet-wrap { flex: 1; display: flex; align-items: stretch; min-height: 0; margin-top: 16px; }
.sheet {
  flex: 1; min-width: 0; position: relative; overflow: hidden;
  min-height: 420px;
  background: var(--sheet);
  border: 1px solid var(--edge);
  /* coin haut-gauche carré : la page est soudée à l'onglet actif au-dessus */
  border-radius: 0 16px 16px 16px;
  /* Ce qui distingue un cahier d'une carte, c'est l'ÉPAISSEUR : on voit la
     tranche des pages du dessous dépasser en bas. Deux feuilles suffisent,
     décalées vers le bas seulement (vers la droite, elles entreraient en
     conflit avec la tranche A-Z du répertoire). */
  box-shadow:
    0 3px 0 -1px var(--sheet-edge), 0 4px 0 -1px var(--edge-soft),
    0 8px 0 -3px var(--sheet-edge), 0 9px 0 -3px var(--edge-soft),
    var(--shadow-sheet);
  display: flex; flex-direction: column;
}
/* Deux couches sur la page, dans cet ordre : la PERFORATION de la reliure
   (une œillet toutes les quatre lignes, donc calée sur le motif : une
   perforation qui flotterait entre deux lignes se lirait comme une pastille
   décorative) et les LIGNES réglées. Le trou laisse voir le bureau derrière,
   c'est ce qui le fait lire comme un trou et non comme un rond gris. */
.sheet-rules {
  position: absolute; inset: 0; pointer-events: none;
  background-image:
    radial-gradient(circle 5.5px at 26px calc(var(--lh) * 2),
      var(--bg) 0 4.4px, var(--edge-soft) 4.4px 5.5px, transparent 5.5px),
    repeating-linear-gradient(to bottom,
      transparent 0 calc(var(--lh) - 1px), var(--line) calc(var(--lh) - 1px) var(--lh));
  background-size: 52px calc(var(--lh) * 4), auto;
  background-repeat: repeat-y, repeat;
}
/* Le grain du papier. Même recette que la couverture de l'accueil, à une
   opacité qui ne doit JAMAIS se voir comme une texture : elle casse le côté
   « aplat d'écran » sans se remarquer. */
/* En pseudo-élément et non en balise : il faudrait sinon le poser dans les
   six pages qui portent une `.sheet`, et la septième l'oublierait. Peint
   après `.sheet-rules` (ordre du DOM) mais sous `.sheet-body`, qui monte en
   `z-index: 1` : le grain passe sur les lignes, jamais sur le texte. */
.sheet::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23p)'/%3E%3C/svg%3E");
  opacity: .1; mix-blend-mode: multiply;
}
:root[data-theme="dark"] .sheet::after { opacity: .16; mix-blend-mode: overlay; }
.sheet-margin {
  position: absolute; top: 0; bottom: 0; left: var(--margin-x); width: 1px;
  background: var(--rule-red); pointer-events: none;
}
.sheet-ghost {
  position: absolute; top: 6px; right: 46px; pointer-events: none;
  font-family: 'Petrona', Georgia, serif; font-weight: 700;
  font-size: 240px; line-height: 1; color: var(--ghost);
  user-select: none;
}
.sheet-body {
  position: relative; z-index: 1; flex: 1; min-height: 0;
  padding: 24px 40px 28px var(--text-x);
  display: flex; flex-direction: column;
}

/* ══ Répertoire ════════════════════════════════════════════════════════════ */
.rep-filter {
  display: flex; align-items: center; gap: 14px;
  margin: 0 0 10px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--faint);
}
.rep-filter strong { color: var(--accent-ink); }

/* Les notes ne sont plus des cartes flottantes : ce sont des entrées posées
   sur la page, l'initiale vivant dans la marge comme un numéro de ligne. */
.notes-list { list-style: none; margin: 0; padding: 0; }
.note-row {
  display: flex; gap: 16px; align-items: flex-start;
  padding: 10px 0 14px; margin-left: -34px;
  border-bottom: 1px solid var(--edge-soft);
  cursor: pointer;
}
.note-row:first-child { padding-top: 2px; }
.note-row:hover .note-title { color: var(--accent-ink); }
.note-letter {
  flex: none; width: 22px; padding-top: 2px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px; font-weight: 700; color: var(--faint); text-align: right;
}
.note-main { flex: 1; min-width: 0; display: block; }
.note-head { display: flex; align-items: baseline; gap: 12px; }
.note-title {
  font-family: 'Petrona', Georgia, serif; font-weight: 700; font-size: 17px;
  letter-spacing: -.01em; overflow-wrap: anywhere;
  transition: color .14s ease;
}
.note-date {
  margin-left: auto; flex: none;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; color: var(--faint);
}
.note-excerpt {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
  margin-top: 3px; font-size: calc(var(--read) - 1.5px);
  color: var(--muted); overflow-wrap: anywhere;
}
.note-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.note-chips:empty { display: none; }
.chip {
  padding: 2px 9px 3px;
  border: 1px solid var(--edge-soft); border-radius: 999px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
  overflow-wrap: anywhere;
}

/* La page et sa tranche sont un seul objet : le bord droit de la page perd
   son arrondi (les languettes s'y greffent), ce sont la première et la
   dernière d'entre elles qui portent le coin. `position: relative` sert de
   repère à la loupe du pouce. */
.view-repertoire .sheet-wrap { position: relative; }
.view-repertoire .sheet { border-radius: 0 0 0 16px; }

/* ══ La tranche A-Z ═══════════════════════════════════════════════════════
   C'est CE qui fait un répertoire plutôt qu'une liste : les onglets découpés
   dans le bord de la page, qu'on attrape au pouce. Trois choses les font
   lire comme du papier découpé et non comme une rangée de boutons :

   1. ils sont SOUDÉS à la page (aucun écart, pas de bord gauche, et le coin
      haut-gauche de la page reste carré de ce côté) ;
   2. ils PARTAGENT leur filet (`margin-top: -1px`), comme des découpes dans
      une même tranche, au lieu d'être 27 pastilles espacées ;
   3. une languette qui porte des notes est de la COULEUR DE LA PAGE : elle
      est taillée dedans. Une languette vide reste en creux, dans le ton du
      bureau, et n'appelle pas le doigt.

   Les 27 languettes se partagent la hauteur (`flex: 1 1 0`) au lieu d'être
   espacées au petit bonheur : c'est une tranche, pas une liste. ═══════════ */
.alpha-rail {
  flex: none; width: 34px;
  display: flex; flex-direction: column;
  /* La tranche suit la lecture au lieu de s'étirer sur toute la hauteur du
     texte : une page de vingt notes fait deux écrans, et des languettes
     réparties sur cette hauteur-là mesurent 130 px pièce (mesuré) : ce ne
     sont plus des onglets, ce sont des pavés, et les dernières lettres sont
     hors de vue. Bornée à la page (`max-height: 100%`) pour ne jamais
     dépasser en bas quand il y a peu de notes. */
  align-self: flex-start; position: sticky; top: 14px;
  /* Le `min()` borne la languette à ~41 px : sur un grand écran, 27 onglets
     répartis sur 1600 px en font des pavés de 59 px (mesuré). */
  height: min(calc(100dvh - 28px), 1120px); max-height: 100%;
  overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none;
  /* Le pouce PARCOURT la tranche : sans cette ligne le navigateur prend le
     glissé vertical pour un défilement de page et la lettre ne suit pas. */
  touch-action: none;
  /* La languette active déborde dans cette réserve (cf. `.is-active`). */
  padding-right: 7px;
}
.alpha-rail::-webkit-scrollbar { display: none; }
.alpha-letter {
  flex: 1 1 0; min-height: 18px;
  display: flex; align-items: center; justify-content: center;
  padding: 0 1px 0 2px; margin-top: -1px;
  /* `--edge` et non `--edge-soft` : au filet le plus léger, les 27 languettes
     se lisaient comme une seule colonne. C'est la DÉCOUPE entre deux onglets
     qui fait la tranche. */
  border: 1px solid var(--edge); border-left: none;
  border-radius: 0 6px 6px 0;
  background: var(--tab-empty); color: var(--faint);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px; font-weight: 700; line-height: 1;
  /* Seule la languette qu'on TIRE s'anime : sous le pouce qui parcourt la
     tranche, un fondu de couleur laisse une traînée de lettres à moitié
     allumées et on ne sait plus laquelle est ouverte. */
  transition: margin-right .12s ease;
}
.alpha-letter:first-child { margin-top: 0; border-radius: 0 15px 6px 0; }
.alpha-letter:last-child { border-radius: 0 6px 15px 0; }
/* Taillée dans la page : même papier, encre pleine. */
.alpha-letter.has-notes { background: var(--sheet); color: var(--ink); }
.alpha-letter:hover { color: var(--ink); margin-right: -4px; }
.alpha-letter.is-active {
  background: var(--accent); border-color: var(--accent); color: #fff;
  margin-right: -7px; z-index: 1;
}
.alpha-letter:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; z-index: 2; }

/* La loupe du pouce : sur téléphone, la languette sous le doigt est cachée
   par le doigt lui-même. Le même geste que le répertoire d'un téléphone. */
.alpha-bubble {
  position: fixed; z-index: 4;
  display: grid; place-items: center;
  width: 52px; height: 52px; margin-top: -26px;
  border-radius: 12px;
  background: var(--ink); color: var(--on-ink);
  font-family: 'Petrona', Georgia, serif; font-weight: 700; font-size: 26px;
  box-shadow: var(--shadow-pop);
  pointer-events: none;
}
.alpha-bubble[hidden] { display: none; }

/* ══ Pages libres ══════════════════════════════════════════════════════════ */
.pages-side { display: flex; flex-direction: column; gap: 12px; padding-top: 20px; }
.pages-new { border-radius: 8px; }
.pages-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.page-item {
  display: flex; align-items: baseline; gap: 10px;
  width: 100%; padding: 11px 14px; min-height: 44px;
  border: 1px solid var(--edge-soft); border-left: 3px solid transparent;
  border-radius: 10px;
  background: var(--sheet); text-align: left;
  transition: border-color .14s ease;
}
.page-item:hover { border-color: var(--edge); border-left-color: var(--edge); }
.page-item.is-active { border-left-color: var(--accent); border-color: var(--edge); }
.page-item-num {
  flex: none;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; color: var(--faint);
}
.page-item.is-active .page-item-num { color: var(--accent-ink); }
.page-item-main { display: flex; flex-direction: column; min-width: 0; gap: 2px; }
.page-item-title {
  font-weight: 600; font-size: 14px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.page-item-date {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; color: var(--faint);
}

/* Le rail et la page démarrent sur la même ligne (le rail a son padding-top). */
.view-pages .sheet-wrap { margin-top: 20px; }
.view-pages .sheet { border-radius: 16px; }
/* Le corps de la page s'écrit SUR les lignes : tout ce qui le précède doit
   donc mesurer un multiple exact du pas du motif. Le bandeau de titre vaut
   une ligne, et le padding haut de la feuille en vaut une autre (redéclaré
   juste dessous) : le texte démarre pile sur la troisième. */
.view-pages .sheet-body { padding-top: var(--lh); }
.page-head {
  display: flex; align-items: center; gap: 12px;
  height: var(--lh); margin: 0;
}
.page-title {
  flex: 1; min-width: 0; padding: 0;
  border: none; background: transparent;
  font-family: 'Petrona', Georgia, serif; font-weight: 700; font-size: 27px;
  letter-spacing: -.02em; line-height: var(--lh);
}
.page-title:focus { outline: none; }
.page-title::placeholder { color: var(--faint); }
.save-state {
  flex: none;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; letter-spacing: .1em; color: var(--faint);
}
/* La corbeille ne doit pas faire grandir le bandeau au-delà d'une ligne :
   centrée, elle peut déborder sans se voir (elle n'a pas de fond au repos). */
.page-head .btn-icon { width: 28px; height: 28px; }
/* Le corps s'aligne sur les lignes réglées : l'interligne EST le pas du motif. */
.page-content {
  flex: 1; width: 100%; min-height: 320px;
  border: none; background: transparent; resize: none;
  font-size: var(--read); line-height: var(--lh); padding: 0;
  color: var(--ink);
}
.page-content:focus { outline: none; }
.page-content::placeholder { color: var(--faint); }
.sheet-blank .sheet-body { justify-content: center; }

/* ══ Agenda ════════════════════════════════════════════════════════════════ */
/* Plus de grille de cartes (ça faisait tableau de bord) : la semaine est une
   liste posée sur la même page réglée que les deux autres écrans. Chaque
   ligne occupe exactement un pas du motif. */
.week-row { gap: 18px; }
.week-nav { display: flex; align-items: center; gap: 8px; }
.week-label {
  margin: 0; font-size: 23px; letter-spacing: -.02em;
}
.week-label::first-letter { text-transform: uppercase; }

#agendaDays { gap: 0; min-width: 0; }
/* `min-width: 0` : la ligne « Noter pour ce jour » porte un <input> sans
   `size`, qui revendique vingt caractères. Avant la refonte, cette largeur
   mini remontait jusqu'à la piste de grille du week-end et faisait déborder
   l'agenda de 38 px sur un écran de 320 px. La structure a changé (une liste
   au lieu de cartes en grille), la ceinture reste : c'est le CONTENEUR qui
   doit accepter de rétrécir, l'input se comprime ensuite par flex-shrink. */
.day { display: block; min-width: 0; }
.day-head {
  height: var(--lh); display: flex; align-items: baseline; gap: 10px;
}
.day-name {
  margin: 0; font-size: 15px; font-weight: 700; letter-spacing: -.01em;
}
.day-name::first-letter { text-transform: uppercase; }
.day-date {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; color: var(--faint);
}
.day-dot { width: 6px; height: 6px; border-radius: 999px; background: var(--accent); }
.day.is-today .day-date { color: var(--accent-ink); }

.day-list { list-style: none; margin: 0; padding: 0; }
.entry {
  height: var(--lh); display: flex; align-items: center; gap: 8px;
}
.entry-check {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 10px; cursor: pointer;
  font-size: 13.5px;
}
.entry-check input { position: absolute; opacity: 0; width: 0; height: 0; }
.entry-box {
  flex: none;
  width: 15px; height: 15px; border-radius: 4px;
  border: 1.5px solid var(--edge); background: transparent; color: transparent;
  display: flex; align-items: center; justify-content: center;
  transition: background .14s ease, border-color .14s ease;
}
.entry-box svg { width: 9px; height: 9px; }
.entry-check input:checked + .entry-box {
  background: var(--ok); border-color: var(--ok); color: #fff;
}
.entry-check input:focus-visible + .entry-box { outline: 2px solid var(--accent); outline-offset: 2px; }
.entry-text {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.entry.is-done .entry-text { text-decoration: line-through; color: var(--faint); }
.entry-del { width: 26px; height: 26px; flex: none; opacity: 0; }
.entry-del svg { width: 13px; height: 13px; }
.entry:hover .entry-del, .entry-del:focus-visible { opacity: 1; }

.day-add { height: var(--lh); display: flex; align-items: center; gap: 8px; min-width: 0; }
.day-add input {
  flex: 1; min-width: 0; padding: 0; height: 100%;
  border: none; background: transparent;
  font-size: 13.5px; color: var(--ink);
}
.day-add input::placeholder { color: var(--faint); }
.day-add input:focus { outline: none; }
.day-add-btn { width: 26px; height: 26px; flex: none; }
.day-add-btn svg { width: 14px; height: 14px; }

/* ══ Partages ══════════════════════════════════════════════════════════════
   La quatrième partie du cahier, posée sur la MÊME page réglée que les trois
   autres : deux blocs (ce qu'on vous prête, ce que vous prêtez), et des
   entrées qui reprennent exactement la ligne d'une note du répertoire, avec
   l'initiale dans la marge en guise de numéro de ligne. Aucun composant
   nouveau, aucune couleur nouvelle : c'est le même cahier. */
.share-block + .share-block { margin-top: calc(var(--lh) * 1.5); }
.share-head {
  height: var(--lh); margin: 0;
  display: flex; align-items: center;
  font-size: 15px; letter-spacing: -.01em;
}
.share-list { list-style: none; margin: 0; padding: 0; }
.share-row {
  display: flex; gap: 16px; align-items: flex-start;
  padding: 10px 0 13px; margin-left: -34px;
  border-bottom: 1px solid var(--edge-soft);
}
.share-row.is-openable { cursor: pointer; }
.share-row.is-openable:hover .share-title { color: var(--accent-ink); }
.share-mark {
  flex: none; width: 22px; padding-top: 2px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px; font-weight: 700; color: var(--faint); text-align: right;
}
.share-main { flex: 1; min-width: 0; display: block; }
.share-line { display: flex; align-items: baseline; gap: 12px; }
.share-title {
  font-family: 'Petrona', Georgia, serif; font-weight: 700; font-size: 16px;
  letter-spacing: -.01em; overflow-wrap: anywhere;
  transition: color .14s ease;
}
/* Le droit accordé se lit d'un coup d'oeil, à droite de la ligne : c'est la
   première question qu'on se pose devant une pochette. */
.share-right {
  margin-left: auto; flex: none;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9px; letter-spacing: .1em; text-transform: uppercase;
  /* `--muted` et non `--faint` : c'est l'information principale de la ligne
     (mesuré : 2,7:1 en clair avec `--faint`, 5,4:1 avec celui-ci). Le token
     le plus pâle est réservé à ce qui accompagne, pas à ce qu'on vient
     lire. */
  color: var(--muted);
  border: 1px solid var(--edge-soft); border-radius: 999px;
  padding: 2px 8px 3px;
}
.share-by {
  display: block; margin-top: 4px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; letter-spacing: .04em; color: var(--muted);
  overflow-wrap: anywhere;
}
.share-excerpt {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
  margin-top: 4px; font-size: calc(var(--read) - 1.5px); color: var(--muted);
  overflow-wrap: anywhere;
}
.share-actions { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 8px; }
.share-foot {
  /* Une consigne se lit : même arbitrage que `.share-right` et que
     `.field-hint`, qui porte déjà `--muted`. */
  margin: 14px 0 0;
  font-size: 12.5px; color: var(--muted);
}

/* La liste compacte de la modale : mêmes lignes, sans la marge du cahier. */
.share-list-compact .share-row { margin-left: 0; gap: 12px; padding: 9px 0 11px; }
.share-list-compact .share-title { font-size: 15px; }

/* ── La modale « partager » ─────────────────────────────────────────────── */
.share-what { margin: 0 0 16px; font-size: 14px; color: var(--muted); }
.share-what strong { color: var(--ink); font-weight: 600; }
/* Le segmenté « avec un ami / par un lien » porte la décision principale :
   il prend toute la largeur au lieu de se blottir à droite comme ceux des
   réglages. */
.seg-wide { margin-bottom: 18px; }
.seg-wide .seg-btn { flex: 1; }

/* Cases à cocher explicites : ce qui part avec l'élément se décide ici, donc
   chaque case porte sa conséquence en toutes lettres sous son intitulé. */
.opt {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 11px 0; cursor: pointer;
}
.opt + .opt { border-top: 1px solid var(--edge-soft); }
.opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.opt-box {
  flex: none; margin-top: 2px;
  width: 18px; height: 18px; border-radius: 5px;
  border: 1.5px solid var(--edge); background: transparent; color: transparent;
  display: flex; align-items: center; justify-content: center;
  transition: background .14s ease, border-color .14s ease;
}
.opt-box svg { width: 11px; height: 11px; }
.opt input:checked + .opt-box {
  background: var(--ink); border-color: var(--ink); color: var(--on-ink);
}
.opt input:focus-visible + .opt-box { outline: 2px solid var(--accent); outline-offset: 2px; }
.opt-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.opt-name { font-size: 14px; font-weight: 600; }
.opt-note { font-size: 12.5px; color: var(--muted); }
.share-current { margin-top: 22px; }

/* ── La lecture d'un élément reçu ───────────────────────────────────────── */
/* `pre-wrap` : les retours à la ligne de l'auteur sont conservés sans qu'on
   ait à fabriquer des <br> (et le texte reste posé par textContent). */
.reader-text {
  white-space: pre-wrap; overflow-wrap: anywhere;
  margin: 14px 0 4px; font-size: var(--read); line-height: 1.65;
}
.reader-edit {
  width: 100%; min-height: 240px; margin: 14px 0 4px;
  padding: 12px 14px;
  border: 1px solid var(--edge-soft); border-radius: 10px;
  background: var(--bg); color: var(--ink);
  font-size: var(--read); line-height: 1.65; resize: vertical;
}
.reader-edit:focus { outline: none; border-color: var(--ink); background: var(--sheet); }

/* Le compteur de la languette « Partages » : ce qui attend dans la pochette. */
.stab-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 17px; height: 17px; margin-left: 7px; padding: 0 5px;
  border-radius: 999px; background: var(--accent); color: #fff;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9.5px; font-weight: 700; line-height: 1;
}

/* ══ Modales ═══════════════════════════════════════════════════════════════ */
.modal {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  background: rgba(10, 10, 10, .45);
  backdrop-filter: blur(3px);
}
.modal-card {
  width: 100%; max-width: 580px; max-height: min(88dvh, 720px);
  display: flex; flex-direction: column;
  background: var(--sheet);
  border: 1px solid var(--edge); border-radius: 16px;
  box-shadow: var(--shadow-pop);
}
.modal-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--edge-soft);
}
.modal-head h2 { margin: 0; font-size: 21px; letter-spacing: -.02em; }
.modal-body { padding: 18px 20px 20px; overflow-y: auto; overscroll-behavior: contain; }
/* `wrap` : la modale d'une note existante porte quatre boutons (Supprimer,
   Partager, Annuler, Enregistrer). Sur 320 px ils ne tiennent pas sur une
   ligne, et sans retour à la ligne c'est « Enregistrer » qui sort de la
   carte. Le `spacer` accepte de disparaître pour laisser la place. */
.modal-actions {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-top: 8px;
}

/* La pastille « Admin » du Portfolio est injectée sur toute page HTML, en
   `position: fixed` bas-gauche et au z-index maximal (2147483645) : sur
   téléphone la modale s'ancre en bas de l'écran et la pastille se posait PILE
   sur « Annuler » / « Supprimer » (mesuré : le clic était intercepté). Elle
   s'efface le temps de la modale et revient à la fermeture ; elle ne perd rien
   à s'absenter, elle ne fait qu'annoncer un état. */
body.has-modal #mn-admin-pill { display: none; }
.modal-actions .spacer { flex: 1 1 0; min-width: 0; }
.account-line { margin: 0 0 18px; font-size: 14px; color: var(--muted); }
.account-line strong { color: var(--ink); font-weight: 600; }

/* ── Réglages de « Mon compte » ───────────────────────────────────────────
   Ils s'appliquent au clic, sans bouton de validation : ce sont des
   préférences d'affichage locales à ce navigateur (thème, écran d'ouverture,
   taille du texte), pas des données à envoyer au serveur. Le formulaire de
   mot de passe garde le sien, lui, parce qu'il touche au compte. */
.settings { margin: 0 0 22px; }
.settings-title {
  margin: 0 0 12px; padding-bottom: 8px;
  border-bottom: 1px solid var(--edge-soft);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: var(--faint);
}
.setting {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
  padding: 11px 0;
}
.setting + .setting { border-top: 1px solid var(--edge-soft); }
.setting-label { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.setting-name { font-size: 14px; font-weight: 600; }
.setting-note { font-size: 12.5px; color: var(--faint); }
.setting-note:empty { display: none; }

/* Segmenté : le même vocabulaire que la barre des trois parties au téléphone. */
.seg {
  display: flex; gap: 2px; flex: none;
  padding: 3px; border-radius: 9px; background: var(--tab-off);
}
.seg-btn {
  padding: 7px 13px; min-height: 34px;
  border: none; border-radius: 7px; background: transparent;
  font-size: 13px; color: var(--muted); white-space: nowrap;
  transition: background .14s ease, color .14s ease;
}
.seg-btn:hover { color: var(--ink); }
.seg-btn.is-active {
  background: var(--sheet); color: var(--ink); font-weight: 600;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .08);
}

/* ══ La page d'un lien de partage ══════════════════════════════════════════
   `share.html` : autoporteuse, hors session, en lecture seule. Elle réutilise
   la page réglée de l'app, sans sa coquille : celui qui reçoit un lien n'a
   pas de cahier ici, lui montrer une barre d'onglets serait lui montrer des
   portes fermées. Un bandeau dit ce qu'il regarde et d'où ça vient. */
.shared { min-height: 100dvh; display: flex; flex-direction: column; }
.shared-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap;
  padding: calc(22px + env(safe-area-inset-top)) clamp(18px, 4vw, 44px) 0;
  max-width: 900px; margin: 0 auto; width: 100%;
}
.shared-flag {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 14px;
  border: 1px solid var(--edge-soft); border-radius: 999px;
  background: var(--sheet);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted);
}
.shared-flag-ico { display: inline-flex; flex: none; color: var(--accent-ink); }
/* Sans taille explicite, un <svg> à `viewBox` seul prend TOUTE la place
   disponible : mesuré au navigateur, la chaîne du bandeau occupait un écran
   entier. Toute icône posée en SVG inline doit porter sa taille. */
.shared-flag-ico svg { width: 13px; height: 13px; }

.shared-main {
  flex: 1; display: flex;
  padding: 20px clamp(18px, 4vw, 44px) 34px;
  max-width: 900px; margin: 0 auto; width: 100%;
}
.shared-main .sheet-wrap { margin-top: 0; }
.shared-main .sheet { border-radius: 16px; }
.shared-by { margin: 0 0 8px; font-size: 13px; color: var(--muted); }
.shared-by strong { color: var(--ink); font-weight: 600; }
.shared-title {
  margin: 0 0 10px; font-size: clamp(23px, 3.2vw, 31px); letter-spacing: -.025em;
  overflow-wrap: anywhere;
}
.shared-content {
  white-space: pre-wrap; overflow-wrap: anywhere;
  margin-top: 16px; font-size: var(--read); line-height: 1.65;
}
.shared-state { margin: 0; color: var(--faint); font-size: 14px; }
/* Le pied reprend celui de l'accueil, recentré sur la même colonne. */
.shared .landing-foot { max-width: 900px; margin: 0 auto; width: 100%; }

/* ══ Toasts ════════════════════════════════════════════════════════════════ */
.toasts {
  position: fixed; left: 50%; bottom: calc(20px + env(safe-area-inset-bottom));
  transform: translateX(-50%); z-index: 200;
  display: flex; flex-direction: column; gap: 8px; align-items: center;
  pointer-events: none;
}
.toast {
  padding: 10px 18px;
  background: var(--ink); color: var(--on-ink);
  border-radius: 999px; font-size: 13.5px; font-weight: 500;
  box-shadow: var(--shadow-pop);
  animation: toast-in .18s ease;
}
.toast.is-error { background: var(--accent); color: #fff; }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } }

/* ══ Responsive ════════════════════════════════════════════════════════════ */
@media (max-width: 980px) {
  .landing-main { grid-template-columns: 1fr; align-items: start; }
  /* Empilée, la colonne du cahier se rangeait sous la présentation, posant le
     champ « Identifiant » à 1246 px sur un écran de 844 : une page et demie de
     défilement avant de pouvoir entrer, à chaque ouverture. Or c'est un outil
     de tous les jours, servi par lien et sans inscription publique : qui
     arrive ici vient ouvrir SON cahier, pas lire le pitch. */
  .auth-side { max-width: 460px; order: -1; margin-left: 0; }
}

@media (max-width: 700px) {
  /* Le sommaire ne tient plus sur une ligne : le nom garde sa ligne, sa
     définition passe dessous, alignée sur la marge du chiffre romain. Les
     points de conduite n'ont plus rien à relier, ils partent. */
  .som-dots { display: none; }
  /* `flex: 1 0 100%` + une marge gauche fait 100 % PLUS 34 px, donc un
     débordement de 34 px sur tout téléphone (mesuré : 404 px de contenu sur
     un écran de 390). C'est `flex-shrink: 1` avec `min-width: 0` qui autorise
     l'élément à redescendre sous sa base : la marge est alors reprise sur
     lui, pas sur l'écran. */
  .som-what {
    flex: 1 1 100%; min-width: 0; margin: 3px 0 0 34px; max-width: none;
  }
  .som-line { padding: 11px 0; }

  /* Le cahier se resserre, et les intercalaires deviennent de simples
     languettes sans texte : sur 390 px, écrire dessus coûterait à l'étiquette
     (donc au formulaire) la moitié de sa largeur. Ils sont décoratifs, le
     sommaire porte l'information. */
  .auth-side { padding-right: 22px; }
  .book { padding: 24px 18px 26px 34px; }
  .book-stitch { width: 24px; }
  .book-stitch::after { left: 12px; }
  /* Posées plus bas que le haut de l'étiquette : au ras, la languette
     accentuée (fond blanc) se confondait avec le papier de l'étiquette. */
  .book-tabs { top: 92px; gap: 6px; }
  .book-tabs li {
    width: 16px; height: 26px; padding: 0; font-size: 0;
  }
  /* Sans texte, seul le fond parle : l'accent passe du texte au fond. */
  .book-tabs li:first-child { background: var(--accent); border-color: var(--accent); }
  .book-label { padding: 20px 18px 18px; }
}

@media (max-width: 880px) {
  :root { --lh: 28px; --margin-x: 34px; --text-x: 46px; }

  /* Téléphone : la barre suit le défilement. Une semaine chargée fait
     plusieurs milliers de pixels ; sans ça, changer de partie du cahier
     oblige à remonter tout en haut d'abord. */
  .topbar {
    position: sticky; top: 0; z-index: 30;
    background: var(--bg);
    padding-top: calc(14px + env(safe-area-inset-top)); padding-bottom: 8px;
  }
  .wordmark { height: 32px; }
  .user-name { display: none; }
  .user-btn { padding: 4px; border: none; }

  /* Les languettes ne tiennent pas en largeur : segmented control. */
  .section-tabs {
    gap: 2px;
    background: var(--tab-off); border-radius: 10px; padding: 3px;
    margin: 16px clamp(18px, 3vw, 36px) 0;
  }
  /* Le filet d'assise ne sert qu'aux languettes : le segmented control est
     autoportant (il a son propre fond), et la ligne dépassait de ses coins
     arrondis d'un bord à l'autre de l'écran. */
  .section-tabs::after { content: none; }
  /* Quatre parties depuis l'arrivée de la pochette : le segmented control
     doit tenir sur 320 px. Les languettes acceptent de rétrécir (`min-width:
     0` : un enfant de flex ne descend pas sous son contenu sans lui) et le
     libellé peut se couper plutôt que pousser l'écran. */
  .stab {
    flex: 1 1 0; min-width: 0; top: 0; padding: 10px 3px; text-align: center;
    border: none; border-radius: 8px;
    background: transparent; font-size: 12.5px;
    overflow: hidden; text-overflow: ellipsis;
  }
  .stab.is-active { box-shadow: 0 1px 2px rgba(0, 0, 0, .08); }
  .stab-long { display: none; }
  .stab-short { display: inline; }
  .stab-count { margin-left: 4px; min-width: 15px; height: 15px; padding: 0 4px; }

  .share-row { margin-left: -30px; gap: 12px; }
  .share-mark { width: 18px; }
  /* Le droit accordé repasse sous le titre : à cette largeur, la pastille en
     bout de ligne écrase le titre au lieu de l'accompagner. */
  .share-line { flex-wrap: wrap; }
  .share-right { margin-left: 0; }

  .sheet { border-radius: 16px; }
  .sheet-ghost { font-size: 120px; right: 20px; }
  .sheet-body { padding: 20px 20px 24px var(--text-x); }

  /* La tranche RESTE sur le côté au téléphone : c'est l'écran que ce cahier
     ouvre le plus souvent, et une rangée de chips au-dessus de la page était
     un filtre d'application. Elle mange 34 px de largeur, que le texte
     récupère sur la marge (le filet rouge se rapproche du bord, comme sur un
     carnet de petit format). */
  .alpha-rail { width: 28px; padding-right: 6px; }
  .alpha-letter { font-size: 10px; }
  .alpha-letter.is-active { margin-right: -6px; }
  /* La marge se resserre d'autant que la tranche prend en largeur : sans ça,
     le titre d'une note passait de une à deux lignes (mesuré : 192 px de
     colonne au lieu de 208). La perforation suit la marge. */
  .view-repertoire { --margin-x: 32px; --text-x: 48px; }
  .view-repertoire .sheet-rules { background-position: -14px 0, 0 0; }

  .note-row { margin-left: -30px; gap: 12px; }
  .note-letter { width: 18px; }
  /* Le texte reprend la place laissée par la marge raccourcie. */
  .view-repertoire .sheet-body { padding-right: 10px; }

  .btn-new-long { display: none; }
  .btn-new-short { display: block; }
  .btn-new { width: 44px; height: 44px; padding: 0; flex: none; border-radius: 12px; }

  /* Le rail horizontal des pages a besoin que SES PARENTS acceptent de
     rétrécir : un enfant de grille garde `min-width: auto`, donc il se
     dimensionne sur le contenu entier du rail (mesuré avant correction :
     1084 px imposés à l'écran, tout le cahier partant en défilement latéral).
     `minmax(0, 1fr)` sur la colonne et `min-width: 0` sur l'aside referment
     les deux portes. */
  .view-pages { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .pages-side { flex-direction: row; align-items: center; gap: 8px; min-width: 0; }
  .pages-new { width: 44px; height: 44px; padding: 0; flex: none; font-size: 0; order: 2; }
  .pages-new::after {
    content: "+"; font-size: 22px; font-weight: 400; line-height: 1;
    font-family: 'Inter Tight', sans-serif;
  }
  .pages-list {
    flex-direction: row; order: 1; flex: 1; min-width: 0;
    overflow-x: auto; padding-bottom: 2px; scrollbar-width: none;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 12px, #000 calc(100% - 12px), transparent);
    mask-image: linear-gradient(90deg, transparent, #000 12px, #000 calc(100% - 12px), transparent);
  }
  .pages-list::-webkit-scrollbar { display: none; }
  .pages-list > li { flex: none; max-width: 220px; }
  .page-title { font-size: 20px; }
  .week-label { font-size: 18px; }

  /* Aucun champ sous 16 px sur téléphone : en dessous, iOS zoome au premier
     tap et laisse la page agrandie (règle maison, seuil exact de Safari).
     On nomme les porteuses, pas seulement l'élément. */
  .field input, .field textarea,
  .search input, .day-add input,
  .page-title, .page-content,
  .auth-form input, .reader-edit {
    font-size: 16px;
  }
  .page-title { font-size: 20px; }
  /* La ligne « Cahier de ____ » est un titre manuscrit avant d'être un champ :
     deux classes battent la règle ci-dessus (une classe + un élément), et
     20 px reste bien au-dessus du seuil de zoom de Safari. */
  .book-label .field-name input { font-size: 20px; }
}

@media (max-width: 560px) {
  .modal { padding: 0; align-items: flex-end; }
  .modal-card {
    max-width: none; max-height: 94dvh;
    border-radius: 16px 16px 0 0; border-bottom: none;
  }
  .modal-body { padding-bottom: calc(20px + env(safe-area-inset-bottom)); }
  .pw-banner .btn { margin-left: 0; }
}

/* Le plus petit écran encore en service (iPhone SE de première génération).
   Quatre languettes n'y laissent que 62 px de texte par cellule : « Partages »
   et son compteur en réclament 71, et c'est le CHIFFRE qui se faisait couper,
   c'est-à-dire l'information qu'on est venu chercher. Le compteur redevient
   donc une pastille pleine, sans chiffre : à cette largeur ce qui compte est
   le signal (« il y a quelque chose dans la pochette »), et le nombre reste
   écrit dans la pochette elle-même. Mesuré au navigateur de 320 à 430 px. */
@media (max-width: 359px) {
  .stab { font-size: 12px; padding: 10px 1px; }
  .stab-count {
    width: 7px; min-width: 7px; height: 7px; padding: 0;
    margin-left: 5px; font-size: 0;
  }
}

/* Cibles tactiles : plancher de la règle maison (44 px, 38 px pour les
   micro-actions en grappe : lettres du répertoire, suppression d'entrée). */
@media (pointer: coarse) {
  .btn, .user-btn { min-height: 44px; }
  .btn-small { min-height: 38px; }
  .btn-icon { width: 44px; height: 44px; }
  .btn-round { width: 40px; height: 40px; }
  .stab { min-height: 44px; }
  .user-pop button { min-height: 44px; }
  /* Réglages de « Mon compte » : trois choix côte à côte, donc des
     micro-actions en grappe (plancher de 38 px de la règle maison). */
  .seg-btn { min-height: 38px; }
  /* La case grossit ET le label qui l'enveloppe prend la cible : c'est lui
     qu'on touche (même règle que les entrées de l'agenda). */
  .opt { min-height: 44px; }
  .opt-box { width: 22px; height: 22px; }
  .opt-box svg { width: 13px; height: 13px; }
  /* Les actions d'une ligne de pochette sont en grappe : plancher de 38 px,
     obtenu par le padding (ce sont des liens, pas des boutons pleins). */
  .share-actions .linkish { min-height: 38px; display: inline-flex; align-items: center; }
  .auth-tab { min-height: 44px; }
  /* La tranche A-Z est la SEULE exception au plancher tactile de cette page,
     et elle est assumée : 27 languettes sur la hauteur d'une page mesurent
     26 à 31 px selon le téléphone, et un plancher de 38 px les ferait
     déborder d'une tranche qu'on ne peut plus faire défiler au doigt
     (`touch-action: none`, sans quoi le glissé ne parcourt rien). C'est le
     GLISSÉ qui les rend utilisables : on corrige en descendant au lieu de
     viser, la loupe dit laquelle est sous le doigt, et le champ de recherche
     juste au-dessus reste le chemin de plein format vers n'importe quelle
     lettre. */
  .note-row { padding: 14px 0 16px; }
  /* Précédent verrouillé de l'audit mobile : la case grossit ET le label qui
     l'enveloppe prend la cible, c'est lui qu'on touche vraiment. */
  .entry-box { width: 20px; height: 20px; }
  .entry-box svg { width: 12px; height: 12px; }
  .entry, .day-add { height: auto; min-height: 44px; }
  .entry-check { min-height: 44px; }
  /* La ligne « Noter pour ce jour » : c'est l'INPUT qu'on vise, pas la
     rangée qui le contient. `height: 100%` dans un parent passé en hauteur
     automatique retombe sur la hauteur du texte, soit 20 px de cible pour le
     geste le plus fréquent de l'agenda (mesuré au navigateur). */
  .day-add input { min-height: 44px; }
  /* Les deux boutons du bandeau de titre d'une page (partager, supprimer)
     tiennent volontairement dans une ligne réglée de 28 px : la hauteur du
     bandeau EST le pas du motif. Ils peuvent en revanche DÉBORDER de cette
     ligne sans que rien ne se voie (pas de fond au repos) et sans pousser le
     bandeau, qui a une hauteur fixe. C'est ce que dit déjà le commentaire de
     `.page-head .btn-icon` ; la cible tactile n'en avait pas encore
     profité. */
  .page-head .btn-icon { width: 40px; height: 40px; }
  .entry-del, .day-add-btn { width: 38px; height: 38px; opacity: .55; }
  .day-head { height: auto; min-height: var(--lh); }
}

/* Écran couché : la hauteur de page tombe sous les 27 × 18 px de la tranche.
   Une tranche qui défile n'existe pas sur l'objet : les languettes se serrent
   plutôt, la lettre reste lisible et le glissé du pouce fait le reste. */
@media (max-height: 620px) {
  .alpha-letter { min-height: 0; }
}

/* Un :hover qui colle après le tap (iOS garde l'état jusqu'au tap suivant) :
   on neutralise les survols sur appareil sans souris. Bloc en FIN de fichier,
   une media query n'ajoutant aucune priorité (règle maison). */
@media (hover: none) {
  .btn:hover { border-color: var(--edge); }
  .btn-primary:hover { opacity: 1; border-color: var(--ink); }
  .btn-danger:hover { background: transparent; color: var(--accent-ink); }
  .btn-icon:hover { color: var(--faint); background: transparent; }
  .btn-round:hover { color: var(--muted); border-color: var(--edge); }
  .note-row:hover .note-title { color: var(--ink); }
  .share-row.is-openable:hover .share-title { color: var(--ink); }
  .page-item:hover { border-color: var(--edge-soft); border-left-color: transparent; }
  .page-item.is-active:hover { border-left-color: var(--accent); border-color: var(--edge); }
  /* La languette ne se « tire » plus au survol : sur iOS l'état collait après
     le tap et laissait un onglet sorti au hasard dans la tranche. */
  .alpha-letter:hover { margin-right: 0; color: var(--faint); }
  .alpha-letter.has-notes:hover { color: var(--ink); }
  .alpha-letter.is-active:hover { margin-right: -6px; color: #fff; }
  .stab:hover { color: var(--muted); }
  .stab.is-active:hover { color: var(--ink); }
  .user-btn:hover { color: var(--muted); border-color: var(--edge); }
  .user-pop button:hover { background: transparent; }
  .entry-del { opacity: .55; }
}
