  @font-face { font-family: 'Geist'; src:url('/Geist.ttf') format('truetype-variations'),url('/Geist.ttf') format('truetype');
               font-weight:100 900; font-style:normal; font-display:swap; }
  * { margin:0; padding:0; box-sizing:border-box; }
  /* ══ Jetons ═══════════════════════════════════════════════════════════════
     Toujours des bleus sombres, mais en surfaces empilees plutot qu en boites
     cernees : iOS ne dessine presque jamais de bordure, il eclaircit la surface.
     Les anciennes bordures bleutees a 1 px sur chaque champ et chaque carte
     etaient ce qui datait le plus l interface. */
  :root {
    --bg:#080d18; --text:#f5f7fa; --accent: var(--wc-accent);
    /* Trois niveaux de surface : la page, la carte, le controle posé dessus. */
    --s1:rgba(255,255,255,0.045); --s2:rgba(255,255,255,0.075); --s3:rgba(255,255,255,0.11);
    --card-bg:var(--s1); --card-border: var(--wc-card-border);
    --sep:rgba(255,255,255,0.07);
    --text-secondary:rgba(245,247,250,0.62); --text-tertiary:rgba(245,247,250,0.40);
    --input-bg:var(--s2); --input-border:transparent; --danger:var(--wc-red);
    --r:16px;   /* rayon des cartes */
    --r2:12px;  /* rayon des controles */
  }
  html,body { background:var(--bg); color:var(--text); font-family:var(--wc-police);
              min-height:100vh; -webkit-font-smoothing:antialiased; letter-spacing:-0.012em; }
  .bg-glow { position:fixed; inset:0; z-index:0; pointer-events:none;
    background:radial-gradient(ellipse 70% 42% at 50% -8%,rgba(var(--wc-accent-rgb),0.13) 0%,transparent 62%); }
  /* Grand titre facon iOS : le retour discret au-dessus, le titre en gros et
     aligne a gauche en dessous. Un titre de 15 px centre entre deux elements ne
     hierarchisait rien — la page n avait pas de point d entree pour l oeil. */
  header { position:relative; z-index:2; max-width:820px; margin:0 auto;
           padding:16px 22px 22px; }
  header .haut { display:flex; align-items:center; gap:16px; margin-bottom:16px; }
  header .haut .lien-retour { flex:1; }
  header img { height:21px; opacity:.9; }
  header .titre { font-size:32px; font-weight:700; letter-spacing:-.025em; line-height:1.08; }
  header .sous { margin-top:5px; font-size:14px; color:var(--text-secondary); }
  .lien-retour { display:inline-flex; align-items:center; gap:3px; color:var(--accent);
                 text-decoration:none; font-size:13px; white-space:nowrap; }
  .lien-retour:hover { opacity:.75; }
  /* 820 px : la largeur d une colonne de contenu dans une app Apple. A 1000 px,
     une ligne de liste haute de 56 px flottait au milieu d un couloir vide. */
  main { position:relative; z-index:1; max-width:820px; margin:0 auto; padding:4px 22px 72px; }

  /* ══ Liste groupee encastree ══════════════════════════════════════════════
     La forme de Reglages, Musique, Raccourcis : un intitule discret au-dessus
     d une seule surface arrondie, des filets entre les rangees qui demarrent
     apres l icone, et surtout du souffle ENTRE les groupes et non a l interieur.
     Les trois cartes cernees d un filet, toutes espacees de 14 px, ne
     hierarchisaient rien. */
  .grp { margin-bottom:30px; }
  .grp-h { font-size:12.5px; font-weight:600; color:var(--text-secondary);
           margin:0 0 9px 4px; display:flex; align-items:center; gap:8px; }
  .grp-h .compte { margin-left:auto; font-weight:500; color:var(--text-tertiary);
                   font-variant-numeric:tabular-nums; }
  .grp-b { background:var(--s1); border-radius:var(--r); overflow:hidden; }
  .grp-b > * { position:relative; }
  /* Filet encastre : il part apres la marge gauche, comme dans une table iOS. */
  .grp-b > * + *::before { content:''; position:absolute; left:14px; right:0; top:0;
                           height:1px; background:var(--sep); }
  .grp-p { padding:14px; }
  /* Les listes vides : un message centré dans la surface du groupe plutôt
     qu'une ligne de texte gris collée en haut à gauche. */
  .vide { padding:30px 18px; text-align:center; font-size:13.5px; color:var(--text-tertiary);
          line-height:1.6; }

  /* Rangee de reglage : l intitule a gauche, la valeur et son chevron a droite. */
  .lgn { display:flex; align-items:center; gap:12px; min-height:50px; padding:0 14px;
         margin:0; text-transform:none; letter-spacing:normal; cursor:pointer; }
  .lgn > .rl { flex:0 0 auto; font-size:14px; font-weight:500; color:var(--text); }
  .lgn > .rv { flex:1; min-width:0; display:flex; align-items:center;
               justify-content:flex-end; gap:4px; }
  .lgn select { background:none; border:none; width:auto; max-width:100%; padding:6px 20px 6px 0;
                text-align:right; text-align-last:right; font-size:14px; color:var(--text-secondary);
                background-position:right 0 center; }
  .lgn select:focus { background-color:transparent; box-shadow:none; color:var(--text); }

  .carte { background:var(--card-bg); border:1px solid var(--card-border); border-radius:var(--r);
           padding:16px; margin-bottom:14px; }
  h2 { font-size:13px; letter-spacing:normal; text-transform:none; color:var(--text-secondary);
       font-weight:600; margin-bottom:12px; }
  /* Les petites capitales grises sur chaque champ etaient un tic de tableau de
     bord des annees 2010. En bas de casse, l intitule se lit au lieu de crier. */
  label { display:block; font-size:12px; letter-spacing:normal; text-transform:none;
          color:var(--text-secondary); font-weight:500; margin-bottom:6px; }
  input[type=text], input[type=url], input[type=number], input[type=date],
  input[type=datetime-local], input[type=password], select, textarea {
    width:100%; background:var(--input-bg); border:1px solid var(--input-border);
    border-radius:var(--r2); padding:9px 12px; color:var(--text);
    font-family:inherit; font-size:13.5px; transition:background .15s, box-shadow .15s; }
  textarea { resize:vertical; min-height:56px; }
  /* Un anneau plutot qu un changement de bordure : la cible ne bouge pas d un
     pixel quand on clique dedans. */
  input:focus, select:focus, textarea:focus {
    outline:none; background:var(--s3); box-shadow:0 0 0 3px rgba(var(--wc-accent-rgb),.30); }
  ::placeholder { color:var(--text-tertiary); }

  /* Les menus deroulants natifs, avec leur fleche systeme, etaient le detail le
     plus vieillot de la page. On dessine la notre. */
  select { -webkit-appearance:none; appearance:none; padding-right:32px; cursor:pointer;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f5f7fa' stroke-opacity='.5' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat:no-repeat; background-position:right 10px center; background-size:15px; }
  select option { background:#111a2e; color:var(--text); }
  .btn { background:var(--accent); color:#fff; border:none; border-radius:var(--r2);
         padding:10px 16px; font-family:inherit; font-size:13px; font-weight:600; cursor:pointer;
         transition:filter .14s, transform .1s; }
  .btn:active { transform:scale(.97); }
  .btn:hover { filter:brightness(1.1); }
  .btn:disabled { opacity:.5; cursor:default; }
  .btn-sec { background:var(--s2); color:var(--text); border:1px solid transparent; }
  .btn-sec:hover { background:var(--s3); filter:none; }
  .btn-dgr { background:rgba(255,69,58,0.16); color:var(--wc-rouge-corail); border:1px solid transparent; }
  .btn-sm { padding:7px 12px; font-size:12px; border-radius:var(--wc-r-m); }
  .barre { display:flex; gap:8px; flex-wrap:wrap; align-items:center; }
  .aide { font-size:11.5px; color:var(--text-tertiary); line-height:1.55; }
  .note { font-size:11.5px; color:var(--text-tertiary); line-height:1.6;
          padding:0 4px; margin:-4px 0 18px; }
  .note b { color:var(--text-secondary); font-weight:600; }
  .grille { display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:10px; }
  .coche { display:flex; align-items:center; gap:8px; font-size:12.5px; color:var(--text-secondary); }
  .coche input { width:15px; height:15px; accent-color:var(--accent); cursor:pointer; }

  /* ══ Icônes ═══════════════════════════════════════════════════════════════
     Elles prennent la couleur du texte courant, donc un bouton désactivé ou
     survolé emmène son icône avec lui sans règle supplémentaire. */
  .i { width:19px; height:19px; flex:0 0 auto; fill:none; stroke:currentColor;
       stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
  .i-sm { width:16px; height:16px; }
  /* text-decoration:none : PNG, JPG et SVG sont des <a>, ils héritaient donc du
     soulignement des liens et ressemblaient à du texte cliquable, pas à des
     boutons. */
  .btn, .btn-sm { display:inline-flex; align-items:center; justify-content:center; gap:7px;
                  text-decoration:none; }
  a.btn, a.btn-sm, a.bic { text-decoration:none; }

  /* ══ Bouton d'action en icône seule ═══════════════════════════════════════
     Le libellé passe en title/aria-label : sur une ligne d'actions, six mots
     empilés deviennent six carrés alignés, et la rangée tient sur un écran de
     téléphone sans se replier. */
  .bic { display:inline-flex; align-items:center; justify-content:center;
         width:34px; height:34px; flex:0 0 auto; border-radius:var(--wc-r-m); cursor:pointer;
         background:var(--s2); border:1px solid transparent;
         color:var(--text-secondary); transition:background .15s, color .15s; }
  .bic:hover { background:var(--s3); color:var(--text); }
  .bic:active { transform:scale(.94); }
  .bic.pri { background:rgba(var(--wc-accent-rgb),.16); border-color:rgba(var(--wc-accent-rgb),.4); color:var(--wc-bleu-ciel); }
  .bic.pri:hover { background:rgba(var(--wc-accent-rgb),.26); color:#bcdfff; }
  .bic.dgr { background:rgba(239,68,68,.12); border-color:rgba(239,68,68,.3); color:var(--wc-rouge-corail); }
  .bic.dgr:hover { background:rgba(239,68,68,.22); color:#ffb4ad; }
  .bic.fait { background:rgba(34,197,94,.18); border-color:rgba(34,197,94,.4); color:var(--wc-vert-clair); }

  /* ══ Sélecteur segmenté ═══════════════════════════════════════════════════
     La forme iOS : un seul creux, la pastille sélectionnée posée dessus. On
     lit d'un coup combien il y a de choix et lequel est actif — ce que des
     boutons séparés ne montrent pas. */
  .seg { display:flex; gap:3px; padding:3px; border-radius:var(--wc-r-m);
         background:rgba(0,0,0,.28); border:1px solid var(--sep); }
  /* min-width:0 est indispensable : sans lui, un élément flex refuse de passer
     sous la largeur de son contenu, donc « flex:1 1 0 » ne produisait PAS des
     colonnes égales — le plus long libellé poussait les autres et débordait. */
  .seg > button { flex:1 1 0; min-width:0; display:inline-flex; align-items:center; justify-content:center; gap:6px;
                  background:none; border:none; border-radius:var(--wc-r-s); padding:7px 10px; cursor:pointer;
                  font:inherit; font-size:12.5px; font-weight:600; color:var(--text-tertiary);
                  transition:background .15s, color .15s; white-space:nowrap; }
  .seg > button:hover { color:var(--text-secondary); }
  .seg > button.on { background:var(--s3); color:var(--text);
                     box-shadow:0 1px 3px rgba(0,0,0,.35); }
  .seg > button.on .i { color:var(--accent); }

  .onglets { margin-bottom:14px; }

  /* Une ligne par lien : l'essentiel lisible sans ouvrir. */
  /* Les lignes ne sont plus des cartes flottantes : elles composent une seule
     surface, separees par un filet, et ne se detachent qu'une fois ouvertes. */
  #liste-liens, #liste-bios { background:var(--s1); border-radius:var(--r); overflow:hidden; }
  .item { background:transparent; border:none; overflow:hidden; transition:background .15s; }
  .item + .item { box-shadow:inset 0 1px 0 var(--sep); }
  .item:hover { background:var(--s2); }
  .item.sel { background:var(--s2); }
  .item.sel + .item, .item.sel { box-shadow:none; }
  .tete { display:flex; align-items:center; gap:11px; padding:11px 13px; cursor:pointer; }
  /* Vignette d'en-tête : elle dit d'un coup d'œil si le lien s'ouvre dans une
     app, s'il est protégé, ou s'il pointe simplement sur le web. Trois états
     que trois pastilles de texte disaient en beaucoup plus de place. */
  .av { width:36px; height:36px; flex:0 0 auto; border-radius:var(--wc-r-m); display:flex;
        align-items:center; justify-content:center; color:var(--text-secondary);
        background:rgba(255,255,255,.06); border:1px solid var(--card-border); }
  .av.app { background:rgba(var(--wc-accent-rgb),.15); border-color:rgba(var(--wc-accent-rgb),.35); color:var(--wc-bleu-ciel); }
  .av.off { background:rgba(239,68,68,.11); border-color:rgba(239,68,68,.28); color:var(--wc-rouge-corail); }
  .av.page { background:rgba(168,85,247,.15); border-color:rgba(168,85,247,.35); color:#c9a0ff; }
  .tete:hover { background:transparent; }
  .tete-nom { flex:1; min-width:0; }
  .tete-nom b { display:block; font-size:13.5px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .tete-nom span { display:block; font-size:11.5px; color:var(--text-tertiary);
                   overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .chevron { color:var(--text-tertiary); width:17px; height:17px; flex:0 0 auto;
             fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round;
             stroke-linejoin:round; transition:transform .2s; }
  .item.sel .chevron { transform:rotate(90deg); }
  .corps { display:none; padding:2px 13px 13px; }
  .item.sel .corps { display:block; }
  .puce { display:inline-flex; align-items:center; gap:4px; font-size:10.5px; padding:2px 7px;
          border-radius:var(--wc-r-pilule); white-space:nowrap; border:1px solid var(--card-border);
          color:var(--text-tertiary); }
  /* Un point coloré suffit à dire « actif » ou « expiré » : le mot n'apporte
     rien que la couleur ne dise déjà, et il coûte quarante pixels par ligne.
     Le texte reste dans le title pour le survol et les lecteurs d'écran. */
  .pt { width:7px; height:7px; border-radius:50%; flex:0 0 auto; background:currentColor; }
  /* Voyant d'état : un point nu, sans gélule autour. Entouré d'une bordure et
     d'un fond, un point de 7 px ressemblait à une pastille vide dont on cherche
     le texte manquant. */
  .puce.on, .puce.off { padding:0; border:none; background:none; }
  .puce.on { color:var(--wc-vert-clair); }
  .puce.off { color:var(--wc-rouge-corail); }
  /* Même logique pour le cadenas : l'icône se suffit, la gélule ne dit rien. */
  .drap { display:inline-flex; color:var(--text-tertiary); flex:0 0 auto; }
  .puce.app { background:rgba(var(--wc-accent-rgb),.14); border-color:rgba(var(--wc-accent-rgb),.35); color:var(--wc-bleu-pale); }

  /* Création sur une ligne, options repliées : l'essentiel tient en un geste. */
  /* Création : une rangée de la liste, pas une boîte à part. Le champ perd son
     cadre — il EST la rangée — et l'action prend la forme d'un bouton rond
     bleu, celle qu'a « ajouter » dans les apps d'Apple. */
  .creer { display:flex; gap:10px; align-items:center; padding:9px 10px 9px 14px; }
  .creer input { flex:1; min-width:0; font-size:15px; padding:8px 0;
                 background:none; border:none; border-radius:0; }
  .creer input:focus { background:none; box-shadow:none; }
  .rond { flex:0 0 auto; width:36px; height:36px; border-radius:50%; border:none;
          background:var(--accent); color:#fff; display:grid; place-items:center;
          cursor:pointer; transition:filter .14s, transform .1s; }
  .rond:hover { filter:brightness(1.1); }
  .rond:active { transform:scale(.92); }
  .rond:disabled { opacity:.45; cursor:default; }
  .rond .i { width:21px; height:21px; }

  /* Champ de recherche : arrondi franc et fond plein, comme la barre de
     recherche d'une app iOS, posé au-dessus du groupe et non dedans. */
  .champ-rech input { border-radius:var(--wc-r-m); padding:11px 12px 11px 38px; font-size:14.5px; }
  .champ-rech > .i { left:12px; }

  /* ══ Champ à icône ════════════════════════════════════════════════════════
     Le glyphe est posé DANS le champ et le texte démarre après lui. Un libellé
     au-dessus aurait mangé une ligne par contrôle, soit trois lignes rien que
     pour cette barre. */
  .champ-ico { position:relative; display:flex; align-items:center; min-width:0; }
  .champ-ico > .i { position:absolute; left:11px; color:var(--text-tertiary); pointer-events:none;
                    transition:color .15s; }
  .champ-ico:focus-within > .i { color:var(--accent); }
  .champ-ico input, .champ-ico select { padding-left:36px; }
  /* La flèche native du menu déroulant reste, mais on lui laisse sa place. */
  .champ-ico select { padding-right:28px; }

  /* ══ Dossiers ═════════════════════════════════════════════════════════════
     Une rangée qui défile horizontalement, à la façon des filtres en tête d'une
     app iOS : on voit tout le rangement d'un coup d'œil, et le défilement reste
     contenu dans la rangée — c'est la seule zone de la page autorisée à
     déborder latéralement. */
  .dossiers { display:flex; align-items:center; gap:7px; margin:0 0 26px;
              overflow-x:auto; padding-bottom:2px;
              scrollbar-width:none; -webkit-overflow-scrolling:touch; }
  .dossiers::-webkit-scrollbar { display:none; }
  .dos { display:inline-flex; align-items:center; gap:6px; flex:0 0 auto; cursor:pointer;
         background:rgba(255,255,255,.05); border:1px solid var(--card-border);
         color:var(--text-secondary); border-radius:var(--wc-r-pilule); padding:6px 12px;
         font:inherit; font-size:12.5px; font-weight:600; white-space:nowrap;
         transition:background .15s, border-color .15s, color .15s; }
  .dos:hover { background:rgba(255,255,255,.1); color:var(--text); }
  /* La teinte du dossier ne colore que l'état sélectionné : si chaque pastille
     portait sa couleur en fond, la rangée deviendrait un arc-en-ciel où le
     dossier courant ne ressortirait plus. */
  .dos.on { background:color-mix(in srgb, var(--teinte) 18%, transparent);
            border-color:var(--teinte); color:var(--text); }
  .dos .nb { font-variant-numeric:tabular-nums; font-size:11px; font-weight:600;
             color:var(--text-tertiary); background:rgba(0,0,0,.28);
             border-radius:var(--wc-r-pilule); padding:1px 6px; min-width:20px; text-align:center; }
  .dos.on .nb { color:var(--text-secondary); }
  .dos-sep { flex:0 0 auto; width:1px; height:22px; background:var(--sep); margin:0 2px; }
  .dossiers .bic { width:32px; height:32px; }

  /* Étiquette de dossier sur une ligne de liste : elle n'apparaît qu'en vue
     « Tous », où l'appartenance n'est pas déjà donnée par le filtre actif. */
  .dos-tag { display:inline-flex; align-items:center; gap:5px; flex:0 0 auto;
             max-width:130px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
             font-size:11px; color:var(--text-tertiary);
             border:1px solid var(--card-border); border-radius:var(--wc-r-pilule); padding:2px 8px; }
  .dos-tag .pt { background:var(--teinte); }
  html.etroit .dos-tag { display:none; }

  /* Barre d'outils : sans elle la page devient inutilisable passé vingt liens. */
  header .sous b { color:var(--text); font-weight:600; }

  /* Compteur de clics : lisible en balayant la liste du regard. */
  .clics { font-variant-numeric:tabular-nums; font-size:12.5px; font-weight:600;
           color:var(--text-secondary); background:rgba(255,255,255,.05);
           border:1px solid var(--card-border); border-radius:var(--wc-r-s); padding:2px 8px; min-width:34px;
           text-align:center; }
  .tete-nom code { font-family:var(--wc-police-mono); font-size:11.5px;
                   color:var(--accent); }

  /* Aperçu du QR : le cadre prend la couleur du mode pour qu'on voie le rendu réel.
     aspect-ratio plutôt qu'une hauteur fixe — le code est carré par nature, et
     sa largeur est désormais celle de sa colonne. */
  .qr-vue { width:100%; aspect-ratio:1; border-radius:var(--wc-r-l); background:#fff; padding:9px;
            display:flex; align-items:center; justify-content:center; }
  .qr-vue.sombre { background:var(--wc-bg); border:1px solid var(--card-border); }
  .qr-vue.damier { background:
      linear-gradient(45deg,rgba(255,255,255,.10) 25%,transparent 25%,transparent 75%,rgba(255,255,255,.10) 75%),
      linear-gradient(45deg,rgba(255,255,255,.10) 25%,transparent 25%,transparent 75%,rgba(255,255,255,.10) 75%);
    background-size:14px 14px; background-position:0 0,7px 7px; background-color:#4a5570; }
  .qr-vue img { width:100%; height:100%; display:block; }
  /* ── Panneau d'un lien ──────────────────────────────────────────────────
     Bandeau d'action, onglets, puis un seul panneau à la fois. */
  .corps { display:none; padding:0; }
  .item.sel .corps { display:block; }
  .bandeau { display:flex; gap:8px; align-items:center; padding:12px 14px;
             background:rgba(var(--wc-accent-rgb),.09); border-bottom:1px solid var(--sep); }
  .bandeau-url { flex:1; min-width:0; overflow:hidden; }
  .bandeau-url code { font-family:var(--wc-police-mono); font-size:13px;
                      color:var(--text); white-space:nowrap; }
  .sous-onglets { margin:12px 14px 0; }
  /* Icône au-dessus du mot, comme une barre d'onglets iOS : la colonne reste
     étroite, donc les quatre rubriques tiennent sur une ligne même sur un
     téléphone — avant, « Statistiques » passait hors écran. */
  .so { flex-direction:column; gap:3px !important; padding:7px 4px !important; font-size:11px !important; }
  .so .i { width:20px; height:20px; }
  /* Le libellé se coupe proprement plutôt que de sortir de sa colonne. */
  .so span { max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .so .ct { display:none; }
  html.etroit .so .lg { display:none; }
  html.etroit .so .ct { display:inline; }
  /* ══ Hauteur commune aux quatre panneaux ══════════════════════════════════
     Les quatre occupent la MÊME cellule de grille : la hauteur du conteneur est
     donc celle du plus grand, et passer d'un onglet à l'autre ne fait plus
     sauter le bouton « Enregistrer » ni la ligne suivante de la liste.
     On masque avec visibility plutôt que display:none — display retirerait le
     panneau de la grille, et la hauteur se remettrait à varier. visibility
     conserve la place, retire l'élément de l'ordre de tabulation et empêche les
     clics, ce qui est exactement ce qu'on veut d'un onglet inactif. */
  .pans { display:grid; }
  /* Colonne flexible : le contenu principal de chaque panneau porte .etire et
     absorbe la hauteur commune, au lieu de laisser un vide sous lui. Réglé
     panneau par panneau plus bas — étirer n'a de sens que si quelque chose
     gagne à être plus grand. */
  /* min-width:0 : un élément de grille refuse par défaut de passer sous la
     largeur minimale de son contenu, donc le panneau débordait de 21 px de sa
     propre colonne dès qu'il contenait un champ de date ou une rangée double. */
  .pan { grid-area:1 / 1; min-width:0; padding:13px 14px; visibility:hidden;
         display:flex; flex-direction:column; }
  .pan.on { visibility:visible; }
  /* La hauteur commune vaut aussi sur téléphone depuis que « Réglages » est
     passé en liste de rangées : il n'impose plus une hauteur que les autres
     panneaux ne peuvent pas remplir. */
  .pied { display:flex; align-items:center; gap:8px; padding:12px 14px;
          border-top:1px solid var(--sep); background:transparent; }

  /* Champs : deux ou trois par ligne, une seule colonne sur mobile. */
  .ch { min-width:0; }
  .ch label { margin-bottom:6px; }
  .ch.plein input { background:var(--s2); }
  .duo { display:grid; grid-template-columns:1fr 1fr; gap:12px; margin-bottom:11px; }
  .trio { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:12px; margin-bottom:11px; }
  .plein { margin-bottom:11px; }
  html.etroit .duo, html.etroit .trio { grid-template-columns:1fr; }
  .sep { height:1px; background:var(--sep); margin:11px 0; }
  .prefixe { display:flex; align-items:stretch; }
  .prefixe span { display:flex; align-items:center; padding:0 9px; font-size:12.5px;
                  color:var(--text-tertiary); background:rgba(255,255,255,.04);
                  border:1px solid var(--input-border); border-right:none;
                  border-radius:var(--wc-r-s) 0 0 var(--wc-r-s); font-family:var(--wc-police-mono); }
  .prefixe input { border-radius:0 var(--wc-r-s) var(--wc-r-s) 0; }

  /* ══ Liste de rangées ═════════════════════════════════════════════════════
     La forme d'une liste de réglages iOS : un intitulé à gauche, la valeur
     alignée à droite, un filet entre deux rangées. Les champs perdent leur
     cadre — c'est ce qui fait tenir un réglage sur une seule ligne — et
     retrouvent un fond au moment de la mise au point, pour qu'on voie
     immédiatement où l'on écrit. */
  .liste { display:flex; flex-direction:column;
           border:1px solid transparent; border-radius:var(--r2);
           background:var(--s1); overflow:hidden; }
  /* La liste absorbe la hauteur libre du panneau et ses rangées la partagent :
     sur grand écran, « Réglages » est devenu le plus court des quatre, et
     laissait à son tour un vide en bas. flex:1 ne fait rien quand il n'y a pas
     de place en trop, donc la règle est sans effet sur téléphone. */
  .pan > .liste { flex:1; }
  .liste > .rang { flex:1 1 auto; }
  .rang { display:flex; align-items:center; gap:12px; min-height:46px;
          padding:0 12px; margin:0; text-transform:none; letter-spacing:normal;
          border-bottom:1px solid var(--sep); cursor:text; }
  .rang:last-child { border-bottom:none; }
  .rl { flex:0 0 auto; font-size:12.5px; font-weight:500; color:var(--text-secondary);
        white-space:nowrap; }
  /* Rangée partagée : deux demi-rangées séparées par un filet vertical, pour
     qu'on voie que ce sont bien deux réglages et non un seul à deux champs. */
  .rang2 { gap:0; padding:0; cursor:default; }
  .rang2 .mi { flex:1 1 0; min-width:0; display:flex; align-items:center; gap:8px;
               min-height:46px; padding:0 12px; margin:0; cursor:text;
               text-transform:none; letter-spacing:normal; }
  .rang2 .mi + .mi { border-left:1px solid var(--sep); }
  /* Un champ de date porte son gabarit jj/mm/aaaa plus l'icône du calendrier :
     il lui faut plus de place qu'à un nombre, sinon il s'affiche tronqué en
     « mm/ ». La demi-rangée de gauche est donc plus large. */
  .rang2 .mi:first-child { flex:1.55 1 0; }
  .rv input[type=date] { font-size:12px; padding-right:2px; }
  .rv { flex:1; min-width:0; display:flex; align-items:center; justify-content:flex-end; gap:4px; }
  /* flex + min-width:0 + width:100% : sans les trois, le champ refuse de
     descendre sous sa largeur intrinsèque (un <input> vaut ~20 caractères par
     défaut, un <input type=date> impose son gabarit de calendrier) et la
     rangée déborde de la carte, qui la rogne. Le cadre étant invisible, un
     champ pleine largeur au texte aligné à droite ne se voit pas. */
  .rv input, .rv select { flex:1 1 auto; min-width:0; width:100%;
                          background:none; border:none; border-radius:var(--wc-r-s); padding:5px 8px;
                          text-align:right; font-size:13.5px; transition:background .15s; }
  .rv select { text-align:left; text-align-last:right; padding-right:20px;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f5f7fa' stroke-opacity='.45' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat:no-repeat; background-position:right 0 center; background-size:14px; }
  .rv input:focus, .rv select:focus { background:var(--input-bg); outline:none; }
  .rv input::placeholder { color:var(--text-tertiary); }
  /* Mots de l'ouverture : un par ligne, la zone prend la largeur de la rangée. */
  /* Aide du style éditorial : un texte, pas un champ. */
  .rv .a-aide { display:block; font-style:normal; font-size:12px; line-height:1.5; color:var(--text-tertiary); text-align:left; margin:4px 0; }
  .rv .a-aide i { font-weight:300; }
  .rv .a-ouv-mots { flex:1 1 auto; width:100%; min-height:84px; margin:6px 0; font-size:13px; line-height:1.45; }
  /* Le préfixe du raccourci reste en gris devant la partie modifiable, et les
     deux se lisent comme une seule adresse. */
  .pfx { font-family:var(--wc-police-mono); font-size:12px;
         color:var(--text-tertiary); white-space:nowrap; }
  .rv .f-slug { font-family:var(--wc-police-mono); font-size:12.5px;
                min-width:60px; }
  /* Sur grand écran la liste se met sur deux colonnes : la fenêtre est large,
     une colonne unique y laisserait les valeurs à un mètre de leur intitulé. */
  @media (min-width:820px) {
    .pan[data-pan="reglages"] .liste { display:grid; grid-template-columns:1fr 1fr; }
    .pan[data-pan="reglages"] .liste > .rang:nth-last-child(2):nth-child(odd) { border-bottom:none; }
    .pan[data-pan="reglages"] .liste > .rang:nth-child(odd) { border-right:1px solid var(--sep); }
    /* Les réglages du QR se centrent en face du code au lieu de se tasser en
       haut d'une colonne deux fois plus haute qu'eux. */
    .qr-col { justify-content:center; }
  }

  /* .bsc est un <label> : il hérite des capitales et de l'interlettrage du style
     global. On les neutralise, sinon l'intitulé crie. */
  .bsc { display:flex; align-items:center; gap:11px; cursor:pointer;
         text-transform:none; letter-spacing:normal; color:var(--text); margin-bottom:0; }
  .bsc.rang { cursor:pointer; padding-top:7px; padding-bottom:7px; }
  .bsc.rang .bsc-t { flex:1; min-width:0; }
  .bsc.rang .piste { order:2; }
  .bsc input { position:absolute; opacity:0; width:0; height:0; }
  .piste { flex:0 0 auto; width:38px; height:22px; border-radius:var(--wc-r-pilule); margin-top:0;
           background:rgba(255,255,255,.12); border:1px solid var(--card-border);
           position:relative; transition:.18s; }
  .piste::after { content:''; position:absolute; top:2px; left:2px; width:16px; height:16px;
                  border-radius:50%; background:var(--wc-gris-bleu); transition:.18s; }
  .bsc input:checked + .piste { background:rgba(var(--wc-accent-rgb),.35); border-color:var(--accent); }
  .bsc input:checked + .piste::after { left:18px; background:#fff; }
  .bsc-t b { display:block; font-size:13px; font-weight:600; }
  .bsc-t em { display:block; font-style:normal; font-size:11.5px; color:var(--text-tertiary);
              line-height:1.45; margin-top:1px; overflow:hidden; text-overflow:ellipsis;
              white-space:nowrap; }

  /* Aperçu au partage : une vraie carte, comme dans un fil de discussion. */
  /* Partage : l'aperçu est le sujet de la page, il occupe donc une vraie
     colonne. À 128 px la vignette était trop petite pour juger de l'image, ce
     qui vidait le panneau de son intérêt. */
  .og { display:flex; gap:14px; align-items:stretch; flex:1; min-height:0; }
  .og-col { flex:0 0 auto; width:296px; align-self:flex-start;
            display:flex; flex-direction:column; gap:9px; }
  .og-act { justify-content:flex-start; }
  .og-form { display:flex; flex-direction:column; min-width:0; }
  .og-form .ch-etire { flex:1; min-height:0; display:flex; flex-direction:column; }
  .og-form .ch-etire textarea { flex:1; min-height:54px; }
  /* La carte garde sa hauteur naturelle : étirée avec le reste, elle devenait
     un grand rectangle vide sous son texte, ce qu'aucun fil de discussion
     n'afficherait jamais. C'est le formulaire qui absorbe la hauteur. */
  .og-carte { width:100%; border:1px solid var(--card-border); border-radius:var(--wc-r-m);
              overflow:hidden; background:rgba(255,255,255,.03); }
  .og-vue { width:100%; aspect-ratio:1200/630; background:var(--wc-bg); }
  .og-vue img { width:100%; height:100%; object-fit:cover; display:block; }
  .og-txt { padding:10px 12px; }
  .og-txt b { display:block; font-size:13px; line-height:1.35; }
  .og-txt span { display:block; font-size:11.5px; color:var(--text-secondary); line-height:1.45;
                 margin-top:3px; max-height:33px; overflow:hidden; }
  .og-txt em { display:block; font-style:normal; font-size:11px; color:var(--text-tertiary);
               margin-top:5px; text-transform:uppercase; letter-spacing:.03em; }
  .og-form { flex:1; min-width:200px; }
  .og-form .ch { margin-bottom:9px; }

  .qr-modes { max-width:330px; }
  .qr-m { font-size:12px !important; }
  /* Pastille de couleur au lieu d'une icône : le mode d'un QR est une affaire
     de fond, autant le montrer littéralement. */
  .pastille { width:13px; height:13px; border-radius:var(--wc-r-xs); flex:0 0 auto;
              border:1px solid rgba(255,255,255,.35); }
  .pastille.damier { background:
      linear-gradient(45deg,rgba(255,255,255,.85) 25%,transparent 25%,transparent 75%,rgba(255,255,255,.85) 75%),
      linear-gradient(45deg,rgba(255,255,255,.85) 25%,transparent 25%,transparent 75%,rgba(255,255,255,.85) 75%);
    background-size:7px 7px; background-position:0 0,3.5px 3.5px; background-color:#4a5570; }

  .url-ligne { display:flex; gap:7px; align-items:center; margin-bottom:7px; }
  .url-ligne input { flex:1; font-family:var(--wc-police-mono); font-size:12.5px; }
  .sous-t { font-size:12px; font-weight:600; letter-spacing:normal; text-transform:none;
            color:var(--text-secondary); margin:16px 0 8px; }
  .qr-zone { display:flex; gap:14px; align-items:stretch; flex:1; min-height:0; }
  .qr-col-g { flex:0 0 auto; width:236px; align-self:flex-start;
              display:flex; flex-direction:column; gap:9px; }
  .qr-col { flex:1; min-width:0; display:flex; flex-direction:column; gap:12px; }
  /* Les trois formats partagent la largeur du code : alignés à gauche, ils
     laissaient un blanc irrégulier sous une image parfaitement carrée. */
  .qr-dl { display:flex; gap:7px; }
  .qr-dl .btn { flex:1 1 0; min-width:0; padding-left:0; padding-right:0; gap:5px; }
  .stat { display:flex; gap:10px; flex-wrap:wrap; }
  .stat > div { background:rgba(255,255,255,.04); border:1px solid var(--card-border);
                border-radius:var(--wc-r-m); padding:9px 12px; min-width:92px; }
  .stat b { display:block; font-size:17px; }
  .stat span { font-size:11px; color:var(--text-tertiary); }
  .rep { font-size:12px; color:var(--text-secondary); line-height:1.7; }
  /* Statistiques : l'en-tête chiffré, puis une grille de groupes qui occupe le
     reste du bloc. */
  .stats-corps { flex:1; min-height:0; display:flex; flex-direction:column; gap:12px; }
  .stats-grille { flex:1; min-height:0; display:grid; gap:12px 20px;
                  grid-template-columns:1fr; align-content:space-between; }
  @media (min-width:820px) { .stats-grille { grid-template-columns:1fr 1fr; } }
  .grp-t { font-size: var(--wc-surtitre-taille); font-weight: var(--wc-surtitre-graisse); letter-spacing: var(--wc-surtitre-espacement); text-transform: var(--wc-surtitre-casse);
           color: var(--wc-surtitre-couleur); margin-bottom:5px; }
  .brg { display:flex; align-items:center; gap:9px; padding:2px 0; }
  .brg-n { flex:0 0 92px; font-size:12px; color:var(--text-secondary);
           overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .brg-b { flex:1; min-width:0; height:7px; border-radius:var(--wc-r-pilule);
           background:rgba(255,255,255,.07); overflow:hidden; }
  .brg-b i { display:block; height:100%; border-radius:var(--wc-r-pilule);
             background:linear-gradient(90deg,var(--accent),var(--wc-bleu-ciel)); }
  .brg-v { flex:0 0 auto; min-width:22px; text-align:right; font-size:12px;
           font-variant-numeric:tabular-nums; color:var(--text); font-weight:600; }
  /* Les deux compteurs de tête s'étalent sur la largeur au lieu de se serrer
     à gauche. */
  .stat { display:flex; gap:10px; }
  .stat > div { flex:1; }
  /* Un bloc de page bio : ses champs sont regroupés, son type reste visible. */
  .bloc { background:rgba(255,255,255,.03); border:1px solid var(--card-border); border-radius:var(--wc-r-m);
          padding:10px 11px; margin-bottom:9px; }
  .bloc-t { display:flex; align-items:center; gap:6px; margin-bottom:9px; }
  /* L'étiquette de type se laisse rogner : « Questions fréquentes » plus quatre
     boutons ne tiennent pas sur 324 px, et c'est le dernier bouton qui sortait
     de la carte. */
  .bloc-t .puce { min-width:0; overflow:hidden; text-overflow:ellipsis; }
  .bloc-t .bic { width:30px; height:30px; border-radius:var(--wc-r-s); }
  .bloc-t .bic .i { width:16px; height:16px; }
  .bl-rl .bic { width:100%; height:100%; min-height:34px; }
  .bl-g2 { display:grid; grid-template-columns:1fr 1fr; gap:8px; }
  .bl-g3 { display:grid; grid-template-columns:70px minmax(0,1fr) minmax(0,1.4fr); gap:8px; }
  .bl-rl { display:grid; grid-template-columns:118px minmax(0,1fr) 34px; gap:7px; margin-bottom:6px; }
  .bl-rx { margin:8px 0; }
  html.etroit .bl-g2, html.etroit .bl-g3, html.etroit .bl-rl { grid-template-columns:1fr; }
  /* Une photo de la galerie : le même sélecteur d'image qu'ailleurs, plus le
     retrait de la rangée entière à côté — pas au-dessus, la case image est déjà
     assez haute. */
  .bl-gal-l { display:flex; align-items:flex-start; gap:8px; margin-bottom:10px; }
  .bl-gal-l .img-choix { flex:1; min-width:0; }
  .bl-gal-l .bic { flex:0 0 auto; margin-top:2px; }
  .bloc textarea { margin-top:0; }

  /* ══ Éditeur de page bio ══════════════════════════════════════════════════ */
  /* Pastille de couleur : le sélecteur natif, donc celui du système, mais
     ramené à une pastille au lieu du champ pleine largeur qu'impose la règle
     générique des rangées. */
  .cpx { -webkit-appearance:none; appearance:none; width:44px !important; height:28px;
         flex:0 0 auto !important; padding:0 !important; border:1px solid var(--card-border) !important;
         border-radius:var(--wc-r-s); background:none; cursor:pointer; }
  .cpx::-webkit-color-swatch-wrapper { padding:2px; }
  .cpx::-webkit-color-swatch { border:none; border-radius:var(--wc-r-s); }
  .cpx::-moz-color-swatch { border:none; border-radius:var(--wc-r-s); }

  .rv input[type=range] { -webkit-appearance:none; appearance:none; height:4px; padding:0;
                          background:rgba(255,255,255,.14); border-radius:var(--wc-r-pilule);
                          accent-color:var(--accent); max-width:150px; }
  .rv input[type=range]::-webkit-slider-thumb { -webkit-appearance:none; width:17px; height:17px;
    border-radius:50%; background:var(--accent); cursor:pointer; border:none; }
  .rv input[type=range]::-moz-range-thumb { width:17px; height:17px; border-radius:50%;
    background:var(--accent); cursor:pointer; border:none; }

  /* Une rangée masquée par `hidden` doit vraiment disparaître : .rang est en
     display:flex, qui l'emporte sur le display:none implicite de l'attribut. */
  .rang[hidden], .bl-prog[hidden] { display:none !important; }

  /* Questions fréquentes : la question, la réponse dessous, le retrait à côté. */
  .bl-ql { display:grid; grid-template-columns:minmax(0,1fr) auto; gap:7px;
           align-items:start; margin-bottom:8px; }
  .bl-ql .ql-q, .bl-ql .ql-r { grid-column:1; }
  .bl-ql .bic { grid-column:2; grid-row:1 / span 2; height:100%; }

  /* ══ Sélecteur d'image ════════════════════════════════════════════════════ */
  .img-choix { display:flex; gap:12px; align-items:flex-start; }
  .img-vue { position:relative; flex:0 0 auto; width:96px; border-radius:var(--wc-r-m); overflow:hidden;
             background:var(--s2); cursor:crosshair; touch-action:none; user-select:none; }
  .img-choix[data-forme="cercle"] .img-vue { border-radius:50%; width:84px; }
  .img-choix[data-forme="large"] .img-vue { width:150px; }
  .img-choix[data-forme="portrait"] .img-vue { width:72px; }
  .img-vue img { width:100%; height:100%; object-fit:cover; display:block; pointer-events:none; }
  .img-vue.vide img, .img-vue.vide .img-point { display:none; }
  .img-vue.libre { cursor:default; }
  .img-vue.libre .img-point { display:none; }
  .img-rien { position:absolute; inset:0; display:none; place-items:center; color:var(--text-tertiary); }
  .img-vue.vide .img-rien { display:grid; }
  .img-vue.vide { cursor:default; }
  /* Le point de cadrage : un anneau blanc cerné de noir, lisible sur toute photo. */
  .img-point { position:absolute; width:16px; height:16px; margin:-8px 0 0 -8px; border-radius:50%;
               border:2px solid #fff; box-shadow:0 0 0 1px rgba(0,0,0,.5), 0 1px 4px rgba(0,0,0,.5);
               pointer-events:none; transition:transform .12s; }
  .img-vue.glisse .img-point { transform:scale(1.25); }
  .img-col { flex:1; min-width:0; display:flex; flex-direction:column; gap:7px; }
  .img-col .barre { gap:6px; }
  .img-col .img-url { font-size:12.5px; padding:7px 10px; }
  .img-aide { font-size:11.5px; }
  /* Dans la liste d'apparence, le sélecteur prend la rangée entière. */
  .rang.a-img-choix { display:block; padding:10px 12px; cursor:default; }

  /* Indicateur d'enregistrement : un point et un mot, dans la couleur de l'état. */
  .auto-etat { display:inline-flex; align-items:center; gap:8px; font-size:12.5px;
               color:var(--text-secondary); padding:6px 4px; }
  .auto-pt { width:8px; height:8px; border-radius:50%; background:#34c759; flex:0 0 auto;
             transition:background .2s; }
  .auto-etat[data-genre="attente"] .auto-pt { background:var(--wc-orange); }
  .auto-etat[data-genre="cours"] .auto-pt { background:var(--accent); animation:pulse 1s ease-in-out infinite; }
  .auto-etat[data-genre="partiel"] { cursor:pointer; text-decoration:underline;
                                     text-decoration-color:var(--card-border); text-underline-offset:3px; }
  .auto-etat[data-genre="partiel"] .auto-pt { background:#8e8e93; }

  /* Bloc pas encore publié : un liseré pointillé et une ligne qui dit quoi
     remplir, au lieu d'une alerte générale sans adresse. */
  .bloc.brouillon { border-style:dashed; border-color:rgba(142,142,147,.55); }
  .bloc-manque { font-size:12px; color:var(--text-secondary); margin:-3px 0 10px;
                 display:flex; align-items:center; gap:6px; }
  .bloc-manque::before { content:''; width:6px; height:6px; border-radius:50%; background:#8e8e93; flex:0 0 auto; }
  .auto-etat[data-genre="erreur"] { color:var(--wc-rouge-corail); }
  .auto-etat[data-genre="erreur"] .auto-pt { background:var(--wc-red); }
  @keyframes pulse { 50% { opacity:.35; } }

  /* Connexion Instagram : les étapes numérotées, puis le champ du jeton. */
  .ig-connexion { margin-top:10px; padding:11px 12px; border-radius:var(--wc-r-m); background:var(--s1);
                  border:1px solid var(--card-border); }
  .ig-etapes { margin:0 0 10px 18px; padding:0; font-size:12.5px; line-height:1.55; color:var(--text-secondary); }
  .ig-etapes li { margin-bottom:5px; }
  .ig-etapes b { color:var(--text); font-weight:600; }
  .ig-etapes a { color:var(--accent); }
  .ig-jeton { font-family:var(--wc-police-mono); font-size:12px; word-break:break-all; }

  /* Statistiques d'une page bio */
  .stats-bio .st-res { display:flex; gap:8px; margin-bottom:12px; }
  .stats-bio .st-res > div { flex:1; background:var(--s1); border-radius:var(--wc-r-m); padding:10px 12px; }
  .stats-bio .st-res b { display:block; font-size:18px; font-variant-numeric:tabular-nums; }
  .stats-bio .st-res span { font-size:11.5px; color:var(--text-tertiary); }
  /* Histogramme des clics : une barre par jour, la plus haute touchant le
     plafond. Les jours sans clic gardent une barre pleine hauteur, presque
     transparente, pour que la grille des trente jours reste lisible. */
  .stats-bio .st-graph { background:var(--s1); border-radius:var(--wc-r-m); padding:12px 13px 10px; margin-bottom:12px; }
  .stats-bio .st-graph-t { display:flex; align-items:baseline; gap:6px; margin-bottom:10px; }
  .stats-bio .st-graph-t b { font-size:17px; font-variant-numeric:tabular-nums; }
  .stats-bio .st-graph-t span { font-size:11.5px; color:var(--text-tertiary); }
  .stats-bio .st-bars { display:flex; align-items:flex-end; gap:2px; height:62px; }
  .stats-bio .st-bars i { flex:1; min-width:0; min-height:3px; border-radius:3px 3px 1px 1px;
                          background:var(--accent); opacity:.8; transition:opacity .12s; }
  .stats-bio .st-bars i:hover { opacity:1; }
  .stats-bio .st-bars i.vide { background:var(--text-tertiary); opacity:.12; border-radius:2px; }
  .stats-bio .st-graph-x { display:flex; justify-content:space-between; margin-top:7px;
                           font-size:11px; color:var(--text-tertiary); }
  .stats-bio .brg-n { flex:0 0 46%; }
  .stats-bio .st-l { margin-bottom:6px; }
  .stats-bio .st-s { font-size:11.5px; color:var(--text-tertiary); margin:1px 0 0; padding-left:2px; }
  .bloc-clics { font-size:11px; font-weight:600; color:var(--accent); padding:2px 8px; border-radius:var(--wc-r-pilule);
                background:rgba(var(--wc-accent-rgb),.13); white-space:nowrap; font-variant-numeric:tabular-nums; }
  /* Messages reçus par un formulaire de contact */
  .ct-m { background:var(--s1); border-radius:var(--wc-r-m); padding:9px 11px; margin-bottom:6px; }
  .ct-m-t { display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; font-size:12.5px; }
  .ct-m-t a { color:var(--accent); text-decoration:none; }
  .ct-m-t span { margin-left:auto; color:var(--text-tertiary); font-size:11.5px; }
  .ct-m p { margin:5px 0 0; font-size:12.5px; color:var(--text-secondary); white-space:pre-wrap; line-height:1.5; }
  .ct-m-e { margin-top:5px; font-size:11.5px; color:var(--wc-orange); }

  /* Espace vide : curseur et valeur sur une ligne, puis le vide dessiné à l'échelle. */
  .bl-esp { display:flex; align-items:center; gap:12px; }
  .bl-esp input[type=range] { flex:1; }
  .bl-esp-val { font-size:12.5px; color:var(--text-secondary); min-width:48px; text-align:right;
                font-variant-numeric:tabular-nums; }
  .bl-esp-vue { margin-top:9px; border-radius:var(--wc-r-s); border:1px dashed var(--card-border);
                background:repeating-linear-gradient(45deg,transparent 0 6px,rgba(255,255,255,.035) 6px 12px);
                transition:height .1s; }

  /* Programmation : un encadré discret, replié tant qu'on ne s'en sert pas. */
  .bl-prog { margin-top:9px; padding:9px 10px; border-radius:var(--wc-r-s);
             background:rgba(255,255,255,.03); border:1px dashed var(--card-border); }

  /* Le corps d'un lien met sa propre marge dans .bandeau et .pan ; celui d'une
     page bio pose son contenu directement, il n'en avait donc aucune et les
     champs venaient mourir sur le bord de la carte. */
  #liste-bios .corps { padding:0 14px 14px; }
  #liste-bios .corps > .url-ligne:first-child { margin-top:2px; }

  /* ══ Éditeur de page bio : onglets, liste de blocs, aperçu ════════════════
     Avec une dizaine de blocs tous dépliés, l'éditeur dépassait 4 500 px et
     l'aperçu était tout en bas. On revient à la forme d'une app iOS : une
     barre fixe (état, ajout, aperçu), quatre onglets, et des blocs repliés en
     rangées lisibles d'un coup d'œil, qu'on ouvre un par un. */
  /* overflow:clip et non hidden : hidden fait de la liste un conteneur de
     défilement, et plus rien à l'intérieur ne peut rester collé en haut. */
  #liste-bios, #liste-bios .item { overflow:hidden; overflow:clip; }
  .ed-tete { position:sticky; top:0; z-index:8; margin:0 -14px 12px; padding:10px 14px;
             background:rgba(24,29,40,.93); backdrop-filter:blur(16px) saturate(1.3);
             -webkit-backdrop-filter:blur(16px) saturate(1.3); box-shadow:0 1px 0 var(--sep); }
  .ed-barre { display:flex; align-items:center; gap:6px; margin-bottom:9px; }
  .ed-barre .auto-etat { flex:1; min-width:0; padding:4px 2px; }
  .ed-barre .auto-etat span { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .ed-barre .btn { display:inline-flex; align-items:center; gap:5px; padding:7px 12px; }
  .ed-seg .ed-n { font-size:11px; font-weight:600; color:var(--text-tertiary); font-variant-numeric:tabular-nums; }
  .ed-seg > button.on .ed-n { color:var(--text-secondary); }
  html.etroit .ed-seg .i { display:none; }
  .ed-pan[hidden] { display:none !important; }
  .ed-vide { padding:22px 12px; text-align:center; color:var(--text-tertiary); font-size:13px; }
  .ed-danger { margin-top:18px; padding-top:14px; border-top:1px solid var(--sep);
               display:flex; flex-wrap:wrap; gap:8px; }
  .btn-dgr { background:rgba(255,69,58,.12); color:var(--wc-rouge-corail); }
  .btn-dgr:hover { background:rgba(255,69,58,.2); filter:none; }

  /* Liste de blocs : une surface, des rangées séparées d'un filet. */
  .bl-liste { background:rgba(255,255,255,.03); border:1px solid var(--sep); border-radius:var(--wc-r-l); }
  .bl-liste:empty { display:none; }
  .bl-liste .bloc { background:none; border:0; border-radius:0; padding:0; margin:0; position:relative;
                    scroll-margin-top:118px; }
  .bl-liste .bloc + .bloc { box-shadow:inset 0 1px 0 var(--sep); }
  .bl-liste .bloc:first-child { border-radius:var(--wc-r-l) var(--wc-r-l) 0 0; }
  .bl-liste .bloc:last-child { border-radius:0 0 var(--wc-r-l) var(--wc-r-l); }
  .bl-liste .bloc:only-child { border-radius:var(--wc-r-l); }
  .bl-liste .bloc-t { display:flex; align-items:center; gap:10px; margin:0; padding:8px 12px 8px 4px;
                      min-height:54px; cursor:pointer; user-select:none; -webkit-user-select:none; }
  .bl-liste .bloc-t:hover { background:rgba(255,255,255,.025); }
  .bl-liste .bloc.ouvert { background:rgba(255,255,255,.045); }
  .bl-poignee { width:30px; height:38px; display:grid; place-items:center; flex:0 0 auto;
                color:var(--text-tertiary); cursor:grab; touch-action:none; border-radius:var(--wc-r-s); }
  .bl-poignee:hover { color:var(--text-secondary); }
  .bl-poignee .i { width:17px; height:17px; }
  .bl-ico { width:30px; height:30px; border-radius:var(--wc-r-s); display:grid; place-items:center; flex:0 0 auto;
            color:#fff; background:var(--c); box-shadow:inset 0 0 0 .5px rgba(255,255,255,.12); }
  .bl-ico .i { width:17px; height:17px; stroke-width:2; }
  .bl-res { flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
  .bl-nom { font-size:14px; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .bl-nom.vide { color:var(--text-secondary); font-weight:500; }
  .bl-sous { display:flex; align-items:center; gap:6px; min-width:0; font-size:12px; color:var(--text-tertiary);
             white-space:nowrap; overflow:hidden; }
  .bl-type { overflow:hidden; text-overflow:ellipsis; }
  .bl-e { flex:0 0 auto; font-size:10.5px; font-weight:600; padding:1px 7px; border-radius:var(--wc-r-pilule);
          background:rgba(255,159,10,.15); color:#ffb340; }
  .bl-e.gris { background:rgba(142,142,147,.2); color:var(--text-secondary); }
  .bl-chev { width:16px; height:16px; flex:0 0 auto; color:var(--text-tertiary); transition:transform .2s; }
  .bloc.ouvert .bl-chev { transform:rotate(90deg); }
  .bloc.masque .bl-res, .bloc.masque .bl-ico { opacity:.45; }
  .bl-liste .bloc[data-type="espace"] .bloc-t { min-height:42px; padding-block:3px; }
  .bl-liste .bloc[data-type="espace"] .bl-ico { width:24px; height:24px; border-radius:var(--wc-r-s); margin-inline:3px; }
  .bl-liste .bloc[data-type="espace"] .bl-ico .i { width:14px; height:14px; }
  .bl-liste .bloc[data-type="espace"] .bl-nom { font-size:12.5px; font-weight:500; color:var(--text-secondary); }
  .bl-corps { display:none; padding:0 14px 14px; }
  .bloc.ouvert .bl-corps { display:block; }
  .bl-actions { display:flex; align-items:center; gap:6px; padding:2px 0 11px; margin-bottom:11px;
                box-shadow:0 1px 0 var(--sep); }
  .bl-actions .bic { width:32px; height:32px; border-radius:var(--wc-r-s); }
  .bl-actions .bic .i { width:16px; height:16px; }
  .bl-liste .bloc-manque { margin:-6px 12px 9px 78px; }
  .bl-liste .bloc.brouillon .bl-ico { box-shadow:0 0 0 2px var(--bg), 0 0 0 3.5px #8e8e93; }
  .bl-liste .bloc .bloc-clics { flex:0 0 auto; }
  .bloc.vu { animation:blocVu 1.3s ease-out; }
  @keyframes blocVu { 0%,30% { background:rgba(var(--wc-accent-rgb),.16); } 100% { background:transparent; } }
  /* Rangée soulevée pendant le glisser. */
  .bl-liste .bloc.glisse { z-index:4; background:#222838; border-radius:var(--wc-r-m);
                           box-shadow:0 12px 32px rgba(0,0,0,.5), 0 0 0 1px rgba(255,255,255,.08); }
  .bl-liste .bloc.glisse .bl-poignee { cursor:grabbing; color:var(--accent); }
  body.glisse-bloc { cursor:grabbing; user-select:none; -webkit-user-select:none; }

  .bl-plus { width:100%; margin-top:10px; display:flex; align-items:center; justify-content:center; gap:7px;
             padding:12px; border-radius:var(--wc-r-l); border:1.5px dashed rgba(255,255,255,.14); background:none;
             color:var(--accent); font:inherit; font-size:13.5px; font-weight:600; cursor:pointer; }
  .bl-plus:hover { background:rgba(var(--wc-accent-rgb),.07); border-color:rgba(var(--wc-accent-rgb),.4); }

  /* Feuilles : choix d'un bloc, aperçu sur petit écran. */
  .feuille { position:fixed; inset:0; z-index:70; display:flex; align-items:center; justify-content:center;
             padding:16px; background:rgba(0,0,0,.5); backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px); }
  .feuille[hidden] { display:none; }
  .feuille-b { width:100%; max-width:580px; max-height:calc(100vh - 32px); overflow:auto; overscroll-behavior:contain;
               background:#141925; border:1px solid var(--sep); border-radius:var(--wc-r-xl); padding:16px;
               box-shadow:0 30px 80px rgba(0,0,0,.55); }
  .feuille-h { display:flex; align-items:center; gap:10px; margin-bottom:4px; }
  .feuille-h b { font-size:17px; }
  .feuille-h .feuille-note { flex:1; min-width:0; font-size:12px; color:var(--text-tertiary);
                             overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  html.etroit .feuille { align-items:flex-end; padding:0; }
  html.etroit .feuille-b { border-radius:var(--wc-r-xl) var(--wc-r-xl) 0 0; max-height:88vh;
                           padding-bottom:calc(18px + env(safe-area-inset-bottom)); }
  .bc-g { font-size:12px; font-weight:600; color:var(--text-secondary); margin:13px 2px 7px; }
  .bc-grille { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px; }
  .bc { display:flex; align-items:center; gap:10px; text-align:left; padding:10px; border-radius:var(--wc-r-m);
        background:var(--s2); border:0; color:var(--text); font:inherit; cursor:pointer; min-width:0; }
  .bc:hover { background:var(--s3); }
  .bc:active { transform:scale(.98); }
  .bc > span:last-child { min-width:0; }
  .bc b { display:block; font-size:13px; font-weight:600; }
  .bc small { display:block; font-size:11.5px; color:var(--text-tertiary); line-height:1.3; margin-top:1px; }
  .bc .bl-ico { width:34px; height:34px; border-radius:var(--wc-r-s); }

  /* Aperçu : un téléphone. À côté de l'éditeur sur un grand écran, en feuille
     ouverte à la demande ailleurs. La feuille reste rendue (invisible) plutôt
     qu'en display:none, sinon l'aperçu ne peut pas défiler jusqu'à un bloc. */
  .ed-ap { position:fixed; inset:0; z-index:65; display:flex; flex-direction:column; align-items:center;
           justify-content:center; gap:12px; padding:14px; background:rgba(0,0,0,.6);
           backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
           visibility:hidden; opacity:0; pointer-events:none; transition:opacity .2s, visibility 0s .2s; }
  .ed-ap.montre { visibility:visible; opacity:1; pointer-events:auto; transition:opacity .2s; }
  .tel { width:100%; max-width:380px; height:min(760px, calc(100vh - 96px)); padding:9px; border-radius:var(--wc-r-pilule);
         background:#000; box-shadow:0 0 0 1.5px #2c2c2e, 0 24px 60px rgba(0,0,0,.5); }
  .tel iframe { display:block; width:100%; height:100%; border:0; border-radius:var(--wc-r-xl); background:var(--wc-bg); }
  .ed-ap-pied { display:flex; align-items:center; gap:8px; font-size:12px; color:var(--text-tertiary); }
  .ed-ap-fermer { display:inline-flex; }
  html.etroit .ed-ap { background:rgba(4,7,14,.9); }
  html.etroit .bc small { display:none; }
  html.etroit .bc { padding:11px 10px; }
  @media (min-width:1100px) {
    html.ed-large:not(.etroit) header, html.ed-large:not(.etroit) main { max-width:1240px; }
    html.ed-large:not(.etroit) .ed { display:grid; grid-template-columns:minmax(0,1fr) 380px; gap:26px; align-items:start; }
    html.ed-large:not(.etroit) .ed-ap { position:sticky; top:14px; inset:auto; z-index:1; padding:0; background:none;
      backdrop-filter:none; -webkit-backdrop-filter:none; visibility:visible; opacity:1; pointer-events:auto;
      justify-content:flex-start; }
    html.ed-large:not(.etroit) .tel { height:min(780px, calc(100vh - 64px)); }
    html.ed-large:not(.etroit) .ed-ap-fermer, html.ed-large:not(.etroit) .ed-apbtn { display:none; }
  }
  .toast-act { margin-left:14px; background:none; border:0; color:var(--accent); font:inherit; font-weight:600;
               cursor:pointer; padding:2px 0; }
  @media (hover:none) and (pointer:coarse) {
    .bl-actions .bic { width:40px; height:40px; border-radius:var(--wc-r-m); }
    .bl-poignee { width:36px; height:44px; }
  }
  /* ══ Appareils tactiles ═══════════════════════════════════════════════════
     Lié au type de POINTEUR, pas à la largeur : une tablette fait 900 px et se
     touche quand même. C'était mon erreur — tout était conditionné à 680 px, si
     bien qu'un iPad gardait des champs de 13,5 px et des boutons de 27 px.
     Deux contraintes concrètes :
       — sous 16 px, iOS zoome à chaque mise au point dans un champ, ce qui
         décale la page et oblige à repincer ;
       — une cible tactile sous ~42 px se rate une fois sur trois. */
  /* ══ Appareils tactiles ═══════════════════════════════════════════════════
     Lié au type de POINTEUR, pas à la largeur : une tablette fait 900 px et se
     touche quand même. Deux contraintes concrètes :
       — sous 16 px, iOS zoome à chaque mise au point dans un champ, ce qui
         décale la page et oblige à repincer ;
       — une cible tactile sous ~42 px se rate une fois sur trois, et c'est
         d'autant plus vrai pour un bouton réduit à son icône : il n'a plus de
         libellé pour élargir la zone touchable. */
  @media (hover:none) and (pointer:coarse) {
    input[type=text], input[type=url], input[type=number], input[type=date],
    input[type=datetime-local], input[type=password], select, textarea { font-size:16px; padding:11px 12px; }
    .champ-ico input, .champ-ico select { padding-left:38px; }
    label { font-size:11.5px; }
    .btn { min-height:44px; padding:11px 16px; font-size:14px; }
    .btn-sm { min-height:40px; padding:9px 14px; font-size:13px; }
    .bic { width:42px; height:42px; border-radius:var(--wc-r-m); }
    .bic .i { width:21px; height:21px; }
    .bloc-t .bic { width:38px; height:38px; }
    .seg > button { min-height:42px; font-size:13px; }
    .so { min-height:52px; font-size:11.5px !important; }
    .so .i { width:21px; height:21px; }
    .clics { font-size:13px; padding:3px 10px; }
    .puce { font-size:11.5px; padding:3px 9px; }
    .av { width:40px; height:40px; }
    .tete { padding:13px; }
    .tete-nom b { font-size:14.5px; }
    .tete-nom span { font-size:12.5px; }
    .bandeau-url code { font-size:14px; }
    .resume { font-size:12.5px; }
    .aide { font-size:12.5px; }
    .bsc-t b { font-size:14px; }
    .bsc-t em { font-size:12.5px; }
    .piste { width:44px; height:26px; }
    .piste::after { width:20px; height:20px; }
    .bsc input:checked + .piste::after { left:20px; }
    .qr-m { font-size:12.5px !important; min-height:42px; }
    .sous-t { font-size:11.5px; }
  }

  /* ══ Écrans étroits ═══════════════════════════════════════════════════════
     Piloté par la classe .etroit posée en JS, et non par @media : sur iOS, un
     zoom de page mémorisé pour le site élargit le viewport CSS (un écran de
     402 pt affiché à 50 % donne 804 px de viewport), si bien qu'un iPhone ne
     déclenchait jamais max-width:680px et gardait la mise en page large.
     screen.width, lui, ignore ce zoom : on croise les deux mesures.

     Depuis le passage aux icônes, ce bloc s'est beaucoup allégé : les rangées
     d'actions tiennent sur une ligne au lieu de s'empiler en barres pleine
     largeur, donc il n'y a presque plus rien à dégrouper. */
  html.etroit main { padding:14px 12px 50px; }
  html.etroit .carte { padding:13px; border-radius:var(--wc-r-m); }

  /* Création : l'adresse mérite toute la largeur ; « + » et réglages restent à
     côté, ils ne prennent plus que leur carré. */
  html.etroit .creer input { font-size:16px; }
  html.etroit .creer { padding-left:12px; }


  /* L'en-tête tient désormais sur une ligne : vignette, nom, compteur, état,
     chevron. C'est exactement le gabarit d'une ligne de réglages iOS. */
  html.etroit .tete { gap:9px; padding:11px; }
  html.etroit .av { border-radius:var(--wc-r-s); }

  html.etroit .bandeau { padding:11px 12px; }
  html.etroit .bandeau-url code { font-size:12px; }

  html.etroit .sous-onglets { margin:11px 11px 0; }
  html.etroit .so { padding:7px 2px !important; font-size:10px !important; }

  html.etroit .pan { padding:14px 12px; }
  html.etroit .pied { padding:12px; }

  /* Aperçu et QR : pleine largeur, centrés. */
  html.etroit .og { gap:11px; flex-direction:column; }
  html.etroit .og-col { width:100%; align-self:stretch; }
  html.etroit .og-txt b { font-size:13px; }
  html.etroit .og-txt span { font-size:11.5px; max-height:none; }
  /* Sur téléphone, le code passe au-dessus des réglages et prend la largeur,
     plafonné pour ne pas devenir une affiche. */
  html.etroit .qr-zone { flex-direction:column; }
  html.etroit .qr-col-g { width:100%; align-self:stretch; }
  html.etroit .qr-vue { max-width:250px; margin:0 auto; }
  html.etroit .qr-dl { max-width:250px; margin:0 auto; width:100%; }
  html.etroit .qr-modes { max-width:none; }

  /* Éditeur de blocs des pages bio. */
  html.etroit .bloc { padding:12px; }
  /* Le réseau sur sa ligne, puis l'adresse et le retrait côte à côte. */
  html.etroit .bl-rl { grid-template-columns:minmax(0,1fr) 46px; }
  html.etroit .bl-rl select { grid-column:1 / -1; }
  html.etroit .bl-g2, html.etroit .bl-g3 { grid-template-columns:1fr; }

  #releve { position:fixed; left:10px; right:10px; bottom:10px; z-index:1000;
            background:rgba(var(--wc-accent-rgb),.14); border:1px solid var(--accent);
            border-radius:var(--wc-r-m); padding:11px 13px; font-size:12px; line-height:1.5;
            display:flex; flex-direction:column; gap:7px; align-items:flex-start; }
  #releve span { color:var(--text-secondary); font-family:var(--wc-police-mono);
                 font-size:11px; word-break:break-word; }
  #releve button { background:var(--accent); color:#fff; border:none; border-radius:var(--wc-r-s);
                   padding:9px 14px; font:inherit; font-size:12.5px; font-weight:600;
                   min-height:40px; cursor:pointer; }

  .toast { position:fixed; bottom:22px; left:50%; transform:translateX(-50%) translateY(8px);
           z-index:999; background:rgba(22,30,52,.94); backdrop-filter:blur(18px) saturate(1.4);
           -webkit-backdrop-filter:blur(18px) saturate(1.4);
           border:1px solid var(--sep); border-radius:var(--wc-r-l); box-shadow:0 8px 28px rgba(0,0,0,.45);
           padding:11px 18px; font-size:13px; font-weight:500; opacity:0;
           transition:opacity .22s, transform .22s; pointer-events:none; }
  .toast.on { opacity:1; transform:translateX(-50%) translateY(0); }
